activeadmin-tom_select 4.1.0

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 (196) 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 +174 -0
  5. data/.github/workflows/npm-publish.yml +50 -0
  6. data/.gitignore +35 -0
  7. data/.npmignore +58 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +75 -0
  10. data/.yardopts +2 -0
  11. data/AGENTS.md +39 -0
  12. data/Appraisals +9 -0
  13. data/CHANGELOG.md +64 -0
  14. data/CLAUDE.md +157 -0
  15. data/Gemfile +12 -0
  16. data/Gemfile.lock +368 -0
  17. data/LICENSE.txt +25 -0
  18. data/README.md +483 -0
  19. data/Rakefile +4 -0
  20. data/activeadmin-tom_select.gemspec +43 -0
  21. data/bin/rspec +17 -0
  22. data/config/database.yml +16 -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/fail.png +0 -0
  27. data/docs/guide-update-your-app.md +283 -0
  28. data/docs/normal.png +0 -0
  29. data/docs/propshaft-readme.md +320 -0
  30. data/docs/propshaft-upgrade.md +484 -0
  31. data/docs/setup-activeadmin-app.md +552 -0
  32. data/docs/setup-activeadmin-gem.md +535 -0
  33. data/docs/tailwind/blog-page.md +341 -0
  34. data/docs/tailwind/upgrade-guide-enhanced.md +438 -0
  35. data/docs/tailwind/upgrade-guide.md +416 -0
  36. data/docs/tailwind-4/active_admin.rake +38 -0
  37. data/docs/tailwind-4/active_admin.tailwind.css +415 -0
  38. data/docs/tailwind-4/tailwind-active_admin.config.js +18 -0
  39. data/docs/test-app-change.md +154 -0
  40. data/docs/test-environment-fixes.md +58 -0
  41. data/docs/update-tom-select.md +184 -0
  42. data/docs/upload-system.md +225 -0
  43. data/gemfiles/rails_7.x_active_admin_4.x.gemfile +10 -0
  44. data/gemfiles/rails_7.x_active_admin_4.x.gemfile.lock +377 -0
  45. data/gemfiles/rails_8.x_active_admin_4.x.gemfile +10 -0
  46. data/gemfiles/rails_8.x_active_admin_4.x.gemfile.lock +372 -0
  47. data/lefthook.yml +17 -0
  48. data/lib/activeadmin/inputs/filters/searchable_select_input.rb +19 -0
  49. data/lib/activeadmin/inputs/searchable_select_input.rb +16 -0
  50. data/lib/activeadmin/tom_select/engine.rb +17 -0
  51. data/lib/activeadmin/tom_select/option_collection.rb +128 -0
  52. data/lib/activeadmin/tom_select/resource_dsl_extension.rb +56 -0
  53. data/lib/activeadmin/tom_select/resource_extension.rb +10 -0
  54. data/lib/activeadmin/tom_select/select_input_extension.rb +168 -0
  55. data/lib/activeadmin/tom_select/version.rb +5 -0
  56. data/lib/activeadmin/tom_select.rb +20 -0
  57. data/lib/activeadmin-tom_select.rb +5 -0
  58. data/lib/generators/active_admin/tom_select/install/install_generator.rb +180 -0
  59. data/npm-package/package-lock.json +51 -0
  60. data/npm-package/package.json +43 -0
  61. data/npm-package/src/index.js +153 -0
  62. data/npm-package/src/tom-select-tailwind.css +392 -0
  63. data/sonar-project.properties +25 -0
  64. data/spec/features/ajax_params_spec.rb +31 -0
  65. data/spec/features/asset_pipeline_diagnostic_spec.rb +155 -0
  66. data/spec/features/end_to_end_spec.rb +273 -0
  67. data/spec/features/filter_input_spec.rb +144 -0
  68. data/spec/features/form_input_spec.rb +122 -0
  69. data/spec/features/inline_ajax_setting_spec.rb +26 -0
  70. data/spec/features/input_errors_spec.rb +76 -0
  71. data/spec/features/input_html_options_spec.rb +30 -0
  72. data/spec/features/options_dsl_spec.rb +230 -0
  73. data/spec/features/production_build_spec.rb +108 -0
  74. data/spec/internal/.node-version +1 -0
  75. data/spec/internal/Gemfile +43 -0
  76. data/spec/internal/Gemfile.lock +333 -0
  77. data/spec/internal/Procfile.dev +3 -0
  78. data/spec/internal/README.md +24 -0
  79. data/spec/internal/Rakefile +6 -0
  80. data/spec/internal/app/admin/categories.rb +26 -0
  81. data/spec/internal/app/admin/dashboard.rb +29 -0
  82. data/spec/internal/app/admin/option_types.rb +19 -0
  83. data/spec/internal/app/admin/option_values.rb +30 -0
  84. data/spec/internal/app/admin/posts.rb +27 -0
  85. data/spec/internal/app/admin/products.rb +22 -0
  86. data/spec/internal/app/admin/rgb_colors.rb +25 -0
  87. data/spec/internal/app/admin/tag_names.rb +21 -0
  88. data/spec/internal/app/admin/test_ajax_params_category.rb +10 -0
  89. data/spec/internal/app/admin/test_ajax_params_post.rb +20 -0
  90. data/spec/internal/app/admin/test_form_post_class.rb +7 -0
  91. data/spec/internal/app/admin/test_form_post_custom.rb +11 -0
  92. data/spec/internal/app/admin/test_form_post_resource.rb +11 -0
  93. data/spec/internal/app/admin/test_form_post_resource_custom.rb +12 -0
  94. data/spec/internal/app/admin/test_inline_ajax_post.rb +9 -0
  95. data/spec/internal/app/admin/test_input_html_post.rb +11 -0
  96. data/spec/internal/app/admin/test_posts_display_text.rb +9 -0
  97. data/spec/internal/app/admin/test_posts_filter.rb +9 -0
  98. data/spec/internal/app/admin/test_posts_named.rb +9 -0
  99. data/spec/internal/app/admin/test_posts_pagination.rb +9 -0
  100. data/spec/internal/app/admin/test_posts_payload_lambda.rb +11 -0
  101. data/spec/internal/app/admin/test_posts_payload_proc.rb +9 -0
  102. data/spec/internal/app/admin/test_posts_scope_lambda.rb +8 -0
  103. data/spec/internal/app/admin/test_posts_scope_params.rb +8 -0
  104. data/spec/internal/app/admin/test_posts_scope_user.rb +8 -0
  105. data/spec/internal/app/admin/test_posts_text_attr.rb +5 -0
  106. data/spec/internal/app/admin/users.rb +23 -0
  107. data/spec/internal/app/admin/variants.rb +31 -0
  108. data/spec/internal/app/assets/config/manifest.js +2 -0
  109. data/spec/internal/app/assets/images/.keep +0 -0
  110. data/spec/internal/app/assets/stylesheets/active_admin.tailwind.css +16 -0
  111. data/spec/internal/app/assets/stylesheets/application.tailwind.css +15 -0
  112. data/spec/internal/app/controllers/application_controller.rb +9 -0
  113. data/spec/internal/app/controllers/concerns/.keep +0 -0
  114. data/spec/internal/app/helpers/application_helper.rb +2 -0
  115. data/spec/internal/app/javascript/active_admin.js +19 -0
  116. data/spec/internal/app/javascript/application.js +2 -0
  117. data/spec/internal/app/jobs/application_job.rb +7 -0
  118. data/spec/internal/app/mailers/application_mailer.rb +4 -0
  119. data/spec/internal/app/models/admin_user.rb +9 -0
  120. data/spec/internal/app/models/application_record.rb +3 -0
  121. data/spec/internal/app/models/article.rb +12 -0
  122. data/spec/internal/app/models/category.rb +12 -0
  123. data/spec/internal/app/models/color.rb +9 -0
  124. data/spec/internal/app/models/concerns/.keep +0 -0
  125. data/spec/internal/app/models/internal/tag_name.rb +14 -0
  126. data/spec/internal/app/models/internal_tag_name.rb +11 -0
  127. data/spec/internal/app/models/option_type.rb +12 -0
  128. data/spec/internal/app/models/option_value.rb +4 -0
  129. data/spec/internal/app/models/post.rb +15 -0
  130. data/spec/internal/app/models/product.rb +12 -0
  131. data/spec/internal/app/models/rgb_color.rb +16 -0
  132. data/spec/internal/app/models/tag.rb +12 -0
  133. data/spec/internal/app/models/tagging.rb +12 -0
  134. data/spec/internal/app/models/user.rb +12 -0
  135. data/spec/internal/app/models/variant.rb +12 -0
  136. data/spec/internal/app/views/layouts/application.html.erb +28 -0
  137. data/spec/internal/app/views/layouts/mailer.html.erb +13 -0
  138. data/spec/internal/app/views/layouts/mailer.text.erb +1 -0
  139. data/spec/internal/app/views/pwa/manifest.json.erb +22 -0
  140. data/spec/internal/app/views/pwa/service-worker.js +26 -0
  141. data/spec/internal/bin/bundle +117 -0
  142. data/spec/internal/bin/dev +11 -0
  143. data/spec/internal/bin/rackup +27 -0
  144. data/spec/internal/bin/rails +4 -0
  145. data/spec/internal/bin/rake +4 -0
  146. data/spec/internal/bin/setup +37 -0
  147. data/spec/internal/config/application.rb +50 -0
  148. data/spec/internal/config/boot.rb +3 -0
  149. data/spec/internal/config/credentials.yml.enc +1 -0
  150. data/spec/internal/config/database.yml +32 -0
  151. data/spec/internal/config/environment.rb +5 -0
  152. data/spec/internal/config/environments/development.rb +63 -0
  153. data/spec/internal/config/environments/production.rb +86 -0
  154. data/spec/internal/config/environments/test.rb +50 -0
  155. data/spec/internal/config/initializers/active_admin.rb +54 -0
  156. data/spec/internal/config/initializers/assets.rb +8 -0
  157. data/spec/internal/config/initializers/content_security_policy.rb +25 -0
  158. data/spec/internal/config/initializers/devise.rb +315 -0
  159. data/spec/internal/config/initializers/filter_parameter_logging.rb +8 -0
  160. data/spec/internal/config/initializers/inflections.rb +16 -0
  161. data/spec/internal/config/initializers/searchable_select.rb +6 -0
  162. data/spec/internal/config/locales/devise.en.yml +65 -0
  163. data/spec/internal/config/locales/en.yml +31 -0
  164. data/spec/internal/config/master.key +1 -0
  165. data/spec/internal/config/puma.rb +38 -0
  166. data/spec/internal/config/routes.rb +17 -0
  167. data/spec/internal/config.ru +6 -0
  168. data/spec/internal/db/schema.rb +174 -0
  169. data/spec/internal/db/seeds.rb +167 -0
  170. data/spec/internal/esbuild.config.js +34 -0
  171. data/spec/internal/lib/tasks/.keep +0 -0
  172. data/spec/internal/lib/tasks/active_admin.rake +55 -0
  173. data/spec/internal/log/.keep +0 -0
  174. data/spec/internal/package-lock.json +1954 -0
  175. data/spec/internal/package.json +21 -0
  176. data/spec/internal/public/400.html +114 -0
  177. data/spec/internal/public/404.html +114 -0
  178. data/spec/internal/public/406-unsupported-browser.html +114 -0
  179. data/spec/internal/public/422.html +114 -0
  180. data/spec/internal/public/500.html +114 -0
  181. data/spec/internal/public/icon.png +0 -0
  182. data/spec/internal/public/icon.svg +3 -0
  183. data/spec/internal/public/robots.txt +1 -0
  184. data/spec/internal/script/.keep +0 -0
  185. data/spec/internal/storage/.keep +0 -0
  186. data/spec/internal/tailwind.config.js +23 -0
  187. data/spec/internal/vendor/.keep +0 -0
  188. data/spec/internal/yarn.lock +824 -0
  189. data/spec/rails_helper.rb +62 -0
  190. data/spec/spec_helper.rb +138 -0
  191. data/spec/support/active_admin_helpers.rb +17 -0
  192. data/spec/support/capybara.rb +8 -0
  193. data/spec/support/models.rb +11 -0
  194. data/spec/support/pluck_polyfill.rb +12 -0
  195. data/spec/support/reset_settings.rb +5 -0
  196. metadata +497 -0
@@ -0,0 +1,184 @@
1
+ # Tom Select Migration Summary
2
+
3
+ ## Overview
4
+ We successfully migrated ActiveAdmin Searchable Select from Select2 (jQuery-based) to Tom Select (vanilla JS, TypeScript-ready) with Tailwind CSS 4 support.
5
+
6
+ ## Key Changes Made
7
+
8
+ ### 1. Package Dependencies
9
+ **Removed:**
10
+ - `jquery` peer dependency
11
+ - `select2` peer dependency
12
+
13
+ **Added:**
14
+ - `tom-select: ^2.4.3` peer dependency
15
+
16
+ ### 2. JavaScript Changes
17
+
18
+ #### `/src/index.js`
19
+ - Complete rewrite without jQuery dependency
20
+ - Uses native `fetch()` for AJAX requests
21
+ - Tom Select initialization with proper option mapping
22
+ - Handles Select2 → Tom Select option conversion (id/text → valueField/labelField)
23
+
24
+ #### Removed Legacy Files:
25
+ - `/src/searchable_select/init.js` - Legacy compatibility file removed
26
+ - `/spec/internal/inject-jquery.js` - jQuery injection hack removed
27
+ - `/spec/internal/build_activeadmin_css.js` - Old CSS build hack removed
28
+
29
+ ### 3. CSS/Styling Changes
30
+
31
+ #### New Files Created:
32
+ - `/src/tom-select-tailwind.css` - Complete Tom Select styles with Tailwind classes (consolidated single file)
33
+
34
+ #### Package Exports Updated:
35
+ ```json
36
+ "exports": {
37
+ "./tom-select-tailwind": "./src/tom-select-tailwind.css"
38
+ }
39
+ ```
40
+
41
+ #### Removed Files:
42
+ - `/src/searchable_select.css` - Consolidated into tom-select-tailwind.css
43
+ - All legacy Select2 CSS imports
44
+
45
+ ### 4. Build Process (Tailwind 3)
46
+
47
+ #### New Test App Structure:
48
+ ```
49
+ /spec/internal/
50
+ ├── tailwind.config.js # Tailwind 3 config
51
+ ├── app/assets/stylesheets/
52
+ │ └── active_admin.tailwind.css # Main CSS entry with Tom Select styles
53
+ ├── build-css.js # Node script for CSS build
54
+ ├── esbuild.config.js # JavaScript build config
55
+ └── package.json # Simplified scripts
56
+ ```
57
+
58
+ #### Build Commands:
59
+ - `npm run build:css` → Runs Tailwind CSS via `build-css.js`
60
+ - `npm run build:js` → Runs esbuild for JavaScript bundling
61
+ - `npm run build` → Builds both JS and CSS
62
+
63
+ #### CSS Build Process Fix:
64
+ - Integrated comprehensive ActiveAdmin styles from docs/tailwind-4 setup
65
+ - Included all ActiveAdmin component styles (panels, data tables, filters, forms, etc.)
66
+ - Tom Select styles are imported at the end of the CSS file
67
+ - All styles are properly processed by Tailwind CSS and included in the final build
68
+ - Fixed styling issues that were breaking ActiveAdmin UI components
69
+
70
+ ### 5. Test Updates
71
+
72
+ #### CSS Class Changes:
73
+ | Select2 | Tom Select |
74
+ |---------|------------|
75
+ | `.select2-container` | `.ts-wrapper` or `.ts-control` |
76
+ | `.select2-dropdown` | `.ts-dropdown` |
77
+ | `.select2-results__option` | `.ts-dropdown .option` |
78
+ | `.select2-selection` | `.ts-control .item` |
79
+ | `.select2-search__field` | `.ts-control input` |
80
+
81
+ #### Helper Method Updates in Tests:
82
+ - `expand_select_box`: Now clicks `.ts-control`
83
+ - `enter_search_term`: Targets `.ts-control input`
84
+ - `select_box_items`: Finds `.ts-dropdown .option`
85
+ - `finished_all_ajax_requests`: No longer uses jQuery.active
86
+
87
+ ### 6. Documentation Structure
88
+
89
+ #### Example Files (with credits):
90
+ `/docs/tailwind-4/` - Example Tailwind 4 setup files
91
+ - Credit: https://gist.github.com/amkisko/af1b2f7dc4f0f941437ea16400277864
92
+
93
+ ### 7. Migration Path for Users
94
+
95
+ Users will need to:
96
+ 1. Update their `Gemfile` to use the new version
97
+ 2. Remove jQuery and Select2 dependencies
98
+ 3. Add Tom Select dependency: `npm install tom-select@^2.4.3`
99
+ 4. Update their CSS imports to use Tom Select styles
100
+ 5. If using Tailwind, import our tom-select-tailwind styles
101
+ 6. Update any custom JavaScript that referenced Select2 APIs
102
+
103
+ ### 8. Breaking Changes
104
+
105
+ 1. **No jQuery Required**: Apps no longer need jQuery for searchable selects
106
+ 2. **CSS Classes Changed**: All Select2 classes replaced with Tom Select equivalents
107
+ 3. **JavaScript API Different**: Tom Select has different initialization and options
108
+ 4. **Legacy init.js Removed**: No backward compatibility layer
109
+
110
+ ### 9. Benefits of Migration
111
+
112
+ 1. **No jQuery Dependency**: Reduces bundle size significantly
113
+ 2. **Modern JavaScript**: ES6+ modules, TypeScript support
114
+ 3. **Better Performance**: Tom Select is lighter and faster
115
+ 4. **Tailwind 4 Ready**: Native Tailwind utility classes
116
+ 5. **Future-Proof**: Active development, modern architecture
117
+
118
+ ### 10. Files to Commit
119
+
120
+ **Modified:**
121
+ - `/package.json` - Updated dependencies and exports
122
+ - `/src/index.js` - Rewritten for Tom Select
123
+ - `/spec/features/*.rb` - Updated test selectors
124
+ - `/spec/internal/package.json` - Removed jQuery, added Tom Select
125
+ - `/spec/internal/app/js/active_admin.js` - Tom Select import
126
+
127
+ **Created:**
128
+ - `/src/tom-select-tailwind.css`
129
+ - `/src/searchable_select.css`
130
+ - `/spec/internal/config/tailwind-active_admin.config.js`
131
+ - `/spec/internal/app/assets/stylesheets/active_admin.tailwind.css`
132
+ - `/spec/internal/lib/tasks/active_admin.rake`
133
+
134
+ **Deleted:**
135
+ - `/src/searchable_select/` directory
136
+ - `/spec/internal/inject-jquery.js`
137
+ - `/spec/internal/build_activeadmin_css.js`
138
+ - `/spec/internal/tailwind-active_admin.config.js` (old location)
139
+
140
+ ### 11. Testing Status
141
+
142
+ ✅ **Tests Fixed and Working:**
143
+ - All JavaScript initialization tests passing
144
+ - Tom Select properly initializes in test environment
145
+ - Clear button functionality working for all searchable selects
146
+ - Assets properly served in test environment
147
+
148
+ **Test Environment Setup:**
149
+ - Assets must be built: `npm run build:js` and `bundle exec rake active_admin:build`
150
+ - Assets copied to public directory for test environment:
151
+ ```bash
152
+ mkdir -p public/javascripts public/stylesheets
153
+ cp app/assets/builds/active_admin.js public/javascripts/
154
+ cp app/assets/builds/active_admin.css public/stylesheets/
155
+ ```
156
+ - Tests use Playwright driver for modern JavaScript support
157
+
158
+ **Remaining Test Issues (4 failures):**
159
+ - AJAX options not loading properly in some integration tests
160
+ - Dropdown visibility detection needs adjustment for Tom Select
161
+ - Search input focus/activation needs refinement
162
+
163
+ ### 12. Key Implementation Details
164
+
165
+ #### Clear Button Feature:
166
+ - All searchable selects are clearable by default
167
+ - Implemented via `data-clearable="true"` attribute
168
+ - Tom Select's `clear_button` plugin automatically added
169
+ - Clear button positioned at `right: 2rem` for better UX
170
+ - Can be disabled by setting `clearable: false` in Ruby options
171
+
172
+ #### JavaScript Module Export:
173
+ - Main module exports both `setupAutoInit` and `initSearchableSelects`
174
+ - Functions made globally available in test environment via `window` object
175
+ - Auto-initialization on DOMContentLoaded, Turbo load, and has_many_add events
176
+
177
+ ### 13. Next Steps
178
+
179
+ 1. ✅ Complete test fixes for remaining failures (mostly done)
180
+ 2. Update README.md with new installation instructions
181
+ 3. Create migration guide at `/docs/guide-update-your-app.md`
182
+ 4. Version bump to 5.0.0 (major version due to breaking changes)
183
+ 5. Test with real ActiveAdmin applications
184
+ 6. Consider adding TypeScript definitions for better IDE support
@@ -0,0 +1,225 @@
1
+ # CKEditor5-Rails Upload System Documentation
2
+
3
+ ## Overview
4
+
5
+ The CKEditor5-Rails gem implements a flexible image upload system that allows users to upload images directly from the editor to a server endpoint instead of embedding them as Base64. The system is designed to be backend-agnostic and can integrate with various storage solutions including ActiveStorage and Shrine.
6
+
7
+ ## Architecture
8
+
9
+ ### Core Components
10
+
11
+ #### 1. SimpleUploadAdapter Plugin (`lib/ckeditor5/rails/plugins/simple_upload_adapter.rb`)
12
+
13
+ The heart of the upload system is an inline JavaScript plugin that:
14
+ - Extends CKEditor5's Plugin class
15
+ - Requires the FileRepository plugin as a dependency
16
+ - Implements the upload adapter factory pattern
17
+ - Handles file uploads via XMLHttpRequest with progress tracking
18
+
19
+ **Location**: `lib/ckeditor5/rails/plugins/simple_upload_adapter.rb`
20
+
21
+ **Key Features**:
22
+ - Async/await based upload handling
23
+ - Progress tracking through XMLHttpRequest events
24
+ - CSRF token integration for Rails security
25
+ - Abort capability for cancelled uploads
26
+ - JSON response parsing for uploaded file URLs
27
+
28
+ #### 2. PropsInlinePlugin Base Class (`lib/ckeditor5/rails/editor/props_inline_plugin.rb`)
29
+
30
+ The upload adapter extends this base class which:
31
+ - Wraps JavaScript code in an async IIFE (Immediately Invoked Function Expression)
32
+ - Supports optional code compression via Terser
33
+ - Provides window-based plugin registration mechanism
34
+ - Handles plugin initialization errors gracefully
35
+
36
+ **Location**: `lib/ckeditor5/rails/editor/props_inline_plugin.rb`
37
+
38
+ #### 3. Plugin Registration System (`lib/ckeditor5/rails/plugins.rb`)
39
+
40
+ Central registry that:
41
+ - Loads all core plugins including SimpleUploadAdapter
42
+ - Manages plugin dependencies
43
+ - Handles plugin patches and fixes
44
+
45
+ **Location**: `lib/ckeditor5/rails/plugins.rb`
46
+
47
+ ## Configuration System
48
+
49
+ ### Preset Builder Integration (`lib/ckeditor5/rails/presets/preset_builder.rb`)
50
+
51
+ The upload adapter is configured through the preset system:
52
+
53
+ ```ruby
54
+ def simple_upload_adapter(upload_url = '/uploads', compress: !@disallow_inline_plugin_compression)
55
+ plugins do
56
+ remove(:Base64UploadAdapter) # Remove default Base64 adapter
57
+ end
58
+
59
+ plugin(Plugins::SimpleUploadAdapter.new(compress: compress))
60
+ configure(:simpleUpload, { uploadUrl: upload_url })
61
+ end
62
+ ```
63
+
64
+ **Location**: `lib/ckeditor5/rails/presets/preset_builder.rb:394-401`
65
+
66
+ **Configuration Steps**:
67
+ 1. Removes the default Base64UploadAdapter plugin
68
+ 2. Adds the SimpleUploadAdapter plugin
69
+ 3. Configures the upload URL endpoint
70
+ 4. Optionally enables/disables JavaScript compression
71
+
72
+ ### Usage in Presets
73
+
74
+ Upload functionality is enabled in presets via:
75
+
76
+ ```ruby
77
+ # In preset definition
78
+ simple_upload_adapter # Uses default '/uploads' endpoint
79
+ simple_upload_adapter '/custom' # Custom endpoint
80
+ ```
81
+
82
+ **Example Location**: `sandbox/config/initializers/ckeditor5.rb:82`
83
+
84
+ ## Frontend Implementation
85
+
86
+ ### Upload Flow
87
+
88
+ 1. **User Action**: User selects/pastes an image in the editor
89
+ 2. **Plugin Activation**: FileRepository triggers createUploadAdapter
90
+ 3. **Adapter Creation**: SimpleUploadAdapter creates an upload instance
91
+ 4. **FormData Preparation**: File wrapped in FormData with 'upload' field name
92
+ 5. **Security Headers**:
93
+ - X-Requested-With: XMLHttpRequest
94
+ - X-CSRF-Token: Extracted from meta tag
95
+ 6. **Upload Process**:
96
+ - Progress events update loader.uploaded/uploadTotal
97
+ - Success (200-299): Parse JSON response for URL
98
+ - Error handling for failed/aborted uploads
99
+ 7. **Editor Update**: Returned URL replaces placeholder image
100
+
101
+ ### Response Format
102
+
103
+ Server must return JSON with structure:
104
+ ```json
105
+ {
106
+ "url": "https://example.com/uploads/image.jpg"
107
+ }
108
+ ```
109
+
110
+ ## Integration Points
111
+
112
+ ### 1. Rails Controller
113
+
114
+ The upload endpoint (not included in gem) should:
115
+ - Accept POST requests to configured URL
116
+ - Process multipart/form-data with 'upload' field
117
+ - Store file using preferred backend (ActiveStorage, Shrine, etc.)
118
+ - Return JSON with uploaded file URL
119
+ - Handle CSRF token validation
120
+
121
+ ### 2. Helper Methods
122
+
123
+ Upload configuration accessible via:
124
+ - `ckeditor5_editor` helper in views
125
+ - Preset configuration in initializers
126
+ - Runtime configuration overrides
127
+
128
+ **Location**: `lib/ckeditor5/rails/editor/helpers/editor_helpers.rb`
129
+
130
+ ### 3. Engine Registration
131
+
132
+ Upload adapter available through:
133
+ - Engine preset system
134
+ - Direct plugin inclusion
135
+ - Configuration DSL methods
136
+
137
+ **Location**: `lib/ckeditor5/rails/engine.rb:83`
138
+
139
+ ## File Structure
140
+
141
+ ```
142
+ lib/ckeditor5/rails/
143
+ ├── plugins/
144
+ │ ├── simple_upload_adapter.rb # Main upload adapter implementation
145
+ │ └── ...
146
+ ├── editor/
147
+ │ ├── props_inline_plugin.rb # Base class for inline plugins
148
+ │ └── helpers/
149
+ │ └── editor_helpers.rb # View helpers for editor
150
+ ├── presets/
151
+ │ └── preset_builder.rb # Configuration DSL with upload method
152
+ └── engine.rb # Rails engine with upload registration
153
+ ```
154
+
155
+ ## Configuration Examples
156
+
157
+ ### Basic Setup
158
+
159
+ ```ruby
160
+ CKEditor5::Rails.configure do
161
+ # Enable with default /uploads endpoint
162
+ simple_upload_adapter
163
+ end
164
+ ```
165
+
166
+ ### Custom Endpoint
167
+
168
+ ```ruby
169
+ CKEditor5::Rails.configure do
170
+ # Custom upload endpoint
171
+ simple_upload_adapter '/api/images/upload'
172
+ end
173
+ ```
174
+
175
+ ### With Compression Disabled
176
+
177
+ ```ruby
178
+ CKEditor5::Rails.configure do
179
+ # Disable JavaScript compression for debugging
180
+ simple_upload_adapter '/uploads', compress: false
181
+ end
182
+ ```
183
+
184
+ ## Key Implementation Details
185
+
186
+ ### JavaScript Plugin Structure
187
+
188
+ The plugin is written as an ES6 module that:
189
+ 1. Imports required CKEditor5 modules dynamically
190
+ 2. Returns a class extending Plugin
191
+ 3. Implements standard CKEditor5 plugin lifecycle
192
+ 4. Integrates with FileRepository for upload management
193
+
194
+ ### Security Considerations
195
+
196
+ - CSRF token automatically extracted from Rails meta tag
197
+ - XMLHttpRequest marked with X-Requested-With header
198
+ - Server-side validation responsibility lies with implementer
199
+
200
+ ### Error Handling
201
+
202
+ - Network errors caught and rejected with descriptive messages
203
+ - HTTP status codes outside 200-299 range treated as errors
204
+ - Upload abort capability for user cancellation
205
+
206
+ ## Backend Requirements
207
+
208
+ To implement the upload endpoint:
209
+
210
+ 1. **Route Definition**: Add POST route to configured URL
211
+ 2. **File Processing**: Handle multipart upload with 'upload' parameter
212
+ 3. **Storage Backend**: Integrate with ActiveStorage, Shrine, or custom solution
213
+ 4. **Response Format**: Return JSON with 'url' key
214
+ 5. **Security**: Validate CSRF tokens and user permissions
215
+
216
+ ## Extension Points
217
+
218
+ The system supports:
219
+ - Multiple upload adapters via plugin system
220
+ - Custom configuration through preset builder
221
+ - Backend flexibility through endpoint abstraction
222
+ - Compression toggle for development/production
223
+ - Integration with various storage backends
224
+
225
+ This architecture provides a clean separation between the editor frontend and storage backend, allowing developers to implement uploads using their preferred Rails patterns and storage solutions.
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activeadmin", "4.0.0.beta16"
6
+ gem "devise", "~> 4.9", group: :test
7
+ gem "propshaft", "~> 1.2", group: :test
8
+ gem "rails", "~> 7.1"
9
+
10
+ gemspec name: "activeadmin-tom_select", path: "../"