activeadmin_addons 1.10.0 → 2.0.0.beta.2

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 (172) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -17
  3. data/app/inputs/active_admin/inputs/select_input.rb +9 -5
  4. data/app/inputs/nested_level_input.rb +13 -7
  5. data/app/inputs/nested_select_input.rb +19 -13
  6. data/app/inputs/search_select_filter_input.rb +15 -1
  7. data/app/inputs/search_select_input.rb +6 -5
  8. data/app/inputs/tags_input.rb +5 -34
  9. data/app/javascript/activeadmin_addons/addons/slim-select-interactive-tag.js +78 -0
  10. data/app/javascript/activeadmin_addons/all.js +2 -7
  11. data/app/javascript/activeadmin_addons/config.js +8 -5
  12. data/app/javascript/activeadmin_addons/inputs/slim-select-nested.js +95 -0
  13. data/app/javascript/activeadmin_addons/inputs/slim-select-search.js +37 -0
  14. data/app/javascript/activeadmin_addons/inputs/slim-select-selected-list.js +103 -0
  15. data/app/javascript/activeadmin_addons/inputs/slim-select-simple-tags.js +22 -0
  16. data/app/javascript/activeadmin_addons/inputs/slim-select-tags.js +28 -0
  17. data/app/javascript/activeadmin_addons/inputs/slim-select-utils.js +70 -0
  18. data/app/javascript/activeadmin_addons/inputs/slim-select.js +93 -0
  19. data/app/{assets/stylesheets/activeadmin_addons → javascript/activeadmin_addons/stylesheets}/all.scss +4 -10
  20. data/app/javascript/activeadmin_addons/stylesheets/imports/slimselect.css +1 -0
  21. data/app/{assets/stylesheets/activeadmin_addons → javascript/activeadmin_addons/stylesheets}/inputs/selected-list.scss +0 -1
  22. data/app/javascript/activeadmin_addons/stylesheets/inputs/slim-select.scss +9 -0
  23. data/lib/activeadmin_addons/addons/image_builder.rb +2 -9
  24. data/lib/activeadmin_addons/addons/state_builder.rb +1 -0
  25. data/lib/activeadmin_addons/addons/tag_builder.rb +3 -22
  26. data/lib/activeadmin_addons/engine.rb +1 -6
  27. data/lib/activeadmin_addons/support/custom_builder.rb +1 -1
  28. data/lib/activeadmin_addons/support/input_base.rb +0 -42
  29. data/lib/activeadmin_addons/support/input_helpers/filter_input_methods.rb +1 -0
  30. data/lib/activeadmin_addons/support/input_helpers/input_html_helpers.rb +42 -0
  31. data/lib/activeadmin_addons/support/input_helpers/select_helpers.rb +10 -12
  32. data/lib/activeadmin_addons/support/select_filter_input_extension.rb +1 -3
  33. data/lib/activeadmin_addons/support/select_input_base.rb +11 -0
  34. data/lib/activeadmin_addons/version.rb +1 -1
  35. data/lib/activeadmin_addons.rb +4 -1
  36. data/lib/generators/activeadmin_addons/install/install_generator.rb +2 -1
  37. data/lib/generators/activeadmin_addons/install/templates/initializer.rb +2 -2
  38. data/lib/generators/activeadmin_addons/webpacker/webpacker_generator.rb +3 -6
  39. metadata +82 -196
  40. data/app/assets/images/fileicons/file_extension_3gp.png +0 -0
  41. data/app/assets/images/fileicons/file_extension_7z.png +0 -0
  42. data/app/assets/images/fileicons/file_extension_ace.png +0 -0
  43. data/app/assets/images/fileicons/file_extension_ai.png +0 -0
  44. data/app/assets/images/fileicons/file_extension_aif.png +0 -0
  45. data/app/assets/images/fileicons/file_extension_aiff.png +0 -0
  46. data/app/assets/images/fileicons/file_extension_amr.png +0 -0
  47. data/app/assets/images/fileicons/file_extension_asf.png +0 -0
  48. data/app/assets/images/fileicons/file_extension_asx.png +0 -0
  49. data/app/assets/images/fileicons/file_extension_bat.png +0 -0
  50. data/app/assets/images/fileicons/file_extension_bin.png +0 -0
  51. data/app/assets/images/fileicons/file_extension_bmp.png +0 -0
  52. data/app/assets/images/fileicons/file_extension_bup.png +0 -0
  53. data/app/assets/images/fileicons/file_extension_cab.png +0 -0
  54. data/app/assets/images/fileicons/file_extension_cbr.png +0 -0
  55. data/app/assets/images/fileicons/file_extension_cda.png +0 -0
  56. data/app/assets/images/fileicons/file_extension_cdl.png +0 -0
  57. data/app/assets/images/fileicons/file_extension_cdr.png +0 -0
  58. data/app/assets/images/fileicons/file_extension_chm.png +0 -0
  59. data/app/assets/images/fileicons/file_extension_dat.png +0 -0
  60. data/app/assets/images/fileicons/file_extension_divx.png +0 -0
  61. data/app/assets/images/fileicons/file_extension_dll.png +0 -0
  62. data/app/assets/images/fileicons/file_extension_dmg.png +0 -0
  63. data/app/assets/images/fileicons/file_extension_doc.png +0 -0
  64. data/app/assets/images/fileicons/file_extension_docx.png +0 -0
  65. data/app/assets/images/fileicons/file_extension_dss.png +0 -0
  66. data/app/assets/images/fileicons/file_extension_dvf.png +0 -0
  67. data/app/assets/images/fileicons/file_extension_dwg.png +0 -0
  68. data/app/assets/images/fileicons/file_extension_eml.png +0 -0
  69. data/app/assets/images/fileicons/file_extension_eps.png +0 -0
  70. data/app/assets/images/fileicons/file_extension_exe.png +0 -0
  71. data/app/assets/images/fileicons/file_extension_fla.png +0 -0
  72. data/app/assets/images/fileicons/file_extension_flv.png +0 -0
  73. data/app/assets/images/fileicons/file_extension_gif.png +0 -0
  74. data/app/assets/images/fileicons/file_extension_gz.png +0 -0
  75. data/app/assets/images/fileicons/file_extension_hqx.png +0 -0
  76. data/app/assets/images/fileicons/file_extension_htm.png +0 -0
  77. data/app/assets/images/fileicons/file_extension_html.png +0 -0
  78. data/app/assets/images/fileicons/file_extension_ifo.png +0 -0
  79. data/app/assets/images/fileicons/file_extension_indd.png +0 -0
  80. data/app/assets/images/fileicons/file_extension_iso.png +0 -0
  81. data/app/assets/images/fileicons/file_extension_jar.png +0 -0
  82. data/app/assets/images/fileicons/file_extension_jpeg.png +0 -0
  83. data/app/assets/images/fileicons/file_extension_jpg.png +0 -0
  84. data/app/assets/images/fileicons/file_extension_lnk.png +0 -0
  85. data/app/assets/images/fileicons/file_extension_log.png +0 -0
  86. data/app/assets/images/fileicons/file_extension_m4a.png +0 -0
  87. data/app/assets/images/fileicons/file_extension_m4b.png +0 -0
  88. data/app/assets/images/fileicons/file_extension_m4p.png +0 -0
  89. data/app/assets/images/fileicons/file_extension_m4v.png +0 -0
  90. data/app/assets/images/fileicons/file_extension_mcd.png +0 -0
  91. data/app/assets/images/fileicons/file_extension_mdb.png +0 -0
  92. data/app/assets/images/fileicons/file_extension_mid.png +0 -0
  93. data/app/assets/images/fileicons/file_extension_mov.png +0 -0
  94. data/app/assets/images/fileicons/file_extension_mp2.png +0 -0
  95. data/app/assets/images/fileicons/file_extension_mp3.png +0 -0
  96. data/app/assets/images/fileicons/file_extension_mp4.png +0 -0
  97. data/app/assets/images/fileicons/file_extension_mpeg.png +0 -0
  98. data/app/assets/images/fileicons/file_extension_mpg.png +0 -0
  99. data/app/assets/images/fileicons/file_extension_msi.png +0 -0
  100. data/app/assets/images/fileicons/file_extension_mswmm.png +0 -0
  101. data/app/assets/images/fileicons/file_extension_ogg.png +0 -0
  102. data/app/assets/images/fileicons/file_extension_pdf.png +0 -0
  103. data/app/assets/images/fileicons/file_extension_png.png +0 -0
  104. data/app/assets/images/fileicons/file_extension_pps.png +0 -0
  105. data/app/assets/images/fileicons/file_extension_ppt.png +0 -0
  106. data/app/assets/images/fileicons/file_extension_pptx.png +0 -0
  107. data/app/assets/images/fileicons/file_extension_ps.png +0 -0
  108. data/app/assets/images/fileicons/file_extension_psd.png +0 -0
  109. data/app/assets/images/fileicons/file_extension_pst.png +0 -0
  110. data/app/assets/images/fileicons/file_extension_ptb.png +0 -0
  111. data/app/assets/images/fileicons/file_extension_pub.png +0 -0
  112. data/app/assets/images/fileicons/file_extension_qbb.png +0 -0
  113. data/app/assets/images/fileicons/file_extension_qbw.png +0 -0
  114. data/app/assets/images/fileicons/file_extension_qxd.png +0 -0
  115. data/app/assets/images/fileicons/file_extension_ram.png +0 -0
  116. data/app/assets/images/fileicons/file_extension_rar.png +0 -0
  117. data/app/assets/images/fileicons/file_extension_rm.png +0 -0
  118. data/app/assets/images/fileicons/file_extension_rmvb.png +0 -0
  119. data/app/assets/images/fileicons/file_extension_rtf.png +0 -0
  120. data/app/assets/images/fileicons/file_extension_sea.png +0 -0
  121. data/app/assets/images/fileicons/file_extension_ses.png +0 -0
  122. data/app/assets/images/fileicons/file_extension_sit.png +0 -0
  123. data/app/assets/images/fileicons/file_extension_sitx.png +0 -0
  124. data/app/assets/images/fileicons/file_extension_ss.png +0 -0
  125. data/app/assets/images/fileicons/file_extension_swf.png +0 -0
  126. data/app/assets/images/fileicons/file_extension_tgz.png +0 -0
  127. data/app/assets/images/fileicons/file_extension_thm.png +0 -0
  128. data/app/assets/images/fileicons/file_extension_tif.png +0 -0
  129. data/app/assets/images/fileicons/file_extension_tmp.png +0 -0
  130. data/app/assets/images/fileicons/file_extension_torrent.png +0 -0
  131. data/app/assets/images/fileicons/file_extension_ttf.png +0 -0
  132. data/app/assets/images/fileicons/file_extension_txt.png +0 -0
  133. data/app/assets/images/fileicons/file_extension_unknown.png +0 -0
  134. data/app/assets/images/fileicons/file_extension_vcd.png +0 -0
  135. data/app/assets/images/fileicons/file_extension_vob.png +0 -0
  136. data/app/assets/images/fileicons/file_extension_wav.png +0 -0
  137. data/app/assets/images/fileicons/file_extension_wma.png +0 -0
  138. data/app/assets/images/fileicons/file_extension_wmv.png +0 -0
  139. data/app/assets/images/fileicons/file_extension_wps.png +0 -0
  140. data/app/assets/images/fileicons/file_extension_xls.png +0 -0
  141. data/app/assets/images/fileicons/file_extension_xlsx.png +0 -0
  142. data/app/assets/images/fileicons/file_extension_xpi.png +0 -0
  143. data/app/assets/images/fileicons/file_extension_zip.png +0 -0
  144. data/app/assets/images/material/icons/keyboard_arrow_down.svg +0 -4
  145. data/app/assets/images/material/icons/keyboard_arrow_left.svg +0 -4
  146. data/app/assets/images/material/icons/keyboard_arrow_right.svg +0 -4
  147. data/app/assets/images/material/icons/keyboard_arrow_up.svg +0 -4
  148. data/app/assets/images/material/icons/today.svg +0 -4
  149. data/app/assets/javascripts/activeadmin_addons/all.js +0 -753
  150. data/app/assets/stylesheets/activeadmin_addons/addons/material-datepicker.scss +0 -173
  151. data/app/assets/stylesheets/activeadmin_addons/addons/material-toggle_bool.scss +0 -52
  152. data/app/assets/stylesheets/activeadmin_addons/inputs/select2.scss +0 -3
  153. data/app/assets/stylesheets/activeadmin_addons/material.scss +0 -53
  154. data/app/javascript/activeadmin_addons/addons/interactive_select_tag.js +0 -95
  155. data/app/javascript/activeadmin_addons/inputs/nested-select.js +0 -170
  156. data/app/javascript/activeadmin_addons/inputs/search-select.js +0 -76
  157. data/app/javascript/activeadmin_addons/inputs/select2.js +0 -52
  158. data/app/javascript/activeadmin_addons/inputs/selected-list.js +0 -107
  159. data/app/javascript/activeadmin_addons/inputs/tags.js +0 -76
  160. data/lib/activeadmin_addons/addons/attachment_builder.rb +0 -60
  161. data/lib/activeadmin_addons/support/enumerize_formtastic_support.rb +0 -18
  162. data/lib/generators/activeadmin_addons/assets/assets_generator.rb +0 -53
  163. data/vendor/assets/select2/select2.css +0 -481
  164. data/vendor/assets/select2/select2.full.js +0 -6820
  165. /data/app/{assets/stylesheets/activeadmin_addons → javascript/activeadmin_addons/stylesheets}/addons/interactive_select_tag.scss +0 -0
  166. /data/app/{assets/stylesheets/activeadmin_addons → javascript/activeadmin_addons/stylesheets}/addons/toggle_bool.scss +0 -0
  167. /data/app/{assets/stylesheets/activeadmin_addons → javascript/activeadmin_addons/stylesheets}/imports/jquery-datepicker.scss +0 -0
  168. /data/app/{assets/stylesheets/activeadmin_addons → javascript/activeadmin_addons/stylesheets}/inputs/color-picker.scss +0 -0
  169. /data/app/{assets/stylesheets/activeadmin_addons → javascript/activeadmin_addons/stylesheets}/inputs/date-time-picker-filter.scss +0 -0
  170. /data/app/{assets/stylesheets/activeadmin_addons → javascript/activeadmin_addons/stylesheets}/inputs/date-time-picker.scss +0 -0
  171. /data/app/{assets/stylesheets/activeadmin_addons → javascript/activeadmin_addons/stylesheets}/inputs/numeric-range-filter.scss +0 -0
  172. /data/app/{assets/stylesheets/activeadmin_addons → javascript/activeadmin_addons/stylesheets}/vendor/palette-color-picker.scss +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d72fffa977c3deca692ef85867b113cff5d81c77448124ce2be3b7bb8bca205e
4
- data.tar.gz: db4ff250da3a471b018b02735185adf0627fcd5ab2b0062fac45994259b125a8
3
+ metadata.gz: 44f61829c24cb573ef14551b359f25c763d2740f72a17e0c64fedb80090afcd6
4
+ data.tar.gz: d0f6bb02709f7c23cb16e10bc882e3c10aecade16cfcf70bf9369beca8050ecd
5
5
  SHA512:
6
- metadata.gz: b2785b849c40e967c81226a546e284185b497ab0359297036f302400685dc0dd2f3bbffdfbf40a03b5f574e98647a8d8707b9fe914cb44e672b54993bbb8e846
7
- data.tar.gz: 2d4f90088726b45b97a67e16db4325fa4b2c24b78d69ce380e8635f089b4ed4cf6c8544689d40e02a63de823aa07d057da9b25c788c4a482fe2b5064bac14ab4
6
+ metadata.gz: 207fb0c30ec42531af763ccb9b346a6fd86b68b522890745c6f2c378e53914ea86132f3e63a461a7750a577bff1fe20a08d383b5e26147395e06caff77869f6f
7
+ data.tar.gz: c831f634ef1529f9706b4357c13c0eb2970aa0f87e3ca271b6a26dbb4ff293a9bae3cefcef229e7604e4db5b4492f350a25674826a6e25559ceb804c02dfe588
data/Rakefile CHANGED
@@ -18,29 +18,13 @@ task :prepare_assets do
18
18
  system "rm -rf spec/dummy/public/packs"
19
19
  system "rm -rf spec/dummy/public/packs-test"
20
20
  system "yarn install"
21
- system "yarn build"
22
21
  system "(cd spec/dummy && yarn install)"
23
22
  end
24
23
 
25
24
  task :tests do
26
25
  system "rspec ./spec/lib"
27
- end
28
-
29
- task :sprockets_tests do
30
- system "rake prepare_assets"
31
- system "export SPROCKETS=true; rspec ./spec/features"
32
- end
33
-
34
- task :webpack_tests do
35
- system "rake prepare_assets"
36
- system "export SPROCKETS=false; rspec ./spec/features"
37
- end
38
-
39
- task :all_tests do
40
26
  system "rake prepare_assets"
41
- system "rake tests"
42
- system "export SPROCKETS=true; rspec ./spec/features"
43
- system "export SPROCKETS=false; rspec ./spec/features"
27
+ system "rspec ./spec/features"
44
28
  end
45
29
 
46
30
  Bundler::GemHelper.install_tasks
@@ -1,14 +1,18 @@
1
1
  class ActiveAdmin::Inputs::SelectInput < Formtastic::Inputs::SelectInput
2
2
  def input_html_options
3
- super.merge(data: { tags: @options[:tags].present? })
3
+ if @options[:tags].present?
4
+ super.deep_merge(class: 'simple-tags-input')
5
+ else
6
+ super
7
+ end
4
8
  end
5
9
 
6
10
  def raw_collection
7
11
  field_value = begin
8
- object.send(method)
9
- rescue NoMethodError
10
- nil
11
- end
12
+ object.send(method)
13
+ rescue NoMethodError
14
+ nil
15
+ end
12
16
 
13
17
  @options[:tags].present? && field_value.present? ? (super.to_a << field_value).uniq : super
14
18
  end
@@ -1,4 +1,4 @@
1
- class NestedLevelInput < ActiveAdminAddons::InputBase
1
+ class NestedLevelInput < ActiveAdminAddons::SelectInputBase
2
2
  include ActiveAdminAddons::SelectHelpers
3
3
 
4
4
  def render_custom_input
@@ -13,8 +13,10 @@ class NestedLevelInput < ActiveAdminAddons::InputBase
13
13
 
14
14
  private
15
15
 
16
+ # rubocop:disable Metrics/MethodLength
16
17
  def load_control_attributes
17
18
  load_class(@options[:class])
19
+ load_data_attr(:association, value: association_name)
18
20
  load_data_attr(:fields, default: ["name"], formatter: :to_json)
19
21
  load_data_attr(:predicate, default: "contains")
20
22
  load_data_attr(:filters)
@@ -23,26 +25,30 @@ class NestedLevelInput < ActiveAdminAddons::InputBase
23
25
  load_data_attr(:minimum_input_length, default: 1)
24
26
  load_data_attr(:url, default: url_from_method)
25
27
  load_data_attr(:response_root, default: tableize_method)
26
- load_data_attr(:width, default: "80%")
28
+ load_data_attr(:width)
27
29
  load_data_attr(:order,
28
- value: @options[:order_by],
29
- default: get_data_attr_value(:fields).first.to_s + "_desc")
30
+ value: @options[:order_by],
31
+ default: "#{get_data_attr_value(:fields).first}_desc")
30
32
  load_parent_data_options
31
33
  load_collection_data
32
34
  end
35
+ # rubocop:enable Metrics/MethodLength
33
36
 
34
37
  def load_parent_data_options
35
38
  return unless @options[:parent_attribute]
39
+
36
40
  load_data_attr(:parent, value: @options[:parent_attribute])
37
- load_data_attr(:parent_id, value: @object.send(@options[:parent_attribute]), default: -1)
41
+ load_data_attr(
42
+ :parent_id, value: @object.send(@options[:parent_id_attribute]), default: -1
43
+ )
38
44
  end
39
45
 
40
46
  def load_collection_data
41
47
  return unless @options[:collection]
42
48
 
43
49
  collection_options = collection_to_select_options do |item, option|
44
- if !!@options[:parent_attribute]
45
- option[@options[:parent_attribute]] = item.send(@options[:parent_attribute])
50
+ if @options[:parent_attribute].present?
51
+ option[@options[:parent_attribute]] = item.send(@options[:parent_id_attribute])
46
52
  end
47
53
  end
48
54
 
@@ -59,32 +59,38 @@ class NestedSelectInput < ActiveAdminAddons::InputBase
59
59
  parent_level_data = hierarchy[next_idx] if hierarchy.count != next_idx
60
60
  if parent_level_data
61
61
  level_data[:parent_attribute] = parent_level_data[:attribute]
62
+ level_data[:parent_id_attribute] = "#{level_data[:parent_attribute]}_id"
62
63
  set_parent_value(level_data)
63
64
  end
64
65
  end
65
66
  end
66
67
 
67
68
  def set_parent_value(level_data)
68
- parent_attribute = level_data[:parent_attribute]
69
- build_virtual_attr(parent_attribute)
70
- instance = instance_from_attribute_name(level_data[:attribute])
71
- if instance&.respond_to?(parent_attribute)
72
- @object.send("#{parent_attribute}=", instance.send(parent_attribute))
69
+ build_virtual_attr(level_data[:parent_attribute])
70
+ build_virtual_attr(level_data[:parent_id_attribute])
71
+ instance = instance_from_attribute_id("#{level_data[:attribute]}_id")
72
+ if instance.respond_to?(level_data[:parent_id_attribute])
73
+ @object.send(
74
+ "#{level_data[:parent_attribute]}=", instance.send(level_data[:parent_attribute])
75
+ )
76
+ @object.send(
77
+ "#{level_data[:parent_id_attribute]}=", instance.send(level_data[:parent_id_attribute])
78
+ )
73
79
  end
74
80
  end
75
81
 
76
- def instance_from_attribute_name(attribute)
77
- return unless attribute
82
+ def instance_from_attribute_id(attribute_id)
83
+ return unless attribute_id
78
84
 
79
- attribute_value = @object.send(attribute)
80
- return unless attribute_value
85
+ attribute_id_value = @object.send(attribute_id)
86
+ return unless attribute_id_value
81
87
 
82
- klass = class_from_attribute(attribute)
83
- klass.find_by(id: attribute_value)
88
+ klass = class_from_attribute_id(attribute_id)
89
+ klass.find_by(id: attribute_id_value)
84
90
  end
85
91
 
86
- def class_from_attribute(attribute)
87
- association_name = attribute.to_s.chomp("_id")
92
+ def class_from_attribute_id(attribute_id)
93
+ association_name = attribute_id.to_s.chomp("_id")
88
94
  association_name.camelize.constantize
89
95
  rescue NameError
90
96
  object_class.reflect_on_association(association_name).klass
@@ -7,6 +7,20 @@ class SearchSelectFilterInput < SearchSelectInput
7
7
  end
8
8
 
9
9
  def input_method
10
- eq_input_name
10
+ "#{input_name}_eq"
11
+ end
12
+
13
+ def input_html_options_name
14
+ "#{object_name}[#{input_method}]"
15
+ end
16
+
17
+ def input_value
18
+ result = valid_object.conditions.find do |condition|
19
+ condition.attributes.map(&:name).include?(input_name.to_s)
20
+ end
21
+
22
+ return unless result
23
+
24
+ result.values.first.value
11
25
  end
12
26
  end
@@ -1,10 +1,11 @@
1
- class SearchSelectInput < ActiveAdminAddons::InputBase
1
+ class SearchSelectInput < ActiveAdminAddons::SelectInputBase
2
2
  include ActiveAdminAddons::SelectHelpers
3
3
 
4
4
  def render_custom_input
5
5
  concat(label_html)
6
- concat(builder.select(input_method,
7
- initial_collection_to_select_options, {}, input_html_options))
6
+ concat(
7
+ builder.select(input_method, initial_collection_to_select_options, {}, input_html_options)
8
+ )
8
9
  end
9
10
 
10
11
  def input_method
@@ -19,11 +20,11 @@ class SearchSelectInput < ActiveAdminAddons::InputBase
19
20
  load_data_attr(:response_root, default: tableize_method)
20
21
  load_data_attr(:display_name, default: "name")
21
22
  load_data_attr(:minimum_input_length, default: 1)
22
- load_data_attr(:width, default: "80%")
23
+ load_data_attr(:width)
23
24
  load_data_attr(
24
25
  :order,
25
26
  value: @options[:order_by],
26
- default: get_data_attr_value(:fields).first.to_s + "_desc"
27
+ default: "#{get_data_attr_value(:fields).first}_desc"
27
28
  )
28
29
  end
29
30
  end
@@ -1,18 +1,13 @@
1
- class TagsInput < ActiveAdminAddons::InputBase
1
+ class TagsInput < ActiveAdminAddons::SelectInputBase
2
2
  include ActiveAdminAddons::SelectHelpers
3
3
 
4
4
  def render_custom_input
5
- if active_record_select?
6
- return render_collection_tags
7
- end
8
-
9
- render_array_tags
5
+ render_collection_tags
10
6
  end
11
7
 
12
8
  def load_control_attributes
13
- load_data_attr(:model, value: model_name)
14
- load_data_attr(:method, value: method)
15
- load_data_attr(:width, default: "80%")
9
+ @options[:multiple] = true
10
+ load_data_attr(:width)
16
11
 
17
12
  if active_record_select?
18
13
  load_data_attr(:relation, value: true)
@@ -24,32 +19,8 @@ class TagsInput < ActiveAdminAddons::InputBase
24
19
 
25
20
  private
26
21
 
27
- def render_array_tags
28
- render_tags_control { build_hidden_control(prefixed_method, method_to_input_name, input_value) }
29
- end
30
-
31
22
  def render_collection_tags
32
- render_tags_control { render_selected_hidden_items }
33
- end
34
-
35
- def render_tags_control(&block)
36
23
  concat(label_html)
37
- concat(block.call)
38
- concat(builder.select(build_virtual_attr, [], {}, input_html_options))
39
- end
40
-
41
- def render_selected_hidden_items
42
- template.content_tag(:div, id: selected_values_id) do
43
- template.concat(build_hidden_control(empty_input_id, method_to_input_array_name, ""))
44
- input_value.each do |item_id|
45
- template.concat(
46
- build_hidden_control(
47
- method_to_input_id(item_id),
48
- method_to_input_array_name,
49
- item_id.to_s
50
- )
51
- )
52
- end
53
- end
24
+ concat(builder.select(method, [], input_options, input_html_options))
54
25
  end
55
26
  end
@@ -0,0 +1,78 @@
1
+ import SlimSelect from 'slim-select';
2
+
3
+ function updateTag(url, data) {
4
+ return fetch(url, {
5
+ method: 'PATCH',
6
+ headers: {
7
+ 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
8
+ 'Accept': 'application/json',
9
+ 'Content-Type': 'application/json',
10
+ },
11
+ body: JSON.stringify(data),
12
+ });
13
+ }
14
+
15
+ function setupSelect(el) {
16
+ if (el.slim) {
17
+ el.slim.destroy();
18
+ }
19
+
20
+ return new SlimSelect({
21
+ select: el,
22
+ events: {
23
+ // eslint-disable-next-line max-statements
24
+ afterClose: () => {
25
+ const containerEl = el.closest('.tag-select-container');
26
+ const selectContainer = containerEl.querySelector('.interactive-tag-select');
27
+ const tagContainer = containerEl.querySelector('.interactive-tag');
28
+ const model = tagContainer.dataset.model;
29
+ const objectId = tagContainer.dataset.objectId;
30
+ const field = tagContainer.dataset.field;
31
+
32
+ if (el.value === tagContainer.dataset.value) {
33
+ selectContainer.classList.add('select-container-hidden');
34
+ containerEl.querySelector('.interactive-tag').classList.remove('interactive-tag-hidden');
35
+ } else {
36
+ const data = { id: objectId };
37
+ data[model] = {};
38
+ data[model][field] = el.value;
39
+ updateTag(tagContainer.dataset.url, data)
40
+ .then(() => {
41
+ const statusTag = tagContainer.querySelector('.status_tag');
42
+ statusTag.innerText = el.selectedOptions[0].text;
43
+ statusTag.classList.remove(tagContainer.dataset.value);
44
+ statusTag.classList.add(el.value);
45
+ tagContainer.dataset.value = el.value;
46
+ selectContainer.dataset.value = el.value;
47
+ })
48
+ .catch(() => {
49
+ const errorMsg = 'Error: Update Unsuccessful';
50
+ console.log(errorMsg);
51
+ })
52
+ .finally(() => {
53
+ selectContainer.classList.add('select-container-hidden');
54
+ containerEl.querySelector('.interactive-tag').classList.remove('interactive-tag-hidden');
55
+ });
56
+ }
57
+ },
58
+ },
59
+ });
60
+ }
61
+
62
+ function setupInteractiveTag(containerEl) {
63
+ const selectContainer = containerEl.querySelector('.interactive-tag-select');
64
+ const slimSelect = setupSelect(selectContainer.querySelector('select'));
65
+ const tag = containerEl.querySelector('.interactive-tag');
66
+
67
+ tag.addEventListener('click', () => {
68
+ selectContainer.classList.remove('select-container-hidden');
69
+ tag.classList.add('interactive-tag-hidden');
70
+ window.setTimeout(() => {
71
+ slimSelect.open();
72
+ }, 0);
73
+ });
74
+ }
75
+
76
+ window.addEventListener('load', () => {
77
+ document.querySelectorAll('.tag-select-container').forEach(setupInteractiveTag);
78
+ });
@@ -1,14 +1,9 @@
1
- import 'select2';
2
1
  import 'jquery-datetimepicker';
3
2
  import './vendor/jquery_palette_color_picker/palette-color-picker';
4
3
 
5
4
  import './config';
6
- import './inputs/select2';
7
- import './inputs/search-select';
8
- import './inputs/nested-select';
9
- import './inputs/tags';
10
- import './inputs/selected-list';
5
+ import './inputs/slim-select';
11
6
  import './inputs/date-time-picker';
12
7
  import './inputs/color-picker';
13
8
  import './addons/toggle_bool';
14
- import './addons/interactive_select_tag';
9
+ import './addons/slim-select-interactive-tag';
@@ -1,10 +1,13 @@
1
- var initializer = function() {
1
+ const loadEvents = ['turbo:load', 'turbolinks:load', 'DOMContentLoaded'];
2
+
3
+ function initializer() {
2
4
  window.ActiveadminAddons = {
3
5
  config: {
4
- defaultSelect: $('body').data('default-select'),
6
+ defaultSelect: document.querySelector('body').dataset.defaultSelect,
5
7
  },
6
8
  };
7
- };
9
+ }
8
10
 
9
- $(initializer);
10
- $(document).on('turbolinks:load turbo:load', initializer);
11
+ loadEvents.forEach((event) => {
12
+ document.addEventListener(event, initializer);
13
+ });
@@ -0,0 +1,95 @@
1
+ import { ransackSearch } from './slim-select-utils';
2
+
3
+ const classes = ['nested-level-input'];
4
+
5
+ function ajaxSearch(search, currentData, args) {
6
+ args.fields.forEach((field) => {
7
+ if (field === 'id') {
8
+ args.textQuery[`${field}_eq`] = search;
9
+ } else {
10
+ args.textQuery[`${field}_${args.predicate}`] = search;
11
+ }
12
+ });
13
+
14
+ if (!!args.parent) {
15
+ args.query.q[`${args.parent}_id_eq`] = args.parentId;
16
+ }
17
+
18
+ args.query.q = { ...args.query.q, ...args.filters };
19
+
20
+ return ransackSearch(search, currentData, args);
21
+ }
22
+
23
+ function collectionSearch(search, args, collection) {
24
+ if (search.length < args.minimumInputLength) {
25
+ return Promise.reject('Search term too short');
26
+ }
27
+
28
+ const data = JSON.parse(collection).filter(
29
+ (item) => (!args.parent || item[args.parent] === Number(args.parentId)) &&
30
+ String(item.text).toLowerCase().includes(search.toLowerCase()),
31
+ ).map(
32
+ (item) => ({ value: String(item.id), text: item.text }),
33
+ );
34
+
35
+ return Promise.resolve(data);
36
+ }
37
+
38
+ function settings(el) {
39
+ return {
40
+ settings: {
41
+ allowDeselect: true,
42
+ },
43
+ events: {
44
+ beforeOpen: () => {
45
+ if (Number(el.dataset.minimumInputLength) === 0) {
46
+ el.slim.search('');
47
+ }
48
+ },
49
+ afterChange: () => {
50
+ const { model, association } = el.dataset;
51
+ const child = el.closest('.nested_level')
52
+ .parentNode
53
+ .querySelector(`.nested_level [data-model=${model}][data-parent=${association}]`);
54
+
55
+ if (child) {
56
+ child.slim.setSelected();
57
+ child.slim.setData([]);
58
+ if (child.slim.events.afterChange) {
59
+ child.slim.events.afterChange();
60
+ }
61
+ child.dispatchEvent(new Event('change'));
62
+ child.dataset.parentId = el.value;
63
+ }
64
+ },
65
+ search(search, currentData) {
66
+ const args = {
67
+ url: el.dataset.url,
68
+ fields: el.dataset.fields && JSON.parse(el.dataset.fields) || {},
69
+ predicate: el.dataset.predicate,
70
+ filters: el.dataset.filters && JSON.parse(el.dataset.filters) || {},
71
+ displayName: el.dataset.displayName,
72
+ parent: el.dataset.parent,
73
+ parentId: el.dataset.parentId,
74
+ responseRoot: el.dataset.responseRoot,
75
+ minimumInputLength: el.dataset.minimumInputLength,
76
+ order: el.dataset.order,
77
+ textQuery: { m: 'or' },
78
+ query: { q: {} },
79
+ };
80
+
81
+ if (el.dataset.collection) {
82
+ return collectionSearch(search, args, el.dataset.collection);
83
+ }
84
+
85
+ return ajaxSearch(search, currentData, args);
86
+ },
87
+ },
88
+ };
89
+ }
90
+
91
+ export {
92
+ settings,
93
+ classes,
94
+ };
95
+
@@ -0,0 +1,37 @@
1
+ import { ransackSearch } from './slim-select-utils';
2
+
3
+ const classes = ['search-select-input', 'search-select-filter-input', 'ajax-filter-input'];
4
+
5
+ function settings(el) {
6
+ const url = el.dataset.url;
7
+ const fields = JSON.parse(el.dataset.fields);
8
+ const predicate = el.dataset.predicate;
9
+ const displayName = el.dataset.displayName;
10
+ const responseRoot = el.dataset.responseRoot;
11
+ const minimumInputLength = el.dataset.minimumInputLength;
12
+ const order = el.dataset.order;
13
+
14
+ const args = { url, fields, predicate, displayName, responseRoot, minimumInputLength, order };
15
+
16
+ return {
17
+ events: {
18
+ search: (search, currentData) => {
19
+ args.textQuery = { m: 'or' };
20
+ args.fields.forEach((field) => {
21
+ if (field === 'id') {
22
+ args.textQuery[`${field}_eq`] = search;
23
+ } else {
24
+ args.textQuery[`${field}_${args.predicate}`] = search;
25
+ }
26
+ });
27
+
28
+ return ransackSearch(search, currentData, args);
29
+ },
30
+ },
31
+ };
32
+ }
33
+
34
+ export {
35
+ settings,
36
+ classes,
37
+ };
@@ -0,0 +1,103 @@
1
+ import { ransackSearch } from './slim-select-utils';
2
+
3
+ const classes = ['selected-list-input'];
4
+
5
+ // eslint-disable-next-line max-statements
6
+ function settings(el) {
7
+ const url = el.dataset.url;
8
+ const fields = JSON.parse(el.dataset.fields);
9
+ const predicate = el.dataset.predicate;
10
+ const displayName = el.dataset.displayName;
11
+ const method = el.dataset.method;
12
+ const model = el.dataset.model;
13
+ const prefix = `${model}_${method}`;
14
+ const responseRoot = el.dataset.responseRoot;
15
+ const minimumInputLength = el.dataset.minimumInputLength;
16
+ const order = el.dataset.order;
17
+
18
+ const args = { url, fields, predicate, displayName, responseRoot, minimumInputLength, order };
19
+
20
+ return {
21
+ settings: {
22
+ allowDeselect: false,
23
+ },
24
+ events: {
25
+ // eslint-disable-next-line max-statements
26
+ afterChange: (newVal) => {
27
+ if (!newVal || newVal[0] && !newVal[0].value) return;
28
+
29
+ const selectedItemsContainer = document.querySelector(`[id='${prefix}_selected_values']`);
30
+ const itemName = `${model}[${method}][]`;
31
+
32
+ // eslint-disable-next-line max-statements
33
+ newVal.forEach((data) => {
34
+ const itemId = `${prefix}_${data.value}`;
35
+ if (!!document.querySelector(`#${itemId}`)) {
36
+ return;
37
+ }
38
+
39
+ const item = document.createElement('div');
40
+ item.id = itemId;
41
+ item.textContent = data.text;
42
+ item.classList.add('selected-item');
43
+
44
+ const hiddenInput = document.createElement('input');
45
+ hiddenInput.name = itemName;
46
+ hiddenInput.type = 'hidden';
47
+ hiddenInput.value = data.value;
48
+
49
+ item.appendChild(hiddenInput);
50
+ selectedItemsContainer.appendChild(item);
51
+ });
52
+ el.slim.setSelected();
53
+ },
54
+ search: (search, currentData) => {
55
+ args.textQuery = { m: 'or' };
56
+ args.fields.forEach((field) => {
57
+ args.textQuery[`${field}_${predicate}`] = search;
58
+ });
59
+
60
+ return ransackSearch(search, currentData, args);
61
+ },
62
+ },
63
+ };
64
+ }
65
+
66
+ function setupSelectedList(containerEl) {
67
+ containerEl.addEventListener('click', (event) => {
68
+ const item = event.target;
69
+ if (item.classList.contains('selected-item')) {
70
+ item.remove();
71
+ }
72
+ });
73
+ }
74
+
75
+ function setupSelectedLists(node) {
76
+ node.querySelectorAll('.selected-list-container').forEach(setupSelectedList);
77
+ }
78
+
79
+ function mutationObserver() {
80
+ return new MutationObserver((mutations) => {
81
+ mutations.forEach((mutation) => {
82
+ if (mutation.type === 'childList') {
83
+ mutation.addedNodes.forEach((node) => {
84
+ if (node instanceof Element) {
85
+ setupSelectedLists(node);
86
+ }
87
+ });
88
+ }
89
+ });
90
+ });
91
+ }
92
+
93
+ function init() {
94
+ setupSelectedLists(document);
95
+ mutationObserver();
96
+ }
97
+
98
+ export {
99
+ settings,
100
+ classes,
101
+ init,
102
+ };
103
+
@@ -0,0 +1,22 @@
1
+ const classes = ['simple-tags-input'];
2
+
3
+ function init(el) {
4
+ el.multiple = true;
5
+ if (!el.value) {
6
+ el.value = null;
7
+ }
8
+ }
9
+
10
+ function settings() {
11
+ return {
12
+ events: {
13
+ addable: (value) => value,
14
+ },
15
+ };
16
+ }
17
+
18
+ export {
19
+ classes,
20
+ init,
21
+ settings,
22
+ };