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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/brakeman.yml +2 -1
  3. data/.github/workflows/linters.yml +2 -1
  4. data/.gitignore +1 -0
  5. data/.rubocop.yml +37 -4
  6. data/.slim-lint.yml +3 -2
  7. data/Rakefile +2 -0
  8. data/additional_tags.gemspec +5 -3
  9. data/app/controllers/additional_tags_controller.rb +4 -1
  10. data/app/controllers/issue_tags_controller.rb +6 -4
  11. data/app/helpers/additional_tags_helper.rb +39 -41
  12. data/app/helpers/additional_tags_issues_helper.rb +3 -1
  13. data/app/helpers/additional_tags_wiki_helper.rb +6 -4
  14. data/app/jobs/additional_tags_job.rb +2 -0
  15. data/app/jobs/additional_tags_remove_unused_tag_job.rb +2 -0
  16. data/app/models/migrate_tag.rb +2 -0
  17. data/app/models/migrate_tagging.rb +2 -0
  18. data/app/models/query_tags_column.rb +7 -0
  19. data/app/views/additional_tags/_tag_list.html.slim +1 -1
  20. data/app/views/additional_tags/merge.html.slim +4 -3
  21. data/app/views/additional_tags/settings/_manage_tags.html.slim +1 -1
  22. data/app/views/issue_tags/_edit_modal.html.slim +2 -2
  23. data/app/views/issues/_tags_form.html.slim +1 -1
  24. data/config/routes.rb +2 -0
  25. data/db/migrate/20201116145429_acts_as_taggable_migration.rb +3 -1
  26. data/db/migrate/20201123093214_migrate_existing_tags.rb +4 -2
  27. data/init.rb +2 -0
  28. data/lib/additional_tags.rb +5 -15
  29. data/lib/additional_tags/hooks.rb +2 -0
  30. data/lib/additional_tags/patches/agile_boards_controller_patch.rb +2 -0
  31. data/lib/additional_tags/patches/agile_query_patch.rb +11 -9
  32. data/lib/additional_tags/patches/agile_versions_controller_patch.rb +2 -0
  33. data/lib/additional_tags/patches/agile_versions_query_patch.rb +3 -1
  34. data/lib/additional_tags/patches/auto_completes_controller_patch.rb +3 -1
  35. data/lib/additional_tags/patches/calendars_controller_patch.rb +2 -0
  36. data/lib/additional_tags/patches/dashboard_async_blocks_controller_patch.rb +2 -0
  37. data/lib/additional_tags/patches/dashboards_controller_patch.rb +2 -0
  38. data/lib/additional_tags/patches/gantts_controller_patch.rb +2 -0
  39. data/lib/additional_tags/patches/imports_controller_patch.rb +2 -0
  40. data/lib/additional_tags/patches/issue_patch.rb +8 -6
  41. data/lib/additional_tags/patches/issue_query_patch.rb +17 -14
  42. data/lib/additional_tags/patches/issues_controller_patch.rb +2 -0
  43. data/lib/additional_tags/patches/journal_patch.rb +2 -0
  44. data/lib/additional_tags/patches/my_controller_patch.rb +2 -0
  45. data/lib/additional_tags/patches/queries_helper_patch.rb +3 -15
  46. data/lib/additional_tags/patches/query_patch.rb +76 -0
  47. data/lib/additional_tags/patches/reports_controller_patch.rb +2 -0
  48. data/lib/additional_tags/patches/settings_controller_patch.rb +2 -0
  49. data/lib/additional_tags/patches/time_entry_patch.rb +2 -0
  50. data/lib/additional_tags/patches/time_entry_query_patch.rb +5 -15
  51. data/lib/additional_tags/patches/time_report_patch.rb +2 -0
  52. data/lib/additional_tags/patches/timelog_controller_patch.rb +2 -0
  53. data/lib/additional_tags/patches/wiki_controller_patch.rb +2 -0
  54. data/lib/additional_tags/patches/wiki_page_patch.rb +4 -2
  55. data/lib/additional_tags/tags.rb +28 -17
  56. data/lib/additional_tags/version.rb +3 -1
  57. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f6573f962ff7b251ce5afae13e2659985887d486d320fcb99f4c99892fa8a52
4
- data.tar.gz: a258bcf71c8c53b40a5b7bcec92e9b6ff8a7dde6070fe5cfdc3eac0adb3d2ccb
3
+ metadata.gz: '094d1e57c687d9c643b002e5e6134a457d47791a2b086c3c159d690242228488'
4
+ data.tar.gz: dbfd7b4cb744aef1df5d132615bc1d8816ac85ccb7b837b04376d2b1eb9a76d6
5
5
  SHA512:
6
- metadata.gz: 46e6f62fae40af6b03d6b09a2b237f4049ab4d54ce30289e1fa7a74b9ee7f57df586feb3cf695f4268a86478365fee580db550e9b044c84281fcb464e2fde321
7
- data.tar.gz: 8b1c9a8b5873b2b993f27d80186e9c7e0a024e201aba3c0125f47331c6fda50d673cbb1f572c17b2aef1b613b687f6a66c86c17d9b325f8c20e9c2bd8e6bf103
6
+ metadata.gz: f95b50b1d98bb7f22c8a2d3bfc5d767ba85a6df06b5e259d9fe2a03ce2980f6577e948f6120f0fb831d3dee5155f88ebdab215534a3264fc24adb31749610122
7
+ data.tar.gz: 417da0e654d1d966592242c95dd12899638758023b0822499c92e2079d03c28f0b9788046ee161f6ce721df325a0cdd91f1bd6dfe621cb88f910d7b9c12dcd3e
@@ -16,7 +16,8 @@ jobs:
16
16
 
17
17
  - name: Setup Gemfile
18
18
  run: |
19
- cp test/support/gemfile.rb Gemfile
19
+ touch .enable_dev
20
+ sed -i "3isource 'https://rubygems.org'" Gemfile
20
21
 
21
22
  - name: Setup Ruby
22
23
  uses: ruby/setup-ruby@v1
@@ -16,7 +16,8 @@ jobs:
16
16
 
17
17
  - name: Setup Gemfile
18
18
  run: |
19
- cp test/support/gemfile.rb Gemfile
19
+ touch .enable_dev
20
+ sed -i "3isource 'https://rubygems.org'" Gemfile
20
21
 
21
22
  - name: Setup Ruby
22
23
  uses: ruby/setup-ruby@v1
data/.gitignore CHANGED
@@ -6,3 +6,4 @@ Gemfile.lock
6
6
  .project
7
7
  .settings/
8
8
  ._*
9
+ .enable_dev
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: false
69
+ Enabled: true
70
+ Exclude:
71
+ - '/**/*.rsb'
60
72
 
61
73
  Style/Documentation:
62
74
  Enabled: false
63
75
 
64
- # required for travis/ci (symbolic links problem)
65
- Style/ExpandPathArguments:
66
- Enabled: false
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
- - Layout/SpaceBeforeBrackets
27
+ - Style/WhileUntilModifier
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rake/testtask'
3
5
 
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  lib = File.expand_path '../lib', __FILE__
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
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(%r{^((test|spec|features)/|Gemfile)})
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(f) }
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(:notice_failed_to_add_tags)
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(:notice_tags_added)
40
+ flash[:notice] = t :notice_tags_added
39
41
  else
40
- flash[:error] = t(:notice_failed_to_add_tags)
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(:notice_failed_to_add_tags)
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
- require 'digest/md5'
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?(:active_issue_tags)
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?(:active_wiki_tags)
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(:style)
50
- tags = tags.all.to_a if tags.respond_to?(:all)
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, options = {})
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 = AdditionalTags.setting?(: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 options[:show_count]
100
+ tag_name << tag.span("(#{tag_object.count})", class: 'tag-count') if show_count
101
101
 
102
- content = if options[:link]
102
+ content = if link
103
103
  link_to safe_join(tag_name),
104
- options[:link],
104
+ link,
105
105
  style: tag_style
106
- elsif options[:link_wiki_tag]
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::MD5.hexdigest(tag_name)[0..5]}"
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
- s = if tags.blank?
145
- ['']
146
- else
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
- if use_colors.nil? || use_colors
154
- ' '
155
- else
156
- ', '
157
- end
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(:unsorted)
164
- tag_list = AdditionalTags::Tags.sort_tag_list(tag_list) unless unsorted
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, options = {})
173
- action = options[:tag_action].presence || (controller_name == 'hrm_user_resources' ? 'show' : 'index')
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 options[:filter].present?
180
- field = options[:filter][:field]
177
+ if filter.present?
178
+ field = filter[:field]
181
179
  fields << field
182
- operators[field] = options[:filter][:operator]
183
- values[field] = options[:filter][:value] if options[:filter].key?(:value)
180
+ operators[field] = filter[:operator]
181
+ values[field] = filter[:value] if filter.key? :value
184
182
  end
185
183
 
186
- { controller: options[:tag_controller].presence || controller_name,
184
+ { controller: tag_controller.presence || controller_name,
187
185
  action: action,
188
186
  set_filter: 1,
189
- project_id: options[:project],
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(id: tag.id, name: tag.name)
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(project: @project) if AdditionalTags.show_sidebar_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(wiki: :project)
42
+ WikiPage.joins wiki: :project
41
43
  end
42
44
 
43
- scope = scope.visible(User.current, project: project) if scope.respond_to? :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(ActsAsTaggableOn.tags_table)}.name) = LOWER(:p)",
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)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AdditionalTagsJob < AdditionalsJob
2
4
  queue_as :additional_tags
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AdditionalTagsRemoveUnusedTagJob < AdditionalTagsJob
2
4
  def perform
3
5
  AdditionalTags::Tags.remove_unused_tags
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class MigrateTag < ActiveRecord::Base
2
4
  self.table_name = 'tags'
3
5
  has_many :migrate_taggings, dependent: :destroy, foreign_key: :tag_id, inverse_of: :migrate_tag
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class MigrateTagging < ActiveRecord::Base
2
4
  self.table_name = 'taggings'
3
5
  belongs_to :migrate_tag, foreign_key: :tag_id, inverse_of: :migrate_taggings
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class QueryTagsColumn < QueryRelationsColumn
4
+ def initialize(name = :tags, **options)
5
+ super name, **options
6
+ end
7
+ end
@@ -2,7 +2,7 @@
2
2
  .tags.attribute
3
3
  - unless defined? hide_label
4
4
  span.label
5
- = l(:field_tag_list)
5
+ = l :field_tag_list
6
6
  ' :
7
7
  - if defined?(editable) && editable
8
8
  #tags-data
@@ -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, { show_count: true,
10
- use_colors: AdditionalTags.setting?(:use_colors),
11
- link: '#' }
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('ids[]', tag.id, false, id: nil)
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(t.name, class: 'most_used_tag') }, ', '
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
- = submit_tag l(:button_cancel), name: nil, onclick: 'hideModal(this);', type: 'button'
30
+ = link_to_function l(:button_cancel), 'hideModal(this);'
@@ -1,4 +1,4 @@
1
- - project = defined?(project) ? project : @project
1
+ - project = @project unless defined?(project)
2
2
  - options = { multiple: true,
3
3
  width: '95%',
4
4
  url: issue_tags_auto_completes_path(project_id: project),
data/config/routes.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Rails.application.routes.draw do
2
4
  resources :auto_completes, only: [] do
3
5
  collection do
@@ -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("ALTER TABLE #{ActsAsTaggableOn.tags_table} MODIFY name varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;")
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!(name: old_tag.name) if cnt.zero? && tag.nil?
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(tag.id, :taggings) unless tag.nil?
33
+ ActsAsTaggableOn::Tag.reset_counters tag.id, :taggings unless tag.nil?
32
34
  end
33
35
  end
34
36
  end
data/init.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Redmine::Plugin.register :additional_tags do
2
4
  name 'Additional Tags'
3
5
  author 'AlphaNodes GmbH'
@@ -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'.freeze
6
- TAGGING_TABLE_NAME = 'additional_taggings'.freeze
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
  class AdditionalTagsHookListener < Redmine::Hook::ViewListener
3
5
  render_on :view_issues_bulk_edit_details_bottom,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdditionalTags
2
4
  module Patches
3
5
  module AgileBoardsControllerPatch
@@ -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 QueryColumn.new(:tags)
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
- when '=', '!'
20
- issues = Issue.tagged_with(value.clone, any: true)
21
- when '!*'
22
- issues = Issue.joins(:tags).uniq
23
- else
24
- issues = Issue.tagged_with(ActsAsTaggableOn::Tag.all.map(&:to_s), any: true)
25
- end
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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdditionalTags
2
4
  module Patches
3
5
  module AgileVersionsControllerPatch
@@ -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 QueryColumn.new(:tags)
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(ActsAsTaggableOn.tags_table)}.name) LIKE ?"
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 CalendarsControllerPatch
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdditionalTags
2
4
  module Patches
3
5
  module DashboardAsyncBlocksControllerPatch
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdditionalTags
2
4
  module Patches
3
5
  module DashboardsControllerPatch
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdditionalTags
2
4
  module Patches
3
5
  module GanttsControllerPatch
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdditionalTags
2
4
  module Patches
3
5
  module ImportsControllerPatch
@@ -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?(tag) }
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(project: project, association: :tags, with_subprojects: with_subprojects)
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
- alias_method :build_from_params_without_tags, :build_from_params
17
- alias_method :build_from_params, :build_from_params_with_tags
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 << QueryColumn.new(:tags)
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 IssuesControllerPatch
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdditionalTags
2
4
  module Patches
3
5
  module JournalPatch
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdditionalTags
2
4
  module Patches
3
5
  module MyControllerPatch
@@ -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
  module AdditionalTags
2
4
  module Patches
3
5
  module ReportsControllerPatch
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdditionalTags
2
4
  module Patches
3
5
  module SettingsControllerPatch
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdditionalTags
2
4
  module Patches
3
5
  module TimeEntryPatch
@@ -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, value)
43
- AdditionalTags.sql_for_tags_field Issue, operator, value
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
  require_dependency 'query'
2
4
 
3
5
  module AdditionalTags
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdditionalTags
2
4
  module Patches
3
5
  module TimelogControllerPatch
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdditionalTags
2
4
  module Patches
3
5
  module WikiControllerPatch
@@ -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
 
@@ -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("#{Project.table_name}.id = ?", options[:project]) if options[:project]
10
+ scope = scope.where "#{Project.table_name}.id = ?", options[:project] if options[:project]
9
11
  if options[:permission]
10
- scope = scope.where(tag_access(options[:permission], user))
12
+ scope = scope.where tag_access(options[:permission], user)
11
13
  elsif options[:visible_condition]
12
- scope = scope.where(klass.visible_condition(user))
14
+ scope = scope.where klass.visible_condition(user)
13
15
  end
14
- scope = scope.where("LOWER(#{TAG_TABLE_NAME}.name) LIKE ?", "%#{options[:name_like].downcase}%") if options[:name_like]
15
- scope = scope.where("#{TAG_TABLE_NAME}.name=?", options[:name]) if options[:name]
16
- scope = scope.where("#{TAGGING_TABLE_NAME}.taggable_id!=?", options[:exclude_id]) if options[:exclude_id]
17
- scope = scope.where(options[:where_field] => options[:where_value]) if options[:where_field].present? && options[:where_value]
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, options = {})
33
- ActsAsTaggableOn::Tag.where({})
34
- .joins(tag_for_joins(klass, options))
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(tag_id: tag.id)
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, options = {})
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 options[:project_join]
111
- joins << options[:project_join]
112
- elsif options[:project] || !options[:without_projects]
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
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdditionalTags
2
- VERSION = '1.0.1'.freeze unless defined? VERSION
4
+ VERSION = '1.0.2' unless defined? VERSION
3
5
  end
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.1
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-04-10 00:00:00.000000000 Z
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