drg_cms 0.6.1.0 → 0.6.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -10
  3. data/app/assets/fonts/ibm-plex-sans-300.woff2 +0 -0
  4. data/app/assets/fonts/ibm-plex-sans-400.woff2 +0 -0
  5. data/app/assets/fonts/ibm-plex-sans-500.woff2 +0 -0
  6. data/app/assets/fonts/ibm-plex-sans-600.woff2 +0 -0
  7. data/app/assets/fonts/ibm-plex-sans-700.woff2 +0 -0
  8. data/app/assets/fonts/ibm-plex-sans-italic.woff2 +0 -0
  9. data/app/assets/javascripts/drg_cms/drg_cms.js +178 -55
  10. data/app/assets/stylesheets/drg_cms/drg_cms.css +218 -94
  11. data/app/assets/stylesheets/drg_cms/select-multiple.css +1 -1
  12. data/app/controllers/cmsedit_controller.rb +29 -24
  13. data/app/controllers/dc_application_controller.rb +78 -166
  14. data/app/controllers/dc_common_controller.rb +56 -47
  15. data/app/controls/dc_help_control.rb +12 -0
  16. data/app/controls/dc_report.rb +7 -9
  17. data/app/controls/design_element_settings_control.rb +1 -1
  18. data/app/forms/all_options.yml +25 -6
  19. data/app/forms/dc_big_table.yml +0 -2
  20. data/app/forms/dc_big_table_value.yml +0 -2
  21. data/app/forms/dc_design.yml +1 -2
  22. data/app/forms/dc_folder_permission.yml +0 -2
  23. data/app/forms/dc_help_1.yml +2 -1
  24. data/app/forms/dc_json_ld.yml +0 -3
  25. data/app/forms/dc_menu.yml +6 -12
  26. data/app/forms/dc_menu_item.yml +1 -3
  27. data/app/forms/dc_page.yml +5 -2
  28. data/app/forms/dc_policy.yml +2 -5
  29. data/app/forms/dc_poll.yml +10 -16
  30. data/app/forms/dc_seo.yml +1 -2
  31. data/app/forms/dc_simple_menu.yml +1 -2
  32. data/app/forms/dc_site.yml +5 -7
  33. data/app/helpers/cms_common_helper.rb +2 -3
  34. data/app/helpers/cms_edit_helper.rb +41 -31
  35. data/app/helpers/cms_helper.rb +6 -6
  36. data/app/helpers/cms_index_helper.rb +79 -34
  37. data/app/helpers/dc_application_helper.rb +99 -85
  38. data/app/models/concerns/dc_page_concern.rb +3 -2
  39. data/app/models/concerns/dc_piece_concern.rb +1 -1
  40. data/app/models/concerns/dc_site_concern.rb +10 -4
  41. data/app/models/concerns/dc_user_concern.rb +3 -3
  42. data/app/models/dc_big_table.rb +2 -2
  43. data/app/models/dc_filter.rb +28 -22
  44. data/app/models/dc_site.rb +0 -1
  45. data/app/models/dc_temp.rb +7 -0
  46. data/app/models/drgcms_form_fields/comment.rb +11 -2
  47. data/app/models/drgcms_form_fields/date_picker.rb +2 -0
  48. data/app/models/drgcms_form_fields/drgcms_field.rb +2 -1
  49. data/app/models/drgcms_form_fields/embedded.rb +4 -2
  50. data/app/models/drgcms_form_fields/number_field.rb +4 -3
  51. data/app/models/drgcms_form_fields/readonly.rb +13 -17
  52. data/app/models/drgcms_form_fields/select.rb +16 -18
  53. data/app/models/drgcms_form_fields/text_autocomplete.rb +39 -23
  54. data/app/renderers/dc_page_renderer.rb +7 -6
  55. data/app/renderers/dc_poll_renderer.rb +16 -20
  56. data/app/views/cmsedit/_edit_stuff.html.erb +5 -2
  57. data/app/views/cmsedit/_form.html.erb +3 -2
  58. data/app/views/cmsedit/_result.html.erb +21 -18
  59. data/app/views/cmsedit/edit.html.erb +2 -1
  60. data/app/views/cmsedit/index.html.erb +1 -1
  61. data/app/views/cmsedit/new.html.erb +3 -2
  62. data/app/views/dc_common/_help.html.erb +12 -3
  63. data/app/views/layouts/cms.html.erb +3 -5
  64. data/config/locales/drgcms_en.yml +5 -2
  65. data/config/locales/drgcms_sl.yml +5 -2
  66. data/config/locales/models_en.yml +2 -0
  67. data/config/locales/models_sl.yml +5 -3
  68. data/drg_cms.gemspec +16 -16
  69. data/lib/drg_cms/version.rb +1 -1
  70. data/lib/drg_cms.rb +46 -12
  71. metadata +35 -29
@@ -91,32 +91,40 @@ end
91
91
  # normal link.
92
92
  ############################################################################
93
93
  def dc_actions_for_form(position)
94
- # create standard actions
94
+ # create standard actions
95
95
  std_actions = {1 => 'back', 2 => {'type' => 'submit', 'caption' => 'drgcms.save'},
96
96
  3 => {'type' => 'submit', 'caption' => 'drgcms.save&back'} }
97
- # when edit only
97
+ # when edit only
98
98
  unless @record.try(:id).nil?
99
99
  std_actions.merge!({6 => 'new'} )
100
100
  std_actions.merge!(@record.active ? {5 => 'disable'} : {5 => 'enable'} ) if @record.respond_to?('active')
101
101
  std_actions.merge!({7 => 'refresh'} )
102
102
  end
103
+ # readonly
104
+ std_actions = { 1 => 'back' } if @form['readonly']
105
+
103
106
  actions = @form['form']['actions']
104
- # shortcut for actions: standard
107
+ # shortcut for actions: standard
105
108
  actions = nil if actions.class == String && actions == 'standard'
106
- # standard actions
107
109
  actions = std_actions if actions.nil?
108
- # readonly
109
- actions = {1 => 'back'} if @form['readonly']
110
- actions = {1 => 'close'} if params[:window_close]
111
- # Actions are strictly forbidden
112
- if @form['form']['actions'] and dc_dont?(@form['form']['actions'])
110
+
111
+ # Actions are strictly forbidden
112
+ if @form['form']['actions'] && dc_dont?(@form['form']['actions'])
113
113
  actions = []
114
114
  elsif actions['standard']
115
115
  actions.merge!(std_actions)
116
116
  actions['standard'] = nil
117
117
  end
118
- # Update save and save&back
119
- actions.each do |k,v|
118
+ # request for close window button present
119
+ if actions.class == Hash
120
+ case params[:window_close]
121
+ when '0' then actions[1] = 'close'; actions[3] = nil
122
+ when '1' then actions = { 1 => 'close' }
123
+ when '2' then actions = { 1 => 'close' }
124
+ end
125
+ end
126
+ # Update save and save&back
127
+ actions.each do |k, v|
120
128
  if v.class == String
121
129
  if v.match(/save\&back/i)
122
130
  actions[k] = {'type' => 'submit', 'caption' => 'drgcms.save&back'}
@@ -125,23 +133,23 @@ def dc_actions_for_form(position)
125
133
  end
126
134
  end
127
135
  end
128
- # remove standard option and sort so that standard actions come first
136
+ # remove standard option and sort so that standard actions come first
129
137
  actions.delete('standard')
130
- actions = actions.to_a.sort {|x,y| x[0] <=> y[0]}
131
- # Add spinner to the beginning
138
+ actions = actions.to_a.sort { |x, y| x[0] <=> y[0] }
139
+ # Add spinner to the beginning
132
140
  html = %Q[<span class="dc-spinner">#{fa_icon('spinner lg spin')}</span><ul class="dc-menu #{position}">]
133
-
141
+
134
142
  actions.each do |key, options|
135
143
  session[:form_processing] = "form:actions: #{key} #{options}"
136
- next if options.nil? # yes it happends
144
+ next if options.nil? # yes it happens
137
145
  parms = @parms.clone
138
146
  if options.class == String
139
- next if params[:readonly] and !options.match(/back|close/)
147
+ next if @form['readonly'] and !options.match(/back|close/)
140
148
 
141
149
  html << '<li class="dc-link dc-animate">'
142
150
  html << case
143
151
  when (options == 'back' or options == 'cancle') then
144
- # If return_to is present link directly to URL
152
+ # If return_to is present link directly to URL
145
153
  if parms['xreturn_to'] # disabled for now
146
154
  dc_link_to( 'drgcms.back','arrow-left', parms['return_to'] )
147
155
  else
@@ -186,6 +194,9 @@ def dc_actions_for_form(position)
186
194
  html << '</td>'
187
195
  # non standard actions
188
196
  else
197
+ # action will be displayed when show: always or readonly option is declared and form is readonly
198
+ next if @form['readonly'] && !%w[readonly always].include?(options['show'].to_s)
199
+
189
200
  options['title'] = t("#{options['title'].downcase}", options['title']) if options['title']
190
201
  html << case
191
202
  # submit button
@@ -296,13 +307,13 @@ def dc_fields_for_tab(fields_on_tab) #:nodoc:
296
307
  group_count = options['group'] || 1
297
308
  group_option = options['group'] || 1
298
309
  end
299
- #
310
+
300
311
  html << if labels_pos == 'top'
301
- %Q[
312
+ %(
302
313
  <div class="dc-form-label-top dc-color-#{odd_even} dc-align-left" title="#{help}">
303
314
  <label for="record_#{options['name']}">#{label} </label>
304
315
  <div id="td_record_#{options['name']}">#{field_html}</div>
305
- </div> ]
316
+ </div> )
306
317
  else
307
318
  # no label
308
319
  if dc_dont?(options['caption'])
@@ -315,13 +326,14 @@ def dc_fields_for_tab(fields_on_tab) #:nodoc:
315
326
  else
316
327
  label_width = 14
317
328
  data_width = 85
318
- end
319
- %Q[
329
+ end
330
+ help.gsub!('<br>',"\n") if help.present?
331
+ %(
320
332
  <div class="dc-form-label dc-color-#{odd_even} dc-align-#{labels_pos} dc-width-#{label_width}" title="#{help}">
321
333
  <label for="record_#{options['name']}">#{label} </label>
322
334
  </div>
323
335
  <div id="td_record_#{options['name']}" class="dc-form-field dc-color-#{odd_even} dc-width-#{data_width}">#{field_html}</div>
324
- ]
336
+ )
325
337
  end
326
338
  # check if group end
327
339
  if (group_count -= 1) == 0
@@ -423,7 +435,7 @@ def dc_head_for_form
423
435
  @record.send(options['name'])
424
436
  end
425
437
  rescue Exception => e
426
- dc_log_exception(e)
438
+ dc_log_exception(e, 'dc_head_for_form')
427
439
  field = '!!!Error'
428
440
  end
429
441
  #
@@ -447,11 +459,10 @@ end
447
459
  # Returns username for id. Subroutine of dc_document_statistics
448
460
  ###########################################################################
449
461
  def dc_document_user_for(field_name) #:nodoc:
450
- if @record[field_name]
451
- u = DcUser.find(@record[field_name])
452
- return u ? u.name : @record[field_name]
453
- end
454
- # nil
462
+ return if @record[field_name].nil?
463
+
464
+ user = DcUser.find(@record[field_name])
465
+ user ? user.name : @record[field_name]
455
466
  end
456
467
 
457
468
  ############################################################################
@@ -502,5 +513,4 @@ def dc_top_bottom_line(location, options)
502
513
  end
503
514
  end
504
515
 
505
-
506
516
  end
@@ -37,7 +37,7 @@ def dc_script_action(yaml)
37
37
  # data = {'request' => 'script', 'script' => yaml['js'] || yaml['script'] }
38
38
  # %Q[<li class="dc-link-ajax with-link dc-animate">#{ dc_link_to(yaml['caption'], yaml['icon'], '#', data: data ) }</li>]
39
39
  icon = dc_icon_for_link yaml['icon']
40
- data = %Q[data-request="script" data-script="#{yaml['js'] || yaml['script']}"]
40
+ data = %(data-request="script" data-script="#{yaml['js'] || yaml['script']}" data-url="script")
41
41
  %Q[<li class="dc-link-ajax dc-animate" #{data}>#{icon} #{ t(yaml['caption'],yaml['caption']) }</li>]
42
42
  end
43
43
 
@@ -182,7 +182,7 @@ end
182
182
  # Returns:
183
183
  # String : HTML code for action
184
184
  ############################################################################
185
- def dc_link_ajax_window_submit_action(yaml, record=nil, action_active=true)
185
+ def dc_link_ajax_window_submit_action(yaml, record = nil, action_active = true)
186
186
  parms = {}
187
187
  caption = yaml['caption'] || yaml['text']
188
188
  caption = caption ? t("#{caption.downcase}", caption) : nil
@@ -241,7 +241,7 @@ def dc_link_ajax_window_submit_action(yaml, record=nil, action_active=true)
241
241
  data-request="#{request}" title="#{yaml['title']}">#{icon}#{caption}</li>]
242
242
 
243
243
  elsif yaml['type'] == 'link' # link button
244
- clas = "dc-link dc-animate"
244
+ clas = "dc-link plus-link dc-animate"
245
245
  link = dc_link_to(caption, yaml['icon'], parms, yaml['html'] )
246
246
  %Q[<li class="#{clas}">#{action_active ? link : caption}</li>]
247
247
 
@@ -256,10 +256,10 @@ def dc_link_ajax_window_submit_action(yaml, record=nil, action_active=true)
256
256
  end
257
257
 
258
258
  ############################################################################
259
- #
259
+ # Log exception to rails log. Usefull for debugging eval errors.
260
260
  ############################################################################
261
- def dc_log_exception(exception)
262
- log = exception ? "\n!!!Error: #{exception.message}\n#{exception.backtrace.first.inspect}\n" : ''
261
+ def dc_log_exception(exception, where = '')
262
+ log = exception ? "\n*** Error:#{where + ':'} #{exception.message}\n#{exception.backtrace.first.inspect}\n" : ''
263
263
  log << "DRG Form processing line: #{session[:form_processing]}\n"
264
264
 
265
265
  logger.error log
@@ -32,14 +32,17 @@ module CmsIndexHelper
32
32
  ############################################################################
33
33
  # Creates action div for cmsedit index action.
34
34
  ############################################################################
35
- def dc_actions_for_index()
35
+ def dc_actions_for_index
36
36
  @js = @form['script'] || @form['js'] || ''
37
37
  @css = @form['css'] || ''
38
- return '' if @form['index'].nil? or @form['readonly']
38
+ return '' if @form['index'].nil?
39
+
39
40
  actions = @form['index']['actions']
40
41
  return '' if actions.blank?
41
42
 
42
43
  std_actions = {2 => 'new', 3 => 'sort', 4 => 'filter' }
44
+ std_actions.delete(2) if @form['readonly']
45
+
43
46
  if actions.class == String
44
47
  actions = dc_define_standard_actions(actions, std_actions)
45
48
  elsif actions['standard']
@@ -60,6 +63,7 @@ def dc_actions_for_index()
60
63
  only_actions.each do |key, options|
61
64
  session[:form_processing] = "index:actions: #{key}=#{options}"
62
65
  next if options.nil? # must be
66
+
63
67
  url = @parms.clone
64
68
  yaml = options.class == String ? {'type' => options} : options # if single definition simulate type parameter
65
69
  action = yaml['type'].to_s.downcase
@@ -80,7 +84,6 @@ def dc_actions_for_index()
80
84
  # html link options
81
85
  yhtml = yaml['html'] || {}
82
86
  yhtml['title'] = yaml['title'] if yaml['title']
83
-
84
87
  code = case
85
88
  # sort
86
89
  when action == 'sort' then
@@ -109,14 +112,23 @@ def dc_actions_for_index()
109
112
  caption
110
113
 
111
114
  # new
112
- when action == 'new' then
115
+ when action == 'new' then
113
116
  caption = yaml['caption'] || 'drgcms.new'
114
- dc_link_to(caption,'plus', url, yhtml )
117
+ html << "<li class=\"dc-link plus-link dc-animate\">#{dc_link_to(caption, 'plus', url, yhtml )}</li>"
118
+ next
119
+
120
+ when action == 'close' then
121
+ html << %(<li class="dc-link dc-animate" onclick="window.close();"'>#{fa_icon('close')} #{t('drgcms.close')}</li>)
122
+ next
115
123
 
116
124
  # menu
117
- when action == 'menu' then
118
- caption = t(options['caption'], options['caption']) + '&nbsp;' + fa_icon('caret-down lg')
119
- caption + eval(options['eval'])
125
+ when action == 'menu' then
126
+ if options['caption']
127
+ caption = t(options['caption'], options['caption']) + '&nbsp;' + fa_icon('caret-down lg')
128
+ caption + eval(options['eval'])
129
+ else # when caption is false, provide own actions
130
+ eval(options['eval'])
131
+ end
120
132
  =begin
121
133
  # reorder
122
134
  when action == 'reorder' then
@@ -262,7 +274,7 @@ end
262
274
  ############################################################################
263
275
  def dc_actions_for_result(document)
264
276
  actions = @form['result_set']['actions']
265
- return '' if actions.nil? or @form['readonly']
277
+ return '' if actions.nil? || @form['readonly']
266
278
 
267
279
  actions, width = dc_actions_column()
268
280
  html = %Q[<ul class="actions" style="width: #{width}px;">]
@@ -278,21 +290,27 @@ def dc_actions_for_result(document)
278
290
  else
279
291
  html << '<li class="dc-link">'
280
292
  html << case
293
+ when yaml['type'] == 'check' then
294
+ check_box_tag("check-#{document.id}", false,false,{ class: 'dc-check' })
295
+
281
296
  when yaml['type'] == 'edit' then
282
297
  parms['action'] = 'edit'
283
298
  parms['id'] = document.id
284
299
  dc_link_to( nil, 'pencil lg', parms )
300
+
285
301
  when yaml['type'] == 'duplicate' then
286
302
  parms['id'] = document.id
287
303
  # duplicate string will be added to these fields.
288
304
  parms['dup_fields'] = yaml['dup_fields']
289
305
  parms['action'] = 'create'
290
306
  dc_link_to( nil, 'copy lg', parms, data: { confirm: t('drgcms.confirm_dup') }, method: :post )
307
+
291
308
  when yaml['type'] == 'delete' then
292
309
  parms['action'] = 'destroy'
293
310
  parms['id'] = document.id
294
- parms['return_to'] = request.url
311
+ #parms['return_to'] = request.url
295
312
  dc_link_to( nil, 'remove lg', parms, data: { confirm: t('drgcms.confirm_delete') }, method: :delete )
313
+
296
314
  # undocumented so far
297
315
  when yaml['type'] == 'edit_embedded'
298
316
  parms['controller'] = 'cmsedit'
@@ -314,11 +332,14 @@ end
314
332
  ############################################################################
315
333
  # Creates header div for result set.
316
334
  ############################################################################
317
- def dc_header_for_result()
335
+ def dc_header_for_result
318
336
  html = '<div class="dc-result-header">'
319
337
  if @form['result_set']['actions'] and !@form['readonly']
320
338
  ignore, width = dc_actions_column()
321
- html << %Q[<div class="actions" style="width:#{width}px;"></div>]
339
+ if width > 0 && @form['result_set']['actions'][0].to_s == 'check'
340
+ check_all = fa_icon('check-square-o', class: 'dc-check-all')
341
+ end
342
+ html << %Q[<div class="actions" style="width:#{width}px;">#{check_all}</div>]
322
343
  end
323
344
  # preparation for sort icon
324
345
  sort_field, sort_direction = nil, nil
@@ -336,7 +357,8 @@ def dc_header_for_result()
336
357
  label = (v['name'] ? "helpers.label.#{@form['table']}.#{v['name']}" : '') if label.nil?
337
358
  label = t(label) if label.match(/\./)
338
359
  # no sorting when embedded documents or custom filter is active
339
- sort_ok = @form['result_set'].nil? || (@form['result_set'] && @form['result_set']['filter'].nil?)
360
+ #sort_ok = @form['result_set'].nil? || (@form['result_set'] && @form['result_set']['filter'].nil?)
361
+ sort_ok = !dc_dont?(@form['result_set']['sort'], false)
340
362
  sort_ok = sort_ok || (@form['index'] && @form['index']['sort'])
341
363
  sort_ok = sort_ok && !dc_dont?(v['sort'], false)
342
364
  if @tables.size == 1 and sort_ok
@@ -387,11 +409,13 @@ def dc_format_value(value, format=nil)
387
409
  return '' if value.nil?
388
410
 
389
411
  klass = value.class.to_s
390
- if klass.match(/time|date/i)
391
- CmsCommonHelper.dc_format_date_time(value, format)
392
- elsif format.to_s[0] == 'N'
393
- return '' if value == 0 and format.match('z')
412
+ return CmsCommonHelper.dc_format_date_time(value, format) if klass.match(/time|date/i)
394
413
 
414
+ format = format.to_s.upcase
415
+ if format[0] == 'N'
416
+ return '' if value == 0 && format.match('Z')
417
+
418
+ format.gsub!('Z', '')
395
419
  dec = format[1].blank? ? nil : format[1].to_i
396
420
  sep = format[2].blank? ? nil : format[2]
397
421
  del = format[3].blank? ? nil : format[3]
@@ -416,6 +440,7 @@ end
416
440
  ############################################################################
417
441
  def dc_columns_for_result(document)
418
442
  return '' unless @form['result_set']['columns']
443
+
419
444
  html = ''
420
445
  @form['result_set']['columns'].sort.each do |k,v|
421
446
  session[:form_processing] = "result_set:columns: #{k}=#{v}"
@@ -438,7 +463,7 @@ def dc_columns_for_result(document)
438
463
  "??? #{v['name']}"
439
464
  end
440
465
  rescue Exception => e
441
- dc_log_exception(e)
466
+ dc_log_exception(e, 'dc_columns_for_result')
442
467
  value = '!!!Error'
443
468
  end
444
469
  html << '<div class="spacer"></div>'
@@ -455,6 +480,14 @@ def dc_columns_for_result(document)
455
480
  html.html_safe
456
481
  end
457
482
 
483
+ ############################################################################
484
+ # Split eval expression to array by parameters.
485
+ # Ex. Will split dc_name4_value(one ,"two") => ['dc_name4_value', 'one', 'two']
486
+ ############################################################################
487
+ def dc_eval_to_array(expression)
488
+ expression.split(/\ |\,|\(|\)/).delete_if {|e| e.blank? }.map {|e| e.gsub(/\'|\"/,'').strip }
489
+ end
490
+
458
491
  private
459
492
 
460
493
  ############################################################################
@@ -474,14 +507,6 @@ def dc_process_eval(evaluate, parameters)
474
507
  end
475
508
  end
476
509
 
477
- ############################################################################
478
- # Split eval expression to array by parameters.
479
- # Will split dc_name4_value(one ,"two") => ['dc_name4_value', 'one', 'two']
480
- ############################################################################
481
- def dc_eval_to_array(expression)
482
- expression.split(/\ |\,|\(|\)/).delete_if {|e| e.blank? }.map {|e| e.gsub(/\'|\"/,'').strip }
483
- end
484
-
485
510
  ############################################################################
486
511
  # Process eval option for field value.
487
512
  # Used for processing single field column on result_set or form head.
@@ -540,15 +565,19 @@ def dc_style_or_class(selector, yaml, value, record)
540
565
  # alias record and value so both names can be used in eval
541
566
  field, document = value, record
542
567
  html = selector ? "#{selector}=\"" : ''
543
- html << if yaml.class == String
544
- yaml
545
- # direct evaluate expression
546
- elsif yaml['eval']
547
- eval(yaml['eval']) rescue 'background-color:red;'
548
- elsif yaml['method']
549
- dc_process_eval(yaml['method'], record)
568
+ begin
569
+ html << if yaml.class == String
570
+ yaml
571
+ # direct evaluate expression
572
+ elsif yaml['eval']
573
+ eval(yaml['eval'])
574
+ elsif yaml['method']
575
+ dc_process_eval(yaml['method'], record)
576
+ end
577
+ rescue Exception => e
578
+ dc_log_exception(e, 'dc_style_or_class')
550
579
  end
551
- html << '"' if selector
580
+ html << '"' if selector
552
581
  html
553
582
  end
554
583
 
@@ -573,4 +602,20 @@ def dc_define_standard_actions(actions_params, standard)
573
602
  actions
574
603
  end
575
604
 
605
+ ############################################################################
606
+ # When result set is to be drawn by Rails helper method.
607
+ ############################################################################
608
+ def dc_process_result_set_method
609
+ if @form['result_set']['view']
610
+ render partial: @form['result_set']['view']
611
+ else
612
+ method = @form['result_set']['eval'] || 'result_set_eval_misssing'
613
+ if respond_to?(method)
614
+ send method
615
+ else
616
+ I18n.t('drgcms.no_method', method: method)
617
+ end
618
+ end
619
+ end
620
+
576
621
  end