redmine_crm 0.0.23 → 0.0.25

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/doc/CHANGELOG +4 -0
  4. data/lib/redmine_crm.rb +28 -20
  5. data/lib/redmine_crm/{rcrm_acts_as_taggable.rb → acts_as_taggable/rcrm_acts_as_taggable.rb} +93 -87
  6. data/lib/redmine_crm/acts_as_taggable/tag.rb +81 -0
  7. data/lib/redmine_crm/acts_as_taggable/tag_list.rb +111 -0
  8. data/lib/redmine_crm/acts_as_taggable/tagging.rb +16 -0
  9. data/lib/redmine_crm/acts_as_viewed/rcrm_acts_as_viewed.rb +274 -0
  10. data/lib/redmine_crm/{rcrm_acts_as_votable.rb → acts_as_votable/rcrm_acts_as_votable.rb} +8 -11
  11. data/lib/redmine_crm/acts_as_votable/rcrm_acts_as_voter.rb +20 -0
  12. data/lib/redmine_crm/{votable.rb → acts_as_votable/votable.rb} +36 -47
  13. data/lib/redmine_crm/{vote.rb → acts_as_votable/vote.rb} +7 -10
  14. data/lib/redmine_crm/{voter.rb → acts_as_votable/voter.rb} +29 -34
  15. data/lib/redmine_crm/currency/formatting.rb +0 -3
  16. data/lib/redmine_crm/currency/heuristics.rb +1 -1
  17. data/lib/redmine_crm/currency/loader.rb +1 -1
  18. data/lib/redmine_crm/helpers/tags_helper.rb +1 -3
  19. data/lib/redmine_crm/helpers/vote_helper.rb +29 -32
  20. data/lib/redmine_crm/liquid/drops/issues_drop.rb +66 -0
  21. data/lib/redmine_crm/liquid/drops/news_drop.rb +54 -0
  22. data/lib/redmine_crm/liquid/drops/projects_drop.rb +86 -0
  23. data/lib/redmine_crm/liquid/drops/users_drop.rb +72 -0
  24. data/lib/redmine_crm/liquid/filters/arrays.rb +178 -0
  25. data/lib/redmine_crm/liquid/filters/base.rb +208 -0
  26. data/lib/redmine_crm/version.rb +1 -1
  27. data/redmine_crm.gemspec +1 -1
  28. data/test/{acts_as_taggable_test.rb → acts_as_taggable/rcrm_acts_as_taggable_test.rb} +114 -151
  29. data/test/acts_as_taggable/tag_list_test.rb +38 -0
  30. data/test/acts_as_taggable/tag_test.rb +74 -0
  31. data/test/acts_as_taggable/tagging_test.rb +15 -0
  32. data/test/{viewed_test.rb → acts_as_viewed/rcrm_acts_as_viewed_test.rb} +17 -15
  33. data/test/{votable_test.rb → acts_as_votable/rcrm_acts_as_votable_test.rb} +3 -3
  34. data/test/acts_as_votable/rcrm_acts_as_voter_test.rb +12 -0
  35. data/test/{votable_model_test.rb → acts_as_votable/votable_test.rb} +4 -4
  36. data/test/{voter_model_test.rb → acts_as_votable/voter_test.rb} +7 -7
  37. data/test/currency_test.rb +10 -10
  38. data/test/fixtures/issue.rb +6 -2
  39. data/test/fixtures/issues.yml +13 -1
  40. data/test/fixtures/news.rb +3 -0
  41. data/test/fixtures/news.yml +8 -0
  42. data/test/fixtures/project.rb +8 -0
  43. data/test/fixtures/projects.yml +10 -0
  44. data/test/fixtures/user.rb +5 -1
  45. data/test/fixtures/users.yml +3 -2
  46. data/test/fixtures/vote_classes.rb +2 -3
  47. data/test/liquid/drops/issues_drop_test.rb +34 -0
  48. data/test/liquid/drops/liquid_test.rb +52 -0
  49. data/test/liquid/drops/news_drop_test.rb +38 -0
  50. data/test/liquid/drops/projects_drop_test.rb +44 -0
  51. data/test/liquid/drops/uses_drop_test.rb +36 -0
  52. data/test/liquid/filters/arrays_filter_test.rb +24 -0
  53. data/test/liquid/filters/base_filter_test.rb +63 -0
  54. data/test/liquid/liquid_helper.rb +32 -0
  55. data/test/money_helper_test.rb +5 -5
  56. data/test/schema.rb +21 -9
  57. data/test/test_helper.rb +26 -25
  58. metadata +76 -28
  59. data/lib/redmine_crm/rcrm_acts_as_viewed.rb +0 -287
  60. data/lib/redmine_crm/rcrm_acts_as_voter.rb +0 -27
  61. data/lib/redmine_crm/tag.rb +0 -81
  62. data/lib/redmine_crm/tag_list.rb +0 -112
  63. data/lib/redmine_crm/tagging.rb +0 -20
  64. data/test/tag_test.rb +0 -64
  65. data/test/tagging_test.rb +0 -14
@@ -26,7 +26,6 @@ module RedmineCrm
26
26
  alias_method name, method
27
27
  end
28
28
 
29
-
30
29
  def format(value, currency, *rules)
31
30
  # support for old format parameters
32
31
  rules = normalize_formatting_rules(rules)
@@ -220,8 +219,6 @@ module RedmineCrm
220
219
  "\\1#{rules[:decimal_mark]}\\3")
221
220
  end
222
221
  end
223
-
224
222
  end
225
-
226
223
  end
227
224
  end
@@ -148,4 +148,4 @@ module RedmineCrm
148
148
  end
149
149
  end
150
150
  end
151
- end
151
+ end
@@ -21,4 +21,4 @@ module RedmineCrm
21
21
  end
22
22
  end
23
23
  end
24
- end
24
+ end
@@ -3,13 +3,11 @@ module RedmineCrm
3
3
  # See the README for an example using tag_cloud.
4
4
  def tag_cloud(tags, classes)
5
5
  return if tags.empty?
6
-
7
6
  max_count = tags.sort_by(&:count).last.count.to_f
8
-
9
7
  tags.each do |tag|
10
8
  index = ((tag.count / max_count) * (classes.size - 1)).round
11
9
  yield tag, classes[index]
12
10
  end
13
11
  end
14
12
  end
15
- end
13
+ end
@@ -1,38 +1,35 @@
1
1
  module RedmineCrm
2
- module ActsAsVotable::Helpers
3
-
4
- # this helper provides methods that help find what words are
5
- # up votes and what words are down votes
6
- #
7
- # It can be called
8
- #
9
- # votable_object.votable_words.that_mean_true
10
- #
11
- module Words
12
-
13
- def votable_words
14
- VotableWords
15
- end
16
-
17
- end
18
-
19
- class VotableWords
20
-
21
- def self.that_mean_true
22
- ['up', 'upvote', 'like', 'liked', 'positive', 'yes', 'good', 'true', 1, true]
2
+ module ActsAsVotable
3
+ module Helpers
4
+ # this helper provides methods that help find what words are
5
+ # up votes and what words are down votes
6
+ #
7
+ # It can be called
8
+ #
9
+ # votable_object.votable_words.that_mean_true
10
+ #
11
+ module Words
12
+ def votable_words
13
+ VotableWords
14
+ end
23
15
  end
24
16
 
25
- def self.that_mean_false
26
- ['down', 'downvote', 'dislike', 'disliked', 'negative', 'no', 'bad', 'false', 0, false]
17
+ class VotableWords
18
+ def self.that_mean_true
19
+ ['up', 'upvote', 'like', 'liked', 'positive', 'yes', 'good', 'true', 1, true]
20
+ end
21
+
22
+ def self.that_mean_false
23
+ ['down', 'downvote', 'dislike', 'disliked', 'negative', 'no', 'bad', 'false', 0, false]
24
+ end
25
+
26
+ # check is word is a true or bad vote
27
+ # if the word is unknown, then it counts it as a true/good
28
+ # vote. this exists to allow all voting to be good by default
29
+ def self.meaning_of(word)
30
+ !that_mean_false.include?(word)
31
+ end
27
32
  end
28
-
29
- # check is word is a true or bad vote
30
- # if the word is unknown, then it counts it as a true/good
31
- # vote. this exists to allow all voting to be good by default
32
- def self.meaning_of word
33
- !that_mean_false.include?(word)
34
- end
35
-
36
33
  end
37
34
  end
38
- end
35
+ end
@@ -0,0 +1,66 @@
1
+ module RedmineCrm
2
+ module Liquid
3
+ class IssuesDrop < ::Liquid::Drop
4
+ def initialize(issues)
5
+ @issues = issues
6
+ end
7
+
8
+ def before_method(id)
9
+ issue = @issues.where(:id => id).first || Issue.new
10
+ IssueDrop.new issue
11
+ end
12
+
13
+ def all
14
+ @all ||= @issues.map do |issue|
15
+ IssueDrop.new issue
16
+ end
17
+ end
18
+
19
+ def each(&block)
20
+ all.each(&block)
21
+ end
22
+
23
+ def size
24
+ @issues.size
25
+ end
26
+ end
27
+
28
+ class IssueDrop < ::Liquid::Drop
29
+ include ActionView::Helpers::UrlHelper
30
+
31
+ delegate :id,
32
+ :subject,
33
+ :description,
34
+ :visible?,
35
+ :open?,
36
+ :start_date,
37
+ :due_date,
38
+ :overdue?,
39
+ :completed_percent,
40
+ :updated_on,
41
+ :created_on,
42
+ :to => :@issue
43
+
44
+ def initialize(issue)
45
+ @issue = issue
46
+ end
47
+
48
+ def link
49
+ link_to @issue.subject, self.url
50
+ end
51
+
52
+ def url
53
+ Rails.application.routes.url_helpers.issue_path(@issue)
54
+ end
55
+
56
+ def author
57
+ @user ||= UserDrop.new(@issue.author)
58
+ end
59
+
60
+ def custom_field_values
61
+ @issue.custom_field_values
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,54 @@
1
+ module RedmineCrm
2
+ module Liquid
3
+ class NewssDrop < ::Liquid::Drop
4
+
5
+ def self.default_drop
6
+ self.new News.visible.order("#{News.table_name}.created_on")
7
+ end
8
+
9
+ def initialize(newss)
10
+ @newss = newss
11
+ end
12
+
13
+ def before_method(id)
14
+ news = @newss.where(:id => id).first || News.new
15
+ NewsDrop.new news
16
+ end
17
+
18
+ def last
19
+ NewsDrop.new News.last
20
+ end
21
+
22
+ def all
23
+ @all ||= @newss.map do |news|
24
+ NewsDrop.new news
25
+ end
26
+ end
27
+
28
+ def each(&block)
29
+ all.each(&block)
30
+ end
31
+
32
+ def size
33
+ @newss.size
34
+ end
35
+ end
36
+
37
+ class NewsDrop < ::Liquid::Drop
38
+ delegate :id, :title, :summary, :description, :visible?, :commentable?, :to => :@news
39
+
40
+ def initialize(news)
41
+ @news = news
42
+ end
43
+
44
+ def author
45
+ UserDrop.new @news.author
46
+ end
47
+
48
+ def custom_field_values
49
+ @news.custom_field_values
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,86 @@
1
+ module RedmineCrm
2
+ module Liquid
3
+ class ProjectsDrop < ::Liquid::Drop
4
+
5
+ def self.default_drop
6
+ self.new Project.visible.order(:name)
7
+ end
8
+
9
+ def initialize(projects)
10
+ @projects = projects
11
+ end
12
+
13
+ def before_method(identifier)
14
+ project = @projects.where(:identifier => identifier).first || Project.new
15
+ ProjectDrop.new project
16
+ end
17
+
18
+ def all
19
+ @all ||= @projects.map do |project|
20
+ ProjectDrop.new project
21
+ end
22
+ end
23
+
24
+ def active
25
+ @active ||= @projects.select(&:active?).map do |project|
26
+ ProjectDrop.new project
27
+ end
28
+ end
29
+
30
+ def each(&block)
31
+ all.each(&block)
32
+ end
33
+
34
+ def size
35
+ @projects.size
36
+ end
37
+ end
38
+
39
+ class ProjectDrop < ::Liquid::Drop
40
+ include ActionView::Helpers::UrlHelper
41
+
42
+ delegate :id,
43
+ :identifier,
44
+ :name,
45
+ :is_public,
46
+ :description,
47
+ :visible?,
48
+ :active?,
49
+ :archived?,
50
+ :short_description,
51
+ :start_date,
52
+ :due_date,
53
+ :overdue?,
54
+ :completed_percent,
55
+ :to => :@project
56
+
57
+ def initialize(project)
58
+ @project = project
59
+ end
60
+
61
+ def link
62
+ link_to @project.name, self.url
63
+ end
64
+
65
+ def url
66
+ Rails.application.routes.url_helpers.project_path(@project)
67
+ end
68
+
69
+ def issues
70
+ @issues ||= IssuesDrop.new @project.issues.visible
71
+ end
72
+
73
+ def users
74
+ @users ||= UsersDrop.new @project.users
75
+ end
76
+
77
+ def subprojects
78
+ @subprojects ||= ProjectsDrop.new @project.children
79
+ end
80
+
81
+ def custom_field_values
82
+ @project.custom_field_values
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,72 @@
1
+ module RedmineCrm
2
+ module Liquid
3
+ class UsersDrop < ::Liquid::Drop
4
+
5
+ def self.default_drop
6
+ self.new User.sorted
7
+ end
8
+
9
+ def initialize(users)
10
+ @users = users
11
+ end
12
+
13
+ def before_method(login)
14
+ user = @users.where(:login => login).first || User.new
15
+ UserDrop.new user
16
+ end
17
+
18
+ def current
19
+ UserDrop.new User.current
20
+ end
21
+
22
+ def all
23
+ @all ||= @users.map do |user|
24
+ UserDrop.new user
25
+ end
26
+ end
27
+
28
+ def each(&block)
29
+ all.each(&block)
30
+ end
31
+
32
+ def size
33
+ @users.size
34
+ end
35
+ end
36
+
37
+ class UserDrop < ::Liquid::Drop
38
+ delegate :id, :name, :firstname, :lastname, :mail, :active?, :admin?, :logged?, :language, :to => :@user
39
+
40
+ def initialize(user)
41
+ @user = user
42
+ end
43
+
44
+ def avatar
45
+ ApplicationController.helpers.avatar(@user)
46
+ end
47
+
48
+ def name
49
+ @user.name
50
+ end
51
+
52
+ def permissions
53
+ roles = @user.memberships.collect { |m| m.roles }.flatten.uniq
54
+ roles << (@user.logged? ? Role.non_member : Role.anonymous)
55
+ roles.map(&:permissions).flatten.uniq.map(&:to_s)
56
+ end
57
+
58
+ def groups
59
+ @user.groups.map(&:name)
60
+ end
61
+
62
+ def projects
63
+ ProjectsDrop.new @user.memberships.map(&:project).flatten.select(&:visible?).uniq
64
+ end
65
+
66
+ def custom_field_values
67
+ @user.custom_field_values
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,178 @@
1
+ module RedmineCrm
2
+ module Liquid
3
+ module Filters
4
+ module Arrays
5
+
6
+ # Get the first element of the passed in array
7
+ #
8
+ # Example:
9
+ # {{ product.images | first | to_img }}
10
+ #
11
+ # {{ product.images | first: 3 }}
12
+ #
13
+ def first(array, count=1)
14
+ (count > 1 ? array.first(count) : array.first) if array.respond_to?(:first)
15
+ end
16
+
17
+ # Convert the input into json string
18
+ #
19
+ # input - The Array or Hash to be converted
20
+ #
21
+ # Returns the converted json string
22
+ def jsonify(input)
23
+ as_liquid(input).to_json
24
+ end
25
+
26
+ # Group an array of items by a property
27
+ #
28
+ # input - the inputted Enumerable
29
+ # property - the property
30
+ #
31
+ # Returns an array of Hashes, each looking something like this:
32
+ # {"name" => "larry"
33
+ # "items" => [...] } # all the items where `property` == "larry"
34
+ def group_by(input, property)
35
+ if groupable?(input)
36
+ input.group_by { |item| item_property(item, property).to_s }
37
+ .each_with_object([]) do |item, array|
38
+ array << {
39
+ "name" => item.first,
40
+ "items" => item.last,
41
+ "size" => item.last.size
42
+ }
43
+ end
44
+ else
45
+ input
46
+ end
47
+ end
48
+
49
+ # Filter an array of objects
50
+ #
51
+ # input - the object array
52
+ # property - property within each object to filter by
53
+ # value - desired value
54
+ #
55
+ # Returns the filtered array of objects
56
+ def where(input, property, value, operator='==')
57
+ return input unless input.respond_to?(:select)
58
+ input = input.values if input.is_a?(Hash)
59
+ if operator == '=='
60
+ input.select do |object|
61
+ Array(item_property(object, property)).map(&:to_s).include?(value.to_s)
62
+ end || []
63
+ elsif operator == '<>'
64
+ input.select do |object|
65
+ !Array(item_property(object, property)).map(&:to_s).include?(value.to_s)
66
+ end || []
67
+ elsif operator == '>'
68
+ input.select do |object|
69
+ item_property(object, property) > value
70
+ end || []
71
+ elsif operator == '<'
72
+ input.select do |object|
73
+ item_property(object, property) < value
74
+ end || []
75
+ elsif operator == 'match'
76
+ input.select do |object|
77
+ Array(item_property(object, property)).map(&:to_s).any?{|i| i.match(value.to_s)}
78
+ end || []
79
+ else
80
+ []
81
+ end
82
+ end
83
+
84
+ # Filter an array of objects by tags
85
+ #
86
+ # input - the object array
87
+ # tags - quoted tags list divided by comma
88
+ # match - (all- defaut, any, exclude)
89
+ #
90
+ # Returns the filtered array of objects
91
+ def tagged_with(input, tags, match='all')
92
+ return input unless input.respond_to?(:select)
93
+ input = input.values if input.is_a?(Hash)
94
+ tag_list = input.is_a?(Array) ? tags.sort : tags.split(',').map(&:strip).sort
95
+ case match
96
+ when "all"
97
+ input.select do |object|
98
+ object.respond_to?(:tag_list) &&
99
+ (tag_list - Array(item_property(object, 'tag_list')).map(&:to_s).sort).empty?
100
+ end || []
101
+ when "any"
102
+ input.select do |object|
103
+ object.respond_to?(:tag_list) &&
104
+ (tag_list & Array(item_property(object, 'tag_list')).map(&:to_s).sort).any?
105
+ end || []
106
+ when "exclude"
107
+ input.select do |object|
108
+ object.respond_to?(:tag_list) &&
109
+ (tag_list & Array(item_property(object, 'tag_list')).map(&:to_s).sort).empty?
110
+ end || []
111
+ else
112
+ []
113
+ end
114
+ end
115
+
116
+ # Sort an array of objects
117
+ #
118
+ # input - the object array
119
+ # property - property within each object to filter by
120
+ # nils ('first' | 'last') - nils appear before or after non-nil values
121
+ #
122
+ # Returns the filtered array of objects
123
+ def sort(input, property = nil, nils = "first")
124
+ if input.nil?
125
+ raise ArgumentError, "Cannot sort a null object."
126
+ end
127
+ if property.nil?
128
+ input.sort
129
+ else
130
+ if nils == "first"
131
+ order = - 1
132
+ elsif nils == "last"
133
+ order = + 1
134
+ else
135
+ raise ArgumentError, "Invalid nils order: " \
136
+ "'#{nils}' is not a valid nils order. It must be 'first' or 'last'."
137
+ end
138
+
139
+ sort_input(input, property, order)
140
+ end
141
+ end
142
+
143
+ def pop(array, input = 1)
144
+ return array unless array.is_a?(Array)
145
+ new_ary = array.dup
146
+ new_ary.pop(input.to_i || 1)
147
+ new_ary
148
+ end
149
+
150
+ def push(array, input)
151
+ return array unless array.is_a?(Array)
152
+ new_ary = array.dup
153
+ new_ary.push(input)
154
+ new_ary
155
+ end
156
+
157
+ def shift(array, input = 1)
158
+ return array unless array.is_a?(Array)
159
+ new_ary = array.dup
160
+ new_ary.shift(input.to_i || 1)
161
+ new_ary
162
+ end
163
+
164
+ def unshift(array, input)
165
+ return array unless array.is_a?(Array)
166
+ new_ary = array.dup
167
+ new_ary.unshift(input)
168
+ new_ary
169
+ end
170
+
171
+ private
172
+
173
+ end # module ArrayFilters
174
+ end
175
+ end
176
+
177
+ ::Liquid::Template.register_filter(RedmineCrm::Liquid::Filters::Arrays)
178
+ end