yeshua_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/yeshua_crm/acts_as_draftable/draft.rb +40 -0
- data/lib/yeshua_crm/acts_as_draftable/rcrm_acts_as_draftable.rb +154 -0
- data/lib/yeshua_crm/acts_as_list/list.rb +282 -0
- data/lib/yeshua_crm/acts_as_taggable/rcrm_acts_as_taggable.rb +350 -0
- data/lib/yeshua_crm/acts_as_taggable/tag.rb +81 -0
- data/lib/yeshua_crm/acts_as_taggable/tag_list.rb +111 -0
- data/lib/yeshua_crm/acts_as_taggable/tagging.rb +16 -0
- data/lib/yeshua_crm/acts_as_viewed/rcrm_acts_as_viewed.rb +274 -0
- data/lib/yeshua_crm/acts_as_votable/rcrm_acts_as_votable.rb +80 -0
- data/lib/yeshua_crm/acts_as_votable/rcrm_acts_as_voter.rb +20 -0
- data/lib/yeshua_crm/acts_as_votable/votable.rb +323 -0
- data/lib/yeshua_crm/acts_as_votable/vote.rb +28 -0
- data/lib/yeshua_crm/acts_as_votable/voter.rb +131 -0
- data/lib/yeshua_crm/assets_manager.rb +43 -0
- data/lib/yeshua_crm/currency/formatting.rb +224 -0
- data/lib/yeshua_crm/currency/heuristics.rb +151 -0
- data/lib/yeshua_crm/currency/loader.rb +24 -0
- data/lib/yeshua_crm/currency.rb +439 -0
- data/lib/yeshua_crm/helpers/external_assets_helper.rb +17 -0
- data/lib/yeshua_crm/helpers/form_tag_helper.rb +123 -0
- data/lib/yeshua_crm/helpers/tags_helper.rb +13 -0
- data/lib/yeshua_crm/helpers/vote_helper.rb +35 -0
- data/lib/yeshua_crm/liquid/drops/cells_drop.rb +86 -0
- data/lib/yeshua_crm/liquid/drops/issues_drop.rb +66 -0
- data/lib/yeshua_crm/liquid/drops/news_drop.rb +54 -0
- data/lib/yeshua_crm/liquid/drops/users_drop.rb +72 -0
- data/lib/yeshua_crm/liquid/filters/arrays.rb +177 -0
- data/lib/yeshua_crm/liquid/filters/base.rb +208 -0
- data/lib/yeshua_crm/money_helper.rb +65 -0
- data/lib/yeshua_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/yeshua_crm.gemspec +28 -0
- metadata +206 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
module YeshuaCrm
|
|
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 YeshuaCrm
|
|
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 YeshuaCrm
|
|
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 YeshuaCrm
|
|
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 YeshuaCrm
|
|
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(YeshuaCrm::Liquid::Filters::Arrays)
|
|
177
|
+
end
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
require 'rack'
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'date'
|
|
5
|
+
require 'liquid'
|
|
6
|
+
|
|
7
|
+
module YeshuaCrm
|
|
8
|
+
module Liquid
|
|
9
|
+
module Filters
|
|
10
|
+
module Base
|
|
11
|
+
include YeshuaCrm::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 = 'BRL')
|
|
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_fields)
|
|
102
|
+
input.custom_fields[field_name]
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def attachment(input, file_name)
|
|
107
|
+
if input.respond_to?(:attachments)
|
|
108
|
+
if input.attachments.is_a?(Hash)
|
|
109
|
+
attachment = input.attachments[file_name]
|
|
110
|
+
else
|
|
111
|
+
attachment = input.attachments.detect{|a| a.file_name == file_name}
|
|
112
|
+
end
|
|
113
|
+
AttachmentDrop.new attachment if attachment
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
protected
|
|
118
|
+
|
|
119
|
+
# Convert an array of properties ('key:value') into a hash
|
|
120
|
+
# Ex: ['width:50', 'height:100'] => { :width => '50', :height => '100' }
|
|
121
|
+
def args_to_options(*args)
|
|
122
|
+
options = {}
|
|
123
|
+
args.flatten.each do |a|
|
|
124
|
+
if (a =~ /^(.*):(.*)$/)
|
|
125
|
+
options[$1.to_sym] = $2
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
options
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Write options (Hash) into a string according to the following pattern:
|
|
132
|
+
# <key1>="<value1>", <key2>="<value2", ...etc
|
|
133
|
+
def inline_options(options = {})
|
|
134
|
+
return '' if options.empty?
|
|
135
|
+
(options.stringify_keys.sort.to_a.collect { |a, b| "#{a}=\"#{b}\"" }).join(' ') << ' '
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def sort_input(input, property, order)
|
|
139
|
+
input.sort do |apple, orange|
|
|
140
|
+
apple_property = item_property(apple, property)
|
|
141
|
+
orange_property = item_property(orange, property)
|
|
142
|
+
|
|
143
|
+
if !apple_property.nil? && orange_property.nil?
|
|
144
|
+
- order
|
|
145
|
+
elsif apple_property.nil? && !orange_property.nil?
|
|
146
|
+
+ order
|
|
147
|
+
else
|
|
148
|
+
apple_property <=> orange_property
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def time(input)
|
|
154
|
+
case input
|
|
155
|
+
when Time
|
|
156
|
+
input.clone
|
|
157
|
+
when Date
|
|
158
|
+
input.to_time
|
|
159
|
+
when String
|
|
160
|
+
Time.parse(input) rescue Time.at(input.to_i)
|
|
161
|
+
when Numeric
|
|
162
|
+
Time.at(input)
|
|
163
|
+
else
|
|
164
|
+
raise Errors::InvalidDateError,
|
|
165
|
+
"Invalid Date: '#{input.inspect}' is not a valid datetime."
|
|
166
|
+
end.localtime
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def groupable?(element)
|
|
170
|
+
element.respond_to?(:group_by)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def item_property(item, property)
|
|
174
|
+
if item.respond_to?(:to_liquid)
|
|
175
|
+
item.to_liquid[property.to_s]
|
|
176
|
+
elsif item.respond_to?(:data)
|
|
177
|
+
item.data[property.to_s]
|
|
178
|
+
else
|
|
179
|
+
item[property.to_s]
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def as_liquid(item)
|
|
184
|
+
case item
|
|
185
|
+
when Hash
|
|
186
|
+
pairs = item.map { |k, v| as_liquid([k, v]) }
|
|
187
|
+
Hash[pairs]
|
|
188
|
+
when Array
|
|
189
|
+
item.map { |i| as_liquid(i) }
|
|
190
|
+
else
|
|
191
|
+
if item.respond_to?(:to_liquid)
|
|
192
|
+
liquidated = item.to_liquid
|
|
193
|
+
# prevent infinite recursion for simple types (which return `self`)
|
|
194
|
+
if liquidated == item
|
|
195
|
+
item
|
|
196
|
+
else
|
|
197
|
+
as_liquid(liquidated)
|
|
198
|
+
end
|
|
199
|
+
else
|
|
200
|
+
item
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
::Liquid::Template.register_filter(YeshuaCrm::Liquid::Filters::Base)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|