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.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/Gemfile +4 -0
- data/README.md +204 -0
- data/Rakefile +11 -0
- data/app/controllers/redmineup_controller.rb +26 -0
- data/app/views/redmine_crm/redmineup_calendar/_calendar.html.erb +34 -0
- data/app/views/redmineup/_money.html.erb +44 -0
- data/app/views/redmineup/settings.html.erb +10 -0
- data/bitbucket-pipelines.yml +50 -0
- data/config/currency_iso.json +2544 -0
- data/config/locales/cs.yml +13 -0
- data/config/locales/de.yml +13 -0
- data/config/locales/en.yml +13 -0
- data/config/locales/es.yml +13 -0
- data/config/locales/ru.yml +13 -0
- data/config/routes.rb +5 -0
- data/doc/CHANGELOG +14 -0
- data/doc/LICENSE.txt +339 -0
- data/lib/redmineup/acts_as_draftable/draft.rb +40 -0
- data/lib/redmineup/acts_as_draftable/up_acts_as_draftable.rb +172 -0
- data/lib/redmineup/acts_as_list/list.rb +282 -0
- data/lib/redmineup/acts_as_priceable/up_acts_as_priceable.rb +33 -0
- data/lib/redmineup/acts_as_taggable/tag.rb +81 -0
- data/lib/redmineup/acts_as_taggable/tag_list.rb +111 -0
- data/lib/redmineup/acts_as_taggable/tagging.rb +16 -0
- data/lib/redmineup/acts_as_taggable/up_acts_as_taggable.rb +357 -0
- data/lib/redmineup/acts_as_viewed/up_acts_as_viewed.rb +274 -0
- data/lib/redmineup/acts_as_votable/up_acts_as_votable.rb +80 -0
- data/lib/redmineup/acts_as_votable/up_acts_as_voter.rb +20 -0
- data/lib/redmineup/acts_as_votable/votable.rb +323 -0
- data/lib/redmineup/acts_as_votable/vote.rb +28 -0
- data/lib/redmineup/acts_as_votable/voter.rb +131 -0
- data/lib/redmineup/assets_manager.rb +43 -0
- data/lib/redmineup/colors_helper.rb +192 -0
- data/lib/redmineup/compatibility/application_controller_patch.rb +33 -0
- data/lib/redmineup/compatibility/routing_mapper_patch.rb +25 -0
- data/lib/redmineup/currency/formatting.rb +224 -0
- data/lib/redmineup/currency/heuristics.rb +151 -0
- data/lib/redmineup/currency/loader.rb +23 -0
- data/lib/redmineup/currency.rb +450 -0
- data/lib/redmineup/engine.rb +4 -0
- data/lib/redmineup/helpers/external_assets_helper.rb +20 -0
- data/lib/redmineup/helpers/form_tag_helper.rb +88 -0
- data/lib/redmineup/helpers/rup_calendar_helper.rb +146 -0
- data/lib/redmineup/helpers/tags_helper.rb +13 -0
- data/lib/redmineup/helpers/vote_helper.rb +35 -0
- data/lib/redmineup/hooks/views_layouts_hook.rb +11 -0
- data/lib/redmineup/liquid/drops/attachment_drop.rb +47 -0
- data/lib/redmineup/liquid/drops/issue_relations_drop.rb +41 -0
- data/lib/redmineup/liquid/drops/issues_drop.rb +217 -0
- data/lib/redmineup/liquid/drops/news_drop.rb +54 -0
- data/lib/redmineup/liquid/drops/projects_drop.rb +86 -0
- data/lib/redmineup/liquid/drops/time_entries_drop.rb +65 -0
- data/lib/redmineup/liquid/drops/users_drop.rb +68 -0
- data/lib/redmineup/liquid/filters/arrays.rb +254 -0
- data/lib/redmineup/liquid/filters/base.rb +249 -0
- data/lib/redmineup/liquid/filters/colors.rb +31 -0
- data/lib/redmineup/money_helper.rb +66 -0
- data/lib/redmineup/patches/liquid_patch.rb +33 -0
- data/lib/redmineup/settings/money.rb +46 -0
- data/lib/redmineup/settings.rb +53 -0
- data/lib/redmineup/version.rb +3 -0
- data/lib/redmineup.rb +108 -0
- data/redmineup.gemspec +29 -0
- data/test/acts_as_draftable/draft_test.rb +29 -0
- data/test/acts_as_draftable/rup_acts_as_draftable_test.rb +178 -0
- data/test/acts_as_taggable/rup_acts_as_taggable_test.rb +350 -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/rup_acts_as_viewed_test.rb +47 -0
- data/test/acts_as_votable/rup_acts_as_votable_test.rb +19 -0
- data/test/acts_as_votable/rup_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/database.yml +17 -0
- data/test/fixtures/attachments.yml +14 -0
- data/test/fixtures/issues.yml +24 -0
- data/test/fixtures/news.yml +8 -0
- data/test/fixtures/projects.yml +10 -0
- data/test/fixtures/taggings.yml +32 -0
- data/test/fixtures/tags.yml +11 -0
- data/test/fixtures/users.yml +9 -0
- data/test/fixtures/votable_caches.yml +2 -0
- data/test/fixtures/votables.yml +4 -0
- data/test/fixtures/voters.yml +6 -0
- data/test/liquid/drops/attachment_drop_test.rb +15 -0
- data/test/liquid/drops/issue_relations_drop_test.rb +24 -0
- data/test/liquid/drops/issues_drop_test.rb +38 -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 +67 -0
- data/test/liquid/filters/colors_filter_test.rb +33 -0
- data/test/liquid/liquid_helper.rb +34 -0
- data/test/models/attachment.rb +3 -0
- data/test/models/issue.rb +21 -0
- data/test/models/issue_relation.rb +10 -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 +144 -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/vendor/assets/images/money.png +0 -0
- data/vendor/assets/images/vcard.png +0 -0
- data/vendor/assets/javascripts/Chart.bundle.min.js +16 -0
- data/vendor/assets/javascripts/select2.js +2 -0
- data/vendor/assets/javascripts/select2_helpers.js +192 -0
- data/vendor/assets/stylesheets/money.css +96 -0
- data/vendor/assets/stylesheets/select2.css +424 -0
- 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,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
|