redmine_api_helper 0.3.24

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.

Potentially problematic release.


This version of redmine_api_helper might be problematic. Click here for more details.

Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +2 -0
  3. data/.gitignore +11 -0
  4. data/CODE_OF_CONDUCT.md +74 -0
  5. data/Gemfile +6 -0
  6. data/LICENSE +339 -0
  7. data/README.md +30 -0
  8. data/Rakefile +2 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/lib/date_helper/date.rb +311 -0
  12. data/lib/odf_writer/bookmark.rb +110 -0
  13. data/lib/odf_writer/bookmark_reader.rb +77 -0
  14. data/lib/odf_writer/document.rb +372 -0
  15. data/lib/odf_writer/field.rb +174 -0
  16. data/lib/odf_writer/field_reader.rb +78 -0
  17. data/lib/odf_writer/image.rb +158 -0
  18. data/lib/odf_writer/image_reader.rb +76 -0
  19. data/lib/odf_writer/images.rb +89 -0
  20. data/lib/odf_writer/list_style.rb +331 -0
  21. data/lib/odf_writer/nested.rb +156 -0
  22. data/lib/odf_writer/odf_helper.rb +56 -0
  23. data/lib/odf_writer/parser/default.rb +685 -0
  24. data/lib/odf_writer/path_finder.rb +114 -0
  25. data/lib/odf_writer/section.rb +120 -0
  26. data/lib/odf_writer/section_reader.rb +61 -0
  27. data/lib/odf_writer/style.rb +417 -0
  28. data/lib/odf_writer/table.rb +135 -0
  29. data/lib/odf_writer/table_reader.rb +61 -0
  30. data/lib/odf_writer/template.rb +222 -0
  31. data/lib/odf_writer/text.rb +97 -0
  32. data/lib/odf_writer/text_reader.rb +77 -0
  33. data/lib/odf_writer/version.rb +29 -0
  34. data/lib/redmine_api_helper/api_helper.rb +333 -0
  35. data/lib/redmine_api_helper/args_helper.rb +106 -0
  36. data/lib/redmine_api_helper/attachments_api_helper.rb +52 -0
  37. data/lib/redmine_api_helper/define_api_helpers.rb +78 -0
  38. data/lib/redmine_api_helper/document_categories_api_helper.rb +38 -0
  39. data/lib/redmine_api_helper/groups_api_helper.rb +80 -0
  40. data/lib/redmine_api_helper/helpers.rb +50 -0
  41. data/lib/redmine_api_helper/issue_priorities_api_helper.rb +38 -0
  42. data/lib/redmine_api_helper/issue_relations_api_helper.rb +66 -0
  43. data/lib/redmine_api_helper/issue_statuses_api_helper.rb +36 -0
  44. data/lib/redmine_api_helper/issues_api_helper.rb +124 -0
  45. data/lib/redmine_api_helper/my_account_api_helper.rb +45 -0
  46. data/lib/redmine_api_helper/news_api_helper.rb +73 -0
  47. data/lib/redmine_api_helper/project_memberships_api_helper.rb +77 -0
  48. data/lib/redmine_api_helper/projects_api_helper.rb +73 -0
  49. data/lib/redmine_api_helper/roles_api_helper.rb +52 -0
  50. data/lib/redmine_api_helper/scripts_api_helper.rb +87 -0
  51. data/lib/redmine_api_helper/search_api_helper.rb +38 -0
  52. data/lib/redmine_api_helper/time_entries_api_helper.rb +73 -0
  53. data/lib/redmine_api_helper/time_entry_activities_api_helper.rb +38 -0
  54. data/lib/redmine_api_helper/trackers_api_helper.rb +38 -0
  55. data/lib/redmine_api_helper/users_api_helper.rb +73 -0
  56. data/lib/redmine_api_helper/version.rb +24 -0
  57. data/lib/redmine_api_helper/wiki_pages_api_helper.rb +66 -0
  58. data/lib/redmine_api_helper.rb +88 -0
  59. data/redmine_api_helper.gemspec +35 -0
  60. metadata +148 -0
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "deep_try"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,311 @@
1
+ ##
2
+ # encoding: utf-8
3
+ #
4
+ # Extension for Date to calculate a forward date with compressed syntax
5
+ #
6
+ # Copyright 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
7
+ #
8
+ # This program is free software; you can redistribute it and/or
9
+ # modify it under the terms of the GNU General Public License
10
+ # as published by the Free Software Foundation; either version 2
11
+ # of the License, or (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
+ #
22
+
23
+ class Date
24
+
25
+ ####################################################################################
26
+ #
27
+ # Date.today.calc(<rule>) -> [<new_date>, <new_rule>]
28
+ # Date.today.forward(<rule) -> <new_date>
29
+ #
30
+ # <rule>: [DWmMqY][n][FMLWX][-!W*]
31
+ #
32
+ # 1. parameter: epoch-identifier (necessary)
33
+ #
34
+ # D - stands for _D_ays
35
+ # W - stands for _W_eeks
36
+ # m - stands for _m_ondays
37
+ # M - stands for _M_onths
38
+ # q - stands for _q_uarters
39
+ # Y - stands for _Y_ears
40
+ #
41
+ # 2. parameter: integer (necessary)
42
+ #
43
+ # n - stands for the number of epochs
44
+ #
45
+ # 3. position of day within epoch
46
+ #
47
+ # F - stands for _F_irst day of epoch, like first day of month, monday, first day of
48
+ # quarter, or January 1st
49
+ # M - stands for _M_id of epoch, like 15th day of month, wednesday, 15th of
50
+ # mid-of-quarter or June 30th
51
+ # L - stands for _L_ast of epoch, like last day of month, friday (last working day),
52
+ # last day of quarter or December 31st
53
+ # W - stands for _W_eekday (Monday), if calculated day falls on a Saturday or Sunday
54
+ # X - stands for no correction
55
+ #
56
+ # 3. control of date calculation
57
+ #
58
+ # - - the sign "-" is a killswitch. After one date calculation the resubmission rule is
59
+ # deleted, so no further resubmissions happen
60
+ # ! - the sign "!" is a force sign to force date calculation even if a resubmission date
61
+ # present
62
+ # W - the sign "W" in this position corrects the date to the next working day
63
+ # * - the sign "*" is a mock switch. The mock-switch is deleted from the resubmission-rule
64
+ # and no resubmission-date is calculated. Needed for Redmine Attribute-Quickie plugin
65
+ #
66
+ # Example: W1F - one week further, first day, so monday
67
+ # Example: M3M - three months further from today, mid-term, so 15th of month
68
+ # Example: q1- - next quarter, first day of quarter, so 1st Jan., Apr., Jul. or Oct., after
69
+ # one calculation further calculations are stopped, rule is deleted.
70
+ # Example: D1- - tomorrow, then delete rule
71
+ # Example: D1-! - tomorrow!, regardsless of date
72
+ #
73
+ # Resubmission dates are always calculated for the future, never for the past.
74
+ # So W0F would calculate "next monday"", if calculated on a friday, though W0 stands for
75
+ # this week (W0 zero weeks further, first day, monday) and would calculate last monday.
76
+ # In this case, the calculated date is advanced monday further into the future.
77
+ # So q0M would calculate "this quarter mid-term" if calculated near to lapse of current
78
+ # quarter. In this case the calculated date is advanced one quarter into the future.
79
+ ####################################################################################
80
+
81
+ ####################################################################################
82
+ # calc
83
+ ####################################################################################
84
+ def calc( rule )
85
+
86
+ new_date = nil
87
+ new_rule = nil
88
+
89
+ if rule.present?
90
+
91
+ m = parse_rule( rule )
92
+
93
+ if m['mockswitch']
94
+
95
+ # mockswitch does not calculate anything
96
+ # mockswitch is removed from new_rule, however
97
+ new_rule = unmock( rule, m )
98
+
99
+ elsif self <= Date.today || m['force']
100
+
101
+ if( m['epoch'] && m['num'] )
102
+
103
+ new_date = move( m['epoch'], m['num'] )
104
+ new_date = new_date.adjust( m['epoch'], m['pos'], self )
105
+ new_date = new_date.adjust("D", "W", new_date) if m["workingday"] # adjust working day
106
+
107
+ if m['killswitch']
108
+ new_rule = ""
109
+ else
110
+ new_rule = rule
111
+ end
112
+
113
+ end #if
114
+ end #if
115
+ end #if
116
+
117
+ [new_date, new_rule]
118
+
119
+ end #def
120
+
121
+ ####################################################################################
122
+ # forward
123
+ ####################################################################################
124
+ def forward( rule )
125
+ calc( rule ).first
126
+ end #def
127
+
128
+ ####################################################################################
129
+ # calculate num times advance of epoch
130
+ # epoch: D - n days
131
+ # epoch: W - n weeks
132
+ # epoch: M - n months
133
+ # epoch: Y - n years
134
+ #
135
+ # epoch: C - n calendar weeks (absolute, within this year, not relative)
136
+ # epoch: m - n mondays
137
+ # epoch: q - q quarters
138
+ ####################################################################################
139
+ def move( epoch, num )
140
+ case epoch
141
+ when "D"
142
+ self + num.to_i
143
+ when "W"
144
+ self + num.to_i * 7
145
+ when "M"
146
+ self >> num.to_i
147
+ when "Y"
148
+ self >> num.to_i * 12
149
+ when "m"
150
+ (self + num.to_i * 7).monday
151
+ when "q"
152
+ (self >> num.to_i * 3).beginning_of_quarter
153
+ when "C"
154
+ # calendar week 1 is the week containing Jan. 4th
155
+ change(:month => 1, :day => 4).advance( :weeks => (num.to_i - 1))
156
+ else
157
+ self
158
+ end #case
159
+ end #def
160
+
161
+ ####################################################################################
162
+ # calculate time adjustmentfor pos in epoch (_F_irst, _M_id, _L_ast, _W_orking day)
163
+ # epoch: D - day: W - Monday
164
+ # epoch: W - week: F - Monday, M - Wednesday, L - Friday, W - Monday
165
+ # epoch: M - month: F - 1st, M - 15th, L - last, W - Monday
166
+ # epoch: Y - year: F - 01/01, M - 06/30, L - 12/31, W - Monday
167
+ # epoch: q - quarter: W - Monday
168
+ ####################################################################################
169
+ def adjust( epoch, pos, ref=self )
170
+
171
+ case epoch
172
+ when "D"
173
+ case pos
174
+ when "W"
175
+ # if saturday or sunday, fall back to last monday, then add one week for monday coming up
176
+ (wday % 6) != 0 ? self : monday.advance(:days => 7)
177
+ else
178
+ self
179
+ end #case
180
+
181
+ when "W", "C"
182
+ # week
183
+ case pos
184
+ when "F"
185
+ # Monday
186
+ monday < ref ? advance( :weeks => 1).monday : monday
187
+
188
+ when "M"
189
+ # Wednesday = Monday + 2 days
190
+ monday.advance(:days => 2) < ref ? advance( :weeks => 1).monday.advance(:days => 2) : monday.advance(:days => 2)
191
+
192
+ when "L"
193
+ # Friday = Monday + 4 days
194
+ monday.advance(:days => 4) < ref ? advance( :weeks => 1).monday.advance(:days => 4) : monday.advance(:days => 4)
195
+
196
+ when "W"
197
+ # if saturday or sunday, fall back to last monday, then add one week for monday coming up
198
+ (wday % 6) != 0 ? self : monday.advance(:days => 7)
199
+
200
+ else
201
+ self
202
+ end #case
203
+
204
+ when "M"
205
+ # month
206
+ case pos
207
+ when "F"
208
+ # 1st
209
+ change(:day => 1) < ref ? advance( :months => 1).beginning_of_month.change(:day => 1) : change(:day => 1)
210
+
211
+ when "M"
212
+ # 15th
213
+ change(:day => 15) < ref ? advance( :months => 1).beginning_of_month.change(:day => 15) : change(:day => 15)
214
+
215
+ when "L"
216
+ # last day
217
+ end_of_month
218
+
219
+ when "W"
220
+ # if saturday or sunday, fall back to last monday, then add one week for monday coming up
221
+ (wday % 6) != 0 ? self : monday.advance(:days => 7)
222
+ else
223
+ self
224
+ end #case
225
+
226
+ when "Y"
227
+ # year
228
+ case pos
229
+ when "F"
230
+ # Jan. 1st
231
+ beginning_of_year < ref ? advanve(:years => 1).beginning_of_year : beginning_of_year
232
+
233
+ when "M"
234
+ # Jun. 30th
235
+ change(:month => 5, :day => 30) < ref ? advance(:years => 1).change(:month => 5, :day => 30) : change(:month => 5, :day => 30)
236
+
237
+ when "L"
238
+ # Dec. 31st
239
+ change(:month => 12, :day => 31)
240
+
241
+ when "W"
242
+ # if saturday or sunday, fall back to last monday, then add one week for monday coming up
243
+ (wday % 6) != 0 ? self : monday.advance(:days => 7)
244
+ else
245
+ self
246
+ end #case
247
+
248
+ when "q"
249
+ case pos
250
+ when "F"
251
+ # Jan. 1st
252
+ beginning_of_quarter < ref ? advance( :months => 3).beginning_of_quarter : beginning_of_quarter
253
+
254
+ when "M"
255
+ # mid quarter
256
+ beginning_of_quarter.advance(:months => 1).advance(:days => 14) < ref ? advance(:quarters => 1).beginning_of_quarter.advance(:months => 1).advance(:days => 14) : beginning_of_quarter.advance(:months => 1).advance(:days => 14)
257
+
258
+ when "L"
259
+ # end quarter
260
+ end_of_quarter
261
+
262
+ when "W"
263
+ # if saturday or sunday, fall back to last monday, then add one week for monday coming up
264
+ (wday % 6) != 0 ? self : monday.advance(:days => 7)
265
+ else
266
+ self
267
+ end #case
268
+
269
+ else
270
+ self
271
+ end #case epoch
272
+ end #def
273
+
274
+
275
+ ####################################################################################
276
+ # private
277
+ ####################################################################################
278
+ private
279
+
280
+ ####################################################################################
281
+ # parse_rule
282
+ ####################################################################################
283
+ def parse_rule(rule)
284
+
285
+ m = {}
286
+ matches = /(?<epoch>[DWMYCmq])(?<num>[0-9]+)(?<pos>[XFMLW]?)(?<kfmw>[-!W\*]*)(?<trailing_rest>.*)/.match(rule)
287
+
288
+ if matches.present?
289
+ m.merge!(Hash[ matches.names.zip( matches.captures ) ])
290
+ m.merge!('killswitch' => m['kfmw'].match(/-/).to_s.presence)
291
+ m.merge!('force' => m['kfmw'].match(/!/).to_s.presence)
292
+ m.merge!('mockswitch' => m['kfmw'].match(/\*/).to_s.presence)
293
+ m.merge!('workingday' => m['kfmw'].match(/W/).to_s.presence)
294
+ end
295
+ m.compact
296
+ end #def
297
+
298
+ ####################################################################################
299
+ # parse_rule
300
+ ####################################################################################
301
+ def unmock( rule, m=nil )
302
+ m = parse_rule( rule ) unless m
303
+ if m['mockswitch'].present?
304
+ "#{m['epoch']}#{m['num']}#{m['pos']}#{m['killswitch']}#{m['force']}#{m['trailing_rest']}"
305
+ else
306
+ nil
307
+ end
308
+ end #def
309
+
310
+ end #class
311
+
@@ -0,0 +1,110 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Ruby Gem to create a self populating Open Document Format (.odf) text file.
4
+ #
5
+ # Copyright 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
6
+ #
7
+ # This program is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License
9
+ # as published by the Free Software Foundation; either version 2
10
+ # of the License, or (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
+ #
21
+
22
+ module ODFWriter
23
+
24
+ ########################################################################################
25
+ #
26
+ # Bookmark: replace bookmarks with given name
27
+ #
28
+ ########################################################################################
29
+ class Bookmark < Field
30
+
31
+ ######################################################################################
32
+ #
33
+ # replace!
34
+ #
35
+ ######################################################################################
36
+ def replace!(doc, item = nil)
37
+
38
+ nodes = find_bookmark_nodes(doc)
39
+ return if nodes.blank?
40
+
41
+ text = value(item)
42
+ text = text.encode(universal_newline: true)
43
+
44
+ text_node_array = text.split(/\n/).map{|a| Nokogiri::XML::Text.new(a, doc) }
45
+ unless text_node_array.length == 1
46
+ text_node_array = text_node_array.inject([]) do |collector, node|
47
+ collector << Nokogiri::XML::Node.new("line-break", doc) unless collector.empty?
48
+ collector << node
49
+ end
50
+ end
51
+
52
+ nodes.each do |node|
53
+
54
+ case node.name
55
+
56
+ when "bookmark"
57
+ text_node_array.each {|tn| node.before(tn)}
58
+
59
+ #
60
+ # find bookmark
61
+ #
62
+ bm = "text:bookmark[@text:name='#{@name}']"
63
+ bmn = doc.xpath(".//.//*[self::#{bm}]")
64
+ #
65
+ # delete bookmark
66
+ #
67
+ bmn.each {|b| b.remove }
68
+
69
+ when "bookmark-start"
70
+ text_node_array.each {|tn| node.before(tn)}
71
+
72
+ #
73
+ # find bookmark-start
74
+ #
75
+ bms = "text:bookmark-start[@text:name='#{@name}']"
76
+ bmsn = doc.xpath(".//.//*[self::#{bms}]")
77
+ #
78
+ # find bookmark text
79
+ #
80
+ bme = "text:bookmark-end[@text:name='#{@name}']"
81
+ bmen = doc.xpath(".//.//*[self::#{bme}]")
82
+ #
83
+ # find bookmark-end
84
+ #
85
+ bmn = doc.xpath(".//text()[preceding-sibling::#{bms} and following-sibling::#{bme}]")
86
+ #
87
+ # delete bookmark -start, text and -end
88
+ #
89
+ bmn.each {|b| b.remove }
90
+ bmsn.each {|b| b.remove }
91
+ bmen.each {|b| b.remove }
92
+
93
+ end #case
94
+ end #each
95
+
96
+ end #def
97
+
98
+ ######################################################################################
99
+ #
100
+ # private
101
+ #
102
+ ######################################################################################
103
+ private
104
+
105
+ def find_bookmark_nodes(doc)
106
+ doc.xpath(".//*[self::text:bookmark[@text:name='#{@name}'] or self::text:bookmark-start[@text:name='#{@name}']]")
107
+ end #def
108
+
109
+ end #class
110
+ end #module