drg_cms 0.6.0.6 → 0.6.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -10
  3. data/app/assets/javascripts/drg_cms/drg_cms.js +281 -106
  4. data/app/assets/stylesheets/drg_cms/drg_cms.css +417 -152
  5. data/app/assets/stylesheets/drg_cms/select-multiple.css +9 -12
  6. data/app/assets/stylesheets/drg_cms_cms.css +1 -1
  7. data/app/controllers/cmsedit_controller.rb +247 -175
  8. data/app/controllers/dc_application_controller.rb +251 -173
  9. data/app/controllers/dc_common_controller.rb +81 -48
  10. data/app/controls/dc_help_control.rb +126 -0
  11. data/app/controls/dc_report.rb +223 -0
  12. data/app/forms/all_options.yml +38 -10
  13. data/app/forms/cms_menu.yml +7 -1
  14. data/app/forms/dc_big_table.yml +1 -0
  15. data/app/forms/dc_big_table_value.yml +1 -0
  16. data/app/forms/dc_category.yml +2 -1
  17. data/app/forms/dc_design.yml +1 -0
  18. data/app/forms/dc_help_1.yml +109 -0
  19. data/app/forms/dc_journal.yml +3 -1
  20. data/app/forms/dc_link.yml +1 -1
  21. data/app/forms/dc_menu.yml +2 -0
  22. data/app/forms/dc_menu_item.yml +1 -0
  23. data/app/forms/dc_page.yml +6 -0
  24. data/app/forms/dc_part.yml +1 -0
  25. data/app/forms/dc_piece.yml +1 -0
  26. data/app/forms/dc_poll.yml +15 -5
  27. data/app/forms/dc_poll_item.yml +2 -1
  28. data/app/forms/dc_poll_result.yml +9 -0
  29. data/app/forms/dc_simple_menu.yml +2 -0
  30. data/app/forms/dc_site.yml +4 -12
  31. data/app/forms/dc_user.yml +27 -11
  32. data/app/forms/dc_user_role.yml +3 -0
  33. data/app/helpers/cms_common_helper.rb +375 -0
  34. data/app/helpers/{cmsedit_edit_helper.rb → cms_edit_helper.rb} +109 -65
  35. data/app/helpers/{cmsedit_helper.rb → cms_helper.rb} +93 -48
  36. data/app/helpers/{cmsedit_index_helper.rb → cms_index_helper.rb} +240 -206
  37. data/app/helpers/dc_application_helper.rb +108 -327
  38. data/app/models/concerns/dc_page_concern.rb +14 -4
  39. data/app/models/concerns/dc_piece_concern.rb +1 -1
  40. data/app/models/concerns/dc_policy_rule_concern.rb +20 -8
  41. data/app/models/concerns/dc_site_concern.rb +67 -44
  42. data/app/models/concerns/dc_user_concern.rb +58 -19
  43. data/app/models/dc_design.rb +29 -19
  44. data/app/models/dc_filter.rb +26 -18
  45. data/app/models/dc_key_value_store.rb +1 -0
  46. data/app/models/dc_permission.rb +49 -9
  47. data/app/models/dc_policy.rb +25 -14
  48. data/app/models/dc_policy_role.rb +22 -11
  49. data/app/models/dc_poll.rb +1 -0
  50. data/app/models/dc_poll_result.rb +4 -2
  51. data/app/models/dc_temp.rb +6 -3
  52. data/app/models/dc_user_role.rb +2 -2
  53. data/app/models/drgcms_form_fields/date_picker.rb +6 -3
  54. data/app/models/drgcms_form_fields/datetime_picker.rb +4 -3
  55. data/app/models/drgcms_form_fields/drgcms_field.rb +20 -5
  56. data/app/models/drgcms_form_fields/embedded.rb +23 -16
  57. data/app/models/drgcms_form_fields/file_field.rb +2 -2
  58. data/app/models/drgcms_form_fields/file_select.rb +2 -2
  59. data/app/models/drgcms_form_fields/hash_field.rb +11 -7
  60. data/app/models/drgcms_form_fields/hidden_field.rb +1 -1
  61. data/app/models/drgcms_form_fields/link_to.rb +2 -2
  62. data/app/models/drgcms_form_fields/method.rb +66 -0
  63. data/app/models/drgcms_form_fields/multitext_autocomplete.rb +18 -12
  64. data/app/models/drgcms_form_fields/number_field.rb +4 -3
  65. data/app/models/drgcms_form_fields/radio.rb +10 -5
  66. data/app/models/drgcms_form_fields/readonly.rb +13 -17
  67. data/app/models/drgcms_form_fields/select.rb +58 -41
  68. data/app/models/drgcms_form_fields/text_autocomplete.rb +41 -33
  69. data/app/models/drgcms_form_fields.rb +12 -1
  70. data/app/renderers/dc_big_menu_renderer.rb +1 -0
  71. data/app/renderers/dc_gallery_renderer.rb +1 -0
  72. data/app/renderers/dc_menu_renderer.rb +1 -0
  73. data/app/renderers/dc_page_renderer.rb +8 -6
  74. data/app/renderers/dc_part_renderer.rb +1 -0
  75. data/app/renderers/dc_piece_renderer.rb +1 -1
  76. data/app/renderers/dc_poll_renderer.rb +56 -55
  77. data/app/renderers/dc_renderer.rb +1 -0
  78. data/app/renderers/dc_simple_menu_renderer.rb +1 -0
  79. data/app/views/cmsedit/_edit_stuff.html.erb +5 -2
  80. data/app/views/cmsedit/edit.html.erb +4 -1
  81. data/app/views/cmsedit/index.html.erb +3 -2
  82. data/app/views/cmsedit/new.html.erb +5 -2
  83. data/app/views/dc_common/_help.html.erb +17 -0
  84. data/app/views/layouts/models.html.erb +2 -1
  85. data/config/locales/drgcms_en.yml +17 -2
  86. data/config/locales/drgcms_sl.yml +22 -4
  87. data/config/locales/models_en.yml +16 -7
  88. data/config/locales/models_sl.yml +21 -12
  89. data/drg_cms.gemspec +16 -16
  90. data/lib/drg_cms/version.rb +1 -1
  91. data/lib/drg_cms.rb +98 -0
  92. data/lib/generators/new_drg_form/new_drg_form_generator.rb +5 -3
  93. data/lib/tasks/database.rake +6 -56
  94. metadata +39 -35
  95. data/app/helpers/application_helper.rb +0 -2
  96. data/app/models/__dc_dummy.rb +0 -102
@@ -1,6 +1,5 @@
1
- #coding: utf-8
2
1
  #--
3
- # Copyright (c) 2012-2013 Damjan Rems
2
+ # Copyright (c) 2012+ Damjan Rems
4
3
  #
5
4
  # Permission is hereby granted, free of charge, to any person obtaining
6
5
  # a copy of this software and associated documentation files (the
@@ -46,28 +45,29 @@ layout false
46
45
  ########################################################################
47
46
  def autocomplete
48
47
  # table parameter must be defined. If not, get it from search parameter
49
- if params['table'].nil? and params['search'].match(/\./)
48
+ if params['table'].nil? && params['search'].match(/\./)
50
49
  name = params['search'].split('.').first
51
50
  params['table'] = name.underscore
52
51
  end
53
-
54
52
  return render plain: t('drgcms.not_authorized') unless dc_user_can(DcPermission::CAN_VIEW)
55
- # TODO Double check if previous line works as it should.
53
+
56
54
  table = params['table'].classify.constantize
57
- id = [params['id']] || '_id'
58
- # call method in class if search parameter has . This is for user defined searches
59
- # result must be returned as array of [id, search_field_value]
55
+ input = params['input'].gsub(/\(|\)|\[|\]|\{|\|\.|\,}/, '')
56
+ # call method in class if search parameter contains . This is for user defined searches
60
57
  a = if params['search'].match(/\./)
61
- name, method = params['search'].split('.')
62
- table.send(method, params['input']).inject([]) do |r,v|
63
- r << { label: v[0], value: v[0], id: (v[1] || v[0]).to_s }
64
- end
65
- # simply search which will search and return field_name defined in params['search']
66
- else
67
- table.where(params['search'] => /#{params['input']}/i).limit(20).inject([]) do |r,v|
68
- r << { label: v[params['search']], value: v[params['search']], id: v.id.to_s }
69
- end
70
- end
58
+ #method, additional_params = params['search'].split('.')
59
+ #data = additional_params ? table.send(method, input, additional_params, self) : table.send(method, input)
60
+ name, method = params['search'].split('.')
61
+ data = table.send(method, input)
62
+ data.map do |v|
63
+ { label: v[0], value: v[0], id: (v[1] || v[0]).to_s }
64
+ end
65
+ # will search and return field_name defined in params['search']
66
+ else
67
+ table.where(params['search'] => /#{input}/i).limit(20).map do |v|
68
+ { label: v[params['search']], value: v[params['search']], id: v.id.to_s }
69
+ end
70
+ end
71
71
 
72
72
  render plain: a.to_json
73
73
  end
@@ -93,18 +93,19 @@ end
93
93
  ##########################################################################
94
94
  def toggle_edit_mode
95
95
  session[:edit_mode] ||= 0
96
- # error when not logged in
97
- return dc_render_404 if session[:edit_mode] < 1
98
- # if return_to_ypos parameter is present it will forward it and thus scroll to
99
- # aproximate position it was when toggle was clicked
96
+ # error when not logged in
97
+ return dc_render_404 if session[:edit_mode] < 1
98
+
99
+ # if return_to_ypos parameter is present it will forward it and thus scroll to
100
+ # aproximate position it was when toggle was clicked
100
101
  session[:edit_mode] = (session[:edit_mode] == 1) ? 2 : 1
101
102
  uri = Rack::Utils.parse_nested_query(request.url)
102
- # it parses only on & so first (return_to) parameter also contains url
103
+ # it parses only on & so first (return_to) parameter also contains url
103
104
  url = uri.first.last
104
105
  if (i = url.index('return_to_ypos')).to_i > 0
105
- url = url[0,i-1]
106
+ url = url[0, i-1]
106
107
  end
107
- # offset CMS menu
108
+ # offset CMS menu
108
109
  if (ypos = uri['return_to_ypos'].to_i) > 0
109
110
  ypos += session[:edit_mode] == 2 ? 250 : -250
110
111
  end
@@ -117,14 +118,16 @@ end
117
118
  # Default user login action.
118
119
  ####################################################################
119
120
  def process_login
120
- # Somebody is probably playing
121
- return dc_render_404 unless ( params[:record] and params[:record][:username] and params[:record][:password] )
121
+ # Somebody is probably playing
122
+ return dc_render_404 unless ( params[:record] && params[:record][:username] && params[:record][:password] )
122
123
 
123
124
  unless params[:record][:password].blank? #password must not be empty
124
125
  user = DcUser.find_by(username: params[:record][:username], active: true)
125
126
  if user and user.authenticate(params[:record][:password])
126
127
  fill_login_data(user, params[:record][:remember_me].to_i == 1)
127
128
  return redirect_to params[:return_to] || '/'
129
+ else
130
+ clear_login_data # on the safe side
128
131
  end
129
132
  end
130
133
  flash[:error] = t('drgcms.invalid_username')
@@ -149,12 +152,11 @@ def login
149
152
  if user and user.active
150
153
  fill_login_data(user, true)
151
154
  return redirect_to params[:return_to]
152
-
153
155
  else
154
156
  clear_login_data # on the safe side
155
157
  end
156
158
  end
157
- # Display login
159
+ # Display login
158
160
  route = params[:route] || 'poll'
159
161
  redirect_to "/#{route}?poll_id=login&return_to=#{params[:return_to]}"
160
162
  end
@@ -163,23 +165,23 @@ end
163
165
  # Action for restoring document data from journal document.
164
166
  ####################################################################
165
167
  def restore_from_journal
166
- # Only administrators can perform this operation
168
+ # Only administrators can perform this operation
167
169
  unless dc_user_has_role('admin')
168
170
  return render plain: { 'msg_info' => (t ('drgcms.not_authorized')) }.to_json
169
171
  end
170
- # selected fields to hash
172
+ # selected fields to hash
171
173
  restore = {}
172
- params[:select].each {|key,value| restore[key] = value if value == '1' }
174
+ params[:select].each { |key,value| restore[key] = value if value == '1' }
173
175
  result = if restore.size == 0
174
176
  { 'msg_error' => (t ('drgcms.dc_journal.zero_selected')) }
175
177
  else
176
178
  journal_doc = DcJournal.find(params[:id])
177
- # update hash with data to be restored
179
+ # update hash with data to be restored
178
180
  JSON.parse(journal_doc.diff).each {|k,v| restore[k] = v.first if restore[k] }
179
- # determine tables and document ids
181
+ # determine tables and document ids
180
182
  tables = journal_doc.tables.split(';')
181
183
  ids = (journal_doc.ids.blank? ? [] : journal_doc.ids.split(';') ) << journal_doc.doc_id
182
- # find document
184
+ # find document
183
185
  doc = nil
184
186
  tables.each_index do |i|
185
187
  doc = if doc.nil?
@@ -188,10 +190,10 @@ def restore_from_journal
188
190
  doc.send(tables[i].pluralize).find(ids[i])
189
191
  end
190
192
  end
191
- # restore and save values
193
+ # restore and save values
192
194
  restore.each { |field,value| doc.send("#{field}=",value) }
193
195
  doc.save
194
- # TODO Error checking
196
+ # TODO Error checking
195
197
  { 'msg_info' => (t ('drgcms.dc_journal.restored')) }
196
198
  end
197
199
  render plain: result.to_json
@@ -202,10 +204,11 @@ end
202
204
  # window with data formatted as json.
203
205
  ########################################################################
204
206
  def copy_clipboard
205
- # Only administrators can perform this operation
207
+ # Only administrators can perform this operation
206
208
  return render(plain: t('drgcms.not_authorized') ) unless dc_user_can(DcPermission::CAN_ADMIN,'dc_site')
209
+
207
210
  respond_to do |format|
208
- # just open new window to same url and come back with html request
211
+ # just open new window to same url and come back with html request
209
212
  format.json { dc_render_ajax(operation: 'window', url: request.url ) }
210
213
 
211
214
  format.html do
@@ -213,7 +216,6 @@ def copy_clipboard
213
216
  text = "<br><br>[#{params[:table]},#{params[:id]},#{params[:ids]}]<br>"
214
217
  render plain: text + doc.as_document.to_json
215
218
  end
216
-
217
219
  end
218
220
  end
219
221
 
@@ -223,17 +225,19 @@ end
223
225
  # ajax call for processing data.
224
226
  ########################################################################
225
227
  def paste_clipboard
226
- # Only administrators can perform this operation
228
+ # Only administrators can perform this operation
227
229
  return render(plain: t('drgcms.not_authorized') ) unless dc_user_can(DcPermission::CAN_ADMIN,'dc_site')
230
+
228
231
  result = ''
229
232
  respond_to do |format|
230
- # just open new window to same url and come back with html request
233
+ # just open new window to same url and come back with html request
231
234
  format.html { return render('paste_clipboard', layout: 'cms') }
232
235
  format.json {
233
236
  table, id, ids = nil
234
237
  params[:data].split("\n").each do |line|
235
238
  line.chomp!
236
239
  next if line.size < 5 # empty line. Skip
240
+
237
241
  begin
238
242
  if line[0] == '[' # id(s)
239
243
  result << "<br>#{line}"
@@ -260,7 +264,7 @@ def add_json_ld_schema
260
264
  edited_document = DcJsonLd.find_document_by_ids(params[:table], params[:ids])
261
265
  yaml = YAML.load_file( dc_find_form_file('json_ld_schema') )
262
266
  schema_data = yaml[params[:schema]]
263
- # Existing document
267
+ # Existing document
264
268
  if edited_document.dc_json_lds.find_by(type: "@#{params[:schema]}")
265
269
  return render json: {'msg_error' => t('helpers.help.dc_json_ld.add_error', schema: params[:schema] ) }
266
270
  else
@@ -269,8 +273,37 @@ def add_json_ld_schema
269
273
  render json: {'reload_' => 1}
270
274
  end
271
275
 
276
+ ########################################################################
277
+ # Will provide help data
278
+ ########################################################################
279
+ def help
280
+ form_name = params[:form_name] || params[:table]
281
+ @form = form_name ? YAML.load_file(dc_find_form_file(form_name)) : {}
282
+ return render json: {} if @form.nil?
283
+
284
+ help_file_name = @form['help'] || @form['extend'] || params[:form_name] || params[:table]
285
+ help_file_name = find_help_file(help_file_name)
286
+ @help = YAML.load_file(help_file_name) if help_file_name
287
+ # no auto generated help on index action
288
+ return render json: {} if params[:type] == 'index' && @help.nil?
289
+
290
+ render json: { popup: render_to_string(partial: 'help') }
291
+ end
292
+
272
293
  protected
273
294
 
295
+ ########################################################################
296
+ # Will search for help file and return it's path if found
297
+ ########################################################################
298
+ def find_help_file(help_file_name)
299
+ file_name = nil
300
+ DrgCms.paths(:forms).reverse.each do |path|
301
+ f = "#{path}/help/#{help_file_name}.#{I18n.locale}"
302
+ file_name = f and break if File.exist?(f)
303
+ end
304
+ file_name
305
+ end
306
+
274
307
  ########################################################################
275
308
  # Subroutine of add_json_ld_schema for adding one element
276
309
  ########################################################################
@@ -308,7 +341,7 @@ def update_json(json, is_update=false) #:nodoc:
308
341
  json.each do |k,v|
309
342
  if v.class == Hash
310
343
  result[k] = v['$oid'] unless is_update
311
- #TODO Double check if unless works as expected
344
+ # TODO Double check if unless works as expected
312
345
  elsif v.class == Array
313
346
  result[k] = []
314
347
  v.each {|e| result[k] << update_json(e, is_update)}
@@ -325,22 +358,22 @@ end
325
358
  def process_document(line, table, id, ids)
326
359
  if params[:do_update] == '1'
327
360
  doc = dc_find_document(table, id, ids)
328
- # document found. Update it and return
361
+ # document found. Update it and return
329
362
  if doc
330
363
  doc.update( update_json(ActiveSupport::JSON.decode(line), true) )
331
364
  msg = dc_check_model(doc)
332
365
  return (msg ? " ERROR! #{msg}" : " UPDATE. OK.")
333
366
  end
334
367
  end
335
- # document will be added to collection
368
+ # document will be added to collection
336
369
  if ids.to_s.size > 5
337
- #TODO Add embedded document
370
+ #TODO Add embedded document
338
371
  " NOT SUPPORTED YET!"
339
372
  else
340
373
  doc = table.classify.constantize.new( update_json(ActiveSupport::JSON.decode(line)) )
341
374
  doc.save
342
375
  end
343
- msg = dc_check_model(doc)
376
+ msg = DrgCms.model_check(doc)
344
377
  msg ? " ERROR! #{msg}" : " NEW. OK."
345
378
  end
346
379
 
@@ -0,0 +1,126 @@
1
+ #--
2
+ # Copyright (c) 2021+ Damjan Rems
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ ######################################################################
25
+ # Controls for creating help files
26
+ ######################################################################
27
+ module DcHelpControl
28
+
29
+ ######################################################################
30
+ # Will fill dc_temp with help documents found in a defined project directory.
31
+ ######################################################################
32
+ def project_refresh
33
+ DcTemp.clear(temp_key)
34
+ if params[:record][:select_project].present?
35
+ # far less complicated if saved to session
36
+ session[:help_project] = params[:record][:select_project]
37
+ session[:help_lang] = params[:record][:lang_1]
38
+ help_dir_name = "#{session[:help_project]}/help/"
39
+ # create help directory if not yet exists
40
+ FileUtils.mkdir(help_dir_name) unless File.exist?(help_dir_name)
41
+ Dir["#{help_dir_name}*"].each do |file_name|
42
+ lang = File.extname(file_name).sub('.','')
43
+ next unless lang == session[:help_lang]
44
+
45
+ DcTemp.new(key: temp_key,
46
+ project: session[:help_project],
47
+ form_name: File.basename(file_name,'.*'),
48
+ lang: lang,
49
+ updated_at: File.mtime(file_name)).save
50
+ end
51
+ end
52
+ render json: { url: url_for(controller: :cmsedit, table: :dc_temp, form_name: :dc_help_1) }
53
+ end
54
+
55
+ ######################################################################
56
+ # Will populate fields with default values
57
+ ######################################################################
58
+ def dc_new_record
59
+ @record.project = session[:help_project]
60
+ @record.lang = session[:help_lang]
61
+ end
62
+
63
+ ######################################################################
64
+ # Will read data from help file
65
+ ######################################################################
66
+ def dc_before_edit
67
+ file_name = "#{session[:help_project]}/help/#{@record.form_name}.#{session[:help_lang]}"
68
+ data = YAML.load_file(file_name)
69
+ @record.index = data['index']
70
+ @record.form = data['form']
71
+ flash[:warning] = "Use only in development!" unless Rails.env.development?
72
+ end
73
+
74
+ ######################################################################
75
+ # Will save data to help file
76
+ ######################################################################
77
+ def dc_before_save
78
+ rec = params[:record]
79
+ file_name = "#{session[:help_project]}/help/#{@record.form_name}.#{@record.lang}"
80
+ data = { 'index' => @record.index, 'form' => @record.form }
81
+ File.write(file_name, data.to_yaml)
82
+ end
83
+
84
+ ######################################################################
85
+ # Will return query to report data
86
+ ######################################################################
87
+ def data_filter
88
+ DcTemp.where(key: temp_key).order_by(order: 1)
89
+ end
90
+
91
+ private
92
+
93
+ ######################################################################
94
+ # Will return choices for select project input field on a form
95
+ ######################################################################
96
+ def self.choices_for_project
97
+ r = DrgCms.paths(:forms).map do |path|
98
+ path = path.to_s
99
+ a = path.split('/')
100
+ project = a[a.size - 3]
101
+ project = if project == 'app'
102
+ a[a.size - 4] + ' : ' + a.last(2).join('/')
103
+ else
104
+ project + ' : ' + a.last
105
+ end
106
+ [project, path]
107
+ end
108
+ [[I18n.t('drgcms.dc_help.project'), nil]] + r.sort
109
+ end
110
+
111
+ ######################################################################
112
+ # Will return choices for selecting help file name, based on forms already
113
+ # present in forms directory.
114
+ ######################################################################
115
+ def self.choices_for_form_name(session)
116
+ Dir["#{session[:help_project]}/*.yml"].map { |file_name| File.basename(file_name,'.*') }.sort
117
+ end
118
+
119
+ ######################################################################
120
+ # Will return temp key for data saved in dc_temp file
121
+ ######################################################################
122
+ def temp_key
123
+ "dc-help-#{session[:user_id]}"
124
+ end
125
+
126
+ end
@@ -0,0 +1,223 @@
1
+ #--
2
+ # Copyright (c) 2020+ Damjan Rems
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ ######################################################################
25
+ # Common methods required by reports
26
+ ######################################################################
27
+ module DcReport
28
+ attr_accessor :report_id
29
+ attr_accessor :bulk
30
+
31
+ ######################################################################
32
+ # Clear result if params[:clear] is 'yes' when form is first displayed
33
+ ######################################################################
34
+ def dc_new_record
35
+ DcTemp.clear(temp_key) unless params[:clear].to_s == 'no'
36
+ end
37
+
38
+ ######################################################################
39
+ # If exists, set report section as form, so it can be used to display result.
40
+ ######################################################################
41
+ def dc_update_form
42
+ return unless @form && @form['report'] && params[:table] == 'dc_temp'
43
+
44
+ @form = @form['report']
45
+ end
46
+
47
+ ######################################################################
48
+ # Print to PDF action
49
+ ######################################################################
50
+ def print
51
+ begin
52
+ pdf_do
53
+ rescue Exception => e
54
+ dc_dump_exception(e)
55
+ render json: { msg_error: t('drgcms.runtime_error') } and return
56
+ end
57
+
58
+ pdf_file = "tmp/dokument-#{Time.now.to_i}.pdf"
59
+ @pdf.render_file Rails.root.join('public', pdf_file)
60
+
61
+ render json: print_response(pdf_file)
62
+ end
63
+
64
+ ######################################################################
65
+ # Export data do excel action
66
+ ######################################################################
67
+ def export
68
+ export_to_excel( temp_key )
69
+ end
70
+
71
+ ######################################################################
72
+ # Default filter to select data for result.
73
+ ######################################################################
74
+ def data_filter
75
+ params['clear'].to_s == 'yes' ? DcTemp.where(key: false) : DcTemp.where(key: temp_key).order_by(order: 1)
76
+ end
77
+
78
+ private
79
+
80
+ ######################################################################
81
+ # Will create response message for print action. Response consists of
82
+ # opening pdf file in new browser tab and additional print_message if defined.
83
+ ######################################################################
84
+ def print_response(pdf_file)
85
+ response = { window: "/#{pdf_file}" }
86
+ response.merge!(report_message) if respond_to?(:report_message, true)
87
+ response
88
+ end
89
+
90
+ ######################################################################
91
+ # Temp key consists of report name and user's id. Key should be added
92
+ # to every dc_temp document and is used to define data, which belongs
93
+ # to current user.
94
+ ######################################################################
95
+ def temp_key
96
+ "#{@report_id}-#{session[:user_id]}"
97
+ end
98
+
99
+ ######################################################################
100
+ # Initialize report. Set report_id internal variable and initialize bulk
101
+ # for bulk saving data to dc_temp collection.
102
+ ######################################################################
103
+ def init_report(id)
104
+ @report_id = id
105
+ @bulk = []
106
+ end
107
+
108
+ ######################################################################
109
+ # Check if all send fields are blank.
110
+ ######################################################################
111
+ def all_blank?(*fields)
112
+ fields.each {|e| e.blank? ? true : (break false) }
113
+ end
114
+
115
+ ######################################################################
116
+ # Will write bulk data to dc_temp collection.
117
+ ######################################################################
118
+ def bulk_write(doc, the_end = false)
119
+ if doc.nil? || doc.class == TrueClass
120
+ the_end = true
121
+ else
122
+ @bulk << doc
123
+ end
124
+
125
+ if (the_end && @bulk.size > 0) || @bulk.size > 100
126
+ DcTemp.collection.insert_many(@bulk)
127
+ @bulk = []
128
+ end
129
+ end
130
+
131
+ ######################################################################
132
+ # Export data to Excel
133
+ ######################################################################
134
+ def export_to_excel(report_id)
135
+ read_drg_form if @form.blank?
136
+ # use report options if present
137
+ columns = (@form['report'] ? @form['report'] : @form)['result_set']['columns'].sort
138
+
139
+ n, workbook = 0, Spreadsheet::Workbook.new
140
+ excel = workbook.create_worksheet(name: report_id)
141
+ # header
142
+ columns.each_with_index do |column, i|
143
+ caption = column.last['caption'] || column.last['label']
144
+ label = t(caption)
145
+ excel[n, i] = label.match('translation missing') ? caption : label
146
+ end
147
+
148
+ data_filter.each do |doc|
149
+ n += 1
150
+ columns.each_with_index do |column, i|
151
+ value = doc[column.last['name']].to_s.gsub('<br>', ";")
152
+ value = value.gsub(/\<\/strong\>|\<strong\>|\<\/b\>|\<b\>/, '')
153
+ excel[n, i] = value
154
+ end
155
+ end
156
+ file_name = "#{report_id}-#{Time.now.to_i}.xls"
157
+ workbook.write Rails.root.join('public', 'tmp', file_name)
158
+ dc_render_ajax(operation: :window, value: "/tmp/#{file_name}")
159
+ end
160
+
161
+ ############################################################################
162
+ # Returns html code for displaying date/time formatted by strftime. Will return '' if value is nil.
163
+ #
164
+ # Parameters:
165
+ # [value] Date/DateTime/Time.
166
+ # [format] String. strftime format mask. Defaults to locale's default format.
167
+ ############################################################################
168
+ def dc_format_date_time(value, format = nil)
169
+ return '' if value.nil?
170
+
171
+ format ||= value.class == Date ? t('date.formats.default') : t('time.formats.default')
172
+ value.strftime(format)
173
+ end
174
+
175
+ ##############################################################################
176
+ # Initialize PDF document for print
177
+ ##############################################################################
178
+ def pdf_init(opts={})
179
+ opts[:margin] ||= [30,30,30,30]
180
+ opts[:page_size] ||= 'A4'
181
+
182
+ pdf = Prawn::Document.new(opts)
183
+ pdf.font_size = opts[:font_size] if opts[:font_size]
184
+
185
+ pdf.encrypt_document( owner_password: :random,
186
+ permissions: { print_document: true,
187
+ modify_contents: false,
188
+ copy_contents: false,
189
+ modify_annotations: false })
190
+ pdf.font_families.update(
191
+ 'Arial' => { normal: Rails.root.join('public', 'arial.ttf'),
192
+ bold: Rails.root.join('public', 'arialbd.ttf') }
193
+ )
194
+ pdf.font 'Arial'
195
+ pdf
196
+ end
197
+
198
+ ################################################################################
199
+ # Prints out single text (or object) on report.
200
+ #
201
+ # @param [Object] txt : Text or object. Result of to_s method of the object is
202
+ # @param [Hash] opts
203
+ ###############################################################################
204
+ def pdf_text(txt, opts = {})
205
+ box_opts = opts.dup
206
+ ypos = @pdf.cursor
207
+ xpos = opts.delete(:atx) || 0
208
+ box_opts[:single_line] ||= true
209
+ box_opts[:at] ||= [xpos, ypos]
210
+
211
+ @pdf.text_box(txt.to_s, box_opts)
212
+ end
213
+
214
+ ################################################################################
215
+ # Skip line on report
216
+ #
217
+ # @param [Integer] skip . Number of lines to skip. Default 1.
218
+ ###############################################################################
219
+ def pdf_skip(skip = 1)
220
+ @pdf.text('<br>' * skip, inline_format: true)
221
+ end
222
+
223
+ end