activeadmin-tom_select 4.1.1 → 4.2.0.beta1
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +10 -7
- data/.gitignore +1 -0
- data/Appraisals +2 -2
- data/CHANGELOG.md +12 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +137 -104
- data/README.md +1 -1
- data/docs/activeadmin-4-asset-setup.md +171 -0
- data/docs/activeadmin-tailwind-4.md +125 -0
- data/docs/guide-update-your-app.md +89 -356
- data/docs/setup-activeadmin-app.md +69 -492
- data/docs/setup-activeadmin-gem.md +83 -449
- data/gemfiles/rails_7.x_active_admin_4.x.gemfile +2 -1
- data/gemfiles/rails_7.x_active_admin_4.x.gemfile.lock +158 -116
- data/gemfiles/rails_8.x_active_admin_4.x.gemfile +2 -1
- data/gemfiles/rails_8.x_active_admin_4.x.gemfile.lock +148 -104
- data/lib/activeadmin/tom_select/option_collection.rb +4 -6
- data/lib/activeadmin/tom_select/select_input_extension.rb +42 -20
- data/lib/activeadmin/tom_select/version.rb +1 -1
- data/npm-package/package.json +1 -1
- data/sonar-project.properties +11 -11
- data/spec/features/ajax_false_input_spec.rb +74 -0
- data/spec/features/end_to_end_spec.rb +33 -20
- data/spec/features/input_errors_spec.rb +1 -3
- data/spec/features/options_dsl_spec.rb +6 -6
- data/spec/internal/Gemfile +1 -0
- data/spec/internal/Gemfile.lock +152 -107
- data/spec/internal/app/admin/option_values.rb +6 -6
- data/spec/internal/app/admin/posts.rb +4 -4
- data/spec/internal/app/admin/test_ajax_false.rb +18 -0
- data/spec/internal/app/admin/variants.rb +2 -2
- data/spec/internal/app/assets/stylesheets/active_admin.tailwind.css +8 -5
- data/spec/internal/app/models/option_value.rb +8 -0
- data/spec/internal/bin/tailwindcss +27 -0
- data/spec/internal/lib/tasks/active_admin.rake +9 -4
- data/spec/internal/package-lock.json +15 -1371
- data/spec/internal/package.json +1 -2
- data/{docs/tailwind-4/tailwind-active_admin.config.js → spec/internal/tailwind-active_admin.config.mjs} +9 -4
- data/spec/internal/yarn.lock +128 -728
- metadata +9 -23
- data/docs/activeadmin-4-detailed-reference.md +0 -932
- data/docs/activeadmin-4-gem-migration-guide.md +0 -313
- data/docs/combustion.md +0 -213
- data/docs/fail.png +0 -0
- data/docs/normal.png +0 -0
- data/docs/propshaft-readme.md +0 -320
- data/docs/propshaft-upgrade.md +0 -484
- data/docs/tailwind/blog-page.md +0 -341
- data/docs/tailwind/upgrade-guide-enhanced.md +0 -438
- data/docs/tailwind/upgrade-guide.md +0 -416
- data/docs/tailwind-4/active_admin.rake +0 -38
- data/docs/tailwind-4/active_admin.tailwind.css +0 -415
- data/docs/test-app-change.md +0 -154
- data/docs/test-environment-fixes.md +0 -58
- data/docs/update-tom-select.md +0 -348
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe 'ajax: false input behavior', type: :feature do
|
|
4
|
+
before do
|
|
5
|
+
# Create test data
|
|
6
|
+
@users = 3.times.map { |i| User.create!(name: "User #{i + 1}") }
|
|
7
|
+
@categories = 3.times.map { |i| Category.create!(name: "Category #{i + 1}") }
|
|
8
|
+
|
|
9
|
+
@post = Post.create!(
|
|
10
|
+
title: 'Test Post',
|
|
11
|
+
body: 'Test content',
|
|
12
|
+
category: @categories.first,
|
|
13
|
+
user: @users.first
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe 'filter inputs with ajax: false' do
|
|
18
|
+
it 'renders all options inline without ajax URL' do
|
|
19
|
+
visit '/admin/ajax_false_posts'
|
|
20
|
+
|
|
21
|
+
# Should have tom-select-input class
|
|
22
|
+
expect(page).to have_selector('.tom-select-input')
|
|
23
|
+
|
|
24
|
+
# Should NOT have data-ajax-url attribute
|
|
25
|
+
page_content = page.html
|
|
26
|
+
expect(page_content).not_to match(/<select[^>]*name="q\[category_id_eq\]"[^>]*data-ajax-url/)
|
|
27
|
+
expect(page_content).not_to match(/<select[^>]*name="q\[user_id_eq\]"[^>]*data-ajax-url/)
|
|
28
|
+
|
|
29
|
+
# Should have options rendered inline
|
|
30
|
+
within('select[name="q[category_id_eq]"]', visible: :all) do
|
|
31
|
+
@categories.each do |category|
|
|
32
|
+
expect(page).to have_selector("option[value='#{category.id}']", text: category.name,
|
|
33
|
+
visible: :all)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe 'form inputs with ajax: false' do
|
|
40
|
+
it 'renders all options inline in new form' do
|
|
41
|
+
visit '/admin/ajax_false_posts/new'
|
|
42
|
+
|
|
43
|
+
expect(page).to have_selector('.tom-select-input')
|
|
44
|
+
|
|
45
|
+
# Check that options are rendered inline
|
|
46
|
+
within('select#post_category_id', visible: :all) do
|
|
47
|
+
@categories.each do |category|
|
|
48
|
+
expect(page).to have_selector("option[value='#{category.id}']", text: category.name,
|
|
49
|
+
visible: :all)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'preselects value in edit form' do
|
|
55
|
+
visit "/admin/ajax_false_posts/#{@post.id}/edit"
|
|
56
|
+
|
|
57
|
+
# Should have the selected option
|
|
58
|
+
within('select#post_category_id', visible: :all) do
|
|
59
|
+
selected_option = find("option[value='#{@categories.first.id}']", visible: :all)
|
|
60
|
+
expect(selected_option).to be_selected
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
describe 'comparison with ajax: true (default)' do
|
|
66
|
+
it 'default inputs use ajax' do
|
|
67
|
+
visit '/admin/posts'
|
|
68
|
+
|
|
69
|
+
# Default searchable_select should have data-ajax-url
|
|
70
|
+
page_content = page.html
|
|
71
|
+
expect(page_content).to match(/<select[^>]*name="q\[category_id_eq\]"[^>]*data-ajax-url/)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -80,17 +80,16 @@ RSpec.describe 'end to end', type: :feature, js: true do
|
|
|
80
80
|
end
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
context 'class with nested belongs_to association'
|
|
84
|
-
skip: 'Nested routes issue with belongs_to in test environment' do
|
|
83
|
+
context 'class with nested belongs_to association' do
|
|
85
84
|
# Using static admin files: option_types.rb, products.rb, option_values.rb, variants.rb
|
|
86
85
|
|
|
87
86
|
describe 'new page with searchable select filter' do
|
|
88
87
|
it 'loads filter input options' do
|
|
89
88
|
option_type = OptionType.create(name: 'Color')
|
|
90
89
|
ot = OptionType.create(name: 'Size')
|
|
91
|
-
OptionValue.create(
|
|
92
|
-
OptionValue.create(
|
|
93
|
-
OptionValue.create(
|
|
90
|
+
OptionValue.create(name: 'Black', option_type: option_type)
|
|
91
|
+
OptionValue.create(name: 'Orange', option_type: option_type)
|
|
92
|
+
OptionValue.create(name: 'M', option_type: ot)
|
|
94
93
|
product = Product.create(name: 'Cap', option_type: option_type)
|
|
95
94
|
|
|
96
95
|
visit "/admin/products/#{product.id}/variants/new"
|
|
@@ -139,9 +138,9 @@ RSpec.describe 'end to end', type: :feature, js: true do
|
|
|
139
138
|
has_searchable = page.has_css?(searchable_select_css)
|
|
140
139
|
puts "Page HTML includes searchable-select-input: #{has_searchable}"
|
|
141
140
|
|
|
142
|
-
# Debug: Print
|
|
141
|
+
# Debug: Print HTML around the select - use first match if there are multiple
|
|
143
142
|
if page.has_css?(searchable_select_css)
|
|
144
|
-
select_element =
|
|
143
|
+
select_element = all(searchable_select_css, visible: :all).first
|
|
145
144
|
parent_html = begin
|
|
146
145
|
select_element.find(:xpath,
|
|
147
146
|
'..')['outerHTML'][0..500]
|
|
@@ -151,7 +150,10 @@ RSpec.describe 'end to end', type: :feature, js: true do
|
|
|
151
150
|
puts "Parent element HTML: #{parent_html}..."
|
|
152
151
|
end
|
|
153
152
|
|
|
154
|
-
|
|
153
|
+
# Target the option_value select specifically
|
|
154
|
+
within('#variant_option_value_input') do
|
|
155
|
+
find('.ts-control', match: :first).click
|
|
156
|
+
end
|
|
155
157
|
wait_for_ajax
|
|
156
158
|
|
|
157
159
|
expect(select_box_items).to eq(%w[Black Orange])
|
|
@@ -160,15 +162,18 @@ RSpec.describe 'end to end', type: :feature, js: true do
|
|
|
160
162
|
it 'allows filtering options by term' do
|
|
161
163
|
option_type = OptionType.create(name: 'Color')
|
|
162
164
|
ot = OptionType.create(name: 'Size')
|
|
163
|
-
OptionValue.create(
|
|
164
|
-
OptionValue.create(
|
|
165
|
-
OptionValue.create(
|
|
165
|
+
OptionValue.create(name: 'Black', option_type: option_type)
|
|
166
|
+
OptionValue.create(name: 'Orange', option_type: option_type)
|
|
167
|
+
OptionValue.create(name: 'M', option_type: ot)
|
|
166
168
|
product = Product.create(name: 'Cap', option_type: option_type)
|
|
167
169
|
|
|
168
170
|
visit "/admin/products/#{product.id}/variants/new"
|
|
169
171
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
+
# Target the option_value select specifically
|
|
173
|
+
within('#variant_option_value_input') do
|
|
174
|
+
find('.ts-control', match: :first).click
|
|
175
|
+
find('input[type="text"]', match: :first).send_keys('O')
|
|
176
|
+
end
|
|
172
177
|
wait_for_ajax
|
|
173
178
|
|
|
174
179
|
expect(select_box_items).to eq(%w[Orange])
|
|
@@ -176,17 +181,22 @@ RSpec.describe 'end to end', type: :feature, js: true do
|
|
|
176
181
|
|
|
177
182
|
it 'loads more items when scrolling down' do
|
|
178
183
|
option_type = OptionType.create(name: 'Color')
|
|
179
|
-
15.times { |i| OptionValue.create(
|
|
184
|
+
15.times { |i| OptionValue.create(name: "Black #{i}", option_type: option_type) }
|
|
180
185
|
product = Product.create(name: 'Cap', option_type: option_type)
|
|
181
186
|
|
|
182
187
|
visit "/admin/products/#{product.id}/variants/new"
|
|
183
188
|
|
|
184
|
-
|
|
189
|
+
# Target the option_value select specifically
|
|
190
|
+
within('#variant_option_value_input') do
|
|
191
|
+
find('.ts-control', match: :first).click
|
|
192
|
+
end
|
|
185
193
|
wait_for_ajax
|
|
186
194
|
scroll_select_box_list
|
|
187
195
|
wait_for_ajax
|
|
188
196
|
|
|
189
|
-
|
|
197
|
+
# Default page size is 10, scrolling might load more pages
|
|
198
|
+
expect(select_box_items.size).to be >= 10
|
|
199
|
+
expect(select_box_items.size).to be <= 20
|
|
190
200
|
end
|
|
191
201
|
end
|
|
192
202
|
|
|
@@ -194,15 +204,18 @@ RSpec.describe 'end to end', type: :feature, js: true do
|
|
|
194
204
|
it 'preselects item' do
|
|
195
205
|
option_type = OptionType.create(name: 'Color')
|
|
196
206
|
ot = OptionType.create(name: 'Size')
|
|
197
|
-
option_value = OptionValue.create(
|
|
198
|
-
OptionValue.create(
|
|
199
|
-
OptionValue.create(
|
|
207
|
+
option_value = OptionValue.create(name: 'Black', option_type: option_type)
|
|
208
|
+
OptionValue.create(name: 'Orange', option_type: option_type)
|
|
209
|
+
OptionValue.create(name: 'M', option_type: ot)
|
|
200
210
|
product = Product.create(name: 'Cap', option_type: option_type)
|
|
201
211
|
variant = Variant.create(product: product, option_value: option_value)
|
|
202
212
|
|
|
203
213
|
visit "/admin/products/#{product.id}/variants/#{variant.id}/edit"
|
|
204
214
|
|
|
205
|
-
|
|
215
|
+
# Target the option_value select specifically
|
|
216
|
+
within('#variant_option_value_input') do
|
|
217
|
+
expect(page).to have_css('.ts-control .item', text: 'Black')
|
|
218
|
+
end
|
|
206
219
|
end
|
|
207
220
|
end
|
|
208
221
|
end
|
|
@@ -38,9 +38,7 @@ RSpec.describe 'searchable select', type: :feature do
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
visit '/admin/test_error_post2s'
|
|
41
|
-
expect(page).to have_content(
|
|
42
|
-
"No option collection named 'nonexistent_collection' defined in 'Category' admin."
|
|
43
|
-
)
|
|
41
|
+
expect(page).to have_content('The required ajax endpoint is missing')
|
|
44
42
|
end
|
|
45
43
|
|
|
46
44
|
it 'shows helpful error message if ajax resource does not have an admin' do
|
|
@@ -192,7 +192,7 @@ RSpec.describe 'searchable_select_options dsl', type: :request do
|
|
|
192
192
|
expect(json_response).to include(results: array_including(a_hash_including(text: 'A post')))
|
|
193
193
|
end
|
|
194
194
|
|
|
195
|
-
it '
|
|
195
|
+
it 'raises error when scope option is missing' do
|
|
196
196
|
expect do
|
|
197
197
|
ActiveAdminHelpers.setup do
|
|
198
198
|
ActiveAdmin.register(Post) do
|
|
@@ -202,7 +202,7 @@ RSpec.describe 'searchable_select_options dsl', type: :request do
|
|
|
202
202
|
end.to raise_error(/Missing option: scope/)
|
|
203
203
|
end
|
|
204
204
|
|
|
205
|
-
it '
|
|
205
|
+
it 'raises error when display_text and text_attribute are missing' do
|
|
206
206
|
expect do
|
|
207
207
|
ActiveAdminHelpers.setup do
|
|
208
208
|
ActiveAdmin.register(Post) do
|
|
@@ -210,18 +210,18 @@ RSpec.describe 'searchable_select_options dsl', type: :request do
|
|
|
210
210
|
filter: ->(_term, scope) { scope })
|
|
211
211
|
end
|
|
212
212
|
end
|
|
213
|
-
end.to raise_error(/Missing option:
|
|
213
|
+
end.to raise_error(/Missing option: text_attribute/)
|
|
214
214
|
end
|
|
215
215
|
|
|
216
|
-
it '
|
|
216
|
+
it 'raises error when filter and text_attribute are missing' do
|
|
217
217
|
expect do
|
|
218
218
|
ActiveAdminHelpers.setup do
|
|
219
219
|
ActiveAdmin.register(Post) do
|
|
220
220
|
searchable_select_options(scope: Post,
|
|
221
|
-
display_text: ->(
|
|
221
|
+
display_text: ->(record) { record.title }) # rubocop:disable Style/SymbolProc
|
|
222
222
|
end
|
|
223
223
|
end
|
|
224
|
-
end.to raise_error(/Missing option:
|
|
224
|
+
end.to raise_error(/Missing option: text_attribute/)
|
|
225
225
|
end
|
|
226
226
|
|
|
227
227
|
def json_response
|
data/spec/internal/Gemfile
CHANGED