activeadmin_addons 1.10.0 → 2.0.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
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
+ };