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
@@ -0,0 +1,135 @@
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
+ # Table: poulate and grow tables
27
+ #
28
+ ########################################################################################
29
+ class Table
30
+
31
+ include Nested
32
+
33
+ attr_accessor :name, :collection, :proc
34
+
35
+ ######################################################################################
36
+ #
37
+ # initialize
38
+ #
39
+ ######################################################################################
40
+ def initialize(options)
41
+ @name = options[:name]
42
+ @field = options[:field]
43
+ @collection = options[:collection]
44
+ @proc = options[:proc]
45
+ @key = @field || @name
46
+
47
+ @fields = []
48
+ @texts = []
49
+ @tables = []
50
+ @images = []
51
+ @bookmarks = []
52
+
53
+ @template_rows = []
54
+ @header = options[:header] || false
55
+ @skip_if_empty = options[:skip_if_empty] || false
56
+
57
+ end #def
58
+
59
+ ######################################################################################
60
+ #
61
+ # replace!
62
+ #
63
+ ######################################################################################
64
+ def replace!(doc, manifest, file, row = nil)
65
+
66
+ return unless table = find_table_node(doc)
67
+
68
+ @template_rows = table.xpath("table:table-row")
69
+
70
+ @header = table.xpath("table:table-header-rows").empty? ? @header : false
71
+
72
+ @collection = items(row, @key, @proc) if row
73
+
74
+ if @skip_if_empty && @collection.empty?
75
+ table.remove
76
+ return
77
+ end
78
+
79
+ @collection.each do |item|
80
+
81
+ new_node = get_next_row
82
+ #
83
+ # experimental: new node must be added to doc prior to replace!
84
+ # else new_section does not have a name space
85
+ #
86
+ table.add_child(new_node)
87
+
88
+ @tables.each { |t| t.replace!(new_node, manifest, file, item) }
89
+ @texts.each { |t| t.replace!(new_node, item) }
90
+ @fields.each { |f| f.replace!(new_node, item) }
91
+ @images.each { |f| f.replace!(new_node, manifest, file, item) }
92
+
93
+ end
94
+ Image.unique_image_names( doc) if @images.present?
95
+
96
+ @template_rows.each_with_index do |r, i|
97
+ r.remove if (get_start_node..template_length) === i
98
+ end
99
+
100
+ end #def
101
+
102
+ ######################################################################################
103
+ #
104
+ # private
105
+ #
106
+ ######################################################################################
107
+ private
108
+
109
+ def get_next_row
110
+ @row_cursor = get_start_node unless defined?(@row_cursor)
111
+
112
+ ret = @template_rows[@row_cursor]
113
+ if @template_rows.size == @row_cursor + 1
114
+ @row_cursor = get_start_node
115
+ else
116
+ @row_cursor += 1
117
+ end
118
+ return ret.dup
119
+ end #def
120
+
121
+ def get_start_node
122
+ @header ? 1 : 0
123
+ end #def
124
+
125
+ def template_length
126
+ @tl ||= @template_rows.size
127
+ end #def
128
+
129
+ def find_table_node(doc)
130
+ tables = doc.xpath(".//table:table[@table:name='#{@name}']")
131
+ tables.empty? ? nil : tables.first
132
+ end #def
133
+
134
+ end #class
135
+ end #module
@@ -0,0 +1,61 @@
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
+ # TableReader: find all tables and set name
27
+ #
28
+ ########################################################################################
29
+ class TableReader
30
+
31
+ attr_accessor :name
32
+
33
+ ######################################################################################
34
+ #
35
+ # initialize
36
+ #
37
+ ######################################################################################
38
+ def initialize(opts)
39
+ @name = opts[:name]
40
+ end #def
41
+
42
+ ######################################################################################
43
+ #
44
+ # tables
45
+ #
46
+ ######################################################################################
47
+ def tables( doc )
48
+ nodes( doc ).keys
49
+ end #def
50
+
51
+ ######################################################################################
52
+ #
53
+ # nodes
54
+ #
55
+ ######################################################################################
56
+ def nodes( doc )
57
+ doc.xpath(".//table:table").map{|node| [node.attr("table:name"), node] }.to_h
58
+ end #def
59
+ end #class
60
+
61
+ end #module
@@ -0,0 +1,222 @@
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
+ # Template: handles files in .odt-package
27
+ #
28
+ ########################################################################################
29
+ class Template
30
+
31
+ ######################################################################################
32
+ #
33
+ # constants - we only work and content and styles (contains headers and footers) parts of odf
34
+ #
35
+ ######################################################################################
36
+ CONTENT_ENTRIES = {
37
+ "content.xml" => {:symbol => :content, :path => "content.xml"},
38
+ "styles.xml" => {:symbol => :styles, :path => "styles.xml" }
39
+ }.freeze
40
+
41
+ CONTENT_FILES = {
42
+ :content => {:file => "content.xml", :path => "content.xml"},
43
+ :styles => {:file => "styles.xml", :path => "styles.xml" }
44
+ }.freeze
45
+
46
+ MANIFEST = 'META-INF/manifest.xml'.freeze
47
+
48
+ ######################################################################################
49
+ #
50
+ # accessors
51
+ #
52
+ ######################################################################################
53
+ attr_accessor :output_stream
54
+
55
+ ######################################################################################
56
+ #
57
+ # initialize
58
+ #
59
+ ######################################################################################
60
+ def initialize(path = nil, zip_stream: nil)
61
+
62
+ raise "You must provide either a filename or a zip_stream: string" unless path || zip_stream
63
+ raise "Template [#{template}] not found." if path && !::File.exist?(path)
64
+
65
+ @path = path
66
+ @zip_stream = zip_stream
67
+ end #def
68
+
69
+ ######################################################################################
70
+ #
71
+ # content
72
+ #
73
+ ######################################################################################
74
+ def content(&block)
75
+
76
+ entries.each do |entry|
77
+
78
+ if entry.directory?
79
+ next
80
+
81
+ elsif CONTENT_ENTRIES.keys.include?(entry.name)
82
+ # relevant file with valid file name
83
+ entry.get_input_stream do |input_stream|
84
+ file_content = input_stream.sysread
85
+ yield CONTENT_ENTRIES[entry.name][:symbol], to_xml(file_content)
86
+ end
87
+
88
+ end #if
89
+ end #each
90
+ end #def
91
+
92
+ ######################################################################################
93
+ #
94
+ # update_content: create write buffer for zip
95
+ #
96
+ ######################################################################################
97
+ def update_content
98
+ @buffer = Zip::OutputStream.write_buffer do |out|
99
+ @output_stream = out
100
+ yield self
101
+ end
102
+ end
103
+
104
+ ######################################################################################
105
+ #
106
+ # update_files: open and traverse zip directory, pick content.xml
107
+ # and styles.xml process and eventually write contents
108
+ # to buffer
109
+ # a pointer to manifest.xml is provided
110
+ #
111
+ ######################################################################################
112
+ def update_files(&block)
113
+
114
+ # get manifest, in case a file is added
115
+ @manifest = manifest; digest = Digest::MD5.hexdigest(@manifest)
116
+
117
+ entries.each do |entry|
118
+
119
+ # search content files
120
+ if entry.directory?
121
+ next
122
+
123
+ # process content files
124
+ elsif CONTENT_ENTRIES.keys.include?(entry.name)
125
+
126
+ entry.get_input_stream do |input_stream|
127
+ file_content = input_stream.sysread
128
+ file_symbol = CONTENT_ENTRIES[entry.name][:symbol]
129
+ process_entry(file_symbol, file_content, @manifest, &block)
130
+ @output_stream.put_next_entry(entry.name)
131
+ @output_stream.write file_content
132
+ end #do
133
+
134
+ else
135
+ entry.get_input_stream do |input_stream|
136
+ @output_stream.put_next_entry(entry.name)
137
+ @output_stream.write input_stream.sysread
138
+ end
139
+ end #if
140
+ end #each
141
+
142
+ # eventually write back content file
143
+ if @manifest && digest != Digest::MD5.hexdigest(@manifest)
144
+ @output_stream.put_next_entry(MANIFEST)
145
+ @output_stream.write @manifest
146
+ end #if
147
+
148
+ end #def
149
+
150
+
151
+ ######################################################################################
152
+ #
153
+ # data: just a handle to data in buffer
154
+ #
155
+ ######################################################################################
156
+ def data
157
+ @buffer.string
158
+ end
159
+
160
+ ######################################################################################
161
+ #
162
+ # private
163
+ #
164
+ ######################################################################################
165
+ private
166
+
167
+ ######################################################################################
168
+ # entries: just open zip file or buffer
169
+ ######################################################################################
170
+ def entries
171
+ if @path
172
+ Zip::File.open(@path)
173
+ elsif @zip_stream
174
+ Zip::File.open_buffer(@zip_stream.force_encoding("ASCII-8BIT"))
175
+ end
176
+ end #def
177
+
178
+ ######################################################################################
179
+ # manifest: read manifest
180
+ ######################################################################################
181
+ def manifest
182
+ manifest = nil
183
+ entries.each do |entry|
184
+ next if entry.directory?
185
+ entry.get_input_stream do |input_stream|
186
+ if MANIFEST == entry.name
187
+ manifest = input_stream.sysread.dup
188
+ end
189
+ end
190
+ end
191
+ manifest
192
+ end #def
193
+
194
+ ######################################################################################
195
+ # to_xml
196
+ ######################################################################################
197
+ def to_xml(raw_xml)
198
+ Nokogiri::XML(raw_xml)
199
+ end #def
200
+
201
+ ######################################################################################
202
+ # process_entry: provide Nokogiri Object to caller, after having provided a file
203
+ ######################################################################################
204
+ def process_entry(file_symbol, file_content, manifest)
205
+
206
+ # create xml from file content
207
+ doc = to_xml(file_content ) # { |x| x.noblanks }
208
+ man = to_xml(manifest ) # { |x| x.noblanks }
209
+
210
+ # yield xml
211
+ yield file_symbol, doc, man
212
+
213
+ # replace file_content and manifest in place
214
+ # remove spurious whitespaces between tags "> <" becomes "><"
215
+ file_content.replace(doc.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML).squish.gsub(/(?<=>)\s+(?=<)/, ""))
216
+ # Microsoft Words complains if no trailing newline is present
217
+ manifest.replace(man.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML))
218
+
219
+ end #def
220
+
221
+ end #class
222
+ end #module
@@ -0,0 +1,97 @@
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
+ # Text: replace text items
27
+ #
28
+ ########################################################################################
29
+ class Text < Field
30
+
31
+ ######################################################################################
32
+ #
33
+ # constants
34
+ #
35
+ ######################################################################################
36
+ DELIMITERS = %w({ })
37
+
38
+ ######################################################################################
39
+ #
40
+ # replace!
41
+ #
42
+ ######################################################################################
43
+ def replace!(content, item = nil)
44
+
45
+ return unless node = find_text_node(content)
46
+
47
+ text = value(item)
48
+
49
+ @parser = Parser::Default.new(text, node,
50
+ :doc => content,
51
+ :remove_classes => @remove_classes,
52
+ :remove_class_prefix => @remove_class_prefix,
53
+ :remove_class_suffix => @remove_class_suffix
54
+ )
55
+
56
+ @parser.paragraphs.each do |p|
57
+ node.before(p)
58
+ end
59
+
60
+ node.remove
61
+
62
+ end #def
63
+
64
+ ######################################################################################
65
+ #
66
+ # private
67
+ #
68
+ ######################################################################################
69
+ private
70
+
71
+ ######################################################################################
72
+ # find_text_node
73
+ ######################################################################################
74
+ def find_text_node(doc)
75
+ texts = doc.xpath(".//text:p[text()='#{placeholder}']")
76
+ if texts.empty?
77
+ texts = doc.xpath(".//text:p/text:span[text()='#{placeholder}']")
78
+ if texts.empty?
79
+ texts = nil
80
+ else
81
+ texts = texts.first.parent
82
+ end
83
+ else
84
+ texts = texts.first
85
+ end
86
+
87
+ texts
88
+ end #def
89
+
90
+ ######################################################################################
91
+ # placeholder
92
+ ######################################################################################
93
+ def placeholder
94
+ "#{DELIMITERS[0]}#{@name.to_s.upcase}#{DELIMITERS[1]}"
95
+ end #def
96
+ end #class
97
+ end #module