active_scaffold 4.1.6 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.rdoc +27 -0
  3. data/README.md +6 -5
  4. data/app/assets/javascripts/jquery/active_scaffold.js +98 -47
  5. data/app/assets/javascripts/jquery/tiny_mce_bridge.js +15 -2
  6. data/app/assets/stylesheets/active_scaffold_images.scss +6 -0
  7. data/app/assets/stylesheets/{active_scaffold_layout.css → active_scaffold_layout.scss} +104 -4
  8. data/app/assets/stylesheets/tiny_mce_bridge.scss +11 -0
  9. data/app/views/active_scaffold_overrides/_base_form.html.erb +3 -2
  10. data/app/views/active_scaffold_overrides/_field_search.html.erb +2 -2
  11. data/app/views/active_scaffold_overrides/_form.html.erb +14 -4
  12. data/app/views/active_scaffold_overrides/_form_association.html.erb +1 -1
  13. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +5 -11
  14. data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +1 -1
  15. data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +1 -3
  16. data/app/views/active_scaffold_overrides/_new_record.js.erb +3 -1
  17. data/app/views/active_scaffold_overrides/_refresh_list.js.erb +1 -1
  18. data/app/views/active_scaffold_overrides/_render_field.js.erb +67 -36
  19. data/app/views/active_scaffold_overrides/_update_field_on_create.js.erb +41 -6
  20. data/app/views/active_scaffold_overrides/action_links_menu.js.erb +1 -0
  21. data/config/locales/de.yml +9 -0
  22. data/config/locales/en.yml +11 -0
  23. data/config/locales/es.yml +8 -0
  24. data/config/locales/fr.yml +8 -0
  25. data/config/locales/hu.yml +8 -0
  26. data/config/locales/ja.yml +8 -0
  27. data/config/locales/ru.yml +8 -0
  28. data/lib/active_scaffold/actions/common_search.rb +2 -0
  29. data/lib/active_scaffold/actions/core.rb +47 -23
  30. data/lib/active_scaffold/actions/create.rb +2 -0
  31. data/lib/active_scaffold/actions/delete.rb +6 -0
  32. data/lib/active_scaffold/actions/field_search.rb +36 -11
  33. data/lib/active_scaffold/actions/list.rb +26 -8
  34. data/lib/active_scaffold/actions/mark.rb +6 -0
  35. data/lib/active_scaffold/actions/nested.rb +2 -0
  36. data/lib/active_scaffold/actions/search.rb +7 -0
  37. data/lib/active_scaffold/actions/show.rb +6 -0
  38. data/lib/active_scaffold/actions/subform.rb +2 -0
  39. data/lib/active_scaffold/actions/update.rb +8 -1
  40. data/lib/active_scaffold/active_record_permissions.rb +3 -3
  41. data/lib/active_scaffold/attribute_params.rb +35 -17
  42. data/lib/active_scaffold/bridges/active_storage/active_storage_bridge.rb +2 -0
  43. data/lib/active_scaffold/bridges/active_storage/active_storage_helpers.rb +10 -9
  44. data/lib/active_scaffold/bridges/active_storage/form_ui.rb +10 -3
  45. data/lib/active_scaffold/bridges/active_storage/list_ui.rb +2 -0
  46. data/lib/active_scaffold/bridges/active_storage.rb +2 -0
  47. data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +2 -0
  48. data/lib/active_scaffold/bridges/ancestry.rb +2 -0
  49. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +2 -0
  50. data/lib/active_scaffold/bridges/bitfields/list_ui.rb +2 -0
  51. data/lib/active_scaffold/bridges/bitfields.rb +2 -0
  52. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +9 -6
  53. data/lib/active_scaffold/bridges/cancan.rb +2 -0
  54. data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +2 -0
  55. data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge_helpers.rb +2 -0
  56. data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +3 -1
  57. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +2 -0
  58. data/lib/active_scaffold/bridges/carrierwave.rb +2 -0
  59. data/lib/active_scaffold/bridges/chosen/helpers.rb +13 -4
  60. data/lib/active_scaffold/bridges/chosen.rb +2 -0
  61. data/lib/active_scaffold/bridges/country_select/country_select_bridge_helper.rb +2 -0
  62. data/lib/active_scaffold/bridges/country_select.rb +2 -0
  63. data/lib/active_scaffold/bridges/date_picker/ext.rb +6 -0
  64. data/lib/active_scaffold/bridges/date_picker/helper.rb +7 -3
  65. data/lib/active_scaffold/bridges/date_picker.rb +2 -0
  66. data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge.rb +2 -0
  67. data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge_helpers.rb +2 -0
  68. data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +3 -1
  69. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +2 -0
  70. data/lib/active_scaffold/bridges/dragonfly.rb +2 -0
  71. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +2 -0
  72. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +10 -9
  73. data/lib/active_scaffold/bridges/file_column/form_ui.rb +2 -0
  74. data/lib/active_scaffold/bridges/file_column/list_ui.rb +2 -0
  75. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +2 -0
  76. data/lib/active_scaffold/bridges/file_column/test/mock_model.rb +2 -0
  77. data/lib/active_scaffold/bridges/file_column.rb +2 -0
  78. data/lib/active_scaffold/bridges/logical_query_parser/tokens_grammar.rb +65 -0
  79. data/lib/active_scaffold/bridges/logical_query_parser/tokens_grammar.treetop +31 -0
  80. data/lib/active_scaffold/bridges/logical_query_parser.rb +9 -0
  81. data/lib/active_scaffold/bridges/paper_trail/actions.rb +2 -0
  82. data/lib/active_scaffold/bridges/paper_trail/config.rb +2 -0
  83. data/lib/active_scaffold/bridges/paper_trail/helper.rb +2 -0
  84. data/lib/active_scaffold/bridges/paper_trail/paper_trail_bridge.rb +2 -0
  85. data/lib/active_scaffold/bridges/paper_trail.rb +2 -0
  86. data/lib/active_scaffold/bridges/paperclip/form_ui.rb +3 -1
  87. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +2 -0
  88. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +2 -0
  89. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +12 -12
  90. data/lib/active_scaffold/bridges/paperclip.rb +2 -0
  91. data/lib/active_scaffold/bridges/record_select/helpers.rb +19 -11
  92. data/lib/active_scaffold/bridges/record_select.rb +2 -0
  93. data/lib/active_scaffold/bridges/semantic_attributes/column.rb +2 -0
  94. data/lib/active_scaffold/bridges/semantic_attributes.rb +2 -0
  95. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +3 -1
  96. data/lib/active_scaffold/bridges/tiny_mce.rb +6 -0
  97. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +2 -0
  98. data/lib/active_scaffold/bridges/usa_state_select.rb +2 -0
  99. data/lib/active_scaffold/bridges.rb +2 -0
  100. data/lib/active_scaffold/config/base.rb +12 -7
  101. data/lib/active_scaffold/config/core.rb +26 -23
  102. data/lib/active_scaffold/config/create.rb +2 -0
  103. data/lib/active_scaffold/config/delete.rb +2 -0
  104. data/lib/active_scaffold/config/field_search.rb +2 -0
  105. data/lib/active_scaffold/config/form.rb +11 -1
  106. data/lib/active_scaffold/config/list.rb +7 -7
  107. data/lib/active_scaffold/config/mark.rb +2 -0
  108. data/lib/active_scaffold/config/nested.rb +28 -0
  109. data/lib/active_scaffold/config/search.rb +2 -0
  110. data/lib/active_scaffold/config/show.rb +2 -0
  111. data/lib/active_scaffold/config/subform.rb +2 -0
  112. data/lib/active_scaffold/config/update.rb +3 -1
  113. data/lib/active_scaffold/configurable.rb +4 -2
  114. data/lib/active_scaffold/constraints.rb +2 -0
  115. data/lib/active_scaffold/core.rb +14 -4
  116. data/lib/active_scaffold/data_structures/action_columns.rb +3 -1
  117. data/lib/active_scaffold/data_structures/action_link.rb +10 -0
  118. data/lib/active_scaffold/data_structures/action_link_separator.rb +2 -0
  119. data/lib/active_scaffold/data_structures/action_links.rb +32 -21
  120. data/lib/active_scaffold/data_structures/actions.rb +4 -2
  121. data/lib/active_scaffold/data_structures/association/abstract.rb +4 -2
  122. data/lib/active_scaffold/data_structures/association/active_mongoid.rb +4 -2
  123. data/lib/active_scaffold/data_structures/association/active_record.rb +3 -9
  124. data/lib/active_scaffold/data_structures/association/mongoid.rb +4 -2
  125. data/lib/active_scaffold/data_structures/association.rb +2 -0
  126. data/lib/active_scaffold/data_structures/bridge.rb +3 -1
  127. data/lib/active_scaffold/data_structures/column.rb +37 -3
  128. data/lib/active_scaffold/data_structures/columns.rb +4 -2
  129. data/lib/active_scaffold/data_structures/filter.rb +3 -3
  130. data/lib/active_scaffold/data_structures/filter_option.rb +2 -0
  131. data/lib/active_scaffold/data_structures/filters.rb +3 -3
  132. data/lib/active_scaffold/data_structures/nested_info.rb +4 -2
  133. data/lib/active_scaffold/data_structures/set.rb +8 -10
  134. data/lib/active_scaffold/data_structures/sorting.rb +5 -7
  135. data/lib/active_scaffold/engine.rb +3 -4
  136. data/lib/active_scaffold/extensions/action_controller_rendering.rb +2 -0
  137. data/lib/active_scaffold/extensions/action_controller_rescueing.rb +2 -0
  138. data/lib/active_scaffold/extensions/action_view_rendering.rb +2 -0
  139. data/lib/active_scaffold/extensions/connection_adapter.rb +2 -0
  140. data/lib/active_scaffold/extensions/ice_nine.rb +2 -0
  141. data/lib/active_scaffold/extensions/localize.rb +2 -0
  142. data/lib/active_scaffold/extensions/name_option_for_datetime.rb +2 -0
  143. data/lib/active_scaffold/extensions/paginator_extensions.rb +3 -1
  144. data/lib/active_scaffold/extensions/routing_mapper.rb +2 -0
  145. data/lib/active_scaffold/extensions/to_label.rb +2 -0
  146. data/lib/active_scaffold/extensions/unsaved_associated.rb +10 -8
  147. data/lib/active_scaffold/extensions/unsaved_record.rb +2 -0
  148. data/lib/active_scaffold/finder.rb +57 -18
  149. data/lib/active_scaffold/helpers/action_link_helpers.rb +112 -37
  150. data/lib/active_scaffold/helpers/association_helpers.rb +4 -2
  151. data/lib/active_scaffold/helpers/controller_helpers.rb +2 -0
  152. data/lib/active_scaffold/helpers/filter_helpers.rb +11 -3
  153. data/lib/active_scaffold/helpers/form_column_helpers.rb +98 -71
  154. data/lib/active_scaffold/helpers/human_condition_helpers.rb +2 -0
  155. data/lib/active_scaffold/helpers/id_helpers.rb +2 -0
  156. data/lib/active_scaffold/helpers/list_column_helpers.rb +9 -5
  157. data/lib/active_scaffold/helpers/pagination_helpers.rb +3 -1
  158. data/lib/active_scaffold/helpers/search_column_helpers.rb +19 -9
  159. data/lib/active_scaffold/helpers/show_column_helpers.rb +4 -2
  160. data/lib/active_scaffold/helpers/tabs_helpers.rb +5 -3
  161. data/lib/active_scaffold/helpers/view_helpers.rb +3 -3
  162. data/lib/active_scaffold/marked_model.rb +6 -5
  163. data/lib/active_scaffold/orm_checks.rb +2 -0
  164. data/lib/active_scaffold/paginator.rb +4 -1
  165. data/lib/active_scaffold/registry.rb +2 -0
  166. data/lib/active_scaffold/responds_to_parent.rb +2 -0
  167. data/lib/active_scaffold/tableless.rb +23 -13
  168. data/lib/active_scaffold/version.rb +4 -2
  169. data/lib/active_scaffold.rb +10 -2
  170. data/lib/generators/active_scaffold/controller/USAGE +19 -0
  171. data/lib/generators/active_scaffold/controller/controller_generator.rb +29 -0
  172. data/lib/generators/active_scaffold/install/USAGE +2 -0
  173. data/lib/generators/active_scaffold/{install_generator.rb → install/install_generator.rb} +10 -6
  174. data/lib/generators/active_scaffold/resource/USAGE +29 -0
  175. data/lib/generators/active_scaffold/resource/resource_generator.rb +30 -0
  176. data/lib/tasks/brakeman.rake +2 -0
  177. data/shoulda_macros/macros.rb +2 -0
  178. metadata +19 -11
  179. data/lib/generators/active_scaffold/controller_generator.rb +0 -49
  180. data/lib/generators/active_scaffold/resource_generator.rb +0 -56
  181. /data/lib/generators/{templates → active_scaffold/controller/templates}/controller.rb +0 -0
  182. /data/lib/generators/{templates → active_scaffold/controller/templates}/helper.rb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32a8692802d39053416d7af7e631ab4c83ba65ebeca2e1f5e8c61d36f5290521
4
- data.tar.gz: 352724ef265132cdcbc025700ef45b4d5699d16f25ceefbd84e6e9890911b2d3
3
+ metadata.gz: 2b0a91aeeb1bc60a06fe9860ed1dd816c7b1c31af2f1ec5ba0edd40eca14aeab
4
+ data.tar.gz: c65e359d10216b4a68740814292c4428adcb92fbc4982143f4bdcb245c40fd19
5
5
  SHA512:
6
- metadata.gz: 2e28a6a5db3582b4a7175320f799b1fcf1c69e9cfcc4c6740937be291d5c86b111e93e544caad63bc6c1cc9089dd1c3d965fd899cb5c74a96172147b24be5191
7
- data.tar.gz: eae22752d95d2b141396d8f1c78421fee01f5bacca00c834012d42ce024f98ac0098c540ef17554ac4fd901c40a5fdff017221e508a6c703190213fe5f576025
6
+ metadata.gz: b6a1157e40597529cc709046dc473313df2f4e57e188b6525ec705a2b2d63ee9e4bd3710dc001aa98ff3dd1c55b3168a8276cca3ff52e4e3464b89edea89dec5
7
+ data.tar.gz: 357b94e6fb8e5de5d90d881ea2f797c33b388e8d01401fd5004c05f16f7e6c0148a67532600cb33d7fb3f44b1935c7d4ad8b76b2fbcd55f9b5edeb37bd6c211b
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,30 @@
1
+ = 4.2.0
2
+ - Integrate LogicalQueryParser, supporting full logical search, or simplified searches with 'all keywords' and 'any keyword' operators.
3
+ - Display unauthorized column in form as show action, so show_ui or show override is used if exists.
4
+ - Display unauthorized subform with show_ui as show action, to display readonly subform tables.
5
+ - Add subform_includes to column, and preload_for_form method to preload associations on edit action, speed up on big forms with long subforms or many nested subforms.
6
+ - Speedup on refreshing columns and saving big forms.
7
+ - Support add_new with chosen bridge.
8
+ - Added translations for millisec and microsec prompts in jquery UI datetime picker.
9
+ - Speed up validating big forms (e.g. nested subforms with many records on each subform).
10
+ - Support hiding field descriptions by default and show them with hover or click.
11
+ - Fix for usage with frozen literal strings enabled, add magic comments to enable frozen string literals in ActiveScaffold.
12
+ - Update code for tabs to work with bootstrap 5.
13
+ - Add ActiveScaffold.setup_callbacks array, so functions can be added to be called when ActiveScaffold.setup is called (form open, page load).
14
+ - Add add_new_link to config.nested, adding a link to create form on an association, refreshing this record instead of adding new row in the list.
15
+ - Support hashes in update_columns, keys are association names or :__root__ to refresh fields on subforms or at top of the form, values are list of columns or nested hashes.
16
+ - Add custom_modules, in active_scaffold_config and global, to add modules which will be included after ActiveScaffold action modules, to customize the controllers.
17
+ - Add active_scaffold_subform_record_actions helper to render the destroy action on the rows of a subform, so it can be used to add more actions.
18
+ - Improve ActiveStorage bridge to keep existing files in has_many_attachments.
19
+ - Helpers used by file upload bridges have been renamed and moved the JS code to active_scaffold.js.
20
+ - Support action link groups to open with click, like actions showing dynamic action link group.
21
+ - Open dynamic action link group nested in the menu tree, under the action opening it.
22
+ - Add sort_joins to column, defaults to includes value, so it's possible to set sort by SQL without joining the includes, or join with some associations, and preload others.
23
+ - Fix when textarea is required and uses tinymce, show the validation error if it's empty and sync the content before submitting.
24
+ - Support add_new in collection associations too, only with popup mode (add_new: true will default to popup in such associations)
25
+ - Support for rails 8.0 and 8.1
26
+ _ Cache action link generation to speed up list rendering
27
+
1
28
  = 4.1.6
2
29
  - Fix add_existing
3
30
 
data/README.md CHANGED
@@ -2,8 +2,8 @@
2
2
  Overview
3
3
  ========
4
4
  [![Build status](https://github.com/activescaffold/active_scaffold/actions/workflows/ci.yml/badge.svg)](https://github.com/activescaffold/active_scaffold/actions/workflows/ci.yml)
5
- [![Code Climate](https://codeclimate.com/github/activescaffold/active_scaffold/badges/gpa.svg)](https://codeclimate.com/github/activescaffold/active_scaffold)
6
- [![Test Coverage](https://codeclimate.com/github/activescaffold/active_scaffold/badges/coverage.svg)](https://codeclimate.com/github/activescaffold/active_scaffold)
5
+ [![Maintainability](https://qlty.sh/gh/activescaffold/projects/active_scaffold/maintainability.svg)](https://qlty.sh/gh/activescaffold/projects/active_scaffold)
6
+ [![Code Coverage](https://qlty.sh/gh/activescaffold/projects/active_scaffold/coverage.svg)](https://qlty.sh/gh/activescaffold/projects/active_scaffold)
7
7
  [![Gem Version](https://badge.fury.io/rb/active_scaffold.svg)](https://badge.fury.io/rb/active_scaffold)
8
8
  [![Inline docs](https://inch-ci.org/github/activescaffold/active_scaffold.svg?branch=master)](https://inch-ci.org/github/activescaffold/active_scaffold)
9
9
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
@@ -12,10 +12,11 @@ ActiveScaffold provides a quick and powerful user interfaces for CRUD (create, r
12
12
 
13
13
  Branch Details
14
14
  --------------
15
- master supports rails >= 7.0.x and <= 7.2.x, and ruby >= 3.1.0
16
- 4-0-stable supports rails >= 6.1.x and <= 7.2.x, and ruby >= 3.0.0
15
+ master supports rails >= 7.2.x and ruby >= 3.2.0
16
+ 4-1-stable supports rails >= 7.0.x and <= 7.2.x, and ruby >= 3.1.0
17
17
 
18
18
  These versions are not supported anymore:
19
+ 4-0-stable supports rails >= 6.1.x and <= 7.2.x, and ruby >= 2.5.0
19
20
  3-7-stable supports rails >= 5.2.x and <= 7.1.x, and ruby >= 2.5.0
20
21
  3-6-stable supports rails >= 4.2.x and <= 6.1.x, and ruby >= 2.3.0
21
22
  3-5-stable supports rails >= 4.0.x and <= 5.1.x, and ruby >= 2.0.0
@@ -69,7 +70,7 @@ When upgrading from 3.x, add `active_scaffold/manifest.js` to `app/assets/config
69
70
 
70
71
  Changing column settings on a request has changed, it must use `active_scaffold_config.columns.override(:name)` at least the first time. After calling `columns.override(:name)`, calling it again or calling `columns[:name]` will return the overrided column. It also supports a block. See [Per Request Configuration](https://github.com/activescaffold/active_scaffold/wiki/Per-Request-Configuration) for examples and more comprehensive explanation.
71
72
 
72
- Changing columns for an action (e.g. add or exclude) on a request must use active_scaffold_config.actions.override_columns, the first time, or use assignment.
73
+ Changing columns for an action (e.g. add or exclude) on a request must use active_scaffold_config.action.override_columns, e.g. active_scaffold_config.list.override_columns, the first time, or use assignment.
73
74
 
74
75
  If you have a `_form_association_record` partial view overrided, use `record` local variable instead of `form_association_record`.
75
76
 
@@ -40,7 +40,11 @@
40
40
  jQuery(document).on('focus', ':input', function() { ActiveScaffold.last_focus = this; });
41
41
  jQuery(document).on('blur', ':input', function(e) { ActiveScaffold.last_focus = e.relatedTarget; });
42
42
  jQuery(document).click(function(event) {
43
- jQuery('.action_group.dyn > ul').hide(); // only hide so action links loading still work
43
+ if (!jQuery(event.target).closest('.action_group.dyn').length) {
44
+ jQuery('.action_group.dyn > .dynamic-menu').each(function() {
45
+ ActiveScaffold.remove_dynamic_action_group(this);
46
+ });
47
+ }
44
48
  });
45
49
  jQuery(document).on('ajax:beforeSend', 'form.as_form', function(event) {
46
50
  var as_form = jQuery(this).closest("form");
@@ -115,6 +119,7 @@
115
119
  if (action_link.is_disabled()) {
116
120
  return false;
117
121
  } else {
122
+ if (action_link.position == 'popup') ActiveScaffold.open_popup('<div class="loading"></div>', action_link);
118
123
  if (action_link.loading_indicator) action_link.loading_indicator.css('visibility','visible');
119
124
  action_link.disable();
120
125
  }
@@ -150,6 +155,8 @@
150
155
  var action_link = ActiveScaffold.ActionLink.get(jQuery(this));
151
156
  if (action_link) {
152
157
  ActiveScaffold.report_500_response(action_link.scaffold_id(), xhr);
158
+ if (action_link.position == 'popup') action_link.close();
159
+ if (action_link.loading_indicator) action_link.loading_indicator.css('visibility','hidden');
153
160
  action_link.enable();
154
161
  }
155
162
  return true;
@@ -241,6 +248,22 @@
241
248
  if (span.data('editInPlace')) span.trigger('click.editInPlace');
242
249
  else ActiveScaffold.in_place_editor_field_clicked(span);
243
250
  });
251
+ jQuery(document).on('click', '.file-input-controls .remove-file-btn', function(event) {
252
+ event.preventDefault();
253
+ var btn = jQuery(this), file_line = btn.closest('.file-input-controls');
254
+ if (file_line.find('.remove_file').val('true').length) {
255
+ btn.parent().hide();
256
+ file_line.find('input').show();
257
+ if (file_line.attr('required')) file_line.find('input').attr('required', 'required');
258
+ } else {
259
+ file_line.remove();
260
+ }
261
+ return false;
262
+ });
263
+ jQuery(document).on('change', '.file-input-controls input[type=file]', function(event) {
264
+ var file_line = jQuery(this).closest('.file-input-controls');
265
+ file_line.find('.remove_file').val('false');
266
+ });
244
267
  jQuery(document).on('ajax:before', 'a.as_paginate',function(event) {
245
268
  var as_paginate = jQuery(this);
246
269
  as_paginate.prevAll('img.loading-indicator').css('visibility','visible');
@@ -270,10 +293,14 @@
270
293
  return true;
271
294
  } else return false;
272
295
  });
273
- jQuery(document).on('ajax:complete', '.action_group.dyn > ul a', function(event) {
274
- var action_link = ActiveScaffold.find_action_link(event.target);
275
- if (action_link && action_link.loading_indicator) action_link.loading_indicator.css('visibility','hidden');
276
- jQuery(event.target).closest('.action_group.dyn > ul').remove();
296
+ jQuery(document).on('ajax:complete', '.action_group.dyn > .dynamic-menu a', function(event) {
297
+ var action_link = ActiveScaffold.find_action_link(event.target), link = jQuery(event.target);
298
+ if (action_link && action_link.loading_indicator) action_link.loading_indicator.css('visibility', 'hidden');
299
+ setTimeout(function() {
300
+ if (!link.parent().is('.action_group.dyn')) {
301
+ ActiveScaffold.remove_dynamic_action_group(link.closest('.action_group.dyn > .dynamic-menu'));
302
+ }
303
+ }, 100);
277
304
  });
278
305
 
279
306
  jQuery(document).on('change', 'input.update_form:not(.recordselect), textarea.update_form, select.update_form, .checkbox-list.update_form input:checkbox', function(event, additional_params) {
@@ -334,7 +361,7 @@
334
361
 
335
362
  jQuery(document).on('click', '.active-scaffold .sub-form a.destroy', function(event) {
336
363
  event.preventDefault();
337
- ActiveScaffold.delete_subform_record(jQuery(this).data('delete-id'));
364
+ ActiveScaffold.remove(jQuery(this).closest('.sub-form-record'));
338
365
  });
339
366
 
340
367
  jQuery(document).on("click", '.hover_click', function(event) {
@@ -367,8 +394,8 @@
367
394
  });
368
395
 
369
396
  jQuery(document).on('click', '.hide-new-subform, .show-new-subform', function(e) {
370
- var $this = jQuery(this), line = $this.closest('.form-element, td'),
371
- subform = line.find('#' + $this.data('subform-id')), radio = false, hide, select;
397
+ var $this = jQuery(this), line = $this.closest('.form-element'),
398
+ subform = line.find('#' + $this.data('subform-id')), radio = false, hide, field;
372
399
  if ($this.is('[type=radio]')) {
373
400
  radio = true;
374
401
  hide = $this.is('.hide-new-subform');
@@ -377,17 +404,16 @@
377
404
  hide = subform.is(':visible');
378
405
  }
379
406
  if ($this.data('select-id')) {
380
- select = line.find('#' + $this.data('select-id'));
381
- if (select.hasClass('recordselect') || select.is('.no-options')) select = select.next(':hidden').addBack();
407
+ field = line.find('#' + $this.data('select-id')).closest('.select-field');
382
408
  }
383
409
  if (hide) {
384
410
  subform.hide().find("input:enabled,select:enabled,textarea:enabled").prop('disabled', true);
385
- if (select) select.show().prop('disabled', false);
411
+ if (field) field.show().find('input:disabled,select:disabled,textarea:disabled').prop('disabled', false);
386
412
  if (radio) {
387
413
  $this.closest('.form-element').find('[name="' + $this.attr('name') + '"].show-new-subform').prop('disabled', false);
388
414
  } else $this.html($this.data('select-text'));
389
415
  } else {
390
- if (select) select.hide().prop('disabled', true);
416
+ if (field) field.hide().find('input:enabled,select:enabled,textarea:enabled').prop('disabled', true);
391
417
  subform.show().find("input:disabled,select:disabled,textarea:disabled").prop('disabled', false);
392
418
  if (radio) $this.prop('disabled', true);
393
419
  else {
@@ -401,7 +427,7 @@
401
427
  jQuery(this).parent().find('[type=submit]').click();
402
428
  }));
403
429
 
404
- jQuery(document).on('click', 'form.search .reset[data-reset]', function(e){
430
+ jQuery(document).on('click', 'form.search [data-reset]', function(e){
405
431
  e.preventDefault();
406
432
  var form = jQuery(this).closest('form.search');
407
433
  form.find(
@@ -468,6 +494,14 @@
468
494
  e.preventDefault();
469
495
  ActiveScaffold.update_all_checkboxes(jQuery(this), false);
470
496
  });
497
+ jQuery(document).on('click', '.descriptions-click .description:not(.visible)', function(e) {
498
+ e.preventDefault();
499
+ $(this).addClass('visible');
500
+ });
501
+ jQuery(document).on('click', '.descriptions-click .description.visible .close', function(e) {
502
+ e.preventDefault();
503
+ $(this).closest('.description').removeClass('visible');
504
+ });
471
505
  });
472
506
 
473
507
  jQuery(document).on('turbolinks:load turbo:load', function($) {
@@ -556,7 +590,7 @@
556
590
  ActiveScaffold.auto_paginate(container);
557
591
  ActiveScaffold.draggable_lists('.draggable-lists', container);
558
592
  ActiveScaffold.sliders(container);
559
- ActiveScaffold.disable_optional_subforms(container);
593
+ setTimeout(function() { ActiveScaffold.disable_optional_subforms(container) }); // delay hiding fields, in case some field need to be visible, e.g. chosen
560
594
  ActiveScaffold.update_floating_form_footer(); // check other forms too, state may change
561
595
  if (container != document) {
562
596
  jQuery('[data-rs-type]', container).each(function() { RecordSelect.from_attributes(jQuery(this)); });
@@ -612,9 +646,8 @@
612
646
  var line = $this.closest('.form-element'), toggle = line.find('.show-new-subform[data-subform-id="' + $this.attr('id') + '"]').first();
613
647
  if (toggle.is('[type=radio]')) toggle.prop('disabled', true);
614
648
  else if (toggle.data('select-id')) {
615
- var select = line.find('#' + toggle.data('select-id'));
616
- if (select.hasClass('recordselect') || select.is('.no-options')) select = select.next(':hidden').addBack();
617
- select.hide().prop('disabled', true);
649
+ var field = line.find('#' + toggle.data('select-id')).closest('.select-field');
650
+ field.hide().find('input:enabled,select:enabled,textarea:enabled').prop('disabled', true);
618
651
  }
619
652
  } else $this.find("input:enabled,select:enabled,textarea:enabled").prop('disabled', true);
620
653
  });
@@ -885,12 +918,6 @@
885
918
  });
886
919
  },
887
920
 
888
- delete_subform_record: function(record) {
889
- if (typeof(record) == 'string') record = '#' + record;
890
- record = jQuery(record).closest('.sub-form-record');
891
- this.remove(record);
892
- },
893
-
894
921
  report_500_response: function(active_scaffold_id, xhr) {
895
922
  var server_error = jQuery(active_scaffold_id).find('.messages-container p.server-error').first();
896
923
  if (server_error.is(':visible')) {
@@ -911,16 +938,21 @@
911
938
  display_dynamic_action_group: function(link, html) {
912
939
  var container;
913
940
  if (typeof(link) == 'string') link = jQuery('#' + link);
914
- if (link.closest('td.actions').length) {
915
- container = link.closest('td').addClass('action_group dyn');
916
- } else {
917
- if (link.parent('div.actions').length) link.wrap(jQuery('<div>'));
918
- container = link.parent().addClass('action_group dyn');
941
+ if (link.parent('.actions').length) link.wrap(jQuery('<div>'));
942
+ container = link.parent().addClass('action_group dyn');
943
+ if (ActiveScaffold.config.dynamic_group_parent_class) {
944
+ container.addClass(ActiveScaffold.config.dynamic_group_parent_class);
919
945
  }
920
- container.find('> ul').remove();
946
+ container.find('> .dynamic-menu').remove();
921
947
  container.append(html);
922
948
  },
923
949
 
950
+ remove_dynamic_action_group: function(group) {
951
+ group = jQuery(group);
952
+ group.closest('.action_group.dyn').removeClass(ActiveScaffold.config.dynamic_group_parent_class);
953
+ group.remove();
954
+ },
955
+
924
956
  scroll_to: function(element, checkInViewport) {
925
957
  if (typeof checkInViewport == 'undefined') checkInViewport = true;
926
958
  if (typeof(element) == 'string') element = '#' + element;
@@ -1004,7 +1036,14 @@
1004
1036
  var element, container = source.closest('.sub-form-record'), selector = '';
1005
1037
  if (container.length === 0) {
1006
1038
  container = source.closest('form > ol.form');
1007
- selector = 'li';
1039
+ selector = '>';
1040
+ }
1041
+ if (options.traverse) {
1042
+ selector = '';
1043
+ options.traverse.forEach(function(step) {
1044
+ if (step === '__root__') container = container.closest('form');
1045
+ else container = container.find(step);
1046
+ });
1008
1047
  }
1009
1048
  // find without entering new subforms
1010
1049
  element = container.find(selector + ':not(.sub-form) .' + options.field_class);
@@ -1012,17 +1051,17 @@
1012
1051
  element = element.filter(function() { return jQuery(this).closest('.sub-form-record').get(0) === container.get(0); });
1013
1052
  else element = element.filter(function() { return jQuery(this).closest('.sub-form-record').length === 0; });
1014
1053
  if (element.length)
1015
- element = element.first().closest('dl');
1054
+ element = element.first().closest('.form-element');
1016
1055
  else if (options.subform_class)
1017
1056
  element = container.find(selector + '.' + options.subform_class).first();
1018
1057
 
1019
1058
  if (element.length) {
1020
- var parent = element.is('li, td') ? element : element.parent('li, td');
1021
- if (element.is('li'))
1059
+ var parent = element.is('.sub-form, .form-element') ? element : element.parent('.form-element, .sub-form');
1060
+ if (element.is('.sub-form, .form-element'))
1022
1061
  this.replace_html(element, content);
1023
1062
  else
1024
1063
  this.replace(element, content);
1025
- if (parent.is('li')) {
1064
+ if (parent.is('.form-element, .sub-form')) {
1026
1065
  for (var attr in options.attrs)
1027
1066
  parent.attr(attr, options.attrs[attr]);
1028
1067
  }
@@ -1262,9 +1301,13 @@
1262
1301
  },
1263
1302
 
1264
1303
  open_popup: function(content, link) {
1265
- var element = jQuery(content).filter(function(){ return this.tagName; }).dialog({
1304
+ var element = jQuery(content).filter(function(){ return this.tagName; })
1305
+ if (link.adapter) link.adapter.dialog('close');
1306
+ element.dialog({
1266
1307
  modal: true,
1267
- close: function() { link.close(); },
1308
+ close: function () {
1309
+ if (!link.adapter.is('.loading')) link.close();
1310
+ },
1268
1311
  width: ActiveScaffold.config.popup_width || '80%'
1269
1312
  });
1270
1313
  link.set_adapter(element);
@@ -1273,6 +1316,7 @@
1273
1316
  close_popup: function(link, callback) {
1274
1317
  link.adapter.dialog('close');
1275
1318
  ActiveScaffold.remove(link.adapter, callback);
1319
+ link.set_adapter(null);
1276
1320
  }
1277
1321
  }
1278
1322
 
@@ -1444,9 +1488,11 @@
1444
1488
 
1445
1489
  set_adapter: function(element) {
1446
1490
  this.adapter = element;
1447
- this.adapter.addClass('as_adapter');
1448
- this.adapter.data('action_link', this);
1449
- if (this.refresh_url) jQuery('.as_cancel', this.adapter).attr('href', this.refresh_url);
1491
+ if (element) {
1492
+ this.adapter.addClass('as_adapter');
1493
+ this.adapter.data('action_link', this);
1494
+ if (this.refresh_url) jQuery('.as_cancel', this.adapter).attr('href', this.refresh_url);
1495
+ }
1450
1496
  },
1451
1497
 
1452
1498
  keep_open: function() {
@@ -1519,14 +1565,19 @@
1519
1565
  close: function(refreshed_content_or_reload) {
1520
1566
  this._super();
1521
1567
  if (refreshed_content_or_reload) {
1522
- if (typeof refreshed_content_or_reload == 'string') {
1523
- ActiveScaffold.update_row(this.target, refreshed_content_or_reload);
1524
- } else if (this.refresh_url) {
1525
- var target = this.target;
1526
- jQuery.get(this.refresh_url, function(e, status, xhr) {
1527
- ActiveScaffold.update_row(target, xhr.responseText);
1528
- });
1529
- }
1568
+ if (typeof refreshed_content_or_reload == 'string') this.refresh(refreshed_content_or_reload);
1569
+ else this.refresh();
1570
+ }
1571
+ },
1572
+
1573
+ refresh: function(content) {
1574
+ if (content) {
1575
+ ActiveScaffold.update_row(this.target, content);
1576
+ } else if (this.refresh_url) {
1577
+ var target = this.target;
1578
+ jQuery.get(this.refresh_url, function(e, status, xhr) {
1579
+ ActiveScaffold.update_row(target, xhr.responseText);
1580
+ });
1530
1581
  }
1531
1582
  },
1532
1583
 
@@ -20,14 +20,27 @@
20
20
  var id = jQuery(this).attr('id');
21
21
  if (tinymce && tinymce.majorVersion >= 6) {
22
22
  settings.selector = '#' + id;
23
- if (settings.setup) settings.setup = eval(settings.setup);
23
+ var userSetup = settings.setup ? eval(settings.setup) : function () {};
24
+ settings.setup = function(editor) {
25
+ userSetup(editor); // run what the user already had
26
+
27
+ /* keep textarea in sync */
28
+ var sync = function() { editor.save(); }; // same as triggerSave()
29
+ editor.on('change input NodeChange Undo Redo', sync);
30
+ };
24
31
  tinymce.init(settings);
25
32
  } else { // tinyMCE.majorVersion < 6
33
+ settings.init_instance_callback = function(editor) {
34
+ var sync = function () { editor.save(); }; // same as triggerSave()
35
+ editor.on('change input NodeChange Undo Redo', sync);
36
+ if (userInit) userInit(editor); // run user’s callback too
37
+ };
26
38
  tinyMCE.settings = settings;
27
39
  tinyMCE.execCommand('mceAddEditor', false, id);
28
40
  }
29
41
  }
30
-
42
+ /*const sync = () => editor.save(); // same as triggerSave for this editor
43
+ editor.on('change input NodeChange Undo Redo', sync);*/
31
44
  jQuery(document).on('submit', 'form.as_form', function() {
32
45
  tinymce.triggerSave();
33
46
  jQuery('textarea.mceEditor', this).each(function() { tinymce.remove('#'+jQuery(this).attr('id')); });
@@ -57,3 +57,9 @@ background-image: image-url('active_scaffold/close_touch.png');
57
57
  .active-scaffold .refresh-link {
58
58
  background-image: image-url('active_scaffold/refresh.png');
59
59
  }
60
+
61
+ .ui-dialog .loading::after {
62
+ background: image-url('active_scaffold/indicator.gif') no-repeat;
63
+ content: 'Loading...';
64
+ padding-left: 20px;
65
+ }
@@ -751,6 +751,14 @@ float: left;
751
751
  margin-top: 6px;
752
752
  }
753
753
 
754
+ .active-scaffold li.form-element dd .select-field:not(.draggable-lists-container) {
755
+ display: inline-block;
756
+ }
757
+ .active-scaffold li.form-element dd .select-field ~ .as_action {
758
+ vertical-align: top;
759
+ margin-left: 5px;
760
+ }
761
+
754
762
  .active-scaffold .form dd {
755
763
  margin: 0;
756
764
  }
@@ -761,6 +769,95 @@ display: inline-block;
761
769
  font-size: 10px;
762
770
  margin-left: 5px;
763
771
  }
772
+ .active-scaffold .description .close {
773
+ display: none;
774
+ }
775
+
776
+ .active-scaffold .descriptions-hover, .active-scaffold .descriptions-click {
777
+ .horizontal-sub-form td .description {
778
+ display: none;
779
+ }
780
+ dd > .description {
781
+ position: absolute;
782
+ }
783
+ .horizontal-sub-form th, dd {
784
+ position: relative;
785
+ .description {
786
+ display: inline-block;
787
+ width: 1.5em;
788
+ height: 1.5em;
789
+ overflow: hidden;
790
+ white-space: nowrap;
791
+ color: blue;
792
+ top: 2px;
793
+ font-weight: normal;
794
+
795
+ &::before {
796
+ display: flex;
797
+ content: '?';
798
+ border-radius: 0.75em;
799
+ background: lightgray;
800
+ height: 1.5em;
801
+ width: 1.5em;
802
+ align-items: center;
803
+ justify-content: center;
804
+ }
805
+ }
806
+ }
807
+ .horizontal-sub-form th .description {
808
+ left: 0;
809
+ }
810
+ dd > .description {
811
+ right: -1em;
812
+ }
813
+ }
814
+
815
+ .active-scaffold .descriptions-hover .horizontal-sub-form th .description:hover,
816
+ .active-scaffold .descriptions-hover dd .description:hover,
817
+ .active-scaffold .descriptions-click .horizontal-sub-form th .description.visible,
818
+ .active-scaffold .descriptions-click dd .description.visible {
819
+ position: absolute;
820
+ width: auto;
821
+ height: auto;
822
+ white-space: normal;
823
+ background: white;
824
+ padding: 2px 5px;
825
+ z-index: 100; /* Ensure it's above other content */
826
+ display: block;
827
+ &::before {
828
+ display: none;
829
+ }
830
+ }
831
+
832
+ .active-scaffold .descriptions-click {
833
+ .horizontal-sub-form th .description, dd .description {
834
+ cursor: pointer;
835
+ &.visible {
836
+ overflow: visible;
837
+ cursor: auto;
838
+ padding-right: 10px;
839
+ }
840
+ &.visible .close {
841
+ &::before {
842
+ content: 'x';
843
+ }
844
+ position: absolute;
845
+ top: -10px;
846
+ right: -5px;
847
+ background: lightgray;
848
+ border-radius: 10px;
849
+ width: 20px;
850
+ height: 20px;
851
+ display: flex;
852
+ align-items: center;
853
+ justify-content: center;
854
+ }
855
+ }
856
+ }
857
+
858
+ .active-scaffold .sub-form.optional[style=""] ~ .description {
859
+ display: none;
860
+ }
764
861
 
765
862
  .active-scaffold .required label {
766
863
  font-weight: bold;
@@ -961,7 +1058,7 @@ clear: left;
961
1058
 
962
1059
  .active-scaffold .sub-form .association-record a.destroy {
963
1060
  font-weight: bold;
964
- display: block;
1061
+ display: inline-block;
965
1062
  height: 16px;
966
1063
  padding: 0;
967
1064
  width: 16px;
@@ -969,6 +1066,9 @@ text-indent: -4000px;
969
1066
  background: 0 0 no-repeat;
970
1067
  overflow: hidden;
971
1068
  }
1069
+ .active-scaffold .sub-form .association-record * + a.destroy {
1070
+ margin-left: 5px;
1071
+ }
972
1072
 
973
1073
  .active-scaffold .sub-form .locked a.destroy {
974
1074
  display: none;
@@ -1052,9 +1152,9 @@ font-size: 100%;
1052
1152
  text-decoration: none;
1053
1153
  background-color: #eee;
1054
1154
  }
1055
- .active-scaffold .tabbed .nav-tabs > li.active > a,
1056
- .active-scaffold .tabbed .nav-tabs > li.active > a:focus,
1057
- .active-scaffold .tabbed .nav-tabs > li.active > a:hover {
1155
+ .active-scaffold .tabbed .nav-tabs > li > a.active,
1156
+ .active-scaffold .tabbed .nav-tabs > li > a.active:focus,
1157
+ .active-scaffold .tabbed .nav-tabs > li > a.active:hover {
1058
1158
  border-color: #ddd;
1059
1159
  border-bottom-color: transparent;
1060
1160
  cursor: default;
@@ -0,0 +1,11 @@
1
+ .active-scaffold textarea.mceEditor {
2
+ opacity: 0;
3
+ pointer-events: none;
4
+ display: inline !important;
5
+ height: 0;
6
+ margin: 0;
7
+ padding: 0;
8
+ width: 0 !important;
9
+ float: left;
10
+ margin-left: -5px;
11
+ }
@@ -7,6 +7,7 @@
7
7
  multipart ||= action_config.multipart? unless local_assigns.key? :multipart
8
8
  columns ||= action_config.columns unless local_assigns.key? :columns
9
9
  persistent ||= action_config.persistent unless local_assigns.key? :persistent
10
+ field_descriptions ||= action_config.field_descriptions
10
11
  if !local_assigns.key?(:floating_footer) && action_config.respond_to?(:floating_footer)
11
12
  floating_footer = action_config.floating_footer
12
13
  end
@@ -17,6 +18,7 @@
17
18
  multipart ||= false
18
19
  columns ||= nil
19
20
  persistent ||= false
21
+ field_descriptions ||= :show
20
22
  end
21
23
  floating_footer ||= false
22
24
  method ||= :post
@@ -29,11 +31,10 @@
29
31
  <%=
30
32
  options = {id: form_id,
31
33
  multipart: multipart,
32
- class: "as_form #{form_action}",
34
+ class: "as_form #{form_action} #{'floating-footer' if floating_footer} #{"descriptions-#{field_descriptions}" if field_descriptions != :show}",
33
35
  method: method,
34
36
  'data-loading' => defined?(loading) ? loading : true}
35
37
  cancel_options = {class: 'as_cancel'}
36
- options[:class] << ' floating-footer' if floating_footer
37
38
  cancel_options[:remote] = true if xhr # cancel link does nt have to care about multipart forms
38
39
  if xhr && multipart # file_uploads
39
40
  form_remote_upload_tag url_options.merge(iframe: true), options
@@ -9,7 +9,7 @@
9
9
  data: {loading: true},
10
10
  method: :get
11
11
  }
12
- options[:class] << ' floating-footer' if active_scaffold_config.field_search.floating_footer
12
+ options[:class] += ' floating-footer' if active_scaffold_config.field_search.floating_footer
13
13
 
14
14
  hidden_params = url_options.except(:controller, :action, :id, :search).to_query.split(Rack::Utils::DEFAULT_SEP)
15
15
  -%>
@@ -28,7 +28,7 @@
28
28
  if active_scaffold_config.field_search.reset_form
29
29
  reset_attrs[:data] = {reset: true}
30
30
  else
31
- reset_attrs[:class] << ' as_cancel'
31
+ reset_attrs[:class] += ' as_cancel'
32
32
  reset_attrs.merge! remote: true, data: {refresh: true}
33
33
  end
34
34
  %>
@@ -16,12 +16,22 @@
16
16
  <li class="sub-section <%= column_css_class %>">
17
17
  <%= render_subsection(column, @record, scope, form_action) %>
18
18
  </li>
19
- <% elsif renders_as == :subform and authorized -%>
20
- <%= content_tag :li, active_scaffold_subform_attributes(column, column_css_class, tab_id: tab_id) do %>
21
- <%= render_column(column, @record, renders_as, scope, tabbed_by: (column.options[:tabbed_by] || tabbed_by if tabbed_by), tab_value: tab_value, tab_id: tab_id) %>
19
+ <% elsif renders_as == :subform && (authorized || column.show_ui) -%>
20
+ <%
21
+ subform_attrs = active_scaffold_subform_attributes(column, column_css_class, tab_id: tab_id)
22
+ subform_attrs[:class] = "#{subform_attrs[:class]} read-only".strip unless authorized
23
+ tab_options = local_assigns.slice(:tabbed_by, :tab_id, :tab_value)
24
+ tab_options[:tabbed_by] = column.options[:tabbed_by] if tabbed_by && column.options[:tabbed_by]
25
+ %>
26
+ <%= content_tag :li, subform_attrs do %>
27
+ <% if authorized %>
28
+ <%= render_column(column, @record, renders_as, scope, **tab_options) %>
29
+ <% else %>
30
+ <%= show_column_value(@record, column, **tab_options) %>
31
+ <% end %>
22
32
  <% end %>
23
33
  <% else -%>
24
- <li class="form-element <%= 'required' if column.required?(action_for_validation?(@record)) %> <%= column.form_ui %> <%= column_css_class %>">
34
+ <li class="form-element <%= 'required' if column.required?(action_for_validation(@record)) %> <%= column.form_ui %> <%= column_css_class %>">
25
35
  <%= render_column(column, @record, renders_as, scope, only_value: !authorized) %>
26
36
  </li>
27
37
  <% end -%>