redmineup 1.0.2 → 1.1.13
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/.gitignore +1 -0
- data/.gitlab-ci.yml +33 -0
- data/README.md +74 -153
- data/app/assets/images/icons.svg +8 -0
- data/app/assets/javascripts/chart.min.js +13 -0
- data/app/assets/javascripts/consumer.js +53 -0
- data/app/assets/javascripts/consumer_worker.js +219 -0
- data/app/assets/javascripts/jquery.colorPicker.min.js +26 -0
- data/{vendor → app}/assets/javascripts/select2_helpers.js +11 -1
- data/app/assets/stylesheets/calendars.css +15 -0
- data/{vendor → app}/assets/stylesheets/money.css +1 -2
- data/app/assets/stylesheets/redmineup.css +509 -0
- data/{vendor → app}/assets/stylesheets/select2.css +1 -1
- data/app/views/redmineup/_additional_assets.html.erb +1 -0
- data/config/locales/en.yml +1 -0
- data/config/locales/ru.yml +1 -0
- data/config/routes.rb +4 -0
- data/doc/CHANGELOG +116 -7
- data/doc/active-record-mixins.md +156 -0
- data/doc/assets-money-and-utilities.md +71 -0
- data/doc/tagging-and-select2.md +108 -0
- data/lib/action_cable/connection/rup_connection.rb +17 -0
- data/lib/action_cable/server/rup_configuration.rb +17 -0
- data/lib/action_cable/server/rup_server.rb +17 -0
- data/lib/application_record.rb +3 -0
- data/lib/redmineup/acts_as_taggable/tag.rb +26 -2
- data/lib/redmineup/acts_as_taggable/up_acts_as_taggable.rb +42 -2
- data/lib/redmineup/acts_as_viewed/up_acts_as_viewed.rb +1 -1
- data/lib/redmineup/acts_as_votable/votable.rb +2 -5
- data/lib/redmineup/assets_manager.rb +12 -1
- data/lib/redmineup/currency.rb +3 -1
- data/lib/redmineup/engine.rb +12 -2
- data/lib/redmineup/helpers/calendars_helper.rb +22 -0
- data/lib/redmineup/helpers/datetime_helper.rb +23 -0
- data/lib/redmineup/helpers/external_assets_helper.rb +15 -7
- data/lib/redmineup/helpers/form_tag_helper.rb +43 -0
- data/lib/redmineup/helpers/tags_helper.rb +41 -0
- data/lib/redmineup/helpers/test_helper.rb +12 -0
- data/lib/redmineup/hooks/views_layouts_hook.rb +1 -3
- data/lib/redmineup/liquid/drops/attachment_drop.rb +8 -0
- data/lib/redmineup/liquid/drops/custom_field_enumeration_drop.rb +11 -0
- data/lib/redmineup/liquid/drops/issues_drop.rb +11 -19
- data/lib/redmineup/liquid/drops/users_drop.rb +2 -3
- data/lib/redmineup/liquid/drops/version_drop.rb +38 -0
- data/lib/redmineup/liquid/filters/additional.rb +31 -0
- data/lib/redmineup/liquid/filters/base.rb +16 -1
- data/lib/redmineup/money_helper.rb +10 -2
- data/lib/redmineup/patches/action_cable_base_patch.rb +25 -0
- data/lib/redmineup/patches/action_cable_patch.rb +19 -0
- data/lib/redmineup/patches/auto_completes_controller_patch.rb +17 -0
- data/lib/redmineup/patches/compatibility/routing_mapper_patch.rb +16 -0
- data/lib/redmineup/patches/compatibility/sprite_patch.rb +13 -0
- data/lib/redmineup/patches/compatibility_patch.rb +4 -0
- data/lib/redmineup/patches/liquid_patch.rb +13 -22
- data/lib/redmineup/version.rb +1 -1
- data/lib/redmineup.rb +66 -40
- data/test/acts_as_taggable/rup_acts_as_taggable_test.rb +1 -1
- data/test/acts_as_taggable/tag_test.rb +16 -0
- data/test/acts_as_votable/votable_test.rb +9 -9
- data/test/acts_as_votable/voter_test.rb +4 -4
- data/test/database.yml +3 -3
- data/test/fixtures/tags.yml +2 -0
- data/test/liquid/drops/issues_drop_test.rb +5 -0
- data/test/liquid/filters/additional_filter_test.rb +35 -0
- data/test/liquid/filters/arrays_filter_test.rb +6 -3
- data/test/liquid/liquid_helper.rb +1 -1
- data/test/models/attachment.rb +5 -0
- data/test/models/issue.rb +5 -0
- data/test/models/journal.rb +6 -0
- data/test/schema.rb +65 -53
- data/test/tags_helper_view_test.rb +41 -0
- data/test/test_helper.rb +13 -12
- metadata +43 -14
- data/app/views/redmine_crm/redmineup_calendar/_calendar.html.erb +0 -34
- data/bitbucket-pipelines.yml +0 -50
- data/lib/redmineup/compatibility/application_controller_patch.rb +0 -33
- data/lib/redmineup/compatibility/routing_mapper_patch.rb +0 -25
- data/lib/redmineup/helpers/rup_calendar_helper.rb +0 -146
- /data/{vendor → app}/assets/images/money.png +0 -0
- /data/{vendor → app}/assets/images/vcard.png +0 -0
- /data/{vendor/assets/javascripts/Chart.bundle.min.js → app/assets/javascripts/Chart.bundle.min.js.bak} +0 -0
- /data/{vendor → app}/assets/javascripts/select2.js +0 -0
data/lib/redmineup.rb
CHANGED
|
@@ -27,6 +27,7 @@ require 'redmineup/money_helper'
|
|
|
27
27
|
require 'redmineup/colors_helper'
|
|
28
28
|
|
|
29
29
|
require 'liquid'
|
|
30
|
+
require 'redmineup/liquid/filters/additional'
|
|
30
31
|
require 'redmineup/liquid/filters/base'
|
|
31
32
|
require 'redmineup/liquid/filters/arrays'
|
|
32
33
|
require 'redmineup/liquid/filters/colors'
|
|
@@ -37,18 +38,38 @@ require 'redmineup/liquid/drops/users_drop'
|
|
|
37
38
|
require 'redmineup/liquid/drops/time_entries_drop'
|
|
38
39
|
require 'redmineup/liquid/drops/attachment_drop'
|
|
39
40
|
require 'redmineup/liquid/drops/issue_relations_drop'
|
|
41
|
+
require 'redmineup/liquid/drops/version_drop'
|
|
42
|
+
require 'redmineup/liquid/drops/custom_field_enumeration_drop'
|
|
40
43
|
|
|
41
44
|
require 'redmineup/helpers/external_assets_helper'
|
|
42
45
|
require 'redmineup/helpers/form_tag_helper'
|
|
43
|
-
require 'redmineup/helpers/
|
|
46
|
+
require 'redmineup/helpers/calendars_helper'
|
|
47
|
+
require 'redmineup/helpers/datetime_helper'
|
|
48
|
+
require 'redmineup/helpers/test_helper'
|
|
44
49
|
require 'redmineup/assets_manager'
|
|
45
50
|
|
|
46
|
-
require 'redmineup/
|
|
47
|
-
require 'redmineup/compatibility/routing_mapper_patch'
|
|
48
|
-
require 'redmineup/patches/liquid_patch' unless BigDecimal.respond_to?(:new)
|
|
51
|
+
require 'redmineup/patches/liquid_patch'
|
|
49
52
|
|
|
50
53
|
module Redmineup
|
|
51
54
|
GEM_NAME = 'redmineup'.freeze
|
|
55
|
+
|
|
56
|
+
def self.plugin_installed?(plugin_id)
|
|
57
|
+
Rails.root.join("plugins/#{plugin_id}/init.rb").exist?
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.cable_available?
|
|
61
|
+
Rails.version > '4.0'
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
require 'application_record' if !defined?(ApplicationRecord) && Rails.version < '7.2.2'
|
|
66
|
+
|
|
67
|
+
if Redmineup.cable_available?
|
|
68
|
+
require 'action_cable/server/rup_configuration'
|
|
69
|
+
require 'action_cable/server/rup_server'
|
|
70
|
+
require 'action_cable/connection/rup_connection'
|
|
71
|
+
require 'redmineup/patches/action_cable_base_patch'
|
|
72
|
+
require 'redmineup/patches/action_cable_patch'
|
|
52
73
|
end
|
|
53
74
|
|
|
54
75
|
if defined?(ActiveRecord::Base)
|
|
@@ -57,52 +78,57 @@ if defined?(ActiveRecord::Base)
|
|
|
57
78
|
ActiveRecord::Base.extend(Redmineup::ActsAsVotable::Votable)
|
|
58
79
|
end
|
|
59
80
|
|
|
60
|
-
|
|
81
|
+
if defined?(Propshaft::Assembly)
|
|
82
|
+
Propshaft::Assembly.prepend(Module.new do
|
|
83
|
+
def self.prepended(base)
|
|
84
|
+
base.class_eval do
|
|
85
|
+
cattr_accessor :redmineup_patched
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def config
|
|
90
|
+
return super if self.class.redmineup_patched
|
|
91
|
+
|
|
92
|
+
original_config = super
|
|
93
|
+
if defined?(Redmine::AssetPath)
|
|
94
|
+
base_dir = Pathname.new(Redmineup::AssetsManager.base_path)
|
|
95
|
+
paths = Redmineup::AssetsManager.assets_paths.map { |path| Pathname.new(path)}
|
|
96
|
+
asset_prefix = "plugin_assets/#{Redmineup::GEM_NAME}"
|
|
97
|
+
|
|
98
|
+
original_config[:redmine_extension_paths] << Redmine::AssetPath.new(base_dir, paths, asset_prefix)
|
|
99
|
+
self.class.redmineup_patched = true
|
|
100
|
+
end
|
|
101
|
+
original_config
|
|
102
|
+
end
|
|
103
|
+
end)
|
|
104
|
+
else
|
|
105
|
+
Redmineup::AssetsManager.install_assets
|
|
106
|
+
end
|
|
61
107
|
|
|
62
108
|
if defined?(ActionView::Base)
|
|
109
|
+
ActionView::Base.send :include, Redmineup::CalendarsHelper
|
|
63
110
|
ActionView::Base.send :include, Redmineup::ExternalAssetsHelper
|
|
64
111
|
ActionView::Base.send :include, Redmineup::FormTagHelper
|
|
112
|
+
ActionView::Base.send :include, Redmineup::TagsHelper
|
|
65
113
|
end
|
|
66
114
|
|
|
67
115
|
def requires_redmineup(arg)
|
|
68
|
-
|
|
69
|
-
|
|
116
|
+
arg = { version_or_higher: arg } unless arg.is_a?(Hash)
|
|
117
|
+
arg.assert_valid_keys(:version_or_higher)
|
|
70
118
|
|
|
71
|
-
|
|
72
|
-
|
|
119
|
+
requirement = arg[:version_or_higher]
|
|
120
|
+
unless requirement.is_a?(String)
|
|
121
|
+
raise ArgumentError, ':version_or_higher accepts a version string only'
|
|
73
122
|
end
|
|
74
123
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
end
|
|
124
|
+
current = Gem::Version.new(Redmineup::VERSION)
|
|
125
|
+
required = Gem::Version.new(requirement)
|
|
78
126
|
|
|
79
|
-
|
|
80
|
-
arg.assert_valid_keys(:version, :version_or_higher)
|
|
127
|
+
return true if required <= current
|
|
81
128
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
unless compare_versions(req, current) <= 0
|
|
89
|
-
Rails.logger.error "\033[31m[ERROR]\033[0m Redmine requires redmineup gem version #{req} or higher (you're using #{Redmineup::VERSION}).\n\033[31m[ERROR]\033[0m Please update with 'bundle update redmineup'." if Rails.logger
|
|
90
|
-
abort "\033[31mRedmine requires redmineup gem version #{req} or higher (you're using #{Redmineup::VERSION}).\nPlease update with 'bundle update redmineup'.\033[0m"
|
|
91
|
-
end
|
|
92
|
-
when :version
|
|
93
|
-
req = [req] if req.is_a?(String)
|
|
94
|
-
if req.is_a?(Array)
|
|
95
|
-
unless req.detect { |ver| compare_versions(ver, current) == 0 }
|
|
96
|
-
abort "\033[31mRedmine requires redmineup gem version #{req} (you're using #{Redmineup::VERSION}).\nPlease update with 'bundle update redmineup'.\033[0m"
|
|
97
|
-
end
|
|
98
|
-
elsif req.is_a?(Range)
|
|
99
|
-
unless compare_versions(req.first, current) <= 0 && compare_versions(req.last, current) >= 0
|
|
100
|
-
abort "\033[31mRedmine requires redmineup gem version between #{req.first} and #{req.last} (you're using #{Redmineup::VERSION}).\nPlease update with 'bundle update redmineup'.\033[0m"
|
|
101
|
-
end
|
|
102
|
-
else
|
|
103
|
-
raise ArgumentError.new(':version option accepts a version string, an array or a range of versions')
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
true
|
|
129
|
+
message = "Redmine requires redmineup gem version #{requirement} or higher " \
|
|
130
|
+
"(you're using #{Redmineup::VERSION}).\n" \
|
|
131
|
+
"Please update with 'bundle update redmineup --conservative'."
|
|
132
|
+
Rails.logger&.error("\033[31m[ERROR]\033[0m #{message}")
|
|
133
|
+
abort "\033[31m#{message}\033[0m"
|
|
108
134
|
end
|
|
@@ -338,7 +338,7 @@ class RupActsAsTaggableTest < ActiveSupport::TestCase
|
|
|
338
338
|
|
|
339
339
|
def test_tags_condition
|
|
340
340
|
assert_equal "(tags_TABLE.name LIKE #{tags(:feature).id} OR tags_TABLE.name LIKE #{tags(:bug).id})",
|
|
341
|
-
Issue.send(:tags_condition, [tags(:feature), tags(:bug)], 'tags_TABLE')
|
|
341
|
+
Issue.send(:tags_condition, [tags(:feature), tags(:bug)], 'tags_TABLE').gsub("'", "")
|
|
342
342
|
end
|
|
343
343
|
|
|
344
344
|
def test_all_tags_list
|
|
@@ -33,6 +33,22 @@ class TagTest < ActiveSupport::TestCase
|
|
|
33
33
|
assert_equal tags(:error).name, tags(:error).to_s
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
def test_color
|
|
37
|
+
assert_equal '#aaaaaa', tags(:feature).color # 11184810 = 0xaaaaaa
|
|
38
|
+
assert_equal '#bbbbbb', tags(:bug).color # 12303291 = 0xbbbbbb
|
|
39
|
+
# no DB color — falls back to color_from_name, not nil
|
|
40
|
+
assert_equal Redmineup::ActsAsTaggable::Tag.color_from_name('error'), tags(:error).color
|
|
41
|
+
assert_equal Redmineup::ActsAsTaggable::Tag.color_from_name('question'), tags(:question).color
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_color_from_name
|
|
45
|
+
color = Redmineup::ActsAsTaggable::Tag.color_from_name('error')
|
|
46
|
+
assert_match(/\A#[0-9a-f]{6}\z/, color)
|
|
47
|
+
assert_equal color, Redmineup::ActsAsTaggable::Tag.color_from_name('error') # deterministic
|
|
48
|
+
assert_not_equal color, Redmineup::ActsAsTaggable::Tag.color_from_name('other')
|
|
49
|
+
assert_match(/\A#[0-9a-f]{6}\z/, Redmineup::ActsAsTaggable::Tag.color_from_name(nil))
|
|
50
|
+
end
|
|
51
|
+
|
|
36
52
|
def test_tag_is_equal_to_itself
|
|
37
53
|
tag = tags(:error)
|
|
38
54
|
assert_equal tag, tag
|
|
@@ -67,7 +67,7 @@ class VotableTest < ActiveSupport::TestCase
|
|
|
67
67
|
assert_equal votable.find_votes_for(:vote_scope => 'rank').size, 1
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
-
def
|
|
70
|
+
def test_two_votes_for_when_voting_on_two_diff_scopes_dup
|
|
71
71
|
votable.vote_by(:voter => voters(:voter), :vote => 'yes', :vote_scope => 'weekly_rank')
|
|
72
72
|
votable.vote_by(:voter => voters(:voter), :vote => 'yes', :vote_scope => 'monthly_rank')
|
|
73
73
|
assert_equal votable.votes_for.size, 2
|
|
@@ -404,7 +404,7 @@ class VotableTest < ActiveSupport::TestCase
|
|
|
404
404
|
assert_equal votable_cache.cached_scoped_test_votes_total, 1
|
|
405
405
|
end
|
|
406
406
|
|
|
407
|
-
def
|
|
407
|
+
def test_update_cached_total_votes_for_when_a_vote_up_is_removed_dup
|
|
408
408
|
votable_cache.vote_by(:voter => voter, :vote => 'true', :vote_scope => "test")
|
|
409
409
|
votable_cache.unvote(:voter => voter, :vote_scope => "test")
|
|
410
410
|
assert_equal votable_cache.cached_scoped_test_votes_total, 0
|
|
@@ -440,44 +440,44 @@ class VotableTest < ActiveSupport::TestCase
|
|
|
440
440
|
assert_equal votable_cache.cached_scoped_test_votes_score, 0
|
|
441
441
|
end
|
|
442
442
|
|
|
443
|
-
def
|
|
443
|
+
def test_update_cached_up_votes_for_if_there_is_an_up_vote_column_dup
|
|
444
444
|
votable_cache.cached_scoped_test_votes_up = 50
|
|
445
445
|
votable_cache.vote_by(:voter => voter, :vote_scope => "test")
|
|
446
446
|
votable_cache.vote_by(:voter => voter, :vote_scope => "test")
|
|
447
447
|
assert_equal votable_cache.cached_scoped_test_votes_up, 1
|
|
448
448
|
end
|
|
449
449
|
|
|
450
|
-
def
|
|
450
|
+
def test_update_cached_down_votes_for_if_there_is_a_down_vote_column_dup
|
|
451
451
|
votable_cache.cached_scoped_test_votes_down = 50
|
|
452
452
|
votable_cache.vote_by(:voter => voter, :vote => 'false', :vote_scope => "test")
|
|
453
453
|
assert_equal votable_cache.cached_scoped_test_votes_down, 1
|
|
454
454
|
end
|
|
455
455
|
|
|
456
|
-
def
|
|
456
|
+
def test_update_cached_up_votes_for_when_a_vote_up_is_removed_dup
|
|
457
457
|
votable_cache.vote_by :voter => voter, :vote => 'true', :vote_scope => "test"
|
|
458
458
|
votable_cache.unvote :voter => voter, :vote_scope => "test"
|
|
459
459
|
assert_equal votable_cache.cached_scoped_test_votes_up, 0
|
|
460
460
|
end
|
|
461
461
|
|
|
462
|
-
def
|
|
462
|
+
def test_update_cached_down_votes_for_when_a_vote_down_is_removed_dup
|
|
463
463
|
votable_cache.vote_by(:voter => voter, :vote => 'false', :vote_scope => "test")
|
|
464
464
|
votable_cache.unvote(:voter => voter, :vote_scope => "test")
|
|
465
465
|
assert_equal votable_cache.cached_scoped_test_votes_down, 0
|
|
466
466
|
end
|
|
467
467
|
|
|
468
|
-
def
|
|
468
|
+
def test_select_from_cached_total_votes_for_if_there_a_total_column_dup
|
|
469
469
|
votable_cache.vote_by(:voter => voter, :vote_scope => "test")
|
|
470
470
|
votable_cache.cached_scoped_test_votes_total = 50
|
|
471
471
|
assert_equal votable_cache.count_votes_total(false, "test"), 50
|
|
472
472
|
end
|
|
473
473
|
|
|
474
|
-
def
|
|
474
|
+
def test_select_from_cached_up_votes_for_if_there_is_an_up_vote_column_dup
|
|
475
475
|
votable_cache.vote_by(:voter => voter, :vote_scope => "test")
|
|
476
476
|
votable_cache.cached_scoped_test_votes_up = 50
|
|
477
477
|
assert_equal votable_cache.count_votes_up(false, "test"), 50
|
|
478
478
|
end
|
|
479
479
|
|
|
480
|
-
def
|
|
480
|
+
def test_select_from_cached_down_votes_for_if_there_is_a_down_vote_column_dup
|
|
481
481
|
votable_cache.vote_by(:voter => voter, :vote => 'false', :vote_scope => "test")
|
|
482
482
|
votable_cache.cached_scoped_test_votes_down = 50
|
|
483
483
|
assert_equal votable_cache.count_votes_down(false, "test"), 50
|
|
@@ -188,7 +188,7 @@ class VoterTest < ActiveSupport::TestCase
|
|
|
188
188
|
end
|
|
189
189
|
|
|
190
190
|
# describe '#find_up_voted_items
|
|
191
|
-
def
|
|
191
|
+
def test_returns_objects_that_a_user_has_upvoted_for_dup
|
|
192
192
|
votable.vote_by(:voter => voter)
|
|
193
193
|
votables(:votable2).vote_by :voter => voters(:voter2)
|
|
194
194
|
assert voter.find_up_voted_items.include? votable
|
|
@@ -197,7 +197,7 @@ class VoterTest < ActiveSupport::TestCase
|
|
|
197
197
|
assert_equal voter.find_liked_items.size, 1
|
|
198
198
|
end
|
|
199
199
|
|
|
200
|
-
def
|
|
200
|
+
def test_returns_objects_that_a_user_has_upvoted_for_using_scope_dup
|
|
201
201
|
votable.vote_by(:voter => voter, :vote_scope => 'rank')
|
|
202
202
|
votables(:votable2).vote_by(:voter => voters(:voter2), :vote_scope => 'rank')
|
|
203
203
|
assert voter.find_up_voted_items(:vote_scope => 'rank').include? votable
|
|
@@ -226,7 +226,7 @@ class VoterTest < ActiveSupport::TestCase
|
|
|
226
226
|
assert_equal voter.find_down_voted_items(:vote_scope => 'rank').size, 0
|
|
227
227
|
end
|
|
228
228
|
|
|
229
|
-
def
|
|
229
|
+
def test_returns_objects_that_a_user_has_downvoted_for_dup
|
|
230
230
|
votable.vote_down voter
|
|
231
231
|
votables(:votable2).vote_down voters(:voter2)
|
|
232
232
|
assert voter.find_down_voted_items.include? votable
|
|
@@ -235,7 +235,7 @@ class VoterTest < ActiveSupport::TestCase
|
|
|
235
235
|
assert_equal voter.find_disliked_items.size, 1
|
|
236
236
|
end
|
|
237
237
|
|
|
238
|
-
def
|
|
238
|
+
def test_returns_objects_that_a_user_has_downvoted_for_using_scope_dup
|
|
239
239
|
votable.vote_down voter, :vote_scope => 'rank'
|
|
240
240
|
votables(:votable2).vote_down voters(:voter2), :vote_scope => 'rank'
|
|
241
241
|
assert voter.find_down_voted_items(:vote_scope => 'rank').include? votable
|
data/test/database.yml
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
sqlite:
|
|
2
2
|
adapter: sqlite3
|
|
3
|
-
database:
|
|
3
|
+
database: ":memory:"
|
|
4
4
|
|
|
5
5
|
mysql:
|
|
6
6
|
adapter: mysql2
|
|
7
7
|
database: redmineup_test
|
|
8
8
|
username: root
|
|
9
9
|
password: password
|
|
10
|
-
host:
|
|
10
|
+
host: mysql
|
|
11
11
|
|
|
12
12
|
postgresql:
|
|
13
13
|
adapter: postgresql
|
|
14
14
|
database: redmineup_test
|
|
15
15
|
user: postgres
|
|
16
16
|
password: password
|
|
17
|
-
host:
|
|
17
|
+
host: postgres
|
data/test/fixtures/tags.yml
CHANGED
|
@@ -26,6 +26,11 @@ module Redmineup
|
|
|
26
26
|
assert_equal @user.name, @liquid_render.render('{{ issue.author.name }}')
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
def test_issue_attachments
|
|
30
|
+
attachment_author = @issue.attachments.first.author.name
|
|
31
|
+
assert_equal attachment_author, @liquid_render.render('{% assign attach = issue.attachments | first %}{{ attach.author.name }}')
|
|
32
|
+
end
|
|
33
|
+
|
|
29
34
|
def test_issue_delegated
|
|
30
35
|
assert_equal [@issue.id, @issue.subject, @issue.description].join('|'),
|
|
31
36
|
@liquid_render.render('{{ issue.id }}|{{ issue.subject }}|{{ issue.description }}')
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../liquid_helper'
|
|
2
|
+
include LiquidHelperMethods
|
|
3
|
+
|
|
4
|
+
module Redmineup
|
|
5
|
+
class AdditionalFilterTest < ActiveSupport::TestCase
|
|
6
|
+
def setup
|
|
7
|
+
@issue = Issue.first
|
|
8
|
+
@issue_drop = Liquid::IssueDrop.new(@issue)
|
|
9
|
+
@strainer = ::Liquid::Context.new.strainer
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_parse_inline_attachments
|
|
13
|
+
text = '<p>description with image <img src="screenshot.png" /></p>'
|
|
14
|
+
attachment = mock_attachment
|
|
15
|
+
attachments = [attachment]
|
|
16
|
+
@issue_drop.define_singleton_method(:attachments) { attachments }
|
|
17
|
+
Attachment.stub(:latest_attach, attachment) do
|
|
18
|
+
expected_string = '<p>description with image ' \
|
|
19
|
+
'<img src=\'data:image/content_type;base64,to_base64_string\' title="attach_image" alt="attach_image" /></p>'
|
|
20
|
+
assert_equal expected_string, @strainer.parse_inline_attachments(text, @issue_drop)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def mock_attachment
|
|
27
|
+
attachment = Minitest::Mock.new
|
|
28
|
+
attachment.expect(:url, 'mock_url')
|
|
29
|
+
attachment.expect(:description, "attach_image")
|
|
30
|
+
attachment.expect(:content_type, "content_type")
|
|
31
|
+
attachment.expect(:to_base64_string, "to_base64_string")
|
|
32
|
+
attachment
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -17,9 +17,9 @@ module Redmineup
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def test_where_filter
|
|
20
|
-
assert_match '{"name"=>"two", "value"=>5}', @liquid_render.render("{{ objects_arr | where: 'name', 'two' }}")
|
|
21
|
-
assert_match '{"name"=>"one", "value"=>10}', @liquid_render.render("{{ objects_arr | where: 'value', 6, '>' }}")
|
|
22
|
-
assert_match '{"name"=>"one", "value"=>10}', @liquid_render.render("{{ objects_arr | where: 'name', 'on', 'match' }}")
|
|
20
|
+
assert_match ws('{"name"=>"two", "value"=>5}'), ws(@liquid_render.render("{{ objects_arr | where: 'name', 'two' }}"))
|
|
21
|
+
assert_match ws('{"name"=>"one", "value"=>10}'), ws(@liquid_render.render("{{ objects_arr | where: 'value', 6, '>' }}"))
|
|
22
|
+
assert_match ws('{"name"=>"one", "value"=>10}'), ws(@liquid_render.render("{{ objects_arr | where: 'name', 'on', 'match' }}"))
|
|
23
23
|
assert_match '3', @liquid_render.render("{{ objects_arr | where: 'value', '', 'any' | size }}")
|
|
24
24
|
assert_match '1', @liquid_render.render("{{ objects_arr | where: 'value', '', 'none' | size }}")
|
|
25
25
|
assert_match '2', @liquid_render.render("{{ issues.all | where: 'author.name', 'Jonathan', '==' | size }}")
|
|
@@ -27,5 +27,8 @@ module Redmineup
|
|
|
27
27
|
assert_match '0', @liquid_render.render("{{ issues.all | where: 'author.name', '', 'none' | size }}")
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def ws(string)
|
|
31
|
+
string.delete(' ')
|
|
32
|
+
end
|
|
30
33
|
end
|
|
31
34
|
end
|
data/test/models/attachment.rb
CHANGED
data/test/models/issue.rb
CHANGED
|
@@ -8,6 +8,7 @@ class Issue < ActiveRecord::Base
|
|
|
8
8
|
|
|
9
9
|
has_many :relations_from, class_name: 'IssueRelation', foreign_key: 'issue_from_id', dependent: :delete_all
|
|
10
10
|
has_many :relations_to, class_name: 'IssueRelation', foreign_key: 'issue_to_id', dependent: :delete_all
|
|
11
|
+
has_many :journals, foreign_key: 'journalized_id'
|
|
11
12
|
|
|
12
13
|
up_acts_as_draftable
|
|
13
14
|
up_acts_as_taggable
|
|
@@ -18,4 +19,8 @@ class Issue < ActiveRecord::Base
|
|
|
18
19
|
def visible?
|
|
19
20
|
true
|
|
20
21
|
end
|
|
22
|
+
|
|
23
|
+
def attachments
|
|
24
|
+
Attachment.all
|
|
25
|
+
end
|
|
21
26
|
end
|
data/test/schema.rb
CHANGED
|
@@ -25,97 +25,109 @@ ActiveRecord::Schema.define version: 0 do
|
|
|
25
25
|
t.datetime :updated_at
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
create_table
|
|
29
|
-
t.
|
|
28
|
+
create_table :journals, force: true do |t|
|
|
29
|
+
t.integer :journalized_id, default: 0, null: false
|
|
30
|
+
t.string :journalized_type, limit: 30, default: "", null: false
|
|
31
|
+
t.integer :user_id, default: 0, null: false
|
|
32
|
+
t.text :notes
|
|
33
|
+
t.datetime :created_on, null: false
|
|
34
|
+
t.boolean :private_notes, default: false, null: false
|
|
30
35
|
end
|
|
31
36
|
|
|
32
|
-
create_table
|
|
33
|
-
t.
|
|
34
|
-
t.
|
|
35
|
-
t.column "taggable_type", :string
|
|
36
|
-
t.column "created_at", :datetime
|
|
37
|
+
create_table :tags, force: true do |t|
|
|
38
|
+
t.string :name
|
|
39
|
+
t.string :color
|
|
37
40
|
end
|
|
38
41
|
|
|
39
|
-
create_table
|
|
40
|
-
t.
|
|
41
|
-
t.
|
|
42
|
+
create_table :taggings, force: true do |t|
|
|
43
|
+
t.integer :tag_id
|
|
44
|
+
t.integer :taggable_id
|
|
45
|
+
t.string :taggable_type
|
|
46
|
+
t.datetime :created_at
|
|
42
47
|
end
|
|
43
48
|
|
|
44
|
-
create_table
|
|
45
|
-
t.
|
|
46
|
-
t.
|
|
47
|
-
t.column "relation_type", :string
|
|
48
|
-
t.column "delay", :integer
|
|
49
|
+
create_table :users, force: true do |t|
|
|
50
|
+
t.string :name
|
|
51
|
+
t.string :language
|
|
49
52
|
end
|
|
50
53
|
|
|
51
|
-
create_table
|
|
52
|
-
t.
|
|
53
|
-
t.column "subject", :string
|
|
54
|
-
t.column "description", :string
|
|
55
|
-
t.column "closed", :boolean
|
|
56
|
-
t.column "cached_tag_list", :string
|
|
57
|
-
t.column "user_id", :integer
|
|
58
|
-
t.column "author_id", :integer
|
|
59
|
-
t.column "views", :integer, :default => 0
|
|
60
|
-
t.column "total_views", :integer, :default => 0
|
|
54
|
+
create_table :categories, force: true do |t|
|
|
55
|
+
t.string :name
|
|
61
56
|
end
|
|
62
57
|
|
|
63
|
-
create_table
|
|
64
|
-
t.
|
|
65
|
-
t.
|
|
66
|
-
|
|
67
|
-
t.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
58
|
+
create_table :issue_relations, force: true do |t|
|
|
59
|
+
t.integer :issue_from_id
|
|
60
|
+
t.integer :issue_to_id
|
|
61
|
+
t.string :relation_type
|
|
62
|
+
t.integer :delay
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
create_table :issues, force: true do |t|
|
|
66
|
+
t.integer :project_id
|
|
67
|
+
t.string :subject
|
|
68
|
+
t.string :description
|
|
69
|
+
t.boolean :closed
|
|
70
|
+
t.string :cached_tag_list
|
|
71
|
+
t.integer :user_id
|
|
72
|
+
t.integer :author_id
|
|
73
|
+
t.integer :views, default: 0
|
|
74
|
+
t.integer :total_views, default: 0
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
create_table :votes, force: true do |t|
|
|
78
|
+
t.references :votable, polymorphic: true
|
|
79
|
+
t.references :voter, polymorphic: true
|
|
80
|
+
t.boolean :vote_flag
|
|
81
|
+
t.string :vote_scope
|
|
82
|
+
t.integer :vote_weight
|
|
83
|
+
t.string :vote_ip
|
|
72
84
|
t.timestamps
|
|
73
85
|
end
|
|
74
86
|
|
|
75
|
-
create_table
|
|
76
|
-
t.string
|
|
77
|
-
t.text
|
|
78
|
-
t.integer
|
|
87
|
+
create_table :news, force: true do |t|
|
|
88
|
+
t.string :title
|
|
89
|
+
t.text :description
|
|
90
|
+
t.integer :author_id
|
|
79
91
|
end
|
|
80
92
|
|
|
81
|
-
create_table
|
|
82
|
-
t.string
|
|
83
|
-
t.text
|
|
84
|
-
t.string
|
|
85
|
-
t.integer
|
|
93
|
+
create_table :projects, force: true do |t|
|
|
94
|
+
t.string :name
|
|
95
|
+
t.text :description
|
|
96
|
+
t.string :identifier
|
|
97
|
+
t.integer :status
|
|
86
98
|
end
|
|
87
99
|
|
|
88
|
-
create_table :voters, :
|
|
100
|
+
create_table :voters, force: true do |t|
|
|
89
101
|
t.string :name
|
|
90
102
|
end
|
|
91
103
|
|
|
92
|
-
create_table :not_voters, :
|
|
104
|
+
create_table :not_voters, force: true do |t|
|
|
93
105
|
t.string :name
|
|
94
106
|
end
|
|
95
107
|
|
|
96
|
-
create_table :votables, :
|
|
108
|
+
create_table :votables, force: true do |t|
|
|
97
109
|
t.string :name
|
|
98
110
|
end
|
|
99
111
|
|
|
100
|
-
create_table :votable_voters, :
|
|
112
|
+
create_table :votable_voters, force: true do |t|
|
|
101
113
|
t.string :name
|
|
102
114
|
end
|
|
103
115
|
|
|
104
|
-
create_table :sti_votables, :
|
|
116
|
+
create_table :sti_votables, force: true do |t|
|
|
105
117
|
t.string :name
|
|
106
118
|
t.string :type
|
|
107
119
|
end
|
|
108
120
|
|
|
109
|
-
create_table :sti_not_votables, :
|
|
121
|
+
create_table :sti_not_votables, force: true do |t|
|
|
110
122
|
t.string :name
|
|
111
123
|
t.string :type
|
|
112
124
|
end
|
|
113
125
|
|
|
114
|
-
create_table :not_votables, :
|
|
126
|
+
create_table :not_votables, force: true do |t|
|
|
115
127
|
t.string :name
|
|
116
128
|
end
|
|
117
129
|
|
|
118
|
-
create_table :votable_caches, :
|
|
130
|
+
create_table :votable_caches, force: true do |t|
|
|
119
131
|
t.string :name
|
|
120
132
|
t.integer :cached_votes_total
|
|
121
133
|
t.integer :cached_votes_score
|
|
@@ -134,11 +146,11 @@ ActiveRecord::Schema.define version: 0 do
|
|
|
134
146
|
t.float :cached_scoped_weighted_average
|
|
135
147
|
end
|
|
136
148
|
|
|
137
|
-
create_table :viewings, :
|
|
149
|
+
create_table :viewings, force: true do |t|
|
|
138
150
|
t.column :viewer_id, :integer
|
|
139
151
|
t.column :viewed_id, :integer
|
|
140
152
|
t.column :viewed_type, :string
|
|
141
|
-
t.column :ip, :string, :
|
|
153
|
+
t.column :ip, :string, limit: '45'
|
|
142
154
|
t.column :created_at, :datetime
|
|
143
155
|
end
|
|
144
156
|
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
|
2
|
+
|
|
3
|
+
class TagsHelperViewTest < ActionView::TestCase
|
|
4
|
+
include Redmineup::TagsHelper
|
|
5
|
+
include Redmineup::FormTagHelper
|
|
6
|
+
|
|
7
|
+
def stub_tag_url(name)
|
|
8
|
+
"/stub_tags/#{name}" # URL stub for tag_cloud_links(tags, :stub)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def test_tag_link
|
|
12
|
+
result = tag_link('/tags/error', 'error', count: 3)
|
|
13
|
+
assert_includes result, 'tag-label-color'
|
|
14
|
+
assert_includes result, 'background-color: #'
|
|
15
|
+
assert_includes result, '(3)'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_tag_links
|
|
19
|
+
result = tag_links(['error', 'bug']) { |t| "/tags/#{t}" }
|
|
20
|
+
assert_includes result, 'class="tag_list"'
|
|
21
|
+
assert_nil tag_links([]) { |t| "/tags/#{t}" }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_tag_cloud_links
|
|
25
|
+
result = tag_cloud_links(Issue.tag_counts, :stub)
|
|
26
|
+
assert_includes result, 'class="tag_list"'
|
|
27
|
+
assert_includes result, '/stub_tags/'
|
|
28
|
+
assert_nil tag_cloud_links([], :stub)
|
|
29
|
+
assert_raises(NoMethodError) { tag_cloud_links(Issue.tag_counts, :unknown_xyz) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_tag_list_field_tag
|
|
33
|
+
result = tag_list_field_tag('issue[tag_list]', ['bug'],
|
|
34
|
+
url: '/auto_completes/taggable_tags',
|
|
35
|
+
width: '60%', tags: false,
|
|
36
|
+
placeholder: '+ add tag')
|
|
37
|
+
assert_includes result, 'name="issue[tag_list][]"'
|
|
38
|
+
assert_includes result, '"width":"60%"'
|
|
39
|
+
assert_includes result, '"tags":false'
|
|
40
|
+
end
|
|
41
|
+
end
|