drg_cms 0.7.0.8 → 0.7.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/drg_cms/drg_cms.js +50 -20
  3. data/app/assets/stylesheets/drg_cms/drg_cms.css +89 -31
  4. data/app/assets/stylesheets/drg_cms/select-multiple.css +5 -6
  5. data/app/controllers/cmsedit_controller.rb +57 -24
  6. data/app/controllers/dc_application_controller.rb +18 -21
  7. data/app/controls/dc_poll_result_control.rb +36 -36
  8. data/app/controls/dc_setup_control.rb +53 -0
  9. data/app/forms/all_options.yml +3 -3
  10. data/app/forms/cms_menu.yml +7 -0
  11. data/app/forms/dc_image_search.yml +2 -2
  12. data/app/forms/dc_poll.yml +2 -1
  13. data/app/forms/dc_poll_result.yml +10 -7
  14. data/app/forms/dc_setup.yml +45 -0
  15. data/app/forms/dc_steps_template.yml +4 -1
  16. data/app/helpers/cms_common_helper.rb +14 -10
  17. data/app/helpers/cms_helper.rb +8 -7
  18. data/app/helpers/cms_index_helper.rb +56 -42
  19. data/app/helpers/dc_application_helper.rb +46 -16
  20. data/app/helpers/dc_image_helper.rb +2 -2
  21. data/app/models/concerns/dc_user_concern.rb +1 -1
  22. data/app/models/dc_big_table.rb +1 -1
  23. data/app/models/dc_filter.rb +5 -9
  24. data/app/models/dc_image.rb +1 -1
  25. data/app/models/dc_memory.rb +2 -2
  26. data/app/models/dc_setup.rb +111 -0
  27. data/app/models/drgcms_form_fields/datetime_picker.rb +1 -1
  28. data/app/models/drgcms_form_fields/embedded.rb +17 -9
  29. data/app/models/drgcms_form_fields/multitext_autocomplete.rb +44 -36
  30. data/app/models/drgcms_form_fields/select.rb +21 -5
  31. data/app/renderers/dc_big_menu_renderer.rb +18 -20
  32. data/app/renderers/dc_menu_renderer.rb +21 -58
  33. data/app/renderers/dc_simple_menu_renderer.rb +1 -1
  34. data/app/views/cmsedit/_edit_stuff.html.erb +3 -0
  35. data/config/locales/drgcms_en.yml +8 -0
  36. data/config/locales/drgcms_sl.yml +12 -4
  37. data/config/locales/models_en.yml +17 -1
  38. data/config/locales/models_sl.yml +17 -1
  39. data/lib/drg_cms/version.rb +1 -1
  40. data/lib/drg_cms.rb +22 -23
  41. data/lib/generators/new_drg_form/new_drg_form_generator.rb +32 -14
  42. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f2d3e3ad52492c5dccf2b91cd7c9c1ea203b7a60c21b0e3d4f7947a3b298bd8b
4
- data.tar.gz: a9b23d36c053d8770a661827a211e88172ccadf10eb0c0f17419e0069799f402
3
+ metadata.gz: 836e52abeb4f9f04c54c21d66c4c053b5bc9cb8906904ce6c608b0c03edc57d7
4
+ data.tar.gz: 86469fb38b082d39f20ce81ee903354e11d693db34060a224cf031facd554b45
5
5
  SHA512:
6
- metadata.gz: f745ccb1e0902369746c51da513b1487eca95b1bc02f1bd427ccca2403fc2fd54341cccf8359ab301206fcc5ae4e61d13f03ee30d42b5d3ce0e14a3d357b7d54
7
- data.tar.gz: e61ee50affe2a0aa4a2ea5fd5a386cad6b3a0f614c2fd3233cab5a5ae47e553eeab290ab527678265153d76352b37dac95867a1ff558b4a4c29dcafbb080fcaf
6
+ metadata.gz: af0af1882f81f7240438b80a4138c415ada71850395ce149f3a9b4d30b5e8858081aad9a438e9a7a9749a8e75cc0b16775aec187785a765870d4d726aa4f66e1
7
+ data.tar.gz: d8c3c2d0184e4e97451962203a64d7d4a2e59dd08e5e48320d05f0203a12f8e50cbd0263958d2af189c7ef84f0627f95067558321fb0d44f4ce88b7683897b5d
@@ -120,6 +120,8 @@ update_select_depend = function(select_name, depend_name, method) {
120
120
  $.each(data, function(index, element) {
121
121
  select_field.append( new Option(element['label'], element['id']) );
122
122
  });
123
+ // refresh multiple select field
124
+ if (select_field.hasClass('select-multiple')) { select_field.selectMultiple('refresh') }
123
125
  }
124
126
  });
125
127
  };
@@ -292,10 +294,12 @@ process_json_result = function(json) {
292
294
  closeClass: 'dc-link' });
293
295
  }
294
296
  else {
295
- $('#popup').html(value);
297
+ if (selector == '') { selector = 'info' }
298
+ let popup_html = '<div class="popup-' + selector + '">' + value + '<br><button class="dc-link">OK</button></div>';
299
+ $('#popup').html(popup_html);
296
300
  $('#popup').bPopup( {
297
301
  transition: 'slideDown', transitionClose: 'slideDown', speed: 300,
298
- opacity: 0, position: ['auto', 20],
302
+ opacity: 0, position: ['auto', 'auto'],
299
303
  closeClass: 'dc-link' });
300
304
  }
301
305
  // resize parent iframe if smaller then 500px to ensure popup some space
@@ -520,19 +524,44 @@ dc_image_preview = function(img) {
520
524
  *******************************************************************/
521
525
  dc_image_select = function(img) {
522
526
  let ck_func_name = $.getUrlParam('CKEditorFuncNum');
523
- let field_name = $.getUrlParam('field_name');
524
- if (ck_func_name !== '') {
527
+ let field_name = $.getUrlParam('field_name');
528
+ if (ck_func_name) {
525
529
  window.opener.CKEDITOR.tools.callFunction(ck_func_name, img);
526
530
  } else {
527
531
  window.opener.document.getElementById(field_name).value = img;
532
+
533
+ // update image preview
534
+ //let img_src = window.opener.$(`#td_${field_name} .dc-image-preview img`);
535
+ //img_src.attr("src", img);
536
+
537
+ // even better. Click save button.
538
+ window.opener.$(`.mi.mi-save`).first().click();
528
539
  }
529
540
  window.close();
530
541
  };
531
542
 
532
-
533
543
  /*******************************************************************
534
- * Events start here
544
+ * Resize iframe_embedded to the size of form.
535
545
  *******************************************************************/
546
+ function resize_iframe_embedded(that) {
547
+ let embedded_height = that.contentWindow.document.body.offsetHeight;
548
+ // workaround. It gets tricky when embedded field is on tab
549
+ if (embedded_height == 0) embedded_height = 50;
550
+ that.style.height = (embedded_height + 30) + 'px';
551
+ // resize parent element too
552
+ let parentWindow= that.contentWindow.parent;
553
+ let parent_height= (parentWindow.document.body.offsetHeight + 30) + 'px';
554
+ parentWindow.frameElement.style.height = parent_height;
555
+ };
556
+
557
+
558
+ /*******************************************************************
559
+ *
560
+ *
561
+ * EVENTS START HERE
562
+ *
563
+ *
564
+ ********************************************************************/
536
565
  $(document).ready( function() {
537
566
  /* This could be the way to focus on first input field on document open
538
567
  if ( $('.dc-form')[0] ) {
@@ -580,6 +609,7 @@ $(document).ready( function() {
580
609
  $('.cms-toggle').bind('click', function(e) {
581
610
  var url = '/dc_common/toggle_edit_mode?return_to=' + window.location.href;
582
611
  if (e.pageX < 30) url = url + '&return_to_ypos=' + e.pageY ;
612
+ console.log(url);
583
613
  window.location.href = url;
584
614
  });
585
615
 
@@ -691,7 +721,7 @@ $(document).ready( function() {
691
721
  });
692
722
 
693
723
  /*******************************************************************
694
- * Resize iframe_cms to the size of its contents. Make at least 500 px high
724
+ * Resize iframe_cms on load to the size of its contents. Make at least 500 px high
695
725
  * unless on initial display.
696
726
  *******************************************************************/
697
727
  $('#iframe_cms').on('load', function() {
@@ -703,7 +733,7 @@ $(document).ready( function() {
703
733
  });
704
734
 
705
735
  /*******************************************************************
706
- * Same goes for editiframe. Resize it + 30px
736
+ * Resize iframe_edit on load to the size of its contents. Resize it + 30px
707
737
  * unless on initial display with no data
708
738
  *******************************************************************/
709
739
  $('#iframe_edit').on('load', function() {
@@ -715,18 +745,16 @@ $(document).ready( function() {
715
745
  });
716
746
 
717
747
  /*******************************************************************
718
- * Same goes for iframe_embedded. Resize it + 30px
748
+ * Resize iframe_embedded on load to the size of its contents.
749
+ * It doesn't work well with firefox, when CK editor object is on the form.
750
+ * Adding some delay is resolving the problem.
719
751
  *******************************************************************/
720
752
  $('.iframe_embedded').on('load', function() {
721
- let embedded_height = this.contentWindow.document.body.offsetHeight;
722
- // workaround. It gets tricky when embedded field is on tab
723
- if (embedded_height == 0) embedded_height = 50;
724
- this.style.height = (embedded_height + 30) + 'px';
725
- // resize parent iframe window too
726
- let parentWindow = this.contentWindow.parent;
727
- let parent_height = (parentWindow.document.body.offsetHeight + 30) + 'px';
728
- //parentWindow.frameElement.setAttribute('style', 'height:' + parent_height);
729
- parentWindow.frameElement.style.height = parent_height;
753
+ if (/Firefox/.test(navigator.userAgent)) {
754
+ setTimeout(resize_iframe_embedded, 100, this);
755
+ } else {
756
+ resize_iframe_embedded(this);
757
+ }
730
758
  });
731
759
 
732
760
  /*******************************************************************
@@ -856,11 +884,13 @@ $(document).ready( function() {
856
884
  let title = this.getAttribute("title");
857
885
  let w = this.getAttribute("data-x") || 1000;
858
886
  let h = this.getAttribute("data-y") || 800;
887
+ let offset = parent.window.scrollY || window.scrollY;
859
888
 
860
889
  url = dc_url_add_params(this, url)
861
890
  $('#popup').bPopup({ loadUrl: url,
862
- transition: 'slideDown', transitionClose: 'slideDown', speed: 300,
863
- opacity: 0, position: ['auto', 20],
891
+ transition: 'slideDown', transitionClose: 'slideDown',
892
+ speed: 300, opacity: 0,
893
+ position: ['auto', offset + 20],
864
894
  closeClass: 'dc-link'
865
895
  });
866
896
  });
@@ -45,7 +45,7 @@
45
45
  font-family: DrgSans;
46
46
  font-style: normal;
47
47
  font-weight: 600;
48
- src: url('ibm-plex-sans-600.woff2') format('woff2')
48
+ src: url('ibm-plex-sans-600.woff2') format('woff2');
49
49
  }
50
50
  @font-face {
51
51
  font-family: DrgSans;
@@ -83,7 +83,6 @@ time, mark, audio, video {
83
83
  margin: 0;
84
84
  padding: 0;
85
85
  border: 0;
86
- font-size: 100%;
87
86
  font: inherit;
88
87
  vertical-align: baseline;
89
88
  }
@@ -138,6 +137,10 @@ textarea, input, select {
138
137
  max-width: 200px;
139
138
  }
140
139
 
140
+ .dc-action-menu .ui-autocomplete-input {
141
+ padding: 8px 4px 8px 12px;
142
+ }
143
+
141
144
  textarea:focus, input:focus, select:focus {
142
145
  border: 1px solid rgba(44, 142, 255, 1);
143
146
  outline: 1px solid rgba(44, 142, 255, 1);
@@ -643,8 +646,7 @@ display: inline-table;
643
646
  /***** FORM *****/
644
647
 
645
648
  #dc-form-container {
646
- display: flex;
647
- padding-left: 4px;
649
+ /*display: flex;*/
648
650
  }
649
651
 
650
652
  #dc-form-left {
@@ -659,7 +661,7 @@ display: inline-table;
659
661
  }
660
662
 
661
663
  .dc-form-frame {
662
- margin: 0px;
664
+ margin: 0;
663
665
  padding: 4px;
664
666
  }
665
667
 
@@ -683,7 +685,6 @@ display: inline-table;
683
685
  border-radius: 2px;
684
686
  margin: 2px 0;
685
687
  }
686
-
687
688
  .dc-form-warning {
688
689
  padding: 8px;
689
690
  background-image: linear-gradient(to bottom, rgba(213, 143, 218, 0.1) 0, rgba(213, 143, 218, 0.5) 100%);
@@ -715,7 +716,7 @@ display: inline-table;
715
716
  color: #555;
716
717
  text-align: right;
717
718
  vertical-align: middle;
718
- font-weight: 600;
719
+ font-weight: 500;
719
720
  padding: 10px 2px;
720
721
  width: 150px;
721
722
  }
@@ -735,6 +736,8 @@ display: inline-table;
735
736
 
736
737
  .dc-form-label.dc-color-odd, .dc-form-label.dc-color-even {background-color: transparent;}
737
738
 
739
+ .dc-form-label.dc-width-0 { padding: 0;}
740
+
738
741
  .dc-align-left {
739
742
  text-align: left;
740
743
  }
@@ -745,7 +748,7 @@ display: inline-table;
745
748
  .dc-form-field {
746
749
  text-align: left;
747
750
  padding: 4px 2px;
748
- z-index: 10;
751
+ /*z-index: 10;*/
749
752
  white-space: nowrap;
750
753
  text-overflow: fade;
751
754
  }
@@ -1076,6 +1079,7 @@ font-size: 1.2em;
1076
1079
  font-size: 1.1em;
1077
1080
  line-height: 1.4em;
1078
1081
  }
1082
+
1079
1083
  /****** jquery ui-autocomplete widget ***************/
1080
1084
  .ui-autocomplete-input {
1081
1085
  padding: 8px 4px 8px 12px;
@@ -1137,16 +1141,7 @@ color: #000;
1137
1141
  margin-left: 4px;
1138
1142
  }
1139
1143
 
1140
-
1141
- .dc-red { color: #f76;}
1142
- .dc-red:hover { color: #c43;}
1143
- .dc-green { color: #9c9;}
1144
- .dc-green:hover { color: #6a6;}
1145
-
1146
- .aui-corner-all {
1147
- background-color: lightyellow;
1148
- }
1149
-
1144
+ /************* login *************/
1150
1145
  #dc-login {
1151
1146
  position: fixed;
1152
1147
  top: 50%;
@@ -1206,10 +1201,10 @@ color: #000;
1206
1201
  color: white;
1207
1202
  }
1208
1203
  .iframe_embedded {
1209
- padding: 4px;
1204
+ padding: 2px;
1210
1205
  background-color: #fff;
1211
1206
  border-radius: 2px;
1212
- border: 2px solid #666;
1207
+ border: 2px solid #888;
1213
1208
  }
1214
1209
 
1215
1210
  #iframe_edit, #iframe_cms {
@@ -1387,6 +1382,7 @@ color: #000;
1387
1382
  max-height: 700px;
1388
1383
  overflow-y: auto;
1389
1384
  max-width: 800px;
1385
+ line-height: 1.5em;
1390
1386
  }
1391
1387
 
1392
1388
  #popup .dc-help h1 {
@@ -1480,6 +1476,35 @@ color: #000;
1480
1476
  display: inline-flex;
1481
1477
  }
1482
1478
 
1479
+ #popup:has(.popup-info) {
1480
+ padding: 1rem;
1481
+ background-image: linear-gradient(to bottom, #dff0d8 0, #c8e5bc 100%);
1482
+ color: darkgreen;
1483
+ font-weight: 600;
1484
+ font-size: 1.1em;
1485
+ min-width: 30%;
1486
+ border: 2px solid darkgreen;
1487
+ }
1488
+
1489
+ #popup:has(.popup-error) {
1490
+ padding: 1rem;
1491
+ background-image: linear-gradient(to bottom, #f2dede 0, #e7c3c3 100%);
1492
+ color: #a94442;
1493
+ font-weight: 600;
1494
+ font-size: 1.1em;
1495
+ min-width: 30%;
1496
+ border: 2px solid #a94442;
1497
+ }
1498
+
1499
+ #popup .popup-info button, #popup .popup-error button {
1500
+ margin-top: 1rem;
1501
+ padding: 4px 2rem;
1502
+ line-height: initial;
1503
+ filter: none;
1504
+ border: 2px solid #222;
1505
+ border-radius: 5px;
1506
+ }
1507
+
1483
1508
  .filter-popup {
1484
1509
  background-color: #fff;
1485
1510
  filter: drop-shadow(2px 2px 8px #888);
@@ -1549,7 +1574,7 @@ cursor: pointer;
1549
1574
 
1550
1575
  #drgcms_filter h1 {
1551
1576
  font-size: 1.8em;
1552
- font-width: 600;
1577
+ font-weight: 600;
1553
1578
  color: rgba(44, 142, 255, 1);
1554
1579
  }
1555
1580
 
@@ -1572,6 +1597,36 @@ cursor: pointer;
1572
1597
  margin-left: 1px;
1573
1598
  }
1574
1599
 
1600
+ /**** reports ****/
1601
+ .report .dc-title { color: #003A68; }
1602
+ .report .dc-result-header {
1603
+ border-bottom: 2px solid #003A68;
1604
+ }
1605
+ .report .dc-result-header .th {
1606
+ color: #003A68;
1607
+ padding: 3px;
1608
+ }
1609
+
1610
+ .report .dc-result-data {
1611
+ padding: 0;
1612
+ }
1613
+
1614
+ .report.dc-form-frame {
1615
+ padding: 0;
1616
+ }
1617
+
1618
+
1619
+ .report .dc-result-data .td {
1620
+ padding: 3px;
1621
+ }
1622
+
1623
+ .iframe_embedded#if_dc_temp {
1624
+ border: none;
1625
+ padding: 0;
1626
+ }
1627
+
1628
+ .report .dc-odd {background-color: #e0eeff;}
1629
+
1575
1630
  /** Radio button input field **/
1576
1631
 
1577
1632
  .dc-radio {
@@ -1613,18 +1668,13 @@ cursor: pointer;
1613
1668
  @media only screen and (max-device-width: 600px) {
1614
1669
  #body-cms {font-size: 11px;}
1615
1670
  #site-top div:nth-of-type(2) {padding-top: 0 !important;}
1616
- .dc-title { font-size: 1.5em;}
1617
-
1618
- .dc-form {
1619
- border: none;
1620
- border-top: 2px solid #888;
1621
- border-bottom: 2px solid #888;
1622
- margin-top: 4px;
1671
+ .dc-title {
1672
+ font-size: 1.5em;
1673
+ padding-bottom: 4px;
1623
1674
  }
1675
+ .dc-form-field { padding-bottom: 4px; }
1624
1676
 
1625
- .dc-form .row-div {
1626
- display: block;
1627
- }
1677
+ .dc-form .row-div { display: block; }
1628
1678
  .dc-form-li {margin-top: 3px;}
1629
1679
 
1630
1680
  .dc-form-label {
@@ -1635,6 +1685,7 @@ cursor: pointer;
1635
1685
  }
1636
1686
  .dc-form-label label {
1637
1687
  font-size: 15px;
1688
+ padding: 0;
1638
1689
  }
1639
1690
 
1640
1691
  .dc-menu { padding: 0;}
@@ -1670,6 +1721,13 @@ cursor: pointer;
1670
1721
  font-size: 2em;
1671
1722
  }
1672
1723
 
1724
+ #menu-hamburger .mi:before{
1725
+ background-color: #222;
1726
+ color: #fff;
1727
+ padding: 1px;
1728
+ border-radius: 2px;
1729
+ }
1730
+
1673
1731
  .cmsedit-container {display: block;}
1674
1732
  .cmsedit-container #cms-menu {display: none;}
1675
1733
  .cmsedit-container #cms-menu.visible {
@@ -63,20 +63,19 @@
63
63
  }
64
64
 
65
65
  .ms-container .ms-selectable li.ms-elem-selectable{
66
- padding: 3px 10px;
66
+ padding: 5px 10px;
67
67
  color: #444;
68
- /* font-size: 14px;*/
69
68
  }
70
69
 
71
- .ms-container .ms-selectable li:nth-child(odd) {
72
- background-color: #f4f4f4;
70
+ .ms-container .ms-selectable li:nth-child(even) {
71
+ background-color: #f8f8f8;
73
72
  }
74
73
 
75
74
  .ms-container .ms-selectable li.ms-hover{
76
75
  cursor: pointer;
77
76
  color: #fff;
78
77
  text-decoration: none;
79
- background-color: #08c;
78
+ background-color: rgba(76,154,255, 0.6);
80
79
  }
81
80
 
82
81
  .ms-container .ms-selectable li.disabled{
@@ -92,10 +91,10 @@
92
91
 
93
92
  .ms-container .ms-selected {
94
93
  font-weight: 600;
94
+ color: darkblue !important;
95
95
  }
96
96
 
97
97
  .pull-right.ms-elem-selected{
98
98
  float: right;
99
- font-size: smaller;
100
99
  padding-left: 4px;
101
100
  }
@@ -77,7 +77,7 @@
77
77
  ########################################################################
78
78
  class CmseditController < DcApplicationController
79
79
  before_action :check_authorization, :except => [:login, :logout, :test, :run]
80
- protect_from_forgery with: :null_session, only: Proc.new { |c| c.request.format.json? }
80
+ protect_from_forgery with: :null_session, only: Proc.new { _1.request.format.json? }
81
81
 
82
82
  layout 'cms'
83
83
 
@@ -108,6 +108,10 @@ end
108
108
  ########################################################################
109
109
  def show
110
110
  find_record
111
+ if @record.nil?
112
+ flash[:error] ||= t('drgcms.doc_no_edit')
113
+ return index
114
+ end
111
115
  # before_show callback
112
116
  if (m = callback_method('before_show') )
113
117
  ret = call_callback_method(m)
@@ -270,11 +274,8 @@ def create
270
274
  # create document
271
275
  if params['id'].nil?
272
276
  # Prevent double form submit
273
- params[:form_time_stamp] = params[:form_time_stamp].to_i
274
- session[:form_time_stamp] ||= 0
275
- return index if params[:form_time_stamp] <= session[:form_time_stamp] && !Rails.env.test?
277
+ return index if double_form_submit?
276
278
 
277
- session[:form_time_stamp] = params[:form_time_stamp]
278
279
  create_new_empty_record
279
280
  if save_data
280
281
  flash[:info] = t('drgcms.doc_saved')
@@ -549,14 +550,14 @@ def check_authorization
549
550
  end
550
551
  dc_form_read
551
552
 
552
- # Permissions can be also defined on form
553
+ # Permissions can be also defined in form
553
554
  #TODO So far only can_view is used. Think about if using other permissions has sense
554
555
  can_view = @form.dig('permissions','can_view')
555
- if can_view.nil? or dc_user_has_role(can_view)
556
+ if can_view.nil? || can_view.split(',').any? { |role| dc_user_has_role(role) }
556
557
  extend_with_control_module
557
558
  else
558
559
  render(action: 'error', locals: { error: t('drgcms.not_authorized')} )
559
- end
560
+ end
560
561
  end
561
562
 
562
563
  ########################################################################
@@ -716,10 +717,10 @@ def save_data
716
717
 
717
718
  form_fields.each do |v|
718
719
  session[:form_processing] = v['name'] # for debuging
719
- next if v['type'].nil? or v['name'].nil? or
720
- v['type'].match('embedded') or # don't wipe embedded types
721
- (params[:edit_only] and params[:edit_only] != v['name']) or # otherwise other fields would be wiped
722
- v['readonly'] or # fields with readonly option don't return value and would be wiped
720
+ next if v['type'].nil? || v['name'].nil? ||
721
+ v['type'].match('embedded') || # don't wipe embedded types
722
+ (params[:edit_only] && params[:edit_only] != v['name']) || # otherwise other fields would be wiped
723
+ v['readonly'] || # fields with readonly option don't return value and would be wiped
723
724
  !@record.respond_to?(v['name']) # there are temporary fields on the form
724
725
  # good to know! How to get type of field @record.fields[v['name']].type
725
726
  # return value from form field definition
@@ -736,7 +737,7 @@ def save_data
736
737
 
737
738
  # save data
738
739
  changes = @record.changes
739
- update_standards() if changes.size > 0 # update only if there has been some changes
740
+ update_standards if changes.size > 0 # update only if there has been some changes
740
741
  if (saved = @record.save)
741
742
  operation = @record.new_record? ? :new : :update
742
743
  save_journal(operation, @record.previous_changes)
@@ -751,9 +752,9 @@ end
751
752
  # in select_fields and deny_fields
752
753
  ########################################################################
753
754
  def separated_to_symbols(data)
754
- data.chomp.split(',').map { |e| e.strip.downcase.to_sym }
755
+ data.chomp.split(',').map { _1.strip.downcase.to_sym }
755
756
  end
756
-
757
+
757
758
  ########################################################################
758
759
  # Will process only (select_fields) and without (deny_fields) option
759
760
  ########################################################################
@@ -877,19 +878,14 @@ def process_collections #:nodoc
877
878
  end
878
879
 
879
880
  ########################################################################
880
- # Process index action for in memory data.
881
+ # Process index action for in memory data. default_filter method must fill @records array
882
+ # with data, that will be shown in browser.
881
883
  ########################################################################
882
884
  def process_in_memory #:nodoc
883
885
  @records = []
884
886
  # result set is defined by filter method in control object
885
- if (method = @form['result_set']['filter'])
886
- send(method) if respond_to?(method)
887
- end
888
- # result set is defined by class method
889
- if (klass_method = @form['result_set']['filter_method'])
890
- _klass, method = klass_method.split('.')
891
- klass = _klass.classify.constantize
892
- @records = klass.send(method) if klass.respond_to?(method)
887
+ if (method = @form['result_set']['filter'] || 'default_filter')
888
+ send(method) if respond_to?(method)
893
889
  end
894
890
  # ensure that record has id field
895
891
  if @records.size > 0
@@ -898,4 +894,41 @@ def process_in_memory #:nodoc
898
894
  false
899
895
  end
900
896
 
897
+ ########################################################################
898
+ # Prevent double form submit
899
+ #
900
+ # There was a problem with old solution when user opened another browser session while
901
+ # entering data into new document. If in new session user added document to some other
902
+ # collection, save to document in primary session was silently ignored. Now creation time for last three forms
903
+ # is remembered. This will work unless user tries to add new document to the same collection in another session.
904
+ # But that is highly unlikely.
905
+ ########################################################################
906
+ def double_form_submit?
907
+ session[:dfs] ||= {}
908
+ form_name = CmsHelper.form_param(params) || CmsHelper.table_param(params)
909
+ params[:form_time_stamp] = params[:form_time_stamp].to_i
910
+ if params[:form_time_stamp] <= update_dfs_time(form_name) && !Rails.env.test? # test must be excluded
911
+ flash[:error] = I18n.t('drgcms.dfs')
912
+ return true
913
+ end
914
+ update_dfs_time(form_name, params[:form_time_stamp])
915
+
916
+ false
917
+ end
918
+
919
+ ########################################################################
920
+ # Updates double_form_submit timings.
921
+ ########################################################################
922
+ def update_dfs_time(form_name, time = nil)
923
+ if time.nil?
924
+ session[:dfs][form_name] ||= 0
925
+ else
926
+ session[:dfs][form_name] = time
927
+ if session[:dfs].size > 3
928
+ oldest = session[:dfs].invert.min
929
+ session[:dfs].delete(oldest.last)
930
+ end
931
+ end
932
+ end
933
+
901
934
  end
@@ -85,7 +85,7 @@ def dc_get_site
85
85
  uri = URI.parse(request.url)
86
86
  cache_key = ['dc_site', uri.host]
87
87
 
88
- @site = dc_cache_read(cache_key)
88
+ @site = DrgCms.cache_read(cache_key)
89
89
  return @site if @site
90
90
 
91
91
  @site = DcSite.find_by(name: uri.host)
@@ -100,7 +100,7 @@ def dc_get_site
100
100
  @site = DcSite.find_by(name: @site.alias_for) if @site
101
101
  end
102
102
  @site = nil if @site && !@site.active # site is disabled
103
- dc_cache_write(cache_key, @site)
103
+ DrgCms.cache_write(cache_key, @site)
104
104
  end
105
105
 
106
106
  ##########################################################################
@@ -160,15 +160,10 @@ protected
160
160
  # if dc_user_can(DcPermission::CAN_VIEW, params[:table]) then ...
161
161
  ############################################################################
162
162
  def dc_user_can(permission, table = params[:table])
163
- table = table.underscore
164
- cache_key = ['dc_permission', table, dc_get_site.id]
165
- permissions = DrgCms.cache_read(cache_key)
166
- if permissions.nil?
167
- permissions = DcPermission.permissions_for_table(table)
168
- DrgCms.cache_write(cache_key, permissions)
169
- end
170
163
  return false if session[:user_roles].nil?
171
164
 
165
+ table = table.underscore
166
+ permissions = DrgCms.cache_read(['dc_permission', table, dc_get_site.id]) { DcPermission.permissions_for_table(table) }
172
167
  session[:user_roles].inject(false) { |r, rule| break true if permissions[rule] && permissions[rule] >= permission }
173
168
  end
174
169
 
@@ -800,7 +795,7 @@ private
800
795
  #
801
796
  # @return [Boolean] : True if redis cache store is active
802
797
  ########################################################################
803
- def redis_cache_store?
798
+ def xredis_cache_store?
804
799
  (Rails.application.config.cache_store.first == :redis_cache_store) rescue false
805
800
  end
806
801
 
@@ -809,31 +804,33 @@ end
809
804
  #
810
805
  # @return [Object] : Redis object
811
806
  ########################################################################
812
- def redis
807
+ def xredis
813
808
  Rails.cache.redis
814
809
  end
815
810
 
816
811
  ########################################################################
817
- # Extends DRGCMS form file. Extended file is processed first and then merged
812
+ # Extends DRG CMS form file. Extended file is processed first and then merged
818
813
  # with code in this form file. Form can extend only single form file.
819
814
  #
820
815
  # [Parameters:]
821
816
  # [extend_option] : Value of @form['extend'] option
822
817
  ########################################################################
823
818
  def dc_form_extend(extend_option)
824
- form_file_name = CmsHelper.form_file_find(extend_option)
825
- @form_js << read_js_drg_form(form_file_name)
826
- form = YAML.load_file( form_file_name )
827
- @form = CmsHelper.forms_merge(form, @form)
828
- # If combined form contains tabs and fields options, merge fields into tabs
829
- if @form['form']['tabs'] && @form['form']['fields']
830
- @form['form']['tabs']['fields'] = @form['form']['fields']
831
- @form['form']['fields'] = nil
819
+ extend_option.chomp.split(',').each do |a_file|
820
+ form_file_name = CmsHelper.form_file_find(a_file.strip)
821
+ @form_js << read_js_drg_form(form_file_name)
822
+ form = YAML.load_file( form_file_name )
823
+ @form = CmsHelper.forms_merge(form, @form)
824
+ # If combined form contains tabs and fields options, move fields into fields tab
825
+ if @form.dig('form', 'tabs') && @form.dig('form', 'fields')
826
+ @form['form']['tabs']['fields'] = @form['form']['fields']
827
+ @form['form']['fields'] = nil
828
+ end
832
829
  end
833
830
  end
834
831
 
835
832
  ########################################################################
836
- # Include code from another DRGCMS form file. Included code is merged
833
+ # Include code from another DRG CMS form file. Included code is merged
837
834
  # with current form file code. Form can include more than one other DRGCMS forms.
838
835
  #
839
836
  # [Parameters:]