redmine_crm 0.0.23 → 0.0.43
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 +4 -1
- data/Gemfile +1 -1
- data/README.md +166 -33
- data/Rakefile +3 -12
- data/bitbucket-pipelines.yml +42 -0
- data/config/currency_iso.json +12 -0
- data/doc/CHANGELOG +81 -2
- data/lib/redmine_crm/acts_as_draftable/draft.rb +40 -0
- data/lib/redmine_crm/acts_as_draftable/rcrm_acts_as_draftable.rb +170 -0
- data/lib/redmine_crm/acts_as_list/list.rb +282 -0
- data/lib/redmine_crm/{rcrm_acts_as_taggable.rb → acts_as_taggable/rcrm_acts_as_taggable.rb} +105 -93
- data/lib/redmine_crm/acts_as_taggable/tag.rb +81 -0
- data/lib/redmine_crm/acts_as_taggable/tag_list.rb +111 -0
- data/lib/redmine_crm/acts_as_taggable/tagging.rb +16 -0
- data/lib/redmine_crm/acts_as_viewed/rcrm_acts_as_viewed.rb +274 -0
- data/lib/redmine_crm/{rcrm_acts_as_votable.rb → acts_as_votable/rcrm_acts_as_votable.rb} +15 -14
- data/lib/redmine_crm/acts_as_votable/rcrm_acts_as_voter.rb +20 -0
- data/lib/redmine_crm/{votable.rb → acts_as_votable/votable.rb} +54 -65
- data/lib/redmine_crm/{vote.rb → acts_as_votable/vote.rb} +6 -8
- data/lib/redmine_crm/{voter.rb → acts_as_votable/voter.rb} +29 -34
- data/lib/redmine_crm/assets_manager.rb +43 -0
- data/lib/redmine_crm/colors_helper.rb +192 -0
- data/lib/redmine_crm/compatibility/application_controller_patch.rb +33 -0
- data/lib/redmine_crm/currency/formatting.rb +0 -3
- data/lib/redmine_crm/currency/heuristics.rb +1 -1
- data/lib/redmine_crm/currency/loader.rb +5 -6
- data/lib/redmine_crm/helpers/external_assets_helper.rb +19 -0
- data/lib/redmine_crm/helpers/form_tag_helper.rb +76 -0
- data/lib/redmine_crm/helpers/tags_helper.rb +1 -3
- data/lib/redmine_crm/helpers/vote_helper.rb +29 -32
- data/lib/redmine_crm/liquid/drops/issues_drop.rb +191 -0
- data/lib/redmine_crm/liquid/drops/news_drop.rb +54 -0
- data/lib/redmine_crm/liquid/drops/projects_drop.rb +86 -0
- data/lib/redmine_crm/liquid/drops/time_entries_drop.rb +65 -0
- data/lib/redmine_crm/liquid/drops/users_drop.rb +68 -0
- data/lib/redmine_crm/liquid/filters/arrays.rb +187 -0
- data/lib/redmine_crm/liquid/filters/base.rb +217 -0
- data/lib/redmine_crm/liquid/filters/colors.rb +31 -0
- data/lib/redmine_crm/money_helper.rb +2 -4
- data/lib/redmine_crm/version.rb +1 -1
- data/lib/redmine_crm.rb +56 -21
- data/redmine_crm.gemspec +9 -4
- data/test/acts_as_draftable/draft_test.rb +29 -0
- data/test/acts_as_draftable/rcrm_acts_as_draftable_test.rb +179 -0
- data/test/{acts_as_taggable_test.rb → acts_as_taggable/rcrm_acts_as_taggable_test.rb} +117 -156
- data/test/acts_as_taggable/tag_list_test.rb +34 -0
- data/test/acts_as_taggable/tag_test.rb +72 -0
- data/test/acts_as_taggable/tagging_test.rb +15 -0
- data/test/{viewed_test.rb → acts_as_viewed/rcrm_acts_as_viewed_test.rb} +17 -15
- data/test/acts_as_votable/rcrm_acts_as_votable_test.rb +19 -0
- data/test/acts_as_votable/rcrm_acts_as_voter_test.rb +14 -0
- data/test/{votable_model_test.rb → acts_as_votable/votable_test.rb} +34 -5
- data/test/{voter_model_test.rb → acts_as_votable/voter_test.rb} +8 -8
- data/test/currency_test.rb +10 -10
- data/test/database.yml +14 -14
- data/test/fixtures/issues.yml +13 -1
- data/test/fixtures/news.yml +8 -0
- data/test/fixtures/projects.yml +10 -0
- data/test/fixtures/users.yml +6 -2
- data/test/liquid/drops/issues_drop_test.rb +34 -0
- data/test/liquid/drops/news_drop_test.rb +38 -0
- data/test/liquid/drops/projects_drop_test.rb +44 -0
- data/test/liquid/drops/uses_drop_test.rb +36 -0
- data/test/liquid/filters/arrays_filter_test.rb +31 -0
- data/test/liquid/filters/base_filter_test.rb +63 -0
- data/test/liquid/filters/colors_filter_test.rb +33 -0
- data/test/liquid/liquid_helper.rb +34 -0
- data/test/models/issue.rb +14 -0
- data/test/models/news.rb +3 -0
- data/test/models/project.rb +8 -0
- data/test/{fixtures → models}/user.rb +5 -1
- data/test/{fixtures → models}/vote_classes.rb +0 -21
- data/test/money_helper_test.rb +5 -5
- data/test/schema.rb +33 -10
- data/test/test_helper.rb +20 -72
- data/vendor/assets/images/vcard.png +0 -0
- data/vendor/assets/javascripts/Chart.bundle.min.js +16 -0
- data/vendor/assets/javascripts/select2.js +3 -0
- data/vendor/assets/javascripts/select2_helpers.js +186 -0
- data/vendor/assets/stylesheets/select2.css +414 -0
- metadata +162 -38
- data/lib/redmine_crm/rcrm_acts_as_viewed.rb +0 -287
- data/lib/redmine_crm/rcrm_acts_as_voter.rb +0 -27
- data/lib/redmine_crm/tag.rb +0 -81
- data/lib/redmine_crm/tag_list.rb +0 -112
- data/lib/redmine_crm/tagging.rb +0 -20
- data/test/fixtures/issue.rb +0 -14
- data/test/tag_test.rb +0 -64
- data/test/tagging_test.rb +0 -14
- data/test/votable_test.rb +0 -17
@@ -0,0 +1,217 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'rack'
|
3
|
+
require 'json'
|
4
|
+
require 'date'
|
5
|
+
require 'liquid'
|
6
|
+
|
7
|
+
module RedmineCrm
|
8
|
+
module Liquid
|
9
|
+
module Filters
|
10
|
+
module Base
|
11
|
+
include RedmineCrm::MoneyHelper
|
12
|
+
|
13
|
+
def textilize(input)
|
14
|
+
RedCloth3.new(input).to_html
|
15
|
+
end
|
16
|
+
|
17
|
+
def default(input, value)
|
18
|
+
input.blank? ? value : input
|
19
|
+
end
|
20
|
+
|
21
|
+
def underscore(input)
|
22
|
+
input.to_s.gsub(' ', '_').gsub('/', '_').underscore
|
23
|
+
end
|
24
|
+
|
25
|
+
def dasherize(input)
|
26
|
+
input.to_s.gsub(' ', '-').gsub('/', '-').dasherize
|
27
|
+
end
|
28
|
+
|
29
|
+
def shuffle(array)
|
30
|
+
array.to_a.shuffle
|
31
|
+
end
|
32
|
+
|
33
|
+
def random(input)
|
34
|
+
rand(input.to_i)
|
35
|
+
end
|
36
|
+
|
37
|
+
def md5(input)
|
38
|
+
Digest::MD5.hexdigest(input) unless input.blank?
|
39
|
+
end
|
40
|
+
|
41
|
+
# example:
|
42
|
+
# {{ "http:://www.example.com?key=hello world" | encode }}
|
43
|
+
#
|
44
|
+
# => http%3A%3A%2F%2Fwww.example.com%3Fkey%3Dhello+world
|
45
|
+
def encode(input)
|
46
|
+
::Rack::Utils.escape(input)
|
47
|
+
end
|
48
|
+
|
49
|
+
# example:
|
50
|
+
# {{ today | plus_days: 2 }}
|
51
|
+
def plus_days(input, distanse)
|
52
|
+
return '' if input.nil?
|
53
|
+
days = distanse.to_i
|
54
|
+
input.to_date + days.days rescue 'Invalid date'
|
55
|
+
end
|
56
|
+
|
57
|
+
# example:
|
58
|
+
# {{ today | date_range: '2015-12-12' }}
|
59
|
+
def date_range(input, distanse)
|
60
|
+
return '' if input.nil?
|
61
|
+
(input.to_date - distanse.to_date).to_i rescue 'Invalid date'
|
62
|
+
end
|
63
|
+
|
64
|
+
# example:
|
65
|
+
# {{ now | utc }}
|
66
|
+
def utc(input)
|
67
|
+
return '' if input.nil?
|
68
|
+
input.to_time.utc rescue 'Invalid date'
|
69
|
+
end
|
70
|
+
|
71
|
+
def modulo(input, operand)
|
72
|
+
apply_operation(input, operand, :%)
|
73
|
+
end
|
74
|
+
|
75
|
+
def round(input, n = 0)
|
76
|
+
result = to_number(input).round(to_number(n))
|
77
|
+
result = result.to_f if result.is_a?(BigDecimal)
|
78
|
+
result = result.to_i if n == 0
|
79
|
+
result
|
80
|
+
end
|
81
|
+
|
82
|
+
def ceil(input)
|
83
|
+
to_number(input).ceil.to_i
|
84
|
+
end
|
85
|
+
|
86
|
+
def floor(input)
|
87
|
+
to_number(input).floor.to_i
|
88
|
+
end
|
89
|
+
|
90
|
+
def currency(input, currency_code = 'USD')
|
91
|
+
price_to_currency(input, currency_code, :converted => false)
|
92
|
+
end
|
93
|
+
|
94
|
+
def call_method(input, method_name)
|
95
|
+
if input.respond_to?(method_name)
|
96
|
+
input.method(method_name).call
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def custom_field(input, field_name)
|
101
|
+
if input.respond_to?(:custom_field_values)
|
102
|
+
custom_value = input.custom_field_values.detect { |cfv| cfv.custom_field.name == field_name }
|
103
|
+
custom_value.custom_field.format.formatted_custom_value(nil, custom_value)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def custom_fields(input)
|
108
|
+
if input.respond_to?(:custom_field_values)
|
109
|
+
input.custom_field_values.map { |cfv| cfv.custom_field.name }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def attachment(input, file_name)
|
114
|
+
if input.respond_to?(:attachments)
|
115
|
+
if input.attachments.is_a?(Hash)
|
116
|
+
attachment = input.attachments[file_name]
|
117
|
+
else
|
118
|
+
attachment = input.attachments.detect{|a| a.file_name == file_name}
|
119
|
+
end
|
120
|
+
AttachmentDrop.new attachment if attachment
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
protected
|
125
|
+
|
126
|
+
# Convert an array of properties ('key:value') into a hash
|
127
|
+
# Ex: ['width:50', 'height:100'] => { :width => '50', :height => '100' }
|
128
|
+
def args_to_options(*args)
|
129
|
+
options = {}
|
130
|
+
args.flatten.each do |a|
|
131
|
+
if (a =~ /^(.*):(.*)$/)
|
132
|
+
options[$1.to_sym] = $2
|
133
|
+
end
|
134
|
+
end
|
135
|
+
options
|
136
|
+
end
|
137
|
+
|
138
|
+
# Write options (Hash) into a string according to the following pattern:
|
139
|
+
# <key1>="<value1>", <key2>="<value2", ...etc
|
140
|
+
def inline_options(options = {})
|
141
|
+
return '' if options.empty?
|
142
|
+
(options.stringify_keys.sort.to_a.collect { |a, b| "#{a}=\"#{b}\"" }).join(' ') << ' '
|
143
|
+
end
|
144
|
+
|
145
|
+
def sort_input(input, property, order)
|
146
|
+
input.sort do |apple, orange|
|
147
|
+
apple_property = item_property(apple, property)
|
148
|
+
orange_property = item_property(orange, property)
|
149
|
+
|
150
|
+
if !apple_property.nil? && orange_property.nil?
|
151
|
+
- order
|
152
|
+
elsif apple_property.nil? && !orange_property.nil?
|
153
|
+
+ order
|
154
|
+
else
|
155
|
+
apple_property <=> orange_property
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def time(input)
|
161
|
+
case input
|
162
|
+
when Time
|
163
|
+
input.clone
|
164
|
+
when Date
|
165
|
+
input.to_time
|
166
|
+
when String
|
167
|
+
Time.parse(input) rescue Time.at(input.to_i)
|
168
|
+
when Numeric
|
169
|
+
Time.at(input)
|
170
|
+
else
|
171
|
+
raise Errors::InvalidDateError,
|
172
|
+
"Invalid Date: '#{input.inspect}' is not a valid datetime."
|
173
|
+
end.localtime
|
174
|
+
end
|
175
|
+
|
176
|
+
def groupable?(element)
|
177
|
+
element.respond_to?(:group_by)
|
178
|
+
end
|
179
|
+
|
180
|
+
def item_property(item, property)
|
181
|
+
if item.respond_to?(:to_liquid)
|
182
|
+
property.to_s.split(".").reduce(item.to_liquid) do |subvalue, attribute|
|
183
|
+
subvalue[attribute]
|
184
|
+
end
|
185
|
+
elsif item.respond_to?(:data)
|
186
|
+
item.data[property.to_s]
|
187
|
+
else
|
188
|
+
item[property.to_s]
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def as_liquid(item)
|
193
|
+
case item
|
194
|
+
when Hash
|
195
|
+
pairs = item.map { |k, v| as_liquid([k, v]) }
|
196
|
+
Hash[pairs]
|
197
|
+
when Array
|
198
|
+
item.map { |i| as_liquid(i) }
|
199
|
+
else
|
200
|
+
if item.respond_to?(:to_liquid)
|
201
|
+
liquidated = item.to_liquid
|
202
|
+
# prevent infinite recursion for simple types (which return `self`)
|
203
|
+
if liquidated == item
|
204
|
+
item
|
205
|
+
else
|
206
|
+
as_liquid(liquidated)
|
207
|
+
end
|
208
|
+
else
|
209
|
+
item
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
::Liquid::Template.register_filter(RedmineCrm::Liquid::Filters::Base)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'liquid'
|
2
|
+
|
3
|
+
module RedmineCrm
|
4
|
+
module Liquid
|
5
|
+
module Filters
|
6
|
+
module Colors
|
7
|
+
def darken_color(input, value=0.4)
|
8
|
+
RedmineCrm::ColorsHelper.darken_color(input, value.to_f)
|
9
|
+
end
|
10
|
+
|
11
|
+
def lighten_color(input, value=0.6)
|
12
|
+
RedmineCrm::ColorsHelper.lighten_color(input, value.to_f)
|
13
|
+
end
|
14
|
+
|
15
|
+
def contrasting_text_color(input)
|
16
|
+
RedmineCrm::ColorsHelper.contrasting_text_color(input)
|
17
|
+
end
|
18
|
+
|
19
|
+
def hex_color(input)
|
20
|
+
RedmineCrm::ColorsHelper.hex_color(input)
|
21
|
+
end
|
22
|
+
|
23
|
+
def convert_to_brightness_value(input)
|
24
|
+
RedmineCrm::ColorsHelper.convert_to_brightness_value(input)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
::Liquid::Template.register_filter(RedmineCrm::Liquid::Filters::Colors)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# byebug
|
2
|
-
# require 'action_controller'
|
3
1
|
require 'action_view'
|
4
2
|
|
5
3
|
module RedmineCrm
|
@@ -41,9 +39,9 @@ module RedmineCrm
|
|
41
39
|
end
|
42
40
|
|
43
41
|
def all_currencies
|
44
|
-
Currency.table.inject([]) do |array, (
|
42
|
+
Currency.table.inject([]) do |array, (_, attributes)|
|
45
43
|
array ||= []
|
46
|
-
array << [
|
44
|
+
array << [attributes[:name].to_s + (attributes[:symbol].blank? ? '' : " (#{attributes[:symbol]})"), attributes[:iso_code]]
|
47
45
|
array
|
48
46
|
end.sort{|x, y| x[0] <=> y[0]}
|
49
47
|
end
|
data/lib/redmine_crm/version.rb
CHANGED
data/lib/redmine_crm.rb
CHANGED
@@ -1,27 +1,62 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
|
4
|
-
require
|
5
|
-
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
1
|
+
require 'active_record'
|
2
|
+
require 'action_view'
|
3
|
+
|
4
|
+
require 'redmine_crm/version'
|
5
|
+
|
6
|
+
require 'redmine_crm/acts_as_list/list'
|
7
|
+
require 'redmine_crm/acts_as_taggable/tag'
|
8
|
+
require 'redmine_crm/acts_as_taggable/tag_list'
|
9
|
+
require 'redmine_crm/acts_as_taggable/tagging'
|
10
|
+
require 'redmine_crm/acts_as_taggable/rcrm_acts_as_taggable'
|
11
|
+
require 'redmine_crm/acts_as_viewed/rcrm_acts_as_viewed'
|
12
|
+
require 'redmine_crm/acts_as_votable/rcrm_acts_as_votable'
|
13
|
+
require 'redmine_crm/acts_as_votable/rcrm_acts_as_voter'
|
14
|
+
require 'redmine_crm/acts_as_votable/vote'
|
15
|
+
require 'redmine_crm/acts_as_votable/voter'
|
16
|
+
require 'redmine_crm/acts_as_draftable/rcrm_acts_as_draftable'
|
17
|
+
require 'redmine_crm/acts_as_draftable/draft'
|
18
|
+
|
19
|
+
require 'redmine_crm/currency'
|
20
|
+
require 'redmine_crm/helpers/tags_helper'
|
21
|
+
require 'redmine_crm/money_helper'
|
22
|
+
require 'redmine_crm/colors_helper'
|
23
|
+
|
24
|
+
require 'liquid'
|
25
|
+
require 'redmine_crm/liquid/filters/base'
|
26
|
+
require 'redmine_crm/liquid/filters/arrays'
|
27
|
+
require 'redmine_crm/liquid/filters/colors'
|
28
|
+
require 'redmine_crm/liquid/drops/issues_drop'
|
29
|
+
require 'redmine_crm/liquid/drops/news_drop'
|
30
|
+
require 'redmine_crm/liquid/drops/projects_drop'
|
31
|
+
require 'redmine_crm/liquid/drops/users_drop'
|
32
|
+
require 'redmine_crm/liquid/drops/time_entries_drop'
|
33
|
+
|
34
|
+
require 'redmine_crm/helpers/external_assets_helper'
|
35
|
+
require 'redmine_crm/helpers/form_tag_helper'
|
36
|
+
require 'redmine_crm/assets_manager'
|
37
|
+
|
38
|
+
require 'redmine_crm/compatibility/application_controller_patch'
|
39
|
+
|
40
|
+
module RedmineCrm
|
41
|
+
GEM_NAME = 'redmine_crm'.freeze
|
42
|
+
end
|
15
43
|
|
16
44
|
if defined?(ActiveRecord::Base)
|
17
|
-
ActiveRecord::Base.
|
45
|
+
ActiveRecord::Base.send :include, RedmineCrm::ActsAsList::List
|
18
46
|
ActiveRecord::Base.extend(RedmineCrm::ActsAsVotable::Voter)
|
47
|
+
ActiveRecord::Base.extend(RedmineCrm::ActsAsVotable::Votable)
|
19
48
|
end
|
20
49
|
|
21
|
-
|
50
|
+
RedmineCrm::AssetsManager.install_assets
|
22
51
|
|
52
|
+
if defined?(ActionView::Base)
|
53
|
+
ActionView::Base.send :include, RedmineCrm::ExternalAssetsHelper
|
54
|
+
ActionView::Base.send :include, RedmineCrm::FormTagHelper
|
55
|
+
end
|
56
|
+
|
57
|
+
def requires_redmine_crm(arg)
|
23
58
|
def compare_versions(requirement, current)
|
24
|
-
raise ArgumentError.new(
|
59
|
+
raise ArgumentError.new('wrong version format') unless check_version_format(requirement)
|
25
60
|
requirement = requirement.split('.').collect(&:to_i)
|
26
61
|
requirement <=> current.slice(0, requirement.size)
|
27
62
|
end
|
@@ -33,11 +68,11 @@ def requires_redmine_crm(arg)
|
|
33
68
|
arg = { :version_or_higher => arg } unless arg.is_a?(Hash)
|
34
69
|
arg.assert_valid_keys(:version, :version_or_higher)
|
35
70
|
|
36
|
-
current = RedmineCrm::VERSION.split(
|
71
|
+
current = RedmineCrm::VERSION.split('.').map { |x| x.to_i }
|
37
72
|
arg.each do |k, req|
|
38
73
|
case k
|
39
74
|
when :version_or_higher
|
40
|
-
raise ArgumentError.new(
|
75
|
+
raise ArgumentError.new(':version_or_higher accepts a version string only') unless req.is_a?(String)
|
41
76
|
unless compare_versions(req, current) <= 0
|
42
77
|
Rails.logger.error "\033[31m[ERROR]\033[0m Redmine requires redmine_crm gem version #{req} or higher (you're using #{RedmineCrm::VERSION}).\n\033[31m[ERROR]\033[0m Please update with 'bundle update redmine_crm'." if Rails.logger
|
43
78
|
abort "\033[31mRedmine requires redmine_crm gem version #{req} or higher (you're using #{RedmineCrm::VERSION}).\nPlease update with 'bundle update redmine_crm'.\033[0m"
|
@@ -53,9 +88,9 @@ def requires_redmine_crm(arg)
|
|
53
88
|
abort "\033[31mRedmine requires redmine_crm gem version between #{req.first} and #{req.last} (you're using #{RedmineCrm::VERSION}).\nPlease update with 'bundle update redmine_crm'.\033[0m"
|
54
89
|
end
|
55
90
|
else
|
56
|
-
raise ArgumentError.new(
|
91
|
+
raise ArgumentError.new(':version option accepts a version string, an array or a range of versions')
|
57
92
|
end
|
58
93
|
end
|
59
94
|
end
|
60
95
|
true
|
61
|
-
end
|
96
|
+
end
|
data/redmine_crm.gemspec
CHANGED
@@ -6,10 +6,10 @@ require 'redmine_crm/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "redmine_crm"
|
8
8
|
spec.version = RedmineCrm::VERSION
|
9
|
-
spec.authors = ["
|
9
|
+
spec.authors = ["RedmineUP"]
|
10
10
|
spec.email = ["support@redminecrm.com"]
|
11
|
-
spec.summary = %q{Common libraries for
|
12
|
-
spec.description = %q{Common libraries for
|
11
|
+
spec.summary = %q{Common libraries for RedmineUP plugins for Redmine}
|
12
|
+
spec.description = %q{Common libraries for RedmineUP plugins (www.redmineup.com) for Redmine. Requered Redmine from http://redmine.org}
|
13
13
|
spec.homepage = ""
|
14
14
|
spec.license = "GPL2"
|
15
15
|
|
@@ -18,5 +18,10 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
|
21
|
+
spec.add_runtime_dependency 'rails'
|
22
|
+
spec.add_runtime_dependency 'liquid', '< 2.6.4'
|
22
23
|
|
24
|
+
spec.add_development_dependency 'sqlite3'
|
25
|
+
spec.add_development_dependency 'mysql2'
|
26
|
+
spec.add_development_dependency 'pg'
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
class DraftTest < ActiveSupport::TestCase
|
4
|
+
def test_restore
|
5
|
+
issue = Issue.new(subject: 'some subject', description: 'some description')
|
6
|
+
|
7
|
+
issue.save_draft
|
8
|
+
restored_issue = RedmineCrm::ActsAsDraftable::Draft.find(issue.draft_id).restore
|
9
|
+
|
10
|
+
assert_equal issue.subject, restored_issue.subject
|
11
|
+
assert_equal issue.description, restored_issue.description
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_restore_all
|
15
|
+
first_issue = Issue.new(subject: 'first subject')
|
16
|
+
first_issue.save_draft
|
17
|
+
second_issue = Issue.new(subject: 'second subject')
|
18
|
+
second_issue.save_draft
|
19
|
+
|
20
|
+
restored_issues = RedmineCrm::ActsAsDraftable::Draft.restore_all
|
21
|
+
assert_equal [first_issue.subject, second_issue.subject], restored_issues.map(&:subject).sort
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def current_user
|
27
|
+
users(:sam)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
class RcrmActsAsDraftableTest < ActiveSupport::TestCase
|
4
|
+
def test_rcrm_acts_as_draftable_without_arguments
|
5
|
+
assert_nothing_raised do
|
6
|
+
Project.rcrm_acts_as_draftable
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class SomeClass < ActiveRecord::Base; end
|
11
|
+
def test_rcrm_acts_as_draftable_with_parent
|
12
|
+
assert_nothing_raised do
|
13
|
+
News.rcrm_acts_as_draftable(parent: :author)
|
14
|
+
end
|
15
|
+
assert User.new.respond_to?(:drafts)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_rcrm_acts_as_draftable_with_non_existing_parent
|
19
|
+
assert_raises do
|
20
|
+
Issue.rcrm_acts_as_draftable(parent: :foo)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_rcrm_acts_as_draftable_with_non_hash_argument
|
25
|
+
assert_raises do
|
26
|
+
Issue.rcrm_acts_as_draftable('bar')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_rcrm_acts_as_draftable_with_invalid_hash_key
|
31
|
+
assert_raises do
|
32
|
+
Issue.rcrm_acts_as_draftable(baz: 'qux')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_drafts
|
37
|
+
Issue.rcrm_acts_as_draftable parent: :project
|
38
|
+
issue = Issue.new
|
39
|
+
issue.save_draft
|
40
|
+
|
41
|
+
assert_equal 1, Issue.drafts(current_user).count
|
42
|
+
assert_equal RedmineCrm::ActsAsDraftable::Draft, Issue.drafts(current_user).first.class
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_from_draft
|
46
|
+
Issue.rcrm_acts_as_draftable parent: :project
|
47
|
+
issue = Issue.new(subject: 'subject')
|
48
|
+
issue.save_draft
|
49
|
+
|
50
|
+
issue_from_draft = Issue.from_draft(issue.draft_id)
|
51
|
+
|
52
|
+
assert_equal Issue, issue_from_draft.class
|
53
|
+
assert_equal true, issue_from_draft.new_record?
|
54
|
+
assert_equal issue.draft_id, issue_from_draft.draft_id
|
55
|
+
|
56
|
+
assert_equal issue.subject, issue_from_draft.subject
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_draft_deleted_after_save
|
60
|
+
issue = Issue.new(subject: 'subject')
|
61
|
+
issue.save_draft
|
62
|
+
|
63
|
+
issue_from_draft = Issue.from_draft(issue.draft_id)
|
64
|
+
|
65
|
+
assert_difference 'Issue.count' do
|
66
|
+
assert_difference 'RedmineCrm::ActsAsDraftable::Draft.count', -1 do
|
67
|
+
issue_from_draft.save!
|
68
|
+
end
|
69
|
+
end
|
70
|
+
assert_nil issue_from_draft.draft_id
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_from_draft_with_non_existing_draft_id
|
74
|
+
assert_raises do
|
75
|
+
Issue.from_draft(999)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_from_draft_with_wrong_type
|
80
|
+
Project.rcrm_acts_as_draftable
|
81
|
+
|
82
|
+
project = Project.new
|
83
|
+
project.save_draft
|
84
|
+
|
85
|
+
assert_raises do
|
86
|
+
Issue.from_draft(project.draft_id)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_dump_to_draft
|
91
|
+
assert_equal String, Issue.new.dump_to_draft.class
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_load_from_draft
|
95
|
+
attributes = {subject: 'subject', description: 'description'}
|
96
|
+
draft = Issue.new(attributes).dump_to_draft
|
97
|
+
|
98
|
+
issue = Issue.new
|
99
|
+
issue.load_from_draft(draft)
|
100
|
+
|
101
|
+
assert_equal attributes[:subject], issue.subject
|
102
|
+
assert_equal attributes[:description], issue.description
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_save_draft
|
106
|
+
Issue.rcrm_acts_as_draftable parent: :project
|
107
|
+
attributes = { subject: 'subject' }
|
108
|
+
issue = Issue.new(attributes)
|
109
|
+
|
110
|
+
assert_no_difference 'Issue.count' do
|
111
|
+
assert_difference 'RedmineCrm::ActsAsDraftable::Draft.count' do
|
112
|
+
result = issue.save_draft
|
113
|
+
assert_equal true, result
|
114
|
+
end
|
115
|
+
end
|
116
|
+
assert_not_nil issue.draft_id
|
117
|
+
|
118
|
+
draft = RedmineCrm::ActsAsDraftable::Draft.find(issue.draft_id)
|
119
|
+
assert_equal 'Issue', draft.target_type
|
120
|
+
assert_equal current_user.id, draft.user_id
|
121
|
+
assert_equal attributes[:subject], draft.restore.subject
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_save_draft_with_associations
|
125
|
+
Issue.rcrm_acts_as_draftable parent: :project
|
126
|
+
issue = Issue.new(project: projects(:second_project))
|
127
|
+
issue.save_draft
|
128
|
+
|
129
|
+
draft = RedmineCrm::ActsAsDraftable::Draft.find(issue.draft_id)
|
130
|
+
assert_equal issue.project.name, draft.restore.project.name
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_save_draft_updates_existing_draft
|
134
|
+
Issue.rcrm_acts_as_draftable parent: :project
|
135
|
+
issue = Issue.new
|
136
|
+
issue.save_draft
|
137
|
+
|
138
|
+
issue.subject = 'changed subject'
|
139
|
+
assert_no_difference 'Issue.count' do
|
140
|
+
assert_no_difference 'RedmineCrm::ActsAsDraftable::Draft.count' do
|
141
|
+
issue.save_draft
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
draft = RedmineCrm::ActsAsDraftable::Draft.find(issue.draft_id)
|
146
|
+
assert_equal issue.subject, draft.restore.subject
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_save_draft_does_not_save_persisted_object
|
150
|
+
issue = issues(:second_issue)
|
151
|
+
assert_equal false, issue.save_draft
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_save_draft_saves_persisted_but_changed_object
|
155
|
+
issue = issues(:second_issue)
|
156
|
+
issue.subject = 'changed subject'
|
157
|
+
assert_equal true, issue.save_draft
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_update_draft
|
161
|
+
issue = Issue.new(subject: 'subject')
|
162
|
+
issue.save_draft
|
163
|
+
|
164
|
+
assert_no_difference 'Issue.count' do
|
165
|
+
assert_no_difference 'RedmineCrm::ActsAsDraftable::Draft.count' do
|
166
|
+
issue.update_draft(subject: 'updated_subject')
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
draft = RedmineCrm::ActsAsDraftable::Draft.find(issue.draft_id)
|
171
|
+
assert_equal issue.subject, draft.restore.subject
|
172
|
+
end
|
173
|
+
|
174
|
+
private
|
175
|
+
|
176
|
+
def current_user
|
177
|
+
users(:sam)
|
178
|
+
end
|
179
|
+
end
|