yeshoua_crm 1.0.0
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 +7 -0
- data/Rakefile +11 -0
- data/lib/yeshoua_crm.rb +87 -0
- data/lib/yeshoua_crm/acts_as_draftable/draft.rb +40 -0
- data/lib/yeshoua_crm/acts_as_draftable/rcrm_acts_as_draftable.rb +154 -0
- data/lib/yeshoua_crm/acts_as_list/list.rb +282 -0
- data/lib/yeshoua_crm/acts_as_taggable/rcrm_acts_as_taggable.rb +350 -0
- data/lib/yeshoua_crm/acts_as_taggable/tag.rb +81 -0
- data/lib/yeshoua_crm/acts_as_taggable/tag_list.rb +111 -0
- data/lib/yeshoua_crm/acts_as_taggable/tagging.rb +16 -0
- data/lib/yeshoua_crm/acts_as_viewed/rcrm_acts_as_viewed.rb +274 -0
- data/lib/yeshoua_crm/acts_as_votable/rcrm_acts_as_votable.rb +80 -0
- data/lib/yeshoua_crm/acts_as_votable/rcrm_acts_as_voter.rb +20 -0
- data/lib/yeshoua_crm/acts_as_votable/votable.rb +323 -0
- data/lib/yeshoua_crm/acts_as_votable/vote.rb +28 -0
- data/lib/yeshoua_crm/acts_as_votable/voter.rb +131 -0
- data/lib/yeshoua_crm/assets_manager.rb +43 -0
- data/lib/yeshoua_crm/currency.rb +439 -0
- data/lib/yeshoua_crm/currency/formatting.rb +224 -0
- data/lib/yeshoua_crm/currency/heuristics.rb +151 -0
- data/lib/yeshoua_crm/currency/loader.rb +24 -0
- data/lib/yeshoua_crm/helpers/external_assets_helper.rb +17 -0
- data/lib/yeshoua_crm/helpers/form_tag_helper.rb +123 -0
- data/lib/yeshoua_crm/helpers/tags_helper.rb +13 -0
- data/lib/yeshoua_crm/helpers/vote_helper.rb +35 -0
- data/lib/yeshoua_crm/liquid/drops/cells_drop.rb +86 -0
- data/lib/yeshoua_crm/liquid/drops/issues_drop.rb +66 -0
- data/lib/yeshoua_crm/liquid/drops/news_drop.rb +54 -0
- data/lib/yeshoua_crm/liquid/drops/users_drop.rb +72 -0
- data/lib/yeshoua_crm/liquid/filters/arrays.rb +177 -0
- data/lib/yeshoua_crm/liquid/filters/base.rb +208 -0
- data/lib/yeshoua_crm/money_helper.rb +65 -0
- data/lib/yeshoua_crm/version.rb +3 -0
- data/test/acts_as_draftable/draft_test.rb +29 -0
- data/test/acts_as_draftable/rcrm_acts_as_draftable_test.rb +185 -0
- data/test/acts_as_taggable/rcrm_acts_as_taggable_test.rb +345 -0
- 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/acts_as_viewed/rcrm_acts_as_viewed_test.rb +47 -0
- 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/acts_as_votable/votable_test.rb +507 -0
- data/test/acts_as_votable/voter_test.rb +296 -0
- data/test/currency_test.rb +292 -0
- 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 +24 -0
- data/test/liquid/filters/base_filter_test.rb +63 -0
- data/test/liquid/liquid_helper.rb +32 -0
- data/test/models/issue.rb +14 -0
- data/test/models/news.rb +3 -0
- data/test/models/project.rb +8 -0
- data/test/models/user.rb +11 -0
- data/test/models/vote_classes.rb +33 -0
- data/test/money_helper_test.rb +12 -0
- data/test/schema.rb +121 -0
- data/test/tags_helper_test.rb +29 -0
- data/test/test_helper.rb +66 -0
- data/test/vote_helper_test.rb +28 -0
- data/yeshoua_crm.gemspec +28 -0
- metadata +206 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
module YeshouaCrm
|
2
|
+
module TagsHelper
|
3
|
+
# See the README for an example using tag_cloud.
|
4
|
+
def tag_cloud(tags, classes)
|
5
|
+
return if tags.empty?
|
6
|
+
max_count = tags.sort_by(&:count).last.count.to_f
|
7
|
+
tags.each do |tag|
|
8
|
+
index = ((tag.count / max_count) * (classes.size - 1)).round
|
9
|
+
yield tag, classes[index]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module YeshouaCrm
|
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
|
15
|
+
end
|
16
|
+
|
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
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module YeshouaCrm
|
2
|
+
module Liquid
|
3
|
+
class CellsDrop < ::Liquid::Drop
|
4
|
+
|
5
|
+
def self.default_drop
|
6
|
+
self.new Cell.visible.order(:name)
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(cells)
|
10
|
+
@cells = cells
|
11
|
+
end
|
12
|
+
|
13
|
+
def before_method(identifier)
|
14
|
+
cell = @cells.where(:identifier => identifier).first || Cell.new
|
15
|
+
CellDrop.new cell
|
16
|
+
end
|
17
|
+
|
18
|
+
def all
|
19
|
+
@all ||= @cells.map do |cell|
|
20
|
+
CellDrop.new cell
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def active
|
25
|
+
@active ||= @cells.select(&:active?).map do |cell|
|
26
|
+
CellDrop.new cell
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def each(&block)
|
31
|
+
all.each(&block)
|
32
|
+
end
|
33
|
+
|
34
|
+
def size
|
35
|
+
@cells.size
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class CellDrop < ::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 => :@cell
|
56
|
+
|
57
|
+
def initialize(cell)
|
58
|
+
@cell = cell
|
59
|
+
end
|
60
|
+
|
61
|
+
def link
|
62
|
+
link_to @cell.name, self.url
|
63
|
+
end
|
64
|
+
|
65
|
+
def url
|
66
|
+
Rails.application.routes.url_helpers.cell_path(@cell)
|
67
|
+
end
|
68
|
+
|
69
|
+
def issues
|
70
|
+
@issues ||= IssuesDrop.new @cell.issues.visible
|
71
|
+
end
|
72
|
+
|
73
|
+
def users
|
74
|
+
@users ||= UsersDrop.new @cell.users
|
75
|
+
end
|
76
|
+
|
77
|
+
def subcells
|
78
|
+
@subcells ||= CellsDrop.new @cell.children
|
79
|
+
end
|
80
|
+
|
81
|
+
def custom_field_values
|
82
|
+
@cell.custom_field_values
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module YeshouaCrm
|
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 YeshouaCrm
|
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,72 @@
|
|
1
|
+
module YeshouaCrm
|
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 cells
|
63
|
+
CellsDrop.new @user.memberships.map(&:cell).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,177 @@
|
|
1
|
+
module YeshouaCrm
|
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 }.each_with_object([]) do |item, array|
|
37
|
+
array << {
|
38
|
+
"name" => item.first,
|
39
|
+
"items" => item.last,
|
40
|
+
"size" => item.last.size
|
41
|
+
}
|
42
|
+
end
|
43
|
+
else
|
44
|
+
input
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Filter an array of objects
|
49
|
+
#
|
50
|
+
# input - the object array
|
51
|
+
# property - property within each object to filter by
|
52
|
+
# value - desired value
|
53
|
+
#
|
54
|
+
# Returns the filtered array of objects
|
55
|
+
def where(input, property, value, operator='==')
|
56
|
+
return input unless input.respond_to?(:select)
|
57
|
+
input = input.values if input.is_a?(Hash)
|
58
|
+
if operator == '=='
|
59
|
+
input.select do |object|
|
60
|
+
Array(item_property(object, property)).map(&:to_s).include?(value.to_s)
|
61
|
+
end || []
|
62
|
+
elsif operator == '<>'
|
63
|
+
input.select do |object|
|
64
|
+
!Array(item_property(object, property)).map(&:to_s).include?(value.to_s)
|
65
|
+
end || []
|
66
|
+
elsif operator == '>'
|
67
|
+
input.select do |object|
|
68
|
+
item_property(object, property) > value
|
69
|
+
end || []
|
70
|
+
elsif operator == '<'
|
71
|
+
input.select do |object|
|
72
|
+
item_property(object, property) < value
|
73
|
+
end || []
|
74
|
+
elsif operator == 'match'
|
75
|
+
input.select do |object|
|
76
|
+
Array(item_property(object, property)).map(&:to_s).any?{|i| i.match(value.to_s)}
|
77
|
+
end || []
|
78
|
+
else
|
79
|
+
[]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Filter an array of objects by tags
|
84
|
+
#
|
85
|
+
# input - the object array
|
86
|
+
# tags - quoted tags list divided by comma
|
87
|
+
# match - (all- defaut, any, exclude)
|
88
|
+
#
|
89
|
+
# Returns the filtered array of objects
|
90
|
+
def tagged_with(input, tags, match='all')
|
91
|
+
return input unless input.respond_to?(:select)
|
92
|
+
input = input.values if input.is_a?(Hash)
|
93
|
+
tag_list = input.is_a?(Array) ? tags.sort : tags.split(',').map(&:strip).sort
|
94
|
+
case match
|
95
|
+
when "all"
|
96
|
+
input.select do |object|
|
97
|
+
object.respond_to?(:tag_list) &&
|
98
|
+
(tag_list - Array(item_property(object, 'tag_list')).map(&:to_s).sort).empty?
|
99
|
+
end || []
|
100
|
+
when "any"
|
101
|
+
input.select do |object|
|
102
|
+
object.respond_to?(:tag_list) &&
|
103
|
+
(tag_list & Array(item_property(object, 'tag_list')).map(&:to_s).sort).any?
|
104
|
+
end || []
|
105
|
+
when "exclude"
|
106
|
+
input.select do |object|
|
107
|
+
object.respond_to?(:tag_list) &&
|
108
|
+
(tag_list & Array(item_property(object, 'tag_list')).map(&:to_s).sort).empty?
|
109
|
+
end || []
|
110
|
+
else
|
111
|
+
[]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Sort an array of objects
|
116
|
+
#
|
117
|
+
# input - the object array
|
118
|
+
# property - property within each object to filter by
|
119
|
+
# nils ('first' | 'last') - nils appear before or after non-nil values
|
120
|
+
#
|
121
|
+
# Returns the filtered array of objects
|
122
|
+
def sort(input, property = nil, nils = "first")
|
123
|
+
if input.nil?
|
124
|
+
raise ArgumentError, "Cannot sort a null object."
|
125
|
+
end
|
126
|
+
if property.nil?
|
127
|
+
input.sort
|
128
|
+
else
|
129
|
+
if nils == "first"
|
130
|
+
order = - 1
|
131
|
+
elsif nils == "last"
|
132
|
+
order = + 1
|
133
|
+
else
|
134
|
+
raise ArgumentError, "Invalid nils order: " \
|
135
|
+
"'#{nils}' is not a valid nils order. It must be 'first' or 'last'."
|
136
|
+
end
|
137
|
+
|
138
|
+
sort_input(input, property, order)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def pop(array, input = 1)
|
143
|
+
return array unless array.is_a?(Array)
|
144
|
+
new_ary = array.dup
|
145
|
+
new_ary.pop(input.to_i || 1)
|
146
|
+
new_ary
|
147
|
+
end
|
148
|
+
|
149
|
+
def push(array, input)
|
150
|
+
return array unless array.is_a?(Array)
|
151
|
+
new_ary = array.dup
|
152
|
+
new_ary.push(input)
|
153
|
+
new_ary
|
154
|
+
end
|
155
|
+
|
156
|
+
def shift(array, input = 1)
|
157
|
+
return array unless array.is_a?(Array)
|
158
|
+
new_ary = array.dup
|
159
|
+
new_ary.shift(input.to_i || 1)
|
160
|
+
new_ary
|
161
|
+
end
|
162
|
+
|
163
|
+
def unshift(array, input)
|
164
|
+
return array unless array.is_a?(Array)
|
165
|
+
new_ary = array.dup
|
166
|
+
new_ary.unshift(input)
|
167
|
+
new_ary
|
168
|
+
end
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
end # module ArrayFilters
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
::Liquid::Template.register_filter(YeshouaCrm::Liquid::Filters::Arrays)
|
177
|
+
end
|