rs-activeadmin-searchable_select 4.0.5
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 +7 -0
- data/.actrc +20 -0
- data/.claude/commands/fix-tests.md +203 -0
- data/.github/workflows/ci.yml +170 -0
- data/.github/workflows/npm-publish.yml +47 -0
- data/.gitignore +27 -0
- data/.npmignore +58 -0
- data/.rspec +2 -0
- data/.rubocop.yml +67 -0
- data/.yardopts +2 -0
- data/AGENTS.md +39 -0
- data/Appraisals +15 -0
- data/CHANGELOG.md +24 -0
- data/CLAUDE.md +104 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +366 -0
- data/LICENSE.txt +25 -0
- data/README.md +439 -0
- data/Rakefile +4 -0
- data/bin/rspec +17 -0
- data/config/database.yml +16 -0
- data/config.ru +28 -0
- data/docs/activeadmin-4-detailed-reference.md +932 -0
- data/docs/activeadmin-4-gem-migration-guide.md +313 -0
- data/docs/combustion.md +213 -0
- data/docs/for-next-session.md +199 -0
- data/docs/guide-update-your-app.md +213 -0
- data/docs/propshaft-readme.md +121 -0
- data/docs/propshaft-upgrade.md +267 -0
- data/docs/rails-7-asset-pipeline.md +279 -0
- data/docs/setup-activeadmin-app.md +552 -0
- data/docs/setup-activeadmin-gem.md +535 -0
- data/docs/upload-system.md +225 -0
- data/gemfiles/rails_7.x_active_admin_4.x.gemfile +11 -0
- data/gemfiles/rails_7.x_active_admin_4.x.gemfile.lock +371 -0
- data/gemfiles/rails_8.x_active_admin_4.x.gemfile +11 -0
- data/gemfiles/rails_8.x_active_admin_4.x.gemfile.lock +366 -0
- data/lefthook.yml +17 -0
- data/lib/activeadmin/inputs/filters/searchable_select_input.rb +13 -0
- data/lib/activeadmin/inputs/searchable_select_input.rb +11 -0
- data/lib/activeadmin/searchable_select/engine.rb +17 -0
- data/lib/activeadmin/searchable_select/option_collection.rb +119 -0
- data/lib/activeadmin/searchable_select/resource_dsl_extension.rb +56 -0
- data/lib/activeadmin/searchable_select/resource_extension.rb +10 -0
- data/lib/activeadmin/searchable_select/select_input_extension.rb +159 -0
- data/lib/activeadmin/searchable_select/version.rb +5 -0
- data/lib/activeadmin/searchable_select.rb +20 -0
- data/lib/activeadmin-searchable_select.rb +4 -0
- data/lib/generators/active_admin/searchable_select/install/install_generator.rb +217 -0
- data/package-lock.json +18 -0
- data/package.json +45 -0
- data/rs-activeadmin-searchable_select.gemspec +38 -0
- data/sonar-project.properties +25 -0
- data/spec/features/ajax_params_spec.rb +31 -0
- data/spec/features/end_to_end_spec.rb +227 -0
- data/spec/features/filter_input_spec.rb +137 -0
- data/spec/features/form_input_spec.rb +122 -0
- data/spec/features/inline_ajax_setting_spec.rb +26 -0
- data/spec/features/input_errors_spec.rb +76 -0
- data/spec/features/input_html_options_spec.rb +30 -0
- data/spec/features/options_dsl_spec.rb +220 -0
- data/spec/features/production_build_spec.rb +108 -0
- data/spec/internal/app/admin/categories.rb +26 -0
- data/spec/internal/app/admin/dashboard.rb +29 -0
- data/spec/internal/app/admin/option_types.rb +19 -0
- data/spec/internal/app/admin/option_values.rb +30 -0
- data/spec/internal/app/admin/posts.rb +27 -0
- data/spec/internal/app/admin/products.rb +22 -0
- data/spec/internal/app/admin/rgb_colors.rb +25 -0
- data/spec/internal/app/admin/tag_names.rb +21 -0
- data/spec/internal/app/admin/test_ajax_params_category.rb +10 -0
- data/spec/internal/app/admin/test_ajax_params_post.rb +20 -0
- data/spec/internal/app/admin/test_form_post_class.rb +7 -0
- data/spec/internal/app/admin/test_form_post_custom.rb +11 -0
- data/spec/internal/app/admin/test_form_post_resource.rb +11 -0
- data/spec/internal/app/admin/test_form_post_resource_custom.rb +12 -0
- data/spec/internal/app/admin/test_inline_ajax_post.rb +9 -0
- data/spec/internal/app/admin/test_input_html_post.rb +11 -0
- data/spec/internal/app/admin/test_posts_display_text.rb +9 -0
- data/spec/internal/app/admin/test_posts_filter.rb +9 -0
- data/spec/internal/app/admin/test_posts_named.rb +9 -0
- data/spec/internal/app/admin/test_posts_pagination.rb +9 -0
- data/spec/internal/app/admin/test_posts_payload_lambda.rb +11 -0
- data/spec/internal/app/admin/test_posts_payload_proc.rb +9 -0
- data/spec/internal/app/admin/test_posts_scope_lambda.rb +8 -0
- data/spec/internal/app/admin/test_posts_scope_params.rb +8 -0
- data/spec/internal/app/admin/test_posts_scope_user.rb +8 -0
- data/spec/internal/app/admin/test_posts_text_attr.rb +5 -0
- data/spec/internal/app/admin/users.rb +23 -0
- data/spec/internal/app/admin/variants.rb +31 -0
- data/spec/internal/app/assets/config/manifest.js +1 -0
- data/spec/internal/app/assets/javascripts/active_admin.js +2 -0
- data/spec/internal/app/assets/javascripts/searchable_select_test.js +2 -0
- data/spec/internal/app/controllers/application_controller.rb +5 -0
- data/spec/internal/app/css/active_admin_source.css +81 -0
- data/spec/internal/app/js/active_admin.js +17 -0
- data/spec/internal/app/models/article.rb +12 -0
- data/spec/internal/app/models/category.rb +12 -0
- data/spec/internal/app/models/internal/tag_name.rb +14 -0
- data/spec/internal/app/models/internal_tag_name.rb +11 -0
- data/spec/internal/app/models/option_type.rb +12 -0
- data/spec/internal/app/models/option_value.rb +4 -0
- data/spec/internal/app/models/post.rb +15 -0
- data/spec/internal/app/models/product.rb +12 -0
- data/spec/internal/app/models/rgb_color.rb +16 -0
- data/spec/internal/app/models/user.rb +12 -0
- data/spec/internal/app/models/variant.rb +12 -0
- data/spec/internal/build_activeadmin_css.js +115 -0
- data/spec/internal/config/database.yml +7 -0
- data/spec/internal/config/environment.rb +48 -0
- data/spec/internal/config/initializers/active_admin.rb +53 -0
- data/spec/internal/config/initializers/assets.rb +9 -0
- data/spec/internal/config/initializers/searchable_select.rb +6 -0
- data/spec/internal/config/routes.rb +4 -0
- data/spec/internal/config.ru +4 -0
- data/spec/internal/db/schema.rb +63 -0
- data/spec/internal/db/seeds.rb +88 -0
- data/spec/internal/esbuild.config.js +30 -0
- data/spec/internal/inject-jquery.js +4 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/internal/package/LICENSE.txt +25 -0
- data/spec/internal/package/README.md +439 -0
- data/spec/internal/package/package.json +45 -0
- data/spec/internal/package/src/index.js +1 -0
- data/spec/internal/package/src/searchable_select/init.js +1 -0
- data/spec/internal/package/src/searchable_select.css +1 -0
- data/spec/internal/package/src/searchable_select.scss +1 -0
- data/spec/internal/package-lock.json +1385 -0
- data/spec/internal/package.json +26 -0
- data/spec/internal/public/favicon.ico +0 -0
- data/spec/internal/spec/internal/app/css/active_admin_source.css +38 -0
- data/spec/internal/spec/internal/log/test.log +0 -0
- data/spec/internal/tailwind-active_admin.config.js +53 -0
- data/spec/rails_helper.rb +86 -0
- data/spec/spec_helper.rb +137 -0
- data/spec/support/active_admin_helpers.rb +17 -0
- data/spec/support/capybara.rb +8 -0
- data/spec/support/models.rb +88 -0
- data/spec/support/pluck_polyfill.rb +12 -0
- data/spec/support/reset_settings.rb +5 -0
- data/src/index.js +77 -0
- data/src/searchable_select/init.js +58 -0
- data/src/searchable_select.css +5 -0
- data/src/searchable_select.css.map +1 -0
- metadata +405 -0
@@ -0,0 +1,11 @@
|
|
1
|
+
# Admin for testing searchable_select_options with additional_payload as lambda
|
2
|
+
ActiveAdmin.register Post, as: 'TestPostPayloadLambda' do
|
3
|
+
menu false
|
4
|
+
searchable_select_options(
|
5
|
+
scope: Post,
|
6
|
+
text_attribute: :title,
|
7
|
+
additional_payload: lambda do |record|
|
8
|
+
{ published: record.published }
|
9
|
+
end
|
10
|
+
)
|
11
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# Admin for testing searchable_select_options with additional_payload as proc
|
2
|
+
ActiveAdmin.register Post, as: 'TestPostPayloadProc' do
|
3
|
+
menu false
|
4
|
+
searchable_select_options(
|
5
|
+
scope: Post,
|
6
|
+
text_attribute: :title,
|
7
|
+
additional_payload: proc { |record| { published: record.published } }
|
8
|
+
)
|
9
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Admin for testing searchable_select_options with lambda that takes params argument
|
2
|
+
ActiveAdmin.register Post, as: 'TestPostScopeParams' do
|
3
|
+
menu false
|
4
|
+
searchable_select_options(
|
5
|
+
scope: ->(params) { Post.where(user_id: params[:user]) },
|
6
|
+
text_attribute: :title
|
7
|
+
)
|
8
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Admin for testing searchable_select_options with lambda scope that uses view helpers
|
2
|
+
ActiveAdmin.register Post, as: 'TestPostScopeUser' do
|
3
|
+
menu false
|
4
|
+
searchable_select_options(
|
5
|
+
scope: -> { Post.where(user: current_user) },
|
6
|
+
text_attribute: :title
|
7
|
+
)
|
8
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
ActiveAdmin.register User do
|
2
|
+
permit_params :name
|
3
|
+
|
4
|
+
searchable_select_options(scope: User.all,
|
5
|
+
text_attribute: :name)
|
6
|
+
|
7
|
+
index do
|
8
|
+
selectable_column
|
9
|
+
id_column
|
10
|
+
column :name
|
11
|
+
column :created_at
|
12
|
+
actions
|
13
|
+
end
|
14
|
+
|
15
|
+
filter :name
|
16
|
+
|
17
|
+
form do |f|
|
18
|
+
f.inputs do
|
19
|
+
f.input :name
|
20
|
+
end
|
21
|
+
f.actions
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
ActiveAdmin.register Variant do
|
2
|
+
belongs_to :product
|
3
|
+
|
4
|
+
permit_params :price, :option_value_id, :product_id
|
5
|
+
|
6
|
+
index do
|
7
|
+
selectable_column
|
8
|
+
id_column
|
9
|
+
column :price
|
10
|
+
column :option_value
|
11
|
+
actions
|
12
|
+
end
|
13
|
+
|
14
|
+
filter :price
|
15
|
+
filter :option_value
|
16
|
+
|
17
|
+
form do |f|
|
18
|
+
f.inputs do
|
19
|
+
f.input :price
|
20
|
+
f.input(:option_value,
|
21
|
+
as: :searchable_select,
|
22
|
+
ajax: {
|
23
|
+
resource: OptionValue,
|
24
|
+
path_params: {
|
25
|
+
option_type_id: f.object.product&.option_type_id
|
26
|
+
}
|
27
|
+
})
|
28
|
+
end
|
29
|
+
f.actions
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link_tree ../builds
|
@@ -0,0 +1,81 @@
|
|
1
|
+
@tailwind base;
|
2
|
+
@tailwind components;
|
3
|
+
@tailwind utilities;
|
4
|
+
|
5
|
+
/* Custom Select2 overrides for ActiveAdmin compatibility */
|
6
|
+
|
7
|
+
.select2-selection {
|
8
|
+
@apply border border-gray-300 rounded-md min-h-[40px];
|
9
|
+
}
|
10
|
+
|
11
|
+
.select2-selection__rendered {
|
12
|
+
@apply p-2;
|
13
|
+
}
|
14
|
+
|
15
|
+
.select2-selection__arrow {
|
16
|
+
@apply h-full;
|
17
|
+
}
|
18
|
+
|
19
|
+
/* Multiple selection styles */
|
20
|
+
.select2-selection--multiple {
|
21
|
+
@apply min-h-[40px];
|
22
|
+
}
|
23
|
+
|
24
|
+
.select2-selection__choice {
|
25
|
+
@apply bg-gray-100 border-gray-300 rounded;
|
26
|
+
}
|
27
|
+
|
28
|
+
/* Dropdown styles */
|
29
|
+
.select2-dropdown {
|
30
|
+
@apply absolute block w-auto box-border border border-gray-300 rounded-md shadow-lg z-50 float-left;
|
31
|
+
}
|
32
|
+
|
33
|
+
/* Fix positioning when dropdown is open */
|
34
|
+
.select2-container--open .select2-dropdown {
|
35
|
+
@apply left-0;
|
36
|
+
}
|
37
|
+
|
38
|
+
.select2-container--open .select2-dropdown--above {
|
39
|
+
@apply border-b-0 rounded-t-none;
|
40
|
+
}
|
41
|
+
|
42
|
+
.select2-container--open .select2-dropdown--below {
|
43
|
+
@apply border-t-0 rounded-t-none;
|
44
|
+
}
|
45
|
+
|
46
|
+
.select2-search__field {
|
47
|
+
@apply border border-gray-300 rounded p-2 w-full;
|
48
|
+
}
|
49
|
+
|
50
|
+
.select2-results__option {
|
51
|
+
@apply p-2 hover:bg-gray-100;
|
52
|
+
}
|
53
|
+
|
54
|
+
.select2-results__option--highlighted {
|
55
|
+
@apply bg-blue-500 text-white;
|
56
|
+
}
|
57
|
+
|
58
|
+
/* Dark mode support */
|
59
|
+
.dark .select2-selection {
|
60
|
+
@apply border-gray-600 bg-gray-800 text-gray-100;
|
61
|
+
}
|
62
|
+
|
63
|
+
.dark .select2-dropdown {
|
64
|
+
@apply bg-gray-800 border-gray-600;
|
65
|
+
}
|
66
|
+
|
67
|
+
.dark .select2-results__option {
|
68
|
+
@apply text-gray-100 hover:bg-gray-700;
|
69
|
+
}
|
70
|
+
|
71
|
+
.dark .select2-results__option--highlighted {
|
72
|
+
@apply bg-blue-600 text-white;
|
73
|
+
}
|
74
|
+
|
75
|
+
.dark .select2-selection__choice {
|
76
|
+
@apply bg-gray-700 border-gray-600 text-gray-100;
|
77
|
+
}
|
78
|
+
|
79
|
+
.dark .select2-search__field {
|
80
|
+
@apply bg-gray-700 border-gray-600 text-gray-100;
|
81
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
// Import ActiveAdmin - this already includes all features and Rails UJS
|
2
|
+
// DO NOT import Rails separately as it's already included and started in ActiveAdmin
|
3
|
+
import '@activeadmin/activeadmin';
|
4
|
+
|
5
|
+
// Import jQuery and make it globally available BEFORE loading Select2
|
6
|
+
import $ from 'jquery';
|
7
|
+
window.$ = window.jQuery = $;
|
8
|
+
|
9
|
+
// Import Select2 and explicitly attach it to jQuery
|
10
|
+
import select2 from 'select2';
|
11
|
+
select2($); // Critical: Initialize Select2 on jQuery
|
12
|
+
|
13
|
+
// Import and setup ActiveAdmin Searchable Select
|
14
|
+
import { setupAutoInit } from '@rocket-sensei/activeadmin-searchable_select';
|
15
|
+
|
16
|
+
// Initialize the module after everything is loaded
|
17
|
+
setupAutoInit();
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Article < ActiveRecord::Base
|
2
|
+
belongs_to :category, optional: true
|
3
|
+
belongs_to :user, optional: true
|
4
|
+
|
5
|
+
def self.ransackable_attributes(_auth_object = nil)
|
6
|
+
%w[category_id title]
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.ransackable_associations(_auth_object = nil)
|
10
|
+
[]
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Category < ActiveRecord::Base
|
2
|
+
has_many :posts
|
3
|
+
belongs_to :created_by, class_name: 'User', optional: true
|
4
|
+
|
5
|
+
def self.ransackable_attributes(_auth_object = nil)
|
6
|
+
%w[created_by_id description id name created_at updated_at]
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.ransackable_associations(_auth_object = nil)
|
10
|
+
%w[posts created_by]
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Internal
|
2
|
+
class TagName < ActiveRecord::Base
|
3
|
+
self.table_name = :internal_tag_names
|
4
|
+
belongs_to :color, class_name: 'RgbColor', foreign_key: :color_id, optional: true
|
5
|
+
|
6
|
+
def self.ransackable_attributes(_auth_object = nil)
|
7
|
+
%w[color_id name]
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.ransackable_associations(_auth_object = nil)
|
11
|
+
[]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class InternalTagName < ActiveRecord::Base
|
2
|
+
belongs_to :color, class_name: 'RgbColor', optional: true
|
3
|
+
|
4
|
+
def self.ransackable_attributes(_auth_object = nil)
|
5
|
+
%w[color_id id name created_at updated_at]
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.ransackable_associations(_auth_object = nil)
|
9
|
+
['color']
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class OptionType < ActiveRecord::Base
|
2
|
+
has_many :option_values
|
3
|
+
has_many :products
|
4
|
+
|
5
|
+
def self.ransackable_attributes(_auth_object = nil)
|
6
|
+
%w[name id created_at updated_at]
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.ransackable_associations(_auth_object = nil)
|
10
|
+
%w[option_values products]
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Post < ActiveRecord::Base
|
2
|
+
belongs_to :category, optional: true
|
3
|
+
belongs_to :user, optional: true
|
4
|
+
|
5
|
+
scope :published, -> { where(published: true) }
|
6
|
+
scope :unpublished, -> { where(published: false) }
|
7
|
+
|
8
|
+
def self.ransackable_attributes(_auth_object = nil)
|
9
|
+
%w[body category_id id published title user_id created_at updated_at]
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.ransackable_associations(_auth_object = nil)
|
13
|
+
%w[category user]
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Product < ActiveRecord::Base
|
2
|
+
belongs_to :option_type, optional: true
|
3
|
+
has_many :variants
|
4
|
+
|
5
|
+
def self.ransackable_attributes(_auth_object = nil)
|
6
|
+
%w[name option_type_id id created_at updated_at]
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.ransackable_associations(_auth_object = nil)
|
10
|
+
%w[option_type variants]
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class RgbColor < ActiveRecord::Base
|
2
|
+
has_many :internal_tag_names, foreign_key: :color_id
|
3
|
+
has_many :tags, class_name: 'Internal::TagName', foreign_key: :color_id
|
4
|
+
|
5
|
+
def display_name
|
6
|
+
"#{code} - #{description}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.ransackable_attributes(_auth_object = nil)
|
10
|
+
%w[code description id created_at updated_at]
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.ransackable_associations(_auth_object = nil)
|
14
|
+
%w[internal_tag_names tags]
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class User < ActiveRecord::Base
|
2
|
+
has_many :posts
|
3
|
+
has_many :created_categories, class_name: 'Category', foreign_key: 'created_by_id'
|
4
|
+
|
5
|
+
def self.ransackable_attributes(_auth_object = nil)
|
6
|
+
%w[email id name created_at updated_at]
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.ransackable_associations(_auth_object = nil)
|
10
|
+
%w[posts created_categories]
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Variant < ActiveRecord::Base
|
2
|
+
belongs_to :product, optional: true
|
3
|
+
belongs_to :option_value, optional: true
|
4
|
+
|
5
|
+
def self.ransackable_attributes(_auth_object = nil)
|
6
|
+
%w[price product_id option_value_id id created_at updated_at]
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.ransackable_associations(_auth_object = nil)
|
10
|
+
%w[product option_value]
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
const fs = require('fs');
|
3
|
+
const path = require('path');
|
4
|
+
const { spawnSync } = require('child_process');
|
5
|
+
|
6
|
+
const root = __dirname;
|
7
|
+
const inputPath = path.join(root, 'app/css/active_admin_source.css');
|
8
|
+
const vendorCssPath = path.join(root, 'node_modules/select2/dist/css/select2.css');
|
9
|
+
const tmpPath = path.join(root, 'app/css/__aa_tmp.css');
|
10
|
+
const outPath = path.join(root, 'app/assets/builds/active_admin.css');
|
11
|
+
|
12
|
+
function build() {
|
13
|
+
// Read source file or create default
|
14
|
+
let srcContent = '';
|
15
|
+
if (fs.existsSync(inputPath)) {
|
16
|
+
srcContent = fs.readFileSync(inputPath, 'utf8');
|
17
|
+
} else {
|
18
|
+
// Create default source if it doesn't exist
|
19
|
+
srcContent = `@tailwind base;
|
20
|
+
@tailwind components;
|
21
|
+
@tailwind utilities;
|
22
|
+
|
23
|
+
/* Custom Select2 overrides */
|
24
|
+
.select2-container {
|
25
|
+
@apply w-full;
|
26
|
+
}
|
27
|
+
|
28
|
+
.select2-selection {
|
29
|
+
@apply border border-gray-300 rounded-md min-h-[40px];
|
30
|
+
}
|
31
|
+
|
32
|
+
.select2-selection__rendered {
|
33
|
+
@apply p-2;
|
34
|
+
}
|
35
|
+
|
36
|
+
/* Dark mode support */
|
37
|
+
.dark .select2-selection {
|
38
|
+
@apply border-gray-600 bg-gray-800 text-gray-100;
|
39
|
+
}
|
40
|
+
|
41
|
+
.dark .select2-dropdown {
|
42
|
+
@apply bg-gray-800 border-gray-600;
|
43
|
+
}
|
44
|
+
|
45
|
+
.dark .select2-results__option {
|
46
|
+
@apply text-gray-100;
|
47
|
+
}
|
48
|
+
|
49
|
+
.dark .select2-results__option--highlighted {
|
50
|
+
@apply bg-gray-700;
|
51
|
+
}`;
|
52
|
+
}
|
53
|
+
|
54
|
+
// Extract tailwind directives and body content
|
55
|
+
const lines = srcContent.split(/\r?\n/);
|
56
|
+
const tailwindLines = lines.filter(line => line.includes('@tailwind'));
|
57
|
+
const bodyLines = lines.filter(line =>
|
58
|
+
!line.includes('@tailwind') &&
|
59
|
+
!line.includes('select2/dist/css/select2.css')
|
60
|
+
);
|
61
|
+
|
62
|
+
const tailwindDirectives = tailwindLines.join('\n') || '@tailwind base;\n@tailwind components;\n@tailwind utilities;';
|
63
|
+
|
64
|
+
// Read Select2 vendor CSS
|
65
|
+
let vendorCss = '';
|
66
|
+
|
67
|
+
if (fs.existsSync(vendorCssPath)) {
|
68
|
+
vendorCss += `\n/* Begin Select2 vendor CSS */\n`;
|
69
|
+
vendorCss += fs.readFileSync(vendorCssPath, 'utf8');
|
70
|
+
vendorCss += `\n/* End Select2 vendor CSS */\n`;
|
71
|
+
} else {
|
72
|
+
console.warn('Warning: Select2 CSS not found at', vendorCssPath);
|
73
|
+
}
|
74
|
+
|
75
|
+
const body = bodyLines.join('\n');
|
76
|
+
|
77
|
+
// Combine all CSS - Tailwind directives, vendor CSS, then custom styles
|
78
|
+
const tmpCss = `${tailwindDirectives}\n${vendorCss}\n${body}`;
|
79
|
+
|
80
|
+
// Create directories if they don't exist
|
81
|
+
const cssDir = path.dirname(tmpPath);
|
82
|
+
if (!fs.existsSync(cssDir)) {
|
83
|
+
fs.mkdirSync(cssDir, { recursive: true });
|
84
|
+
}
|
85
|
+
|
86
|
+
const buildDir = path.dirname(outPath);
|
87
|
+
if (!fs.existsSync(buildDir)) {
|
88
|
+
fs.mkdirSync(buildDir, { recursive: true });
|
89
|
+
}
|
90
|
+
|
91
|
+
fs.writeFileSync(tmpPath, tmpCss, 'utf8');
|
92
|
+
|
93
|
+
// Run tailwindcss build
|
94
|
+
const res = spawnSync('npx', [
|
95
|
+
'tailwindcss',
|
96
|
+
'-c', path.join(root, 'tailwind-active_admin.config.js'),
|
97
|
+
'-i', tmpPath,
|
98
|
+
'-o', outPath,
|
99
|
+
'--minify'
|
100
|
+
], { stdio: 'inherit', cwd: root });
|
101
|
+
|
102
|
+
if (res.status !== 0) {
|
103
|
+
console.error('Tailwind build failed');
|
104
|
+
process.exit(res.status || 1);
|
105
|
+
}
|
106
|
+
|
107
|
+
// Clean up temp file
|
108
|
+
fs.unlinkSync(tmpPath);
|
109
|
+
|
110
|
+
console.log(`ActiveAdmin CSS built successfully: ${outPath}`);
|
111
|
+
const stats = fs.statSync(outPath);
|
112
|
+
console.log(`File size: ${(stats.size / 1024).toFixed(2)} KB`);
|
113
|
+
}
|
114
|
+
|
115
|
+
build();
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'combustion'
|
2
|
+
|
3
|
+
# Initialize the Combustion app in all environments (dev server and tests)
|
4
|
+
Combustion.path = 'spec/internal'
|
5
|
+
Combustion.initialize!(
|
6
|
+
:active_record,
|
7
|
+
:action_controller,
|
8
|
+
:action_view,
|
9
|
+
:propshaft,
|
10
|
+
:action_mailer
|
11
|
+
) do
|
12
|
+
config.load_defaults Rails::VERSION::STRING.to_f if Rails::VERSION::MAJOR >= 7
|
13
|
+
|
14
|
+
# Friendly defaults for dev/test
|
15
|
+
config.eager_load = false
|
16
|
+
config.consider_all_requests_local = true
|
17
|
+
config.action_controller.perform_caching = false
|
18
|
+
config.action_dispatch.show_exceptions = :all
|
19
|
+
|
20
|
+
# Propshaft assets (guarded in case of alternate stacks)
|
21
|
+
if config.respond_to?(:assets)
|
22
|
+
config.assets.debug = true
|
23
|
+
config.assets.compile = true
|
24
|
+
end
|
25
|
+
|
26
|
+
# Logging
|
27
|
+
config.log_level = :debug
|
28
|
+
|
29
|
+
# Action Mailer
|
30
|
+
config.action_mailer.raise_delivery_errors = false
|
31
|
+
config.action_mailer.perform_caching = false
|
32
|
+
end
|
33
|
+
|
34
|
+
# Load ActiveAdmin configuration
|
35
|
+
require_relative 'initializers/active_admin'
|
36
|
+
|
37
|
+
# Load models
|
38
|
+
require_relative '../app/models/category'
|
39
|
+
require_relative '../app/models/post'
|
40
|
+
require_relative '../app/models/user'
|
41
|
+
require_relative '../app/models/rgb_color'
|
42
|
+
require_relative '../app/models/internal_tag_name'
|
43
|
+
require_relative '../app/models/option_type'
|
44
|
+
require_relative '../app/models/option_value'
|
45
|
+
require_relative '../app/models/product'
|
46
|
+
require_relative '../app/models/variant'
|
47
|
+
|
48
|
+
# The Rails application is initialized by Combustion
|
@@ -0,0 +1,53 @@
|
|
1
|
+
ActiveAdmin.setup do |config|
|
2
|
+
config.site_title = 'Test Admin'
|
3
|
+
config.authentication_method = false
|
4
|
+
config.current_user_method = false
|
5
|
+
config.batch_actions = true
|
6
|
+
config.filter_attributes = %i[encrypted_password password password_confirmation]
|
7
|
+
config.localize_format = :long
|
8
|
+
# Avoid rendering ActiveAdmin comments (routes are not mounted in Combustion app)
|
9
|
+
config.comments = false
|
10
|
+
end
|
11
|
+
|
12
|
+
# Load the searchable_select module first
|
13
|
+
require 'activeadmin/searchable_select'
|
14
|
+
|
15
|
+
# Register custom inputs with Formtastic
|
16
|
+
require 'activeadmin/inputs/searchable_select_input'
|
17
|
+
require 'activeadmin/inputs/filters/searchable_select_input'
|
18
|
+
|
19
|
+
# ActiveAdmin 4 expects importmap-rails in host apps. The Combustion app used
|
20
|
+
# for tests doesn't include it, so provide minimal no-op shims so rendering
|
21
|
+
# doesn't error when calling `javascript_importmap_tags` and `ActiveAdmin.importmap`.
|
22
|
+
module ActiveAdmin
|
23
|
+
# Provide a stub importmap accessor to satisfy `ActiveAdmin.importmap` calls
|
24
|
+
def self.importmap
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
module Importmap
|
29
|
+
def self.draw(*)
|
30
|
+
# no-op in tests
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Provide a working `javascript_importmap_tags` helper that includes required JS for tests
|
36
|
+
module ActionView
|
37
|
+
module Helpers
|
38
|
+
module ImportmapHelperShim
|
39
|
+
def javascript_importmap_tags(*, **)
|
40
|
+
# In tests/dev, include built assets via Rails helpers so Propshaft
|
41
|
+
# can resolve digested paths.
|
42
|
+
safe_join([
|
43
|
+
stylesheet_link_tag('active_admin', 'data-turbo-track': 'reload'),
|
44
|
+
javascript_include_tag('active_admin', 'data-turbo-track': 'reload')
|
45
|
+
], "\n")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
ActiveSupport.on_load(:action_view) do
|
52
|
+
include ActionView::Helpers::ImportmapHelperShim
|
53
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Be sure to restart your server when you modify this file.
|
4
|
+
|
5
|
+
# Configure asset paths for Propshaft if available
|
6
|
+
if Rails.application.config.respond_to?(:assets)
|
7
|
+
# Add the builds directory to asset paths for Propshaft
|
8
|
+
Rails.application.config.assets.paths << Rails.root.join('app/assets/builds')
|
9
|
+
end
|