redmineup 1.0.2

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.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/Gemfile +4 -0
  4. data/README.md +204 -0
  5. data/Rakefile +11 -0
  6. data/app/controllers/redmineup_controller.rb +26 -0
  7. data/app/views/redmine_crm/redmineup_calendar/_calendar.html.erb +34 -0
  8. data/app/views/redmineup/_money.html.erb +44 -0
  9. data/app/views/redmineup/settings.html.erb +10 -0
  10. data/bitbucket-pipelines.yml +50 -0
  11. data/config/currency_iso.json +2544 -0
  12. data/config/locales/cs.yml +13 -0
  13. data/config/locales/de.yml +13 -0
  14. data/config/locales/en.yml +13 -0
  15. data/config/locales/es.yml +13 -0
  16. data/config/locales/ru.yml +13 -0
  17. data/config/routes.rb +5 -0
  18. data/doc/CHANGELOG +14 -0
  19. data/doc/LICENSE.txt +339 -0
  20. data/lib/redmineup/acts_as_draftable/draft.rb +40 -0
  21. data/lib/redmineup/acts_as_draftable/up_acts_as_draftable.rb +172 -0
  22. data/lib/redmineup/acts_as_list/list.rb +282 -0
  23. data/lib/redmineup/acts_as_priceable/up_acts_as_priceable.rb +33 -0
  24. data/lib/redmineup/acts_as_taggable/tag.rb +81 -0
  25. data/lib/redmineup/acts_as_taggable/tag_list.rb +111 -0
  26. data/lib/redmineup/acts_as_taggable/tagging.rb +16 -0
  27. data/lib/redmineup/acts_as_taggable/up_acts_as_taggable.rb +357 -0
  28. data/lib/redmineup/acts_as_viewed/up_acts_as_viewed.rb +274 -0
  29. data/lib/redmineup/acts_as_votable/up_acts_as_votable.rb +80 -0
  30. data/lib/redmineup/acts_as_votable/up_acts_as_voter.rb +20 -0
  31. data/lib/redmineup/acts_as_votable/votable.rb +323 -0
  32. data/lib/redmineup/acts_as_votable/vote.rb +28 -0
  33. data/lib/redmineup/acts_as_votable/voter.rb +131 -0
  34. data/lib/redmineup/assets_manager.rb +43 -0
  35. data/lib/redmineup/colors_helper.rb +192 -0
  36. data/lib/redmineup/compatibility/application_controller_patch.rb +33 -0
  37. data/lib/redmineup/compatibility/routing_mapper_patch.rb +25 -0
  38. data/lib/redmineup/currency/formatting.rb +224 -0
  39. data/lib/redmineup/currency/heuristics.rb +151 -0
  40. data/lib/redmineup/currency/loader.rb +23 -0
  41. data/lib/redmineup/currency.rb +450 -0
  42. data/lib/redmineup/engine.rb +4 -0
  43. data/lib/redmineup/helpers/external_assets_helper.rb +20 -0
  44. data/lib/redmineup/helpers/form_tag_helper.rb +88 -0
  45. data/lib/redmineup/helpers/rup_calendar_helper.rb +146 -0
  46. data/lib/redmineup/helpers/tags_helper.rb +13 -0
  47. data/lib/redmineup/helpers/vote_helper.rb +35 -0
  48. data/lib/redmineup/hooks/views_layouts_hook.rb +11 -0
  49. data/lib/redmineup/liquid/drops/attachment_drop.rb +47 -0
  50. data/lib/redmineup/liquid/drops/issue_relations_drop.rb +41 -0
  51. data/lib/redmineup/liquid/drops/issues_drop.rb +217 -0
  52. data/lib/redmineup/liquid/drops/news_drop.rb +54 -0
  53. data/lib/redmineup/liquid/drops/projects_drop.rb +86 -0
  54. data/lib/redmineup/liquid/drops/time_entries_drop.rb +65 -0
  55. data/lib/redmineup/liquid/drops/users_drop.rb +68 -0
  56. data/lib/redmineup/liquid/filters/arrays.rb +254 -0
  57. data/lib/redmineup/liquid/filters/base.rb +249 -0
  58. data/lib/redmineup/liquid/filters/colors.rb +31 -0
  59. data/lib/redmineup/money_helper.rb +66 -0
  60. data/lib/redmineup/patches/liquid_patch.rb +33 -0
  61. data/lib/redmineup/settings/money.rb +46 -0
  62. data/lib/redmineup/settings.rb +53 -0
  63. data/lib/redmineup/version.rb +3 -0
  64. data/lib/redmineup.rb +108 -0
  65. data/redmineup.gemspec +29 -0
  66. data/test/acts_as_draftable/draft_test.rb +29 -0
  67. data/test/acts_as_draftable/rup_acts_as_draftable_test.rb +178 -0
  68. data/test/acts_as_taggable/rup_acts_as_taggable_test.rb +350 -0
  69. data/test/acts_as_taggable/tag_list_test.rb +34 -0
  70. data/test/acts_as_taggable/tag_test.rb +72 -0
  71. data/test/acts_as_taggable/tagging_test.rb +15 -0
  72. data/test/acts_as_viewed/rup_acts_as_viewed_test.rb +47 -0
  73. data/test/acts_as_votable/rup_acts_as_votable_test.rb +19 -0
  74. data/test/acts_as_votable/rup_acts_as_voter_test.rb +14 -0
  75. data/test/acts_as_votable/votable_test.rb +507 -0
  76. data/test/acts_as_votable/voter_test.rb +296 -0
  77. data/test/currency_test.rb +292 -0
  78. data/test/database.yml +17 -0
  79. data/test/fixtures/attachments.yml +14 -0
  80. data/test/fixtures/issues.yml +24 -0
  81. data/test/fixtures/news.yml +8 -0
  82. data/test/fixtures/projects.yml +10 -0
  83. data/test/fixtures/taggings.yml +32 -0
  84. data/test/fixtures/tags.yml +11 -0
  85. data/test/fixtures/users.yml +9 -0
  86. data/test/fixtures/votable_caches.yml +2 -0
  87. data/test/fixtures/votables.yml +4 -0
  88. data/test/fixtures/voters.yml +6 -0
  89. data/test/liquid/drops/attachment_drop_test.rb +15 -0
  90. data/test/liquid/drops/issue_relations_drop_test.rb +24 -0
  91. data/test/liquid/drops/issues_drop_test.rb +38 -0
  92. data/test/liquid/drops/news_drop_test.rb +38 -0
  93. data/test/liquid/drops/projects_drop_test.rb +44 -0
  94. data/test/liquid/drops/uses_drop_test.rb +36 -0
  95. data/test/liquid/filters/arrays_filter_test.rb +31 -0
  96. data/test/liquid/filters/base_filter_test.rb +67 -0
  97. data/test/liquid/filters/colors_filter_test.rb +33 -0
  98. data/test/liquid/liquid_helper.rb +34 -0
  99. data/test/models/attachment.rb +3 -0
  100. data/test/models/issue.rb +21 -0
  101. data/test/models/issue_relation.rb +10 -0
  102. data/test/models/news.rb +3 -0
  103. data/test/models/project.rb +8 -0
  104. data/test/models/user.rb +11 -0
  105. data/test/models/vote_classes.rb +33 -0
  106. data/test/money_helper_test.rb +12 -0
  107. data/test/schema.rb +144 -0
  108. data/test/tags_helper_test.rb +29 -0
  109. data/test/test_helper.rb +66 -0
  110. data/test/vote_helper_test.rb +28 -0
  111. data/vendor/assets/images/money.png +0 -0
  112. data/vendor/assets/images/vcard.png +0 -0
  113. data/vendor/assets/javascripts/Chart.bundle.min.js +16 -0
  114. data/vendor/assets/javascripts/select2.js +2 -0
  115. data/vendor/assets/javascripts/select2_helpers.js +192 -0
  116. data/vendor/assets/stylesheets/money.css +96 -0
  117. data/vendor/assets/stylesheets/select2.css +424 -0
  118. metadata +295 -0
@@ -0,0 +1,146 @@
1
+ module RedmineUp
2
+ module CalendarHelper
3
+ # Simple class to compute the start and end dates of a calendar
4
+ class Calendar
5
+ attr_reader :startdt, :enddt
6
+
7
+ def initialize(date, options={}, lang = current_language, period = :month)
8
+ @date = date
9
+ @events = []
10
+ @ending_events_by_days = {}
11
+ @starting_events_by_days = {}
12
+ # ADDED FOR CONTACTS-DEALS
13
+ @start_date_field = options[:start_date_field] || "start_date"
14
+ @due_date_field = options[:due_date_field] || "due_date"
15
+ # /ADDED FOR CONTACTS-DEALS
16
+ set_language_if_valid lang
17
+ case period
18
+ when :month
19
+ @startdt = Date.civil(date.year, date.month, 1)
20
+ @enddt = (@startdt >> 1)-1
21
+ # starts from the first day of the week
22
+ @startdt = @startdt - (@startdt.cwday - first_wday)%7
23
+ # ends on the last day of the week
24
+ @enddt = @enddt + (last_wday - @enddt.cwday)%7
25
+ when :week
26
+ @startdt = date - (date.cwday - first_wday)%7
27
+ @enddt = date + (last_wday - date.cwday)%7
28
+ else
29
+ raise 'Invalid period'
30
+ end
31
+ end
32
+
33
+ def format_month
34
+ (@startdt..@enddt).to_a
35
+ end
36
+
37
+ def week_number(day)
38
+ (day + (11 - day.cwday) % 7).cweek
39
+ end
40
+
41
+ def day_css_classes(day)
42
+ css = day.month==month ? +'even' : +'odd'
43
+ css << " today" if User.current.today == day
44
+ css << " nwday" if non_working_week_days.include?(day.cwday)
45
+ css
46
+ end
47
+
48
+ # Sets calendar events
49
+ def events=(events)
50
+ @events = events
51
+ # CHANGED FOR CONTACTS-DEALS
52
+ @ending_events_by_days = @events.group_by {|event| event.send(@start_date_field) ? event.send(@start_date_field).to_date : event.due_date}
53
+ @starting_events_by_days = @events.group_by {|event| event.send(@due_date_field) ? event.send(@due_date_field).to_date : event.start_date}
54
+ # /CHANGED FOR CONTACTS-DEALS
55
+ end
56
+
57
+ # Returns events for the given day
58
+ def events_on(day)
59
+ ((@ending_events_by_days[day] || []) + (@starting_events_by_days[day] || [])).uniq
60
+ end
61
+
62
+ # Calendar current month
63
+ def month
64
+ @date.month
65
+ end
66
+
67
+ # Return the first day of week
68
+ # 1 = Monday ... 7 = Sunday
69
+ def first_wday
70
+ case Setting.start_of_week.to_i
71
+ when 1
72
+ @first_dow ||= (1 - 1)%7 + 1
73
+ when 6
74
+ @first_dow ||= (6 - 1)%7 + 1
75
+ when 7
76
+ @first_dow ||= (7 - 1)%7 + 1
77
+ else
78
+ @first_dow ||= (l(:general_first_day_of_week).to_i - 1)%7 + 1
79
+ end
80
+ end
81
+
82
+ def last_wday
83
+ @last_dow ||= (first_wday + 5)%7 + 1
84
+ end
85
+
86
+ def abbr_day_name(day)
87
+ ::I18n.t('date.abbr_day_names')[day % 7]
88
+ end
89
+
90
+ def current_language
91
+ ::I18n.locale
92
+ end
93
+
94
+ def set_language_if_valid(lang)
95
+ if l = find_language(lang)
96
+ ::I18n.locale = l
97
+ end
98
+ end
99
+
100
+ def find_language(lang)
101
+ @@languages_lookup ||=
102
+ valid_languages.inject({}) do |k, v|
103
+ k[v.to_s.downcase] = v
104
+ k
105
+ end
106
+ @@languages_lookup[lang.to_s.downcase]
107
+ end
108
+
109
+ def valid_languages
110
+ ::I18n.available_locales
111
+ end
112
+
113
+ def l(*args)
114
+ case args.size
115
+ when 1
116
+ ::I18n.t(*args)
117
+ when 2
118
+ if args.last.is_a?(Hash)
119
+ ::I18n.t(*args.first, **args.last)
120
+ elsif args.last.is_a?(String)
121
+ ::I18n.t(args.first, :value => args.last)
122
+ else
123
+ ::I18n.t(args.first, :count => args.last)
124
+ end
125
+ else
126
+ raise "Translation string with multiple values: #{args.first}"
127
+ end
128
+ end
129
+
130
+ def non_working_week_days
131
+ @non_working_week_days ||= begin
132
+ days = Setting.non_working_week_days
133
+ if days.is_a?(Array) && days.size < 7
134
+ days.map(&:to_i)
135
+ else
136
+ []
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ unless ActionView::Base.included_modules.include?(RedmineUp::CalendarHelper)
145
+ ActionView::Base.send(:include, RedmineUp::CalendarHelper)
146
+ end
@@ -0,0 +1,13 @@
1
+ module Redmineup
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 Redmineup
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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Redmineup
4
+ module Hooks
5
+ class ViewsLayoutsHook < Redmine::Hook::ViewListener
6
+ def view_layouts_base_html_head(_context = {})
7
+ stylesheet_link_tag(:money, plugin: 'redmineup')
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,47 @@
1
+ module Redmineup
2
+ module Liquid
3
+ class AttachmentDrop < ::Liquid::Drop
4
+ delegate :id,
5
+ :filename,
6
+ :title,
7
+ :description,
8
+ :filesize,
9
+ :content_type,
10
+ :digest,
11
+ :downloads,
12
+ :created_on,
13
+ :token,
14
+ :visible?,
15
+ :image?,
16
+ :thumbnailable?,
17
+ :is_text?,
18
+ :readable?,
19
+ to: :@attachment
20
+
21
+ def initialize(attachment)
22
+ @attachment = attachment
23
+ end
24
+
25
+ def url(options = {})
26
+ Rails.application.routes.url_helpers.download_named_attachment_url(@attachment, { filename: filename,
27
+ host: Setting.host_name,
28
+ protocol: Setting.protocol }.merge(options))
29
+ end
30
+
31
+ def link
32
+ link_to((@attachment.description.blank? ? @attachment.filename : @attachment.description), url)
33
+ end
34
+
35
+ def author
36
+ @author ||= UserDrop.new @attachment.author
37
+ end
38
+
39
+ def read
40
+ @content ||= if @attachment.is_text? && @attachment.filesize <= Setting.file_max_size_displayed.to_i.kilobyte
41
+ File.new(@attachment.diskfile, "rb").read
42
+ end
43
+ @content
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,41 @@
1
+ module Redmineup
2
+ module Liquid
3
+ class IssueRelationsDrop < ::Liquid::Drop
4
+ def initialize(relations)
5
+ @relations = relations
6
+ end
7
+
8
+ def all
9
+ @all ||= @relations.map { |relation| IssueRelationDrop.new(relation) }
10
+ end
11
+
12
+ def visible
13
+ @visible ||= @all.select(&:visible?)
14
+ end
15
+
16
+ def each(&block)
17
+ all.each(&block)
18
+ end
19
+
20
+ def size
21
+ @relations.size
22
+ end
23
+ end
24
+
25
+ class IssueRelationDrop < ::Liquid::Drop
26
+ delegate :relation_type, :delay, to: :@relation
27
+
28
+ def initialize(relation)
29
+ @relation = relation
30
+ end
31
+
32
+ def issue_from
33
+ @issue_from ||= IssueDrop.new(@relation.issue_from)
34
+ end
35
+
36
+ def issue_to
37
+ @issue_to ||= IssueDrop.new(@relation.issue_to)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,217 @@
1
+ module Redmineup
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 ||=
15
+ @issues.map do |issue|
16
+ IssueDrop.new issue
17
+ end
18
+ end
19
+
20
+ def visible
21
+ @visible ||= @all.select(&:visible?)
22
+ end
23
+
24
+ def each(&block)
25
+ all.each(&block)
26
+ end
27
+
28
+ def size
29
+ @issues.size
30
+ end
31
+ end
32
+
33
+ class IssueDrop < ::Liquid::Drop
34
+ include ActionView::Helpers::UrlHelper
35
+
36
+ delegate :id,
37
+ :subject,
38
+ :visible?,
39
+ :closed?,
40
+ :start_date,
41
+ :due_date,
42
+ :overdue?,
43
+ :done_ratio,
44
+ :estimated_hours,
45
+ :spent_hours,
46
+ :total_spent_hours,
47
+ :total_estimated_hours,
48
+ :is_private?,
49
+ :closed_on,
50
+ :updated_on,
51
+ :created_on,
52
+ to: :@issue
53
+
54
+ def initialize(issue)
55
+ @issue = issue
56
+ end
57
+
58
+ def link
59
+ link_to @issue.subject, url
60
+ end
61
+
62
+ def url
63
+ Rails.application.routes.url_helpers.issue_path(@issue)
64
+ end
65
+
66
+ def author
67
+ @user ||= UserDrop.new(@issue.author)
68
+ end
69
+
70
+ def assignee
71
+ @assignee ||= UserDrop.new(@issue.assigned_to)
72
+ end
73
+
74
+ def tracker
75
+ @tracker ||= @issue.tracker && @issue.tracker.name
76
+ end
77
+
78
+ def status
79
+ @status ||= @issue.status && @issue.status.name
80
+ end
81
+
82
+ def priority
83
+ @priority ||= @issue.priority && @issue.priority.name
84
+ end
85
+
86
+ def category
87
+ @category ||= @issue.category && @issue.category.name
88
+ end
89
+
90
+ def version
91
+ @version ||= @issue.fixed_version && @issue.fixed_version.name
92
+ end
93
+
94
+ def time_entries
95
+ @time_entries ||= TimeEntriesDrop.new @issue.time_entries
96
+ end
97
+
98
+ def parent
99
+ @parent ||= IssueDrop.new @issue.parent if @issue.parent
100
+ end
101
+
102
+ def project
103
+ @project ||= ProjectDrop.new @issue.project if @issue.project
104
+ end
105
+
106
+ def description
107
+ @description ||= replace_images_urls(@issue.description)
108
+ end
109
+
110
+ def subtasks
111
+ @subtasks ||= IssuesDrop.new @issue.children
112
+ end
113
+
114
+ def relations_from
115
+ @relations_from ||= IssueRelationsDrop.new(@issue.relations_from.select { |r| r.other_issue(@issue) && r.other_issue(@issue).visible? })
116
+ end
117
+
118
+ def relations_to
119
+ @relations_to ||= IssueRelationsDrop.new(@issue.relations_to.select { |r| r.other_issue(@issue) && r.other_issue(@issue).visible? })
120
+ end
121
+
122
+ def notes
123
+ @notes ||= @issue.journals.where.not(notes: [nil, '']).order(:created_on).map(&:notes).map { |note| replace_images_urls(note) }
124
+ end
125
+
126
+ def journals
127
+ @journals ||= JournalsDrop.new(@issue.journals.where.not(notes: nil).find_each { |journal| journal.notes = replace_images_urls(journal.notes) })
128
+ end
129
+
130
+ def tags
131
+ @issue.respond_to?(:tag_list) && @issue.tag_list
132
+ end
133
+
134
+ def story_points
135
+ @issue.respond_to?(:story_points) && @issue.story_points
136
+ end
137
+
138
+ def color
139
+ @issue.respond_to?(:color) && @issue.color
140
+ end
141
+
142
+ def day_in_state
143
+ @issue.respond_to?(:day_in_state) && @issue.day_in_state
144
+ end
145
+
146
+ def checklists
147
+ @issue.respond_to?(:checklists) && @issue.checklists.map do |item|
148
+ { 'id_done' => item.is_done, 'subject' => item.subject, 'is_section' => item.is_section }
149
+ end
150
+ end
151
+
152
+ def helpdesk_ticket
153
+ return nil unless defined?(::HelpdeskTicketDrop)
154
+
155
+ @helpdesk_ticket ||= HelpdeskTicketDrop.new(@issue)
156
+ end
157
+
158
+ def custom_field_values
159
+ @issue.custom_field_values
160
+ end
161
+
162
+ private
163
+
164
+ def replace_images_urls(text)
165
+ text.gsub(/\!.*\!/) do |i_name|
166
+ i_name = i_name.delete('!')
167
+ i_name_css = i_name.scan(/^\{.*\}/).first.to_s
168
+ attachment = @issue.attachments.find_by(filename: i_name.gsub(i_name_css, ''))
169
+ image = AttachmentDrop.new attachment if attachment
170
+ attach_url = image.try(:url)
171
+ attach_url ? "!#{i_name_css}#{attach_url}!" : i_name
172
+ end
173
+ end
174
+ end
175
+
176
+ class JournalsDrop < ::Liquid::Drop
177
+ def initialize(journals)
178
+ @journals = journals
179
+ end
180
+
181
+ def all
182
+ @all ||=
183
+ @journals.map do |journal|
184
+ JournalDrop.new journal
185
+ end
186
+ end
187
+
188
+ def visible
189
+ @visible ||= @all.select(&:visible?)
190
+ end
191
+
192
+ def each(&block)
193
+ all.each(&block)
194
+ end
195
+
196
+ def size
197
+ @journals.size
198
+ end
199
+ end
200
+
201
+ class JournalDrop < ::Liquid::Drop
202
+ delegate :id, :notes, :created_on, :private_notes, to: :@journal, allow_nil: true
203
+
204
+ def initialize(journal)
205
+ @journal = journal
206
+ end
207
+
208
+ def user
209
+ @user ||= UserDrop.new(@journal.user)
210
+ end
211
+
212
+ def issue
213
+ @issue ||= IssueDrop.new @journal.issue if @journal.issue
214
+ end
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,54 @@
1
+ module Redmineup
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 Redmineup
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
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