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
  #
@@ -95,17 +94,17 @@ end
95
94
  ############################################################################
96
95
  def dc_render(renderer, opts={})
97
96
  return dc_render_design_part(renderer[:part]) if renderer.class == Hash
98
- #
97
+
99
98
  opts[:edit_mode] = session[:edit_mode]
100
99
  opts[:editparams] = {}
101
100
 
102
101
  opts = @options.merge(opts) # merge options with parameters passed on site, page, design ...
103
102
  opts.symbolize_keys! # this makes lots of things easier
104
- # Create renderer object
103
+ # Create renderer object
105
104
  klass = renderer.to_s.downcase
106
105
  klass += '_renderer' unless klass.match('_renderer') #
107
106
  obj = Kernel.const_get(klass.classify, Class.new).new(self, opts) rescue nil
108
- #
107
+
109
108
  if obj
110
109
  html = obj.render_html
111
110
  @css << obj.render_css.to_s
@@ -133,7 +132,7 @@ def dc_replace_in_design(opts={})
133
132
  design = opts[:piece] ? DcPiece.find(name: opts[:piece]).script : dc_get_site.design
134
133
  layout = opts[:layout] || (dc_get_site.site_layout.size > 2 ? dc_get_site.site_layout : nil)
135
134
  if opts[:replace]
136
- # replace more than one part of code
135
+ # replace more than one part of code
137
136
  if opts[:replace].class == Array
138
137
  0.upto(opts[:replace].size - 1) {|i| design.sub!(opts[:replace][i], opts[:with][i])}
139
138
  else
@@ -179,13 +178,12 @@ end
179
178
  #
180
179
  # This helper is replacement dc_render_from_site method which will soon be deprecated.
181
180
  ########################################################################
182
- def dc_render_design_part(part)
183
-
181
+ def dc_render_design_part(part)
184
182
  case
185
183
  when part.nil? then logger.error('ERROR dc_render_design_part! part is NIL !'); ''
186
- # Send as array. Part may be defined with options on page. First element has
187
- # name of element which defines what to do. If not defined default behaviour is
188
- # called. That is what is defined in second part of array.
184
+ # Send as array. Part may be defined with options on page. First element has
185
+ # name of element which defines what to do. If not defined default behaviour is
186
+ # called. That is what is defined in second part of array.
189
187
  when part.class == Array then
190
188
  if @options.dig(:settings, part.first)
191
189
  #TODO to be defined
@@ -196,9 +194,9 @@ def dc_render_design_part(part)
196
194
  when part.class == Proc then
197
195
  result = part.call
198
196
  result.class == Array ? result.first : result
199
- # Send as string. Evaluate content of string
197
+ # Send as string. Evaluate content of string
200
198
  when part.class == String then eval part
201
- # For future maybe. Just call objects to_s method.
199
+ # For future maybe. Just call objects to_s method.
202
200
  else
203
201
  part.to_s
204
202
  end.html_safe
@@ -231,9 +229,9 @@ end
231
229
  ########################################################################
232
230
  # Helper for rendering top CMS menu when in editing mode
233
231
  ########################################################################
234
- def dc_page_top()
235
- if @design and !@design.rails_view.blank?
236
- # Evaluate parameters in design body
232
+ def dc_page_top
233
+ if @design && @design.rails_view.present?
234
+ # Evaluate parameters in design body
237
235
  eval(@design.body)
238
236
  end
239
237
  session[:edit_mode] > 0 ? render(partial: 'cmsedit/edit_stuff') : ''
@@ -243,8 +241,8 @@ end
243
241
  # Helper for adding additional css and javascript code added by documents
244
242
  # and renderers during page rendering.
245
243
  ########################################################################
246
- def dc_page_bottom()
247
- %Q[<style type="text/css">#{@css}</style>#{javascript_tag @js}].html_safe
244
+ def dc_page_bottom
245
+ %(<style type="text/css">#{@css}</style>#{javascript_tag @js}).html_safe
248
246
  end
249
247
 
250
248
  ############################################################################
@@ -258,10 +256,16 @@ end
258
256
  # Returns:
259
257
  # String. HTML code for title.
260
258
  ############################################################################
261
- def dc_table_title(text, result_set=nil)
262
- c = %Q[<div class="dc-title">#{text}]
259
+ def dc_table_title(text, result_set = nil)
260
+ c = %(<div class="dc-title">#{text})
261
+ # help button
262
+ type = result_set.nil? ? 'form' : 'index'
263
+ form_name = params[:form_name] || params[:table]
264
+ url = url_for(controller: :dc_common, action: :help, type: type, form_name: form_name)
265
+ c << %(<div class="dc-help dc-link-ajax" data-url=#{url}>#{fa_icon('question-circle')}</div>)
266
+
263
267
  if result_set and result_set.respond_to?(:current_page)
264
- c << %Q[<div class="dc-paginate">#{paginate(result_set, :params => {action: 'index', clear: 'no'})}</div>]
268
+ c << %(<div class="dc-paginate">#{paginate(result_set, :params => {action: 'index', clear: 'no', filter: nil})}</div>)
265
269
  end
266
270
  c << '<div style="clear: both;"></div></div>'
267
271
  c.html_safe
@@ -273,21 +277,21 @@ end
273
277
  # Returns:
274
278
  # String. HTML code for title.
275
279
  ############################################################################
276
- def dc_edit_title()
280
+ def dc_edit_title
277
281
  session[:form_processing] = "form:title:"
278
282
  title = @form['form']['title']
279
- # defined as form:title:edit
283
+ # defined as form:title:edit
280
284
  if title and title['edit'] and !@form['readonly']
281
285
  t( title['edit'], title['edit'] )
282
286
  elsif title and title['show'] and @form['readonly']
283
287
  t( title['show'], title['show'] )
284
288
  else
285
- # concatenate title
289
+ # concatenate title
286
290
  c = (@form['readonly'] ? t('drgcms.show') : t('drgcms.edit')) + " : "
287
291
  c << (@form['title'] ? t( @form['title'], @form['title'] ) : t_tablename(@form['table'])) + ' : '
288
292
  title = (title and title['field']) ? title['field'] : @form['form']['edit_title']
289
293
  dc_deprecate('form:edit_title will be deprecated. Use form:title:field instead.') if @form['form']['edit_title']
290
- #
294
+
291
295
  c << "#{@record[ title ]} : " if title and @record.respond_to?(title)
292
296
  c << @record.id if @record
293
297
  end
@@ -303,15 +307,11 @@ end
303
307
  def dc_new_title()
304
308
  session[:form_processing] = "form:title:"
305
309
  title = @form['form']['title']
306
- # defined as form:title:new
310
+ # defined as form:title:new
307
311
  if title and title['new']
308
312
  t( title['new'], title['new'] )
309
313
  else
310
- if @form['table'] == 'dc_dummy'
311
- dc_deprecate('dc_dummy will be deprecated. Use dc_memory instead.')
312
- @form['table'] = 'dc_memory'
313
- end
314
- # in memory variables
314
+ # in memory structures
315
315
  if @form['table'] == 'dc_memory'
316
316
  t( @form['title'], @form['title'] )
317
317
  else
@@ -352,14 +352,16 @@ def dc_submit_tag(caption, icon, parms, rest={})
352
352
  end
353
353
  end
354
354
  html = icon_image || ''
355
- html << submit_tag(t(caption, caption), parms)
355
+ #html << submit_tag(t(caption, caption), parms)
356
+ %Q[<button type="submit" class="dc-submit" name="commit" value="#{t(caption, caption)}">#{icon_image} #{t(caption, caption)}</button>].html_safe
356
357
  end
357
358
 
358
359
  ############################################################################
359
360
  # Returns icon code if icon is specified
360
361
  ############################################################################
361
362
  def dc_icon_for_link(icon)
362
- return nil unless icon
363
+ return nil if icon.nil?
364
+
363
365
  if icon.match(/\./)
364
366
  _origin.image_tag(icon, class: 'dc-link-img dc-animate')
365
367
  elsif icon.match('<i')
@@ -377,7 +379,7 @@ def dc_link_to(caption, icon, parms, rest={})
377
379
  if parms.class == Hash
378
380
  parms.stringify_keys!
379
381
  rest.stringify_keys!
380
- rest['class'] = rest['class'].to_s + ' dc-animate'
382
+ rest['class'] = rest['class'].to_s + ' dc-animate' unless rest['class'].to_s.match('dc-animate')
381
383
  rest['target'] ||= parms.delete('target')
382
384
  parms['controller'] ||= 'cmsedit'
383
385
  icon_pos = parms.delete('icon_pos') || 'first'
@@ -432,22 +434,13 @@ end
432
434
  # Therefore it is very unwise to use non ascii chars for table (collection) names.
433
435
  #
434
436
  # Parameters:
435
- # [string] String. String to be converted into decamelized string.
437
+ # [Object] model_string. String or model to be converted into decamelized string.
436
438
  #
437
439
  # Returns:
438
440
  # String. Decamelized string.
439
441
  ########################################################################
440
- def decamelize_type(string)
441
- return nil if string.nil?
442
- r = ''
443
- string.to_s.each_char do |c|
444
- r << case
445
- when r.size == 0 then c.downcase
446
- when c.downcase != c then '_' + c.downcase
447
- else c
448
- end
449
- end
450
- r
442
+ def decamelize_type(model_string)
443
+ model_string ? model_string.to_s.underscore : nil
451
444
  end
452
445
 
453
446
  ####################################################################
@@ -461,11 +454,12 @@ end
461
454
  # String. HTML code formatted for display.
462
455
  ####################################################################
463
456
  def dc_error_messages_for(doc)
464
- return '' unless doc and doc.errors.any?
457
+ return '' unless doc && doc.errors.any?
458
+
465
459
  msgs = ''
466
- doc.errors.each do |attribute, errors_array|
467
- label = t("helpers.label.#{decamelize_type(doc.class)}.#{attribute}", attribute)
468
- msgs << "<li>#{label} : #{errors_array}</li>"
460
+ doc.errors.each do |error|
461
+ label = t("helpers.label.#{decamelize_type(doc.class)}.#{error.attribute}", error.attribute)
462
+ msgs << "<li>#{label} : #{error.message}</li>"
469
463
  end
470
464
 
471
465
  c = <<eot
@@ -548,14 +542,14 @@ end
548
542
  # Create edit link with edit picture. Subroutine of dc_page_edit_menu.
549
543
  ####################################################################
550
544
  def dc_link_menu_tag(title) #:nodoc:
551
- html = %Q[
545
+ html = %(
552
546
  <dl>
553
547
  <dt><div class='drgcms_popmenu' href="#">
554
548
  #{_origin.fa_icon('file-text-o lg', class: 'dc-inline-link', title: title)}
555
549
  </div></dt>
556
550
  <dd>
557
551
  <ul class=' div-hidden drgcms_popmenu_class'>
558
- ]
552
+ )
559
553
 
560
554
  yield html
561
555
  html << "</ul></dd></dl>"
@@ -589,10 +583,11 @@ end
589
583
  # Returns:
590
584
  # String. HTML code required for manipulation of currently processed document.
591
585
  ########################################################################
592
- def dc_page_edit_menu(opts=@opts)
586
+ def dc_page_edit_menu(opts = @opts)
593
587
  opts[:edit_mode] ||= _origin.session[:edit_mode]
594
588
  return '' if opts[:edit_mode] < 2
595
- # save some data to cookie. This can not go to session.
589
+
590
+ # save some data to cookie. This can not go to session.
596
591
  page = opts[:page] || @page
597
592
  table = _origin.site.page_class.underscore
598
593
  kukis = { "#{table}.dc_design_id" => page.dc_design_id,
@@ -609,11 +604,9 @@ def dc_page_edit_menu(opts=@opts)
609
604
  opts[:editparams].merge!( :id => page.id, :table => _origin.site.page_class.underscore, form_name: opts[:form_name], edit_only: 'body' )
610
605
  html << dc_link_for_edit1( opts[:editparams], t('drgcms.edit_content') )
611
606
 
612
- # opts[:editparams][:edit_only] = nil
613
607
  opts[:editparams].merge!( edit_only: nil, 'icon' => 'pencil' )
614
608
  html << dc_link_for_edit1( opts[:editparams], t('drgcms.edit_advanced') )
615
609
 
616
- # opts[:editparams][:action] = 'new'
617
610
  opts[:editparams].merge!( action: 'new', 'icon' => 'plus' )
618
611
  html << dc_link_for_edit1( opts[:editparams], t('drgcms.edit_new_page') )
619
612
 
@@ -635,8 +628,7 @@ end
635
628
  # type: text_with_select
636
629
  # eval: 'dc_page_class.all_pages_for_site(@parent.dc_get_site)'
637
630
  ########################################################################
638
- def dc_page_class()
639
- # dc_get_site.page_class.classify.constantize
631
+ def dc_page_class
640
632
  dc_get_site.page_klass
641
633
  end
642
634
 
@@ -651,230 +643,10 @@ end
651
643
  # type: tree_view
652
644
  # eval: 'dc_menu_class.all_menus_for_site(@parent.dc_get_site)'
653
645
  ########################################################################
654
- def dc_menu_class()
646
+ def dc_menu_class
655
647
  dc_get_site.menu_class.classify.constantize
656
648
  end
657
649
 
658
-
659
- ####################################################################
660
- # Wrapper for i18 t method, with some spice added. If translation is not found English
661
- # translation value will be returned. And if still not found default value will be returned if passed.
662
- #
663
- # Parameters:
664
- # [key] String. String to be translated into locale.
665
- # [default] String. Value returned if translation is not found.
666
- #
667
- # Example:
668
- # t('translate.this','Enter text for ....')
669
- #
670
- # Returns:
671
- # String. Translated text.
672
- ####################################################################
673
- def t(key, default=nil)
674
- c = I18n.t(key)
675
- if c.class == Hash or c.match( 'translation missing' )
676
- c = I18n.t(key, locale: 'en')
677
- # Still not found. Return default if set
678
- if c.class == Hash or c.match( 'translation missing' )
679
- c = default.nil? ? key : default
680
- end
681
- end
682
- c
683
- end
684
-
685
- ####################################################################
686
- # Returns table (collection) name translation for usage in dialog title. Tablename
687
- # title is provided by helpers.label.table_name.tabletitle locale.
688
- #
689
- # Parameters:
690
- # [tablename] String. Table (collection) name to be translated.
691
- # [default] String. Value returned if translation is not found.
692
- #
693
- # Returns:
694
- # String. Translated text.
695
- ####################################################################
696
- def t_tablename(tablename, default=nil)
697
- t('helpers.label.' + tablename + '.tabletitle', default || tablename)
698
- end
699
-
700
- ############################################################################
701
- # Returns label for field translated to current locale for usage on data entry form.
702
- # Translation is provided by lang.helpers.label.table_name.field_name locale. If
703
- # translation is not found method will capitalize field_name and replace '_' with ' '.
704
- ############################################################################
705
- def t_name(field_name, default='')
706
- c = t("helpers.label.#{@form['table']}.#{field_name}", default)
707
- c = field_name.capitalize.gsub('_',' ') if c.match( 'translation missing' )
708
- c
709
- end
710
-
711
- ############################################################################
712
- # When select field is used on form options for select can be provided by
713
- # helpers.label.table_name.choices4_name locale. This is how select
714
- # field options are translated. Method returns selected choice translated
715
- # to current locale.
716
- #
717
- # Parameters:
718
- # [model] String. Table (collection) model name (lowercase).
719
- # [field] String. Field name used.
720
- # [value] String. Value of field which translation will be returned.
721
- #
722
- # Example:
723
- # # usage in program. Choice values for state are 'Deactivated:0,Active:1,Waiting:2'
724
- # dc_name4_value('dc_user', 'state', @record.active )
725
- #
726
- # # usage in form
727
- # columns:
728
- # 2:
729
- # name: state
730
- # eval: dc_name4_value dc_user, state
731
- #
732
- # Returns:
733
- # String. Descriptive text (translated) for selected choice value.
734
- ############################################################################
735
- def dc_name4_value(model, field, value)
736
- return '' if value.nil?
737
- c = t('helpers.label.' + model + '.choices4_' + field )
738
- a = c.chomp.split(',').inject([]) {|r,v| r << v.split(':') }
739
- a.each {|e| return e.first if e.last.to_s == value.to_s }
740
- ''
741
- end
742
-
743
- ############################################################################
744
- # Return choices for field in model if choices are defined in localization text.
745
- #
746
- # Parameters:
747
- # [model] String. Table (collection) model name (lowercase).
748
- # [field] String. Field name used.
749
- #
750
- # Example:
751
- # dc_choices4_field('dc_user', 'state' )
752
- #
753
- # Returns:
754
- # Array. Choices for select input field
755
- ############################################################################
756
- def dc_choices4_field(model, field)
757
- c = t('helpers.label.' + model + '.choices4_' + field )
758
- return ['error'] if c.match( 'translation missing' )
759
- c.chomp.split(',').inject([]) {|r,v| r << v.split(':') }
760
- end
761
-
762
- ############################################################################
763
- # Will return descriptive text for id key when field in one table (collection) has belongs_to
764
- # relation to other table.
765
- #
766
- # Parameters:
767
- # [model] String. Table (collection) model name (lowercase).
768
- # [field] String. Field name holding the value of descriptive text.
769
- # [field_name] String. ID field name. This is by default id, but can be any other
770
- # (preferred unique) field.
771
- # [value] Value of id_field. Usually a BSON Key but can be any other data type.
772
- #
773
- # Example:
774
- # # usage in program.
775
- # dc_name4_id('dc_user', 'name', nil, dc_page.created_by)
776
- #
777
- # # usage in form
778
- # columns:
779
- # 2:
780
- # name: site_id
781
- # eval: dc_name4_id,site,name
782
- # # username is saved to document instead of user.id field
783
- # 5:
784
- # name: user
785
- # eval: dc_name4_id,dc_user,name,username
786
- #
787
- # Returns:
788
- # String. Name (descriptive value) for specified key in table.
789
- ############################################################################
790
- def dc_name4_id(model, field, field_name, id=nil)
791
- return '' if id.nil?
792
- field_name = (field_name || 'id').strip.to_sym
793
- field = field.strip.to_sym
794
-
795
- model = model.strip.classify.constantize if model.class == String
796
- rec = Mongoid::QueryCache.cache { model.find_by(field_name => id) }
797
- rec.nil? ? '' : (rec.send(field) rescue 'not defined')
798
- end
799
-
800
- ############################################################################
801
- # Return html code for icon presenting boolean value. Icon is a picture of checked or unchecked box.
802
- #
803
- # Parameters:
804
- # [value] Boolean.
805
- #
806
- # Example:
807
- # # usage from program
808
- # dc_icon4_boolean(some_value)
809
- #
810
- # # usage from form description
811
- # columns:
812
- # 10:
813
- # name: active
814
- # eval: dc_icon4_boolean
815
- ############################################################################
816
- def dc_icon4_boolean(value=false)
817
- dc_dont?(value, true) ? fa_icon('square-o lg') : fa_icon('check-square-o lg')
818
- end
819
-
820
- ############################################################################
821
- # Returns html code for displaying date/time formatted by strftime. Will return '' if value is nil.
822
- #
823
- # Parameters:
824
- # [value] Date/DateTime/Time.
825
- # [format] String. strftime format mask. Defaults to locale's default format.
826
- ############################################################################
827
- def dc_format_date_time(value, format=nil)
828
- return '' if value.nil?
829
- format ||= value.class == Date ? t('date.formats.default') : t('time.formats.default')
830
- value.strftime(format)
831
- end
832
-
833
- ####################################################################
834
- #
835
- ####################################################################
836
- def dc_date_time(value, format) #:nodoc:
837
- dc_deprecate 'dc_date_time will be deprecated! Use dc_format_date_time instead.'
838
- dc_format_date_time(value, format)
839
- end
840
-
841
- ############################################################################
842
- # Returns html code for displaying formatted number.
843
- #
844
- # Parameters:
845
- # [value] Numeric number.
846
- # [decimals] Integer. Number of decimals
847
- # [separator] String. Decimals separator
848
- # [delimiter] String. Thousands delimiter.
849
- # [currency] String. Currency symbol if applied to result string.
850
- ############################################################################
851
- def dc_format_number(value=0, decimals=nil, separator=nil, delimiter=nil, currency=nil)
852
- decimals ||= I18n.t('number.currency.format.precision')
853
- separator ||= I18n.t('number.currency.format.separator')
854
- separator = '' if decimals == 0
855
- delimiter ||= I18n.t('number.currency.format.delimiter')
856
- whole, dec = value.to_s.split('.')
857
- whole = '0' if whole.blank?
858
- # remove and remember sign
859
- sign = ''
860
- if whole[0] == '-'
861
- whole.delete_prefix!('-')
862
- sign << '-'
863
- end
864
- # format decimals
865
- dec ||= '0'
866
- dec = dec[0,decimals]
867
- while dec.size < decimals do dec += '0' end
868
- # slice whole on chunks of 3
869
- ar = []
870
- while whole.size > 0 do
871
- n = whole.size >=3 ? 3 : whole.size
872
- ar << whole.slice!(n*-1,n)
873
- end
874
- # put it all back and format
875
- "#{sign}#{ar.reverse.join(delimiter)}#{separator}#{dec}"
876
- end
877
-
878
650
  ####################################################################
879
651
  # Parse site name from url and return dc_site document. Site document will be cached in
880
652
  # @site variable.
@@ -885,23 +657,20 @@ end
885
657
  # Returns:
886
658
  # DCSite. Site document.
887
659
  ####################################################################
888
- def dc_get_site()
660
+ def dc_get_site
889
661
  return @site if @site # already cached
890
- #
662
+
891
663
  req = _origin.request.url # different when called from renderer
892
664
  uri = URI.parse(req)
893
665
  @site = DcSite.find_by(name: uri.host)
894
- # Site can be aliased
895
- if @site and !@site.alias_for.blank?
896
- @site = DcSite.find_by(name: @site.alias_for)
897
- end
898
- # Development environment. Check if site with name test exists and use
899
- # alias_for field as pointer to real site name.
900
- if @site.nil? and ENV["RAILS_ENV"] != 'production'
666
+ # Site can be aliased
667
+ @site = DcSite.find_by(name: @site.alias_for) if @site&.alias_for.present?
668
+ # Development. If site with name test exists use alias_for field as pointer to real site data
669
+ if @site.nil? && ENV["RAILS_ENV"] != 'production'
901
670
  @site = DcSite.find_by(name: 'test')
902
671
  @site = DcSite.find_by(name: @site.alias_for) if @site
903
672
  end
904
- @site = nil if @site and !@site.active # site is disabled
673
+ @site = nil if @site && !@site.active # site is disabled
905
674
  @site
906
675
  end
907
676
 
@@ -917,9 +686,9 @@ end
917
686
  # html:
918
687
  # include_blank: true
919
688
  ############################################################################
920
- def dc_choices4_site_policies()
689
+ def dc_choices4_site_policies
921
690
  site = dc_get_site()
922
- site.dc_policies.all.inject([]) { |r, policy| r << [ policy.name, policy.id] if policy.active }
691
+ site.dc_policies.where(active: true).order_by(name: 1).map { |policy| [ policy.name, policy.id] }
923
692
  end
924
693
 
925
694
  ############################################################################
@@ -940,7 +709,7 @@ def dc_choices4_all_collections
940
709
  DrgCms.paths(:forms).reverse.each do |path|
941
710
  filename = "#{path}/cms_menu.yml"
942
711
  next unless File.exist?(filename)
943
- #
712
+
944
713
  menu = YAML.load_file(filename) rescue nil # load menu
945
714
  next if menu.nil? or !menu['menu'] # not menu or error
946
715
  menu['menu'].each do |section|
@@ -967,14 +736,14 @@ def forms_merge(hash1, hash2) #:nodoc:
967
736
  end
968
737
  target[key] = hash2[key] == '/' ? nil : hash2[key]
969
738
  end
970
- # delete keys with nil value
971
- target.delete_if{ |k,v| v.nil? }
739
+ # delete keys with nil value
740
+ target.delete_if{ |k, v| v.nil? }
972
741
  end
973
742
 
974
743
  ##########################################################################
975
744
  # Returns choices for creating collection edit select field on CMS top menu.
976
745
  ##########################################################################
977
- def dc_choices4_cmsmenu()
746
+ def dc_choices4_cmsmenu
978
747
  menus = {}
979
748
  DrgCms.paths(:forms).reverse.each do |path|
980
749
  filename = "#{path}/cms_menu.yml"
@@ -983,7 +752,7 @@ def dc_choices4_cmsmenu()
983
752
  next if menu.nil? or !menu['menu'] # not menu or error
984
753
  menus = forms_merge(menu['menu'], menus) # ignore top level part
985
754
  end
986
- #
755
+
987
756
  html = '<ul>'
988
757
  menus.to_a.sort.each do |index, menu| # sort menus, result is array of sorted hashes
989
758
  next unless menu['caption']
@@ -1048,12 +817,11 @@ def dc_choices4(model, name, id='_id', options = {})
1048
817
  sites << nil if param == :with_nil
1049
818
  qry = qry.in(dc_site_id: sites) if sites
1050
819
  end
1051
- qry = qry.and(active: true) if model.method_defined?(:active)
1052
- # qry = qry.sort(name => 1)
1053
- # choices = []
1054
- # qry.each {|v| choices << [ v[name], v[id] ] }
1055
- choices = qry.inject([]) {|result,e| result << [ e[name], e[id] ]}
1056
- choices.sort_alphabetical_by(&:first) # use UTF-8 sort
820
+ qry = qry.and(active: true) if model.method_defined?(:active)
821
+ qry = qry.order_by(name => 1).collation(locale: I18n.locale.to_s)
822
+ #choices = qry.inject([]) {|result,e| result << [ e[name], e[id] ]}
823
+ #choices.sort_alphabetical_by(&:first) # use UTF-8 sort
824
+ qry.map { |e| [e[name], e[id]] }
1057
825
  end
1058
826
 
1059
827
  ############################################################################
@@ -1114,35 +882,35 @@ end
1114
882
  ############################################################################
1115
883
  def dc_user_can_view(ctrl, policy_id)
1116
884
  policy_id = policy_id.policy_id if policy_id and policy_id.respond_to?(:policy_id)
1117
- # Eventualy object without policy_id will be checked. This is to prevent error
885
+ # Eventualy object without policy_id will be checked. This is to prevent error
1118
886
  policy_id = nil unless policy_id.class == BSON::ObjectId
1119
- #
887
+
1120
888
  site = ctrl.site
1121
889
  policies = if site.inherit_policy.blank?
1122
890
  site.dc_policies
1123
891
  else
1124
892
  Mongoid::QueryCache.cache { DcSite.find(site.inherit_policy) }.dc_policies
1125
893
  end
1126
- # permission defined by default policy
894
+ # permission defined by default policy
1127
895
  default_policy = Mongoid::QueryCache.cache { policies.find_by(is_default: true) }
1128
896
  return false, 'Default access policy not found for the site!' unless default_policy
1129
- #
897
+
1130
898
  permissions = {}
1131
899
  default_policy.dc_policy_rules.to_a.each { |v| permissions[v.dc_policy_role_id] = v.permission }
1132
- # update permissions with defined policy
900
+ # update permissions with defined policy
1133
901
  part_policy = nil
1134
902
  if policy_id
1135
903
  part_policy = Mongoid::QueryCache.cache { policies.find(policy_id) }
1136
904
  return false, 'Access policy not found for part!' unless part_policy
1137
905
  part_policy.dc_policy_rules.to_a.each { |v| permissions[v.dc_policy_role_id] = v.permission }
1138
906
  end
1139
- # apply guest role if no roles defined
907
+ # apply guest role if no roles defined
1140
908
  if ctrl.session[:user_roles].nil?
1141
909
  role = Mongoid::QueryCache.cache { DcPolicyRole.find_by(system_name: 'guest', active: true) }
1142
910
  return false, 'System guest role not defined!' unless role
1143
911
  ctrl.session[:user_roles] = [role.id]
1144
912
  end
1145
- # Check if user has any role that allows him to view part
913
+ # Check if user has any role that allows him to view part
1146
914
  can_view, msg = false,''
1147
915
  ctrl.session[:user_roles].each do |role|
1148
916
  next unless permissions[role] # role not yet defined. Will die in next line.
@@ -1178,10 +946,10 @@ def dc_user_has_role( role, user=nil, roles=nil )
1178
946
  roles = _origin.session[:user_roles] if roles.nil?
1179
947
  user = _origin.session[:user_id] if user.nil?
1180
948
  return false if user.nil? or roles.nil?
1181
- #
949
+
1182
950
  role = DcPolicyRole.get_role(role)
1183
951
  return false if role.nil?
1184
- # role is included in roles array
952
+ # role is included in roles array
1185
953
  roles.include?(role._id)
1186
954
  end
1187
955
 
@@ -1200,7 +968,8 @@ end
1200
968
  ####################################################################
1201
969
  def dc_dont?(what, default=false)
1202
970
  return default if what.nil?
1203
- %w(0 no - false none).include?(what.to_s.downcase.strip)
971
+
972
+ %w(0 n - no none false).include?(what.to_s.downcase.strip)
1204
973
  end
1205
974
 
1206
975
  ############################################################################
@@ -1219,6 +988,7 @@ end
1219
988
  ############################################################################
1220
989
  def dc_limit_string(string, size)
1221
990
  return string if string.size < size
991
+
1222
992
  string = string[0,size]
1223
993
  string.chop! until (string[-1,1] == ' ' or string == '')
1224
994
  string << '...'
@@ -1246,10 +1016,11 @@ def dc_big_table(key)
1246
1016
  bt = DcBigTable.find_by(key: key, site: dc_get_site._id, active: true)
1247
1017
  bt = DcBigTable.find_by(key: key, site: nil, active: true) if bt.nil?
1248
1018
  return ret if bt.nil?
1249
- #
1019
+
1250
1020
  locale = I18n.locale.to_s
1251
1021
  bt.dc_big_table_values.each do |v| # iterate each value
1252
1022
  next unless v.active
1023
+
1253
1024
  desc = ''
1254
1025
  v.dc_big_table_locales.each do |l| # iterate each locale
1255
1026
  if l.locale == locale
@@ -1304,40 +1075,50 @@ def dc_iframe_edit(table, opts={})
1304
1075
  end
1305
1076
 
1306
1077
  ########################################################################
1307
- # Will return value from internal DRG variables.
1308
- # This objects can be params, session, ...
1078
+ # Will return value from Rails and DRG internal objects.
1079
+ # This objects can be params, session, record, site, page
1309
1080
  #
1310
1081
  # Parameters:
1311
- # [object] String: Internal object holding variable. Current values can be session, params, site, page
1082
+ # [object] String: Internal object holding variable. Possible values are session, params, record, site, page, class
1312
1083
  # [var_name] String[symbol]: Variable name (:user_name, 'user_id', ...)
1084
+ # [current_document] Object: If passed and object is 'record' then it will be used for retrieving data.
1313
1085
  #
1314
1086
  # Example:
1315
1087
  # # called when constructing iframe for display
1316
- # dc_internal_var(session, :user_id)
1317
- # dc_internal_var(params, :some_external_parameter)
1318
- # dc_internal_var(site, :name)
1088
+ # dc_internal_var('session', :user_id)
1089
+ # dc_internal_var('params', :some_external_parameter)
1090
+ # dc_internal_var('site', :name)
1091
+ # # or even
1092
+ # dc_internal_var('class', 'ClassName.class_method_name')
1093
+ #
1319
1094
  #
1320
1095
  # Returns:
1321
- # Value of variable or nil when not found
1096
+ # Value of variable or error when not found
1322
1097
  ########################################################################
1323
- def dc_internal_var(object, var_name)
1098
+ def dc_internal_var(object, var_name, current_document = nil)
1324
1099
  begin
1325
1100
  case
1326
- when object == 'session' then _origin.session[var_name]
1327
- when object == 'params' then _origin.params[var_name]
1328
- when object == 'site' then _origin.dc_get_site.send(var_name)
1329
- when object == 'page' then _origin.page.send(var_name)
1330
- when object == 'record' then _origin.record.send(var_name)
1101
+ when object == 'session' then _origin.session[var_name]
1102
+ when object == 'params' then _origin.params[var_name]
1103
+ when object == 'site' then _origin.dc_get_site.send(var_name)
1104
+ when object == 'page' then _origin.page.send(var_name)
1105
+ when object == 'record' then
1106
+ current_document ? current_document.send(var_name) : _origin.record.send(var_name)
1107
+ when object == 'class' then
1108
+ clas, method_name = var_name.split('.')
1109
+ klas = clas.classify.constantize
1110
+ # call method. Error will be caught below.
1111
+ klas.send(method_name)
1331
1112
  else
1332
1113
  'VARIABLE: UNKNOWN OBJECT'
1333
1114
  end
1334
1115
  rescue Exception => e
1335
- logger.error "Method dc_internal_var. Runtime error. #{e.message}"
1116
+ Rails.logger.debug "\ndc_internal_var. Runtime error. #{e.message}\n"
1117
+ Rails.logger.debug(e.backtrace.join($/)) if Rails.env.development?
1336
1118
  'VARIABLE: ERROR'
1337
1119
  end
1338
1120
  end
1339
1121
 
1340
-
1341
1122
  ########################################################################
1342
1123
  # Will return whole path to document if document is embedded in another document.
1343
1124
  #