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.
Files changed (145) hide show
  1. checksums.yaml +7 -0
  2. data/.actrc +20 -0
  3. data/.claude/commands/fix-tests.md +203 -0
  4. data/.github/workflows/ci.yml +170 -0
  5. data/.github/workflows/npm-publish.yml +47 -0
  6. data/.gitignore +27 -0
  7. data/.npmignore +58 -0
  8. data/.rspec +2 -0
  9. data/.rubocop.yml +67 -0
  10. data/.yardopts +2 -0
  11. data/AGENTS.md +39 -0
  12. data/Appraisals +15 -0
  13. data/CHANGELOG.md +24 -0
  14. data/CLAUDE.md +104 -0
  15. data/Gemfile +11 -0
  16. data/Gemfile.lock +366 -0
  17. data/LICENSE.txt +25 -0
  18. data/README.md +439 -0
  19. data/Rakefile +4 -0
  20. data/bin/rspec +17 -0
  21. data/config/database.yml +16 -0
  22. data/config.ru +28 -0
  23. data/docs/activeadmin-4-detailed-reference.md +932 -0
  24. data/docs/activeadmin-4-gem-migration-guide.md +313 -0
  25. data/docs/combustion.md +213 -0
  26. data/docs/for-next-session.md +199 -0
  27. data/docs/guide-update-your-app.md +213 -0
  28. data/docs/propshaft-readme.md +121 -0
  29. data/docs/propshaft-upgrade.md +267 -0
  30. data/docs/rails-7-asset-pipeline.md +279 -0
  31. data/docs/setup-activeadmin-app.md +552 -0
  32. data/docs/setup-activeadmin-gem.md +535 -0
  33. data/docs/upload-system.md +225 -0
  34. data/gemfiles/rails_7.x_active_admin_4.x.gemfile +11 -0
  35. data/gemfiles/rails_7.x_active_admin_4.x.gemfile.lock +371 -0
  36. data/gemfiles/rails_8.x_active_admin_4.x.gemfile +11 -0
  37. data/gemfiles/rails_8.x_active_admin_4.x.gemfile.lock +366 -0
  38. data/lefthook.yml +17 -0
  39. data/lib/activeadmin/inputs/filters/searchable_select_input.rb +13 -0
  40. data/lib/activeadmin/inputs/searchable_select_input.rb +11 -0
  41. data/lib/activeadmin/searchable_select/engine.rb +17 -0
  42. data/lib/activeadmin/searchable_select/option_collection.rb +119 -0
  43. data/lib/activeadmin/searchable_select/resource_dsl_extension.rb +56 -0
  44. data/lib/activeadmin/searchable_select/resource_extension.rb +10 -0
  45. data/lib/activeadmin/searchable_select/select_input_extension.rb +159 -0
  46. data/lib/activeadmin/searchable_select/version.rb +5 -0
  47. data/lib/activeadmin/searchable_select.rb +20 -0
  48. data/lib/activeadmin-searchable_select.rb +4 -0
  49. data/lib/generators/active_admin/searchable_select/install/install_generator.rb +217 -0
  50. data/package-lock.json +18 -0
  51. data/package.json +45 -0
  52. data/rs-activeadmin-searchable_select.gemspec +38 -0
  53. data/sonar-project.properties +25 -0
  54. data/spec/features/ajax_params_spec.rb +31 -0
  55. data/spec/features/end_to_end_spec.rb +227 -0
  56. data/spec/features/filter_input_spec.rb +137 -0
  57. data/spec/features/form_input_spec.rb +122 -0
  58. data/spec/features/inline_ajax_setting_spec.rb +26 -0
  59. data/spec/features/input_errors_spec.rb +76 -0
  60. data/spec/features/input_html_options_spec.rb +30 -0
  61. data/spec/features/options_dsl_spec.rb +220 -0
  62. data/spec/features/production_build_spec.rb +108 -0
  63. data/spec/internal/app/admin/categories.rb +26 -0
  64. data/spec/internal/app/admin/dashboard.rb +29 -0
  65. data/spec/internal/app/admin/option_types.rb +19 -0
  66. data/spec/internal/app/admin/option_values.rb +30 -0
  67. data/spec/internal/app/admin/posts.rb +27 -0
  68. data/spec/internal/app/admin/products.rb +22 -0
  69. data/spec/internal/app/admin/rgb_colors.rb +25 -0
  70. data/spec/internal/app/admin/tag_names.rb +21 -0
  71. data/spec/internal/app/admin/test_ajax_params_category.rb +10 -0
  72. data/spec/internal/app/admin/test_ajax_params_post.rb +20 -0
  73. data/spec/internal/app/admin/test_form_post_class.rb +7 -0
  74. data/spec/internal/app/admin/test_form_post_custom.rb +11 -0
  75. data/spec/internal/app/admin/test_form_post_resource.rb +11 -0
  76. data/spec/internal/app/admin/test_form_post_resource_custom.rb +12 -0
  77. data/spec/internal/app/admin/test_inline_ajax_post.rb +9 -0
  78. data/spec/internal/app/admin/test_input_html_post.rb +11 -0
  79. data/spec/internal/app/admin/test_posts_display_text.rb +9 -0
  80. data/spec/internal/app/admin/test_posts_filter.rb +9 -0
  81. data/spec/internal/app/admin/test_posts_named.rb +9 -0
  82. data/spec/internal/app/admin/test_posts_pagination.rb +9 -0
  83. data/spec/internal/app/admin/test_posts_payload_lambda.rb +11 -0
  84. data/spec/internal/app/admin/test_posts_payload_proc.rb +9 -0
  85. data/spec/internal/app/admin/test_posts_scope_lambda.rb +8 -0
  86. data/spec/internal/app/admin/test_posts_scope_params.rb +8 -0
  87. data/spec/internal/app/admin/test_posts_scope_user.rb +8 -0
  88. data/spec/internal/app/admin/test_posts_text_attr.rb +5 -0
  89. data/spec/internal/app/admin/users.rb +23 -0
  90. data/spec/internal/app/admin/variants.rb +31 -0
  91. data/spec/internal/app/assets/config/manifest.js +1 -0
  92. data/spec/internal/app/assets/javascripts/active_admin.js +2 -0
  93. data/spec/internal/app/assets/javascripts/searchable_select_test.js +2 -0
  94. data/spec/internal/app/controllers/application_controller.rb +5 -0
  95. data/spec/internal/app/css/active_admin_source.css +81 -0
  96. data/spec/internal/app/js/active_admin.js +17 -0
  97. data/spec/internal/app/models/article.rb +12 -0
  98. data/spec/internal/app/models/category.rb +12 -0
  99. data/spec/internal/app/models/internal/tag_name.rb +14 -0
  100. data/spec/internal/app/models/internal_tag_name.rb +11 -0
  101. data/spec/internal/app/models/option_type.rb +12 -0
  102. data/spec/internal/app/models/option_value.rb +4 -0
  103. data/spec/internal/app/models/post.rb +15 -0
  104. data/spec/internal/app/models/product.rb +12 -0
  105. data/spec/internal/app/models/rgb_color.rb +16 -0
  106. data/spec/internal/app/models/user.rb +12 -0
  107. data/spec/internal/app/models/variant.rb +12 -0
  108. data/spec/internal/build_activeadmin_css.js +115 -0
  109. data/spec/internal/config/database.yml +7 -0
  110. data/spec/internal/config/environment.rb +48 -0
  111. data/spec/internal/config/initializers/active_admin.rb +53 -0
  112. data/spec/internal/config/initializers/assets.rb +9 -0
  113. data/spec/internal/config/initializers/searchable_select.rb +6 -0
  114. data/spec/internal/config/routes.rb +4 -0
  115. data/spec/internal/config.ru +4 -0
  116. data/spec/internal/db/schema.rb +63 -0
  117. data/spec/internal/db/seeds.rb +88 -0
  118. data/spec/internal/esbuild.config.js +30 -0
  119. data/spec/internal/inject-jquery.js +4 -0
  120. data/spec/internal/log/.gitignore +1 -0
  121. data/spec/internal/package/LICENSE.txt +25 -0
  122. data/spec/internal/package/README.md +439 -0
  123. data/spec/internal/package/package.json +45 -0
  124. data/spec/internal/package/src/index.js +1 -0
  125. data/spec/internal/package/src/searchable_select/init.js +1 -0
  126. data/spec/internal/package/src/searchable_select.css +1 -0
  127. data/spec/internal/package/src/searchable_select.scss +1 -0
  128. data/spec/internal/package-lock.json +1385 -0
  129. data/spec/internal/package.json +26 -0
  130. data/spec/internal/public/favicon.ico +0 -0
  131. data/spec/internal/spec/internal/app/css/active_admin_source.css +38 -0
  132. data/spec/internal/spec/internal/log/test.log +0 -0
  133. data/spec/internal/tailwind-active_admin.config.js +53 -0
  134. data/spec/rails_helper.rb +86 -0
  135. data/spec/spec_helper.rb +137 -0
  136. data/spec/support/active_admin_helpers.rb +17 -0
  137. data/spec/support/capybara.rb +8 -0
  138. data/spec/support/models.rb +88 -0
  139. data/spec/support/pluck_polyfill.rb +12 -0
  140. data/spec/support/reset_settings.rb +5 -0
  141. data/src/index.js +77 -0
  142. data/src/searchable_select/init.js +58 -0
  143. data/src/searchable_select.css +5 -0
  144. data/src/searchable_select.css.map +1 -0
  145. 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 scope
2
+ ActiveAdmin.register Post, as: 'TestPostScopeLambda' do
3
+ menu false
4
+ searchable_select_options(
5
+ scope: -> { Post.published },
6
+ text_attribute: :title
7
+ )
8
+ 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,5 @@
1
+ # Admin for testing searchable_select_options with text_attribute
2
+ ActiveAdmin.register Post, as: 'TestPostTextAttr' do
3
+ menu false
4
+ searchable_select_options(scope: Post, text_attribute: :title)
5
+ 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,2 @@
1
+ // Minimal JS for tests; ActiveAdmin 4 assets are managed externally
2
+ //= require active_admin/searchable_select
@@ -0,0 +1,2 @@
1
+ // Test setup for searchable_select - loads the init code directly
2
+ // This is loaded via the helper in active_admin.rb initializer
@@ -0,0 +1,5 @@
1
+ class ApplicationController < ActionController::Base
2
+ cattr_accessor :current_user
3
+
4
+ helper_method :current_user
5
+ end
@@ -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,4 @@
1
+ class OptionValue < ActiveRecord::Base
2
+ belongs_to :option_type
3
+ has_many :variants
4
+ 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,7 @@
1
+ development:
2
+ adapter: sqlite3
3
+ database: db/combustion_dev.sqlite
4
+
5
+ test:
6
+ adapter: sqlite3
7
+ database: db/combustion_test.sqlite
@@ -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
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Ensure the Searchable Select input is loaded for Formtastic
4
+ Rails.application.config.after_initialize do
5
+ require 'activeadmin/searchable_select'
6
+ end
@@ -0,0 +1,4 @@
1
+ Rails.application.routes.draw do
2
+ ActiveAdmin.routes(self)
3
+ root to: 'admin/dashboard#index'
4
+ end
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+ require_relative 'config/environment'
3
+
4
+ run Rails.application