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,4 +1,3 @@
1
- #coding: utf-8
2
1
  #--
3
2
  # Copyright (c) 2012+ Damjan Rems
4
3
  #
@@ -89,7 +88,7 @@ def index
89
88
  @form['result_set'] ||= {}
90
89
  redirected = (@form['table'] == 'dc_memory' ? process_in_memory : process_collections)
91
90
  return if redirected
92
- #
91
+
93
92
  call_callback_method(@form['result_set']['footer'] || 'dc_footer')
94
93
  respond_to do |format|
95
94
  format.html { render action: :index }
@@ -109,9 +108,9 @@ end
109
108
  ########################################################################
110
109
  def show
111
110
  find_record
111
+ # before_show callback
112
112
  if (m = callback_method('before_show') )
113
113
  ret = call_callback_method(m)
114
- # Don't do anything if return is false
115
114
  if ret.class == FalseClass
116
115
  @form['readonly'] = nil # must be
117
116
  return index
@@ -149,20 +148,21 @@ def logout
149
148
  end
150
149
 
151
150
  ########################################################################
152
- # Logout action. Used to logout direct from CMS.
153
- #
154
- # Logout can be called directly with url http://site.com/cmsedit/logout
151
+ # Shortcut for setting currently selected site in development. Will search
152
+ # for dc_site document with site name 'test' and set alias_for to site
153
+ # url parameter.
155
154
  ########################################################################
156
155
  def set_test_site
157
156
  # only in development
158
- return dc_render_404 if !Rails.env.development?
157
+ return dc_render_404 unless Rails.env.development?
158
+
159
159
  alias_site = DcSite.find_by(:name => params[:site])
160
160
  return dc_render_404 unless alias_site
161
+
161
162
  # update alias for
162
- site = DcSite.find_by(:name => 'test')
163
+ site = DcSite.find_by(:name => 'test')
163
164
  site.alias_for = params[:site]
164
165
  site.save
165
- # redirect to root
166
166
  redirect_to '/'
167
167
  end
168
168
 
@@ -170,17 +170,17 @@ end
170
170
  # New action.
171
171
  ########################################################################
172
172
  def new
173
- # clear flash messages.
173
+ # clear flash messages.
174
174
  flash[:error] = flash[:warning] = flash[:info] = nil
175
175
  create_new_empty_record
176
+ # before_new callback
176
177
  if (m = callback_method('before_new') )
177
178
  ret = call_callback_method(m)
178
- # Don't do anything if return is false
179
179
  return index if ret.class == FalseClass
180
180
  end
181
181
  table = @tables.last[1] + '.'
182
- # initial values set on page
183
- if cookies[:record] and cookies[:record].size > 0
182
+ # initial values set on page
183
+ if cookies[:record] && cookies[:record].size > 0
184
184
  Marshal.load(cookies[:record]).each do |k,v|
185
185
  k = k.to_s
186
186
  if k.match(table)
@@ -189,15 +189,14 @@ def new
189
189
  end
190
190
  end
191
191
  end
192
- # initial values set in url
192
+ # initial values set in url (params)
193
193
  params.each do |k,v|
194
194
  if k.match(table)
195
195
  field = k.split('.').last
196
196
  @record.send("#{field}=", v) if @record.respond_to?(field)
197
197
  end
198
198
  end
199
- # This is how we set default values for new record
200
- #dc_new_record() if respond_to?('dc_new_record')
199
+ # new_record callback. Set default values for new record
201
200
  if (m = callback_method('new_record') ) then call_callback_method(m) end
202
201
  @parms['action'] = 'create'
203
202
  end
@@ -205,19 +204,21 @@ end
205
204
  ########################################################################
206
205
  # Duplicate embedded document. Since embedded documents are returned differently
207
206
  # then top level document. Subroutine of duplicate_socument.
207
+ #
208
+ #TODO Works for two embedded levels. Dies with third and more levels.
208
209
  ########################################################################
209
210
  def duplicate_embedded(source) #:nodoc:
210
- # TODO Works for two embedded levels. Dies with third and more levels.
211
211
  dest = {}
212
212
  source.each do |attribute_name, value|
213
213
  next if attribute_name == '_id' # don't duplicate _id
214
+
214
215
  if value.class == Array
215
216
  dest[attribute_name] = []
216
217
  value.each do |ar|
217
218
  dest[attribute_name] << duplicate_embedded(ar)
218
219
  end
219
- else
220
- # if duplicate string must be added. Useful for unique attributes
220
+ else
221
+ # if duplicate, string dup is added. For unique fields
221
222
  add_duplicate = params['dup_fields'].to_s.match(attribute_name + ',')
222
223
  dest[attribute_name] = value
223
224
  dest[attribute_name] << ' dup' if add_duplicate
@@ -230,20 +231,22 @@ end
230
231
 
231
232
  ########################################################################
232
233
  # Will create duplicate document of source document. This method is used for
233
- # duplicating document and is called from create action.
234
+ # duplicating document and is subroutine of create action.
234
235
  ########################################################################
235
236
  def duplicate_document(source)
236
237
  dest = {}
237
238
  source.attribute_names.each do |attribute_name|
238
239
  next if attribute_name == '_id' # don't duplicate _id
239
- # if duplicate, string must be added. Useful for unique attributes
240
+
241
+ # if duplicate, string dup is added. For unique fields
240
242
  add_duplicate = params['dup_fields'].to_s.match(attribute_name + ',')
241
243
  dest[attribute_name] = source[attribute_name]
242
244
  dest[attribute_name] << ' dup' if add_duplicate
243
245
  end
244
- # embedded documents
246
+ # embedded documents
245
247
  source.embedded_relations.keys.each do |embedded_name|
246
248
  next if source[embedded_name].nil? # it happens
249
+
247
250
  dest[embedded_name] = []
248
251
  source[embedded_name].each do |embedded|
249
252
  dest[embedded_name] << duplicate_embedded(embedded)
@@ -258,32 +261,35 @@ end
258
261
  # Create (or duplicate) action. Action is also used for turning filter on.
259
262
  ########################################################################
260
263
  def create
261
- # abusing create for turning filter on
264
+ # abusing create for turning filter on
262
265
  return index if params[:filter].to_s == 'on'
263
- # not authorized
266
+
267
+ # not authorized
264
268
  unless dc_user_can(DcPermission::CAN_CREATE)
265
269
  flash[:error] = t('drgcms.not_authorized')
266
270
  return index
267
271
  end
268
- #
269
- if params['id'].nil? # create record
270
- # Prevent double form submit
272
+
273
+ # create document
274
+ if params['id'].nil?
275
+ # Prevent double form submit
271
276
  params[:form_time_stamp] = params[:form_time_stamp].to_i
272
277
  session[:form_time_stamp] ||= 0
273
278
  return index if params[:form_time_stamp] <= session[:form_time_stamp]
279
+
274
280
  session[:form_time_stamp] = params[:form_time_stamp]
275
- #
276
281
  create_new_empty_record
277
282
  if save_data
278
283
  flash[:info] = t('drgcms.doc_saved')
279
284
  params[:return_to] = 'index' if params[:commit] == t('drgcms.save&back') # save & back
280
285
  return process_return_to(params[:return_to]) if params[:return_to]
281
286
 
282
- @parms['id'] = @record.id # must be set, for proper update link
283
- params[:id] = @record.id # must be set, for find_record
287
+ @parms['id'] = @record.id # must be set, for proper update link
288
+ params[:id] = @record.id # must be set, for find_record
284
289
  edit
285
290
  else # error
286
291
  return process_return_to(params[:return_to]) if params[:return_to]
292
+
287
293
  render action: :new
288
294
  end
289
295
  else # duplicate record
@@ -305,7 +311,7 @@ def edit
305
311
  find_record
306
312
  if (m = callback_method('before_edit') )
307
313
  ret = call_callback_method(m)
308
- # Don't do anything if return is false
314
+ # don't do anything if return is false
309
315
  return index if ret.class == FalseClass
310
316
  end
311
317
  @parms['action'] = 'update'
@@ -317,29 +323,27 @@ end
317
323
  ########################################################################
318
324
  def update
319
325
  find_record
320
- # check if record was not updated in mean time
326
+ # check if record was not updated in mean time
321
327
  if @record.respond_to?(:updated_at)
322
328
  if params[:last_updated_at].to_i != @record.updated_at.to_i
323
329
  flash[:error] = t('drgcms.updated_by_other')
324
330
  return render(action: :edit)
325
331
  end
326
332
  end
327
- #
333
+
328
334
  if dc_user_can(DcPermission::CAN_EDIT_ALL) or
329
335
  ( @record.respond_to?('created_by') and
330
336
  @record.created_by == session[:user_id] and
331
337
  dc_user_can(DcPermission::CAN_EDIT) )
332
- #
338
+
333
339
  if save_data
334
340
  params[:return_to] = 'index' if params[:commit] == t('drgcms.save&back') # save & back
335
341
  @parms['action'] = 'update'
336
- # Process return_to link
342
+ # Process return_to
337
343
  return process_return_to(params[:return_to]) if params[:return_to]
338
344
  else
339
345
  # do not forget before_edit callback
340
- if m = callback_method('before_edit')
341
- call_callback_method(m)
342
- end
346
+ if m = callback_method('before_edit') then call_callback_method(m) end
343
347
  return render action: :edit
344
348
  end
345
349
  else
@@ -353,7 +357,7 @@ end
353
357
  ########################################################################
354
358
  def destroy
355
359
  find_record
356
- # Which permission is required to delete
360
+ # check permission required to delete
357
361
  permission = if params['operation'].nil?
358
362
  if @record.respond_to?('created_by') # needs can_delete_all if created_by is present and not owner
359
363
  (@record.created_by == session[:user_id]) ? DcPermission::CAN_DELETE : DcPermission::CAN_DELETE_ALL
@@ -368,38 +372,39 @@ def destroy
368
372
  end
369
373
  end
370
374
  ok2delete = dc_user_can(permission)
371
- #
375
+
372
376
  case
373
- # not authorized
377
+ # not authorized
374
378
  when !ok2delete then
375
379
  flash[:error] = t('drgcms.not_authorized')
376
380
  return index
377
-
381
+
382
+ # delete document
378
383
  when params['operation'].nil? then
379
- # Process before delete callback
384
+ # before_delete callback
380
385
  if (m = callback_method('before_delete') )
381
386
  ret = call_callback_method(m)
382
- # Don't do anything if return is false
387
+ # don't do anything if return is false
383
388
  return index if ret.class == FalseClass
384
389
  end
385
- # document deleted
390
+
386
391
  if @record.destroy
387
392
  save_journal(:delete)
388
393
  flash[:info] = t('drgcms.record_deleted')
389
- # Process after delete callback
394
+ # after_delete callback
390
395
  if (m = callback_method('after_delete') )
391
396
  call_callback_method(m)
392
397
  elsif params['after-delete'].to_s.match('return_to')
393
398
  params[:return_to] = params['after-delete']
394
399
  end
395
- # Process return_to link
400
+ # Process return_to link
396
401
  return process_return_to(params[:return_to]) if params[:return_to]
397
402
  else
398
403
  flash[:error] = dc_error_messages_for(@record)
399
404
  end
400
405
  return index
401
406
 
402
- # deaktivate document
407
+ # deactivate document
403
408
  when params['operation'] == 'disable' then
404
409
  if @record.respond_to?('active')
405
410
  @record.active = false
@@ -409,7 +414,7 @@ def destroy
409
414
  flash[:info] = t('drgcms.doc_disabled')
410
415
  end
411
416
 
412
- # reaktivate document
417
+ # reactivate document
413
418
  when params['operation'] == 'enable' then
414
419
  if @record.respond_to?('active')
415
420
  @record.active = true
@@ -419,11 +424,11 @@ def destroy
419
424
  flash[:info] = t('drgcms.doc_enabled')
420
425
  end
421
426
 
422
- # reorder documents
427
+ #TODO reorder documents
423
428
  when params['operation'] == 'reorder' then
424
429
 
425
430
  end
426
- #
431
+
427
432
  @parms['action'] = 'update'
428
433
  render action: :edit
429
434
  end
@@ -432,35 +437,77 @@ end
432
437
  # Run action
433
438
  ########################################################################
434
439
  def run
440
+ # determine control file name and method
435
441
  control_name, method_name = params[:control].split('.')
436
442
  if method_name.nil?
437
443
  method_name = control_name
438
444
  control_name = params[:table]
439
445
  end
446
+ # extend with control methods
440
447
  extend_with_control_module(control_name)
441
448
  if respond_to?(method_name)
449
+ # can it be called
450
+ return return_run_error t('drgcms.not_authorized') unless can_process_run
451
+ # call method
442
452
  respond_to do |format|
443
453
  format.json { send method_name }
444
454
  format.html { send method_name }
445
455
  end
446
- else
447
- # Error message
448
- text = "Method #{method_name} not defined in #{control_name}_control"
449
- respond_to do |format|
450
- format.json { render json: {msg_error: text} }
451
- format.html { render plain: text }
452
- end
456
+ else # Error message
457
+ return_run_error "Method #{method_name} not defined in #{control_name}_control"
453
458
  end
454
-
455
459
  end
456
460
 
457
461
  protected
458
462
 
459
463
  ########################################################################
460
- # Merges two forms when current form extends other form. Subroutine of read_drg_cms_form.
464
+ # Respond with error on run action
465
+ ########################################################################
466
+ def return_run_error(text)
467
+ respond_to do |format|
468
+ format.json { render json: { msg_error: text } }
469
+ format.html { render plain: text }
470
+ end
471
+ end
472
+
473
+ ########################################################################
474
+ # Can run call be processed
475
+ ########################################################################
476
+ def can_process_run
477
+ if respond_to?(:dc_can_process)
478
+ response = send(:dc_can_process)
479
+ return response unless response.class == Array
480
+ else
481
+ response = [DcPermission::CAN_VIEW, params[:table] || 'dc_memory']
482
+ end
483
+ dc_user_can *response
484
+ end
485
+
486
+ ########################################################################
487
+ # Checks if user has permissions to perform operation on table and if not
488
+ # prepares response for not authorized message.
489
+ #
490
+ # @param [Integer] permission : Permission level defined in DcPermission constants eg. DcPermission::CAN_EDIT
491
+ # @param [String] collection_name : Table name on which user must have permission
492
+ #
493
+ # @return [Boolean] true when user has required permission otherwise false
494
+ ########################################################################
495
+ def user_has_permission?(permission, collection_name)
496
+ unless dc_user_can(permission, collection_name.to_s)
497
+ respond_to do |format|
498
+ format.json { render json: {msg_error: t('drgcms.not_authorized') } }
499
+ format.html { render plain: t('drgcms.not_authorized') }
500
+ end
501
+ return false
502
+ end
503
+ true
504
+ end
505
+
506
+ ########################################################################
507
+ # Merges two forms when current form extends other form. Subroutine of read_drg_form.
461
508
  # With a little help of https://www.ruby-forum.com/topic/142809
462
509
  ########################################################################
463
- def forms_merge(hash1, hash2)
510
+ def forms_merge(hash1, hash2)
464
511
  target = hash1.dup
465
512
  hash2.keys.each do |key|
466
513
  if hash2[key].is_a? Hash and hash1[key].is_a? Hash
@@ -469,8 +516,8 @@ def forms_merge(hash1, hash2)
469
516
  end
470
517
  target[key] = hash2[key] == '/' ? nil : hash2[key]
471
518
  end
472
- # delete keys with nil value
473
- target.delete_if{ |k,v| v.nil? }
519
+ # delete keys with nil value
520
+ target.delete_if { |k, v| v.nil? }
474
521
  end
475
522
 
476
523
  ########################################################################
@@ -480,13 +527,13 @@ end
480
527
  # [Parameters:]
481
528
  # [extend_option] : Value of @form['extend'] option
482
529
  ########################################################################
483
- def extend_drg_cms_form(extend_option)
530
+ def extend_drg_form(extend_option)
484
531
  form_file_name = dc_find_form_file(extend_option)
485
- @form_js << read_js_drg_cms_form(form_file_name)
532
+ @form_js << read_js_drg_form(form_file_name)
486
533
  form = YAML.load_file( form_file_name )
487
534
  @form = forms_merge(form, @form)
488
- # If combined form contains tabs and fields options, merge fields into tabs
489
- if @form['form']['tabs'] and @form['form']['fields']
535
+ # If combined form contains tabs and fields options, merge fields into tabs
536
+ if @form['form']['tabs'] && @form['form']['fields']
490
537
  @form['form']['tabs']['fields'] = @form['form']['fields']
491
538
  @form['form']['fields'] = nil
492
539
  end
@@ -499,79 +546,97 @@ end
499
546
  # [Parameters:]
500
547
  # [include_option] : Value of @form['include'] option
501
548
  ########################################################################
502
- def include_drg_cms_form(include_option)
549
+ def include_drg_form(include_option)
503
550
  includes = include_option.class == Array ? include_option : include_option.split(/\,|\;/)
504
551
  includes.each do |include_file|
505
552
  form_file_name = dc_find_form_file(include_file)
506
- @form_js << read_js_drg_cms_form(form_file_name)
553
+ @form_js << read_js_drg_form(form_file_name)
507
554
  form = YAML.load_file(form_file_name)
508
555
  @form = forms_merge(@form, form)
509
556
  end
510
557
  end
511
558
 
512
559
  ########################################################################
513
- # Will read data from form_file_name.js if it exists.
560
+ # Will read data from form_file_name.js if exists.
514
561
  #
515
562
  # [Parameters:]
516
563
  # [form_file_name] : Physical form filename
517
564
  ########################################################################
518
- def read_js_drg_cms_form(form_file_name)
565
+ def read_js_drg_form(form_file_name)
519
566
  js_form_file_name = form_file_name.sub('.yml','.js')
520
567
  File.read(js_form_file_name) rescue ''
521
568
  end
522
569
 
523
570
  ########################################################################
524
- # Read drgcms form into yaml object. Subroutine of check_authorization.
571
+ # Read DRG form into @form object. Subroutine of check_authorization.
525
572
  ########################################################################
526
- def read_drg_cms_form
573
+ def read_drg_form
527
574
  table_name = decamelize_type(params[:table].strip)
528
575
  @tables = table_name.split(';').inject([]) { |r,v| r << [(v.classify.constantize rescue nil), v] }
529
- # split ids passed when embedded document
576
+
577
+ # split ids passed when embedded document
530
578
  ids = params[:ids].to_s.strip.downcase
531
579
  @ids = ids.split(';').inject([]) { |r,v| r << v }
532
- # form_name defaults to last table specified
580
+
581
+ # form_name defaults to last table specified
533
582
  form_name = params[:form_name] || @tables.last[1]
534
583
  @form_js = ''
535
- # dynamicaly generated form
584
+
585
+ # dynamically generated form
536
586
  @form = if params[:form_name] == 'method'
537
- dc_eval_class_method(params[:form_method], params)
538
- else
539
- form_file_name = dc_find_form_file(form_name)
540
- @form_js = read_js_drg_cms_form(form_file_name)
541
- YAML.load_file(form_file_name)
542
- end
543
- # form includes or extends another form file
544
- include_drg_cms_form(@form['include']) if @form['include']
545
- extend_drg_cms_form(@form['extend']) if @form['extend']
587
+ dc_eval_class_method(params[:form_method], params)
588
+ else
589
+ form_file_name = dc_find_form_file(form_name)
590
+ @form_js = read_js_drg_form(form_file_name)
591
+ YAML.load_file(form_file_name)
592
+ end
593
+
594
+ # form includes or extends another form file
595
+ include_drg_form(@form['include']) if @form['include']
596
+ extend_drg_form(@form['extend']) if @form['extend']
546
597
  @form['script'] = (@form['script'].blank? ? @form_js : @form['script'] + @form_js)
547
- # add readonly key to form if readonly parameter is passed in url
598
+ # add readonly key to form if readonly parameter is passed in url
548
599
  @form['readonly'] = 1 if params['readonly'] #and %w(1 yes true).include?(params['readonly'].to_s.downcase.strip)
549
- # !!!!!! Always use strings for key names since @parms['table'] != @parms[:table]
600
+
601
+ # !!!!!! Always use strings for key names since @parms['table'] != @parms[:table]
550
602
  @parms = { 'table' => table_name, 'ids' => params[:ids], 'form_name' => form_name,
551
603
  'return_to' => params['return_to'], 'edit_only' => params['edit_only'],
552
604
  'readonly' => params['readonly']
553
605
  }
554
606
  end
555
607
 
608
+ ############################################################################
609
+ # Load module if available. Try not to mask errors in control module
610
+ ############################################################################
611
+ def load_controls_module(controls_string)
612
+ begin
613
+ controls_string.classify.constantize
614
+ rescue NameError => e
615
+ return nil if e.message.match('uninitialized constant') || e.message.match('wrong constant name')
616
+ # report errors when loading existing module
617
+ raise e
618
+ end
619
+ end
620
+
556
621
  ############################################################################
557
622
  # Dynamically extend cmsedit class with methods defined in controls module.
558
623
  ############################################################################
559
- def extend_with_control_module(control_name=@form['controls'])
560
- # May include embedded forms therefor ; => _
561
- controls_string = "#{control_name || params[:table].gsub(';','_')}_control"
562
- controls = "#{controls_string.classify}".constantize rescue nil
563
- # old version. Will be deprecated
564
- if controls.nil?
565
- controls_string = (control_name ? control_name : params[:table].gsub(';','_')) + '_control'
566
- controls = "DrgcmsControls::#{controls_string.classify}".constantize rescue nil
567
- dc_deprecate('Putting controls into app/controllers/drgcms_controls directory will be deprecated. Put them into app/controls instead.') if controls
568
- end
569
- # Form may be dynamically updated before processed
570
- if controls
624
+ def extend_with_control_module(control_name = @form['controls'] || @form['control'])
625
+ # May include embedded forms so ; => _
626
+ control_name ||= params[:table].gsub(';','_')
627
+ control_name += '_control' unless control_name.match(/control$|report$/i)
628
+ # p '************', control_name
629
+ controls = load_controls_module(control_name)
630
+ if controls
631
+ # extend first with dc_report when report
632
+ if control_name.match(/report$/i)
633
+ extend DcReport
634
+ init_report(control_name)
635
+ end
571
636
  extend controls
637
+ # Form may be dynamically updated before processed
572
638
  send(:dc_update_form) if respond_to?(:dc_update_form)
573
639
  end
574
-
575
640
  end
576
641
 
577
642
  ############################################################################
@@ -589,8 +654,9 @@ def check_authorization
589
654
  (table.size < 3 or !dc_user_can(DcPermission::CAN_VIEW))
590
655
  return render(action: 'error', locals: { error: t('drgcms.not_authorized')} )
591
656
  end
592
- read_drg_cms_form
657
+ read_drg_form
593
658
  return render( plain: t('drgcms.form_error') ) if @form.nil?
659
+
594
660
  # Permissions can be also defined on form
595
661
  #TODO So far only can_view is used. Think about if using other permissions has sense
596
662
  can_view = @form.dig('permissions','can_view')
@@ -617,7 +683,7 @@ end
617
683
  ########################################################################
618
684
  # Creates new empty record for new and create action.
619
685
  ########################################################################
620
- def create_new_empty_record(initial_data=nil) #:nodoc:
686
+ def create_new_empty_record(initial_data = nil) #:nodoc:
621
687
  if @tables.size == 1
622
688
  @record = @tables.first[0].new(initial_data)
623
689
  else
@@ -634,9 +700,9 @@ def update_standards(record = @record)
634
700
  record.updated_by = session[:user_id] if record.respond_to?('updated_by')
635
701
  if record.new_record?
636
702
  record.created_by = session[:user_id] if record.respond_to?('created_by')
637
- # set this only initialy. Allow to be set to nil on updates. This documents can then belong to all sites
638
- # and will be directly visible only to admins
639
- record.dc_site_id = dc_get_site._id if record.respond_to?('dc_site_id') and record.dc_site_id.nil?
703
+ # set this only initialy. Allow to be set to nil on updates. Document can then belong to all sites
704
+ # and will be directly visible only to admins
705
+ record.dc_site_id = dc_get_site.id if record.respond_to?('dc_site_id') && record.dc_site_id.nil?
640
706
  end
641
707
  end
642
708
 
@@ -648,17 +714,15 @@ end
648
714
  # [changes] Current document changed fields.
649
715
  ########################################################################
650
716
  def save_journal(operation, changes = {})
651
- # return unless session[:save_journal]
652
717
  if operation == :delete
653
718
  @record.attributes.each {|k,v| changes[k] = v}
654
- # elsif operation == :new
655
- # changes = {}
656
719
  end
657
- #
658
- if (operation != :update) or changes.size > 0
659
- # determine site_id
720
+
721
+ if (operation != :update) || changes.size > 0
722
+ # determine site_id
660
723
  site_id = @record.site_id if @record.respond_to?('site_id')
661
- site_id = dc_get_site._id if site_id.nil? and dc_get_site
724
+ site_id = dc_get_site._id if site_id.nil? && dc_get_site
725
+
662
726
  DcJournal.create(site_id: site_id,
663
727
  operation: operation,
664
728
  user_id: session[:user_id],
@@ -676,23 +740,23 @@ end
676
740
  # Returns callback method name or nil if not defined.
677
741
  ########################################################################
678
742
  def callback_method(key) #:nodoc:
679
- data_key = key.gsub('_','-') # data fields translate _ to -
680
- cb = case
743
+ data_key = key.gsub('_','-') # convert _ to -
744
+ callback = case
681
745
  when params['data'] && params['data'][data_key] then params['data'][data_key]
682
- # if dc_ + key method is present in model then it will be called automatically
746
+ # dc_ + key method is present then call it automatically
683
747
  when @form['form'][key] then @form['form'][key]
684
748
  when respond_to?('dc_' + key) then 'dc_' + key
685
749
  when params[data_key] then params[data_key]
686
750
  else nil
687
751
  end
688
- #
752
+
689
753
  ret = case
690
- when cb.nil? then cb # otherwise there will be errors in next lines
691
- when cb.match('eval ') then cb.sub('eval ','')
692
- when cb.match('return_to ')
693
- params[:return_to] = cb.sub('return_to ','')
754
+ when callback.nil? then callback # otherwise there will be errors in next lines
755
+ when callback.match('eval ') then callback.sub('eval ','')
756
+ when callback.match('return_to ')
757
+ params[:return_to] = callback.sub('return_to ','')
694
758
  return nil
695
- else cb
759
+ else callback
696
760
  end
697
761
  ret
698
762
  end
@@ -731,16 +795,16 @@ end
731
795
 
732
796
  ########################################################################
733
797
  # Since tabs have been introduced on form it is a little more complicated
734
- # to get all edit fields on form. This method does it. Subroutine of save_data.
798
+ # to collect all edit fields on form. This method does it. Subroutine of save_data.
735
799
  ########################################################################
736
- def fields_on_form() #:nodoc:
800
+ def fields_on_form #:nodoc:
737
801
  form_fields = []
738
802
  if @form['form']['fields']
739
- # read only field elements (key is Integer)
740
- @form['form']['fields'].each {|key,options| form_fields << options if key.class == Integer }
803
+ # read only field elements (key is Integer)
804
+ @form['form']['fields'].each { |key, options| form_fields << options if key.class == Integer }
741
805
  else
742
806
  @form['form']['tabs'].keys.each do |tab|
743
- @form['form']['tabs'][tab].each {|key,options| form_fields << options if key.class == Integer }
807
+ @form['form']['tabs'][tab].each { |key, options| form_fields << options if key.class == Integer }
744
808
  end
745
809
  end
746
810
  form_fields
@@ -753,7 +817,7 @@ end
753
817
  def save_data
754
818
  form_fields = fields_on_form()
755
819
  return true if form_fields.size == 0
756
- #
820
+
757
821
  form_fields.each do |v|
758
822
  session[:form_processing] = v['name'] # for debuging
759
823
  next if v['type'].nil? or v['name'].nil? or
@@ -766,43 +830,42 @@ def save_data
766
830
  value = DrgcmsFormFields.const_get(v['type'].camelize).get_data(params, v['name'])
767
831
  @record.send("#{v['name']}=", value)
768
832
  end
769
- # controls callback method
833
+ # before_save callback
770
834
  if (m = callback_method('before_save') )
771
835
  ret = call_callback_method(m)
772
- # dont's save if callback method returns false
836
+ # don't save if callback returns false
773
837
  return false if ret.class == FalseClass
774
838
  end
775
- # save data
839
+
840
+ # save data
776
841
  changes = @record.changes
777
842
  update_standards() if changes.size > 0 # update only if there has been some changes
778
843
  if (saved = @record.save)
779
844
  operation = @record.new_record? ? :new : :update
780
845
  save_journal(operation, changes)
781
- # callback methods
782
- if (m = callback_method('after_save') ) then call_callback_method(m) end
846
+ # after_save callback
847
+ if (m = callback_method('after_save') ) then call_callback_method(m) end
783
848
  end
784
849
  saved
785
850
  end
786
851
 
787
852
  ########################################################################
788
- # Will return commma separated data (field names) as hash. For usage
853
+ # Will return comma separated data (field names) as array of symbols. For usage
789
854
  # in select_fields and deny_fields
790
855
  ########################################################################
791
- def separated_to_hash(data)
792
- data.chomp.split(',').inject([]) {|r,element| r << element.strip.downcase.to_sym }
856
+ def separated_to_symbols(data)
857
+ data.chomp.split(',').map { |e| e.strip.downcase.to_sym }
793
858
  end
794
859
 
795
860
  ########################################################################
796
- # Will process select_fields and deny_fields if specified
861
+ # Will process only (select_fields) and without (deny_fields) option
797
862
  ########################################################################
798
863
  def process_select_and_deny_fields
799
- if @form['result_set']['select_fields']
800
- @records = @records.only( separated_to_hash(@form['result_set']['select_fields']) )
801
- end
802
- # deny fields specified
803
- if @form['result_set']['deny_fields']
804
- @records = @records.without( separated_to_hash(@form['result_set']['deny_fields']) )
805
- end
864
+ only = @form['result_set']['select_fields'] || @form['result_set']['only']
865
+ @records = @records.only( separated_to_symbols(only) ) if only
866
+
867
+ without = @form['result_set']['deny_fields'] || @form['result_set']['without']
868
+ @records = @records.without( separated_to_symbols(without) ) if without
806
869
  end
807
870
 
808
871
  ########################################################################
@@ -812,18 +875,18 @@ def check_sort_options() #:nodoc:
812
875
  table_name = @tables.first[1]
813
876
  old_sort = session[table_name][:sort].to_s
814
877
  sort, direction = old_sort.split(' ')
815
- # sort is requested
878
+
816
879
  if params['sort']
817
880
  # reverse sort if same selected
818
881
  if params['sort'] == sort
819
882
  direction = (direction == '1') ? '-1' : '1'
820
883
  end
821
- direction ||= 1
884
+ direction ||= '1'
822
885
  sort = params[:sort]
823
886
  session[table_name][:sort] = "#{params['sort']} #{direction}"
824
887
  session[table_name][:page] = 1
825
888
  end
826
- @records.sort( sort => direction.to_i ) if session[table_name][:sort]
889
+ @records.sort( sort => direction.to_i ) if session[table_name][:sort] && @records.class == Mongoid::Criteria
827
890
  params['sort'] = nil # otherwise there is problem with other links
828
891
  end
829
892
 
@@ -839,6 +902,17 @@ def user_filter_options(model) #:nodoc:
839
902
  end
840
903
  end
841
904
 
905
+ ########################################################################
906
+ # Return current sort options for model (table)
907
+ ########################################################################
908
+ def user_sort_options(model) #:nodoc:
909
+ table_name = (model.class == String ? model : model.to_s).underscore
910
+ return nil unless session[table_name][:sort]
911
+
912
+ field, direction = session[table_name][:sort].split(' ')
913
+ { field.to_sym => direction.to_i }
914
+ end
915
+
842
916
  ########################################################################
843
917
  # Will set session[table_name][:filter] and save last filter settings to session.
844
918
  # subroutine of check_filter_options.
@@ -846,53 +920,54 @@ end
846
920
  def set_session_filter(table_name)
847
921
  # models that can not be filtered (for now)
848
922
  return if %w(dc_temp dc_memory).include?(params[:table])
849
-
850
923
  # clear filter
851
924
  if params[:filter] == 'off'
852
925
  session[table_name][:filter] = nil
853
926
  return
854
927
  end
928
+ # field_name should exist on set filter condition
929
+ return if params[:filter_oper] && params[:filter_field].blank?
855
930
 
856
931
  filter_value = if params[:filter_value].nil?
857
- # NIL indicates that no filtering is needed
932
+ #NIL indicates that no filtering is needed
858
933
  '#NIL'
859
934
  else
860
935
  if params[:filter_value].class == String and params[:filter_value][0] == '@'
861
- # Internal value. Remove leading @ and evaluate expression
936
+ # Internal value. Remove leading @ and evaluate expression
862
937
  expression = DcInternals.get(params[:filter_value])
863
938
  eval(expression) rescue nil
864
939
  else
865
- # No filter when empty
940
+ # No filter when empty
866
941
  params[:filter_value] == '' ? '#NIL' : params[:filter_value]
867
942
  end
868
943
  end
869
- # if filter field parameter is omitted then just set filter value
944
+ # if filter field parameter is omitted then just set filter value
870
945
  session[table_name][:filter] =
871
946
  if params[:filter_field].nil?
872
947
  saved = YAML.load(session[table_name][:filter])
873
948
  saved['value'] = filter_value
874
949
  saved.to_yaml
875
950
  else
876
- # As field defined. Split name and alternative input field
951
+ # as field defined. Split name and alternative input field
877
952
  field = if params[:filter_field].match(' as ')
878
953
  params[:filter_input] = params[:filter_field].split(' as ').last.strip
879
954
  params[:filter_field].split(' as ').first.strip
880
955
  else
881
956
  params[:filter_field]
882
957
  end
883
- #
958
+
884
959
  {'field' => field,
885
960
  'operation' => params[:filter_oper],
886
961
  'value' => filter_value,
887
962
  'input' => params[:filter_input],
888
963
  'table' => table_name }.to_yaml
889
964
  end
890
- # must be. Otherwise kaminari includes parameter on paging
891
- params[:filter] = nil
892
- params[:filter_id] = nil
893
- params[:filter_oper] = nil
894
- params[:filter_input] = nil
895
- params[:filter_field] = nil
965
+ # must be. Otherwise kaminari includes parames on paging links
966
+ params[:filter] = nil
967
+ params[:filter_id] = nil
968
+ params[:filter_oper] = nil
969
+ params[:filter_input] = nil
970
+ params[:filter_field] = nil
896
971
  end
897
972
 
898
973
  ########################################################################
@@ -902,31 +977,27 @@ def check_filter_options() #:nodoc:
902
977
  table_name = @tables.first[1]
903
978
  model = @tables.first[0]
904
979
  session[table_name] ||= {}
905
- # process page
980
+ # page is set
906
981
  session[table_name][:page] = params[:page] if params[:page]
907
- # new filter is applied
982
+ # new filter is applied
908
983
  if params[:filter]
909
984
  set_session_filter(table_name)
910
985
  session[table_name][:page] = 1
911
986
  end
912
- # if data model has field dc_site_id ensure that only documents which belong to the site are selected.
987
+ # if data model has field dc_site_id ensure that only documents which belong to the site are selected.
913
988
  site_id = dc_get_site._id if dc_get_site
914
- # dont't filter site if no dc_site_id field or user is ADMIN
989
+
990
+ # don't filter site if no dc_site_id field or user is ADMIN
915
991
  site_id = nil if !model.method_defined?('dc_site_id') or dc_user_can(DcPermission::CAN_ADMIN)
916
992
  site_id = nil if session[table_name][:filter].to_s.match('dc_site_id')
917
- #
993
+
918
994
  if @records = DcFilter.get_filter(session[table_name][:filter])
919
995
  @records = @records.and(dc_site_id: site_id) if site_id
920
996
  else
921
- @records = if site_id
922
- model.where(dc_site_id: site_id)
923
- else
924
- model
925
- end
997
+ @records = site_id ? model.where(dc_site_id: site_id) : model
926
998
  end
927
- # select only fields or deny fields specified
928
999
  process_select_and_deny_fields
929
- # pagination if required
1000
+ # pagination if required
930
1001
  per_page = (@form['result_set']['per_page'] || 30).to_i
931
1002
  @records = @records.page(session[table_name][:page]).per(per_page) if per_page > 0
932
1003
  end
@@ -946,9 +1017,10 @@ def process_collections #:nodoc
946
1017
  check_sort_options()
947
1018
  end
948
1019
  # result set is defined by filter method in control object
949
- if @form['result_set']['filter']
950
- if respond_to?(@form['result_set']['filter'])
951
- @records = send @form['result_set']['filter']
1020
+ form_filter = @form['result_set']['filter']
1021
+ if form_filter
1022
+ if respond_to?(form_filter)
1023
+ @records = send(form_filter)
952
1024
  # something went wrong. flash[] should have explanation.
953
1025
  if @records.class == FalseClass
954
1026
  @records = []
@@ -961,7 +1033,7 @@ def process_collections #:nodoc
961
1033
  per_page = (@form['result_set']['per_page'] || 30).to_i
962
1034
  @records = @records.page(params[:page]).per(per_page) if per_page > 0
963
1035
  end
964
- else
1036
+ elsif form_filter != 'dc_filter'
965
1037
  Rails.logger.error "Error: result_set:filter: #{@form['result_set']['filter']} not found in controls!"
966
1038
  end
967
1039
  else