inline_forms 7.2.11 → 7.5.2
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/CHANGELOG.md +176 -0
- data/README.rdoc +4 -2
- data/app/assets/javascripts/inline_forms/inline_forms.js +23 -0
- data/app/assets/stylesheets/inline_forms/inline_forms.scss +32 -16
- data/app/controllers/concerns/versions_concern.rb +2 -1
- data/app/controllers/inline_forms_application_controller.rb +5 -1
- data/app/controllers/inline_forms_controller.rb +120 -24
- data/app/helpers/form_elements/ckeditor.rb +4 -30
- data/app/helpers/form_elements/plain_text.rb +23 -0
- data/app/helpers/form_elements/plain_text_area.rb +7 -3
- data/app/helpers/form_elements/text_area.rb +4 -44
- data/app/helpers/form_elements/text_area_without_ckeditor.rb +5 -4
- data/app/helpers/form_elements/text_field.rb +2 -2
- data/app/helpers/inline_forms_helper.rb +127 -71
- data/app/views/devise/sessions/_form.html.erb +4 -1
- data/app/views/inline_forms/_close.html.erb +6 -4
- data/app/views/inline_forms/_edit.html.erb +7 -40
- data/app/views/inline_forms/_list.html.erb +52 -39
- data/app/views/inline_forms/_new.html.erb +23 -11
- data/app/views/inline_forms/_show.html.erb +13 -11
- data/app/views/inline_forms/_versions_list.html.erb +4 -8
- data/app/views/inline_forms/create_list_frame.html.erb +3 -0
- data/app/views/inline_forms/field_edit.html.erb +3 -0
- data/app/views/inline_forms/field_show.html.erb +3 -0
- data/app/views/inline_forms/new_record.html.erb +3 -0
- data/app/views/inline_forms/row_close.html.erb +5 -0
- data/app/views/inline_forms/row_destroyed.html.erb +9 -0
- data/app/views/inline_forms/row_show.html.erb +3 -0
- data/app/views/inline_forms/versions_list_panel.html.erb +3 -0
- data/app/views/inline_forms/versions_panel.html.erb +3 -0
- data/app/views/layouts/application.html.erb +0 -1
- data/app/views/layouts/inline_forms.html.erb +10 -1
- data/bin/inline_forms +22 -1
- data/bin/inline_forms_installer_core.rb +38 -3
- data/docs/ujs-to-turbo.md +193 -0
- data/lib/generators/USAGE +2 -2
- data/lib/generators/assets/stylesheets/inline_forms.scss +32 -16
- data/lib/inline_forms/version.rb +1 -1
- data/lib/inline_forms.rb +58 -2
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_field_turbo_test.rb +74 -0
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_name_list_test.rb +73 -0
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_photos_pagination_test.rb +199 -15
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_row_turbo_test.rb +94 -0
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_top_level_new_test.rb +100 -0
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_versions_turbo_test.rb +27 -0
- data/lib/installer_templates/example_app_tests/test/models/example_app_plain_text_rich_text_edge_cases_test.rb +46 -0
- data/lib/installer_templates/example_app_views/apartments/name_list.html.erb +26 -0
- data/lib/installer_templates/example_app_views/inline_forms/_header.html.erb +45 -0
- data/test/inline_forms_generator_test.rb +10 -0
- data/test/plain_text_configuration_test.rb +90 -0
- metadata +21 -5
- data/app/views/inline_forms/edit.js.erb +0 -1
- data/app/views/inline_forms/show_element.js.erb +0 -1
- data/app/views/inline_forms/update.js.erb +0 -1
- data/lib/generators/assets/javascripts/ckeditor/config.js +0 -72
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bbf211e9092af732b645bf10e9f9c338ced10c55e3ebf0a533146537669d1a4d
|
|
4
|
+
data.tar.gz: 90bc8cf55083ca23bbc1d3122a49e835620bf2e4800c8c83a93b871230d54718
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5f66995db3089c59e1654f92f1a7c78b9701ccad3ea0a12fb4cf7729ea5ed1bff70003847af80ebcae6347c05e29f7e6fc9e8a9317252ea120a7a09d790c2284
|
|
7
|
+
data.tar.gz: 2e04d9869aff6e13a1eb6556e9865e640725dee6d9ad5a56887ed23f125bd9378ab679c773fd84cbc72b8df408335dd7026998e113254366e4cc358155c70785
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,182 @@ All notable changes to this project are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [7.5.2] - 2026-05-16
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **Field re-edit after Turbo update / cancel (Photo image, name, etc.):** `render_turbo_field` now sets **`@inline_forms_turbo_field = true`**, so the link inside the swapped **`<turbo-frame id="photo_<id>_image">`** carries **`data-turbo`** instead of legacy **`data-remote`**. 7.5.1 set the flag only in `_show.html.erb` (the row open template); the bare `field_show` re-render after a field cancel/update lost it, the link fell back to **`remote: true`**, jquery_ujs intercepted as a JS request the controller does not register, and the second click silently failed (no swap, no edit form).
|
|
12
|
+
- **Top-level `+ new` flow (e.g. /apartments):** `link_to_new_record` falls back to **UJS (`remote: true`)** when called without a `parent_class`. The top-level list root stays a **`<div id="apartments_list">`** (a `<turbo-frame>` there collapses inside `position: absolute` `#outer_container` and hides rows under the fixed top bar), so a Turbo target on the **`+`** link is invalid -- 7.5.1 emitted `data-turbo-frame="apartments_list"`, which made cancel/create produce Turbo's "Content missing" or fall back to a full-page navigation. UJS (`new.js.erb` / `list.js.erb`) swap **`#apartments_list`** in place; nested has_many lists keep the Turbo contract unchanged.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Defensive CSS:** `turbo-frame { display: block; }` so any `<turbo-frame>` inside `#outer_container` (custom elements default to `display: inline`) does not collapse and hide its row content.
|
|
17
|
+
- **Regression tests:**
|
|
18
|
+
- `example_app_apartment_top_level_new_test.rb` -- top-level list root stays `<div>`, **`+`** link is UJS, `new` / `cancel` / `create` go through `format.js` and swap **`#apartments_list`**.
|
|
19
|
+
- `example_app_apartment_photos_pagination_test.rb` -- after Turbo update / cancel of a Photo image field, `field_show` carries `data-turbo="true"` (not `data-remote="true"`).
|
|
20
|
+
|
|
21
|
+
### Verified
|
|
22
|
+
|
|
23
|
+
- **`bundle exec rails test`** -- **60 runs, 302 assertions, 0 failures**.
|
|
24
|
+
- **curl:** field show after cancel/update emits `data-turbo="true" data-turbo-frame="_self"` (no `data-remote`); top-level new returns `format.js` swap of `#apartments_list`.
|
|
25
|
+
- **Browser:** top-level `+ new Apartment` form renders inline + cancel returns to list (no "Content missing"); nested Photo image edit can be reopened immediately after cancel and after replacement.
|
|
26
|
+
|
|
27
|
+
## [7.5.1] - 2026-05-16
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- **Nested associated `+` (New) on `not_accessible_through_html?` models (Photo):** `new` now serves **`format.html`** when `parent_class` and `update` are present (was **406** / empty frame for Photo).
|
|
32
|
+
- **New / Cancel / OK after New:** associated-list frame responses use the **`inline_forms`** layout (styled) instead of bare **`turbo_rails/frame`**; **`create`** restores the list with **`@ul_needed = true`** so the inner **`…_photos_list`** `<turbo-frame>` matches **`_show`** (fixes Turbo **“Content missing”** on cancel and create).
|
|
33
|
+
- **`_new.html.erb`:** Turbo form sets **`data-turbo-frame`** to the parent list frame id.
|
|
34
|
+
|
|
35
|
+
### Verified
|
|
36
|
+
|
|
37
|
+
- **`bundle exec rails test`** — **53 runs, 260 assertions, 0 failures**; nested Photo new → cancel → create integration test.
|
|
38
|
+
- **curl:** new **200** + stylesheet; cancel/create **200** with **`apartment_<id>_photos`** + **`…_photos_list`** frames.
|
|
39
|
+
|
|
40
|
+
## [7.5.0] - 2026-05-16
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- **Step 3 completion (UJS → Turbo row/field lifecycle):** row toolbar **`soft_delete` / `soft_restore` / `destroy` / `revert`** respond with **`format.html`** (`row_close`, `row_destroyed`) inside matching **`<turbo-frame>`**; helpers default to Turbo (`inline_forms_turbo_link_data`, `turbo_row:` on toolbar / versions / nested **`+`** links).
|
|
45
|
+
- **Nested `+new` / `create` / versions panel:** `new_record`, `create_list_frame`, `versions_panel`, `versions_list_panel` HTML templates; associated/has_one/versions regions in **`_show`** wrapped in **`<turbo-frame>`**.
|
|
46
|
+
- **`turbo:frame-load`** in **`inline_forms.js`:** re-init datepicker, timepicker, and Trix after frame swaps.
|
|
47
|
+
- **Regression tests:** row destroy/revert Turbo, versions panel Turbo (`example_app_apartment_row_turbo_test.rb`, `example_app_apartment_versions_turbo_test.rb`).
|
|
48
|
+
|
|
49
|
+
### Removed
|
|
50
|
+
|
|
51
|
+
- **`edit.js.erb`**, **`update.js.erb`**, **`show_element.js.erb`** — scalar field edit/update/cancel is Turbo HTML only.
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- **`docs/ujs-to-turbo.md`:** Step 3 checklist marked done except **`show.js.erb` / `close.js.erb` / …** retained for **`_tree.html.erb`** (Step 4).
|
|
56
|
+
|
|
57
|
+
### Verified (end-to-end against the `--example` install)
|
|
58
|
+
|
|
59
|
+
- **`bundle exec rails test`** — **52 runs, 236 assertions, 0 failures, 0 errors, 0 skips** against the generated MyApp.
|
|
60
|
+
- **curl smoke:** versions panel **`GET /apartments/1/list_versions?update=apartment_1_versions`** with **`Turbo-Frame`** → **200** + matching **`<turbo-frame id="apartment_1_versions">`**.
|
|
61
|
+
- **curl + browser** — row toolbar, versions, field edit, nested photos (same contract as 7.4.x).
|
|
62
|
+
|
|
63
|
+
## [7.4.5] - 2026-05-15
|
|
64
|
+
|
|
65
|
+
### Added
|
|
66
|
+
|
|
67
|
+
- **Example app integration test** (`example_app_apartment_photos_pagination_test.rb`): nested Photo **`image`** field — Turbo **`Turbo-Frame`** GET edit (multipart form) and **multipart `PUT`** — asserts **200** HTML with matching **`<turbo-frame id="…_image">`** and no **`UnknownFormat`** / **406** (Step 3 multipart regression guard from the 7.2.0 nested-frame era).
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
|
|
71
|
+
- **`docs/ujs-to-turbo.md`:** Step 3 checklist — “replace photo image (multipart) inside nested frame” marked done.
|
|
72
|
+
|
|
73
|
+
### Verified (end-to-end against the `--example` install)
|
|
74
|
+
|
|
75
|
+
- **`bundle exec rails test`** — **47 runs, 208 assertions, 0 failures, 0 errors, 0 skips** against the generated MyApp (Apartment + Photo).
|
|
76
|
+
- **curl smoke** (authenticated **`Turbo-Frame`** GETs / **`POST` multipart** with **`_method=put`**): same contract as 7.4.4 plus nested Photo **`/photos/1/edit?attribute=image&form_element=image_field&update=apartment_1_photo_<id>_image`** and image replace **`POST /photos/1?...`** — **200** and matching **`<turbo-frame id="…_image">`** (Devise scope **`/auth/users/sign_in`**; cookie jar must be sent on the multipart step).
|
|
77
|
+
- **Browser** (cursor-ide-browser MCP, dev server): already-signed-in session — open **Konferensha** row (URL stays **`/`**, gallery appears) — **Next page** (gallery shows page-2 filenames) — **`/apartments/name_list`** — edit name — **ok** (read-only link shows new value).
|
|
78
|
+
|
|
79
|
+
## [7.4.4] - 2026-05-16
|
|
80
|
+
|
|
81
|
+
### Fixed
|
|
82
|
+
|
|
83
|
+
- **`inline_forms create … --example` against a Rails 8 system gem:** `bin/inline_forms` now prefers a locally installed Rails **`~> 7.0`** (`rails _7.0.X_ new …`) when one is present, so the generated **`config/application.rb`** matches the **`rails ~> 7.0.0`** pin the installer writes into the **`Gemfile`**. Without this, a system **`rails 8.x`** wrote **`config.load_defaults 8.0`** and **`config.autoload_lib(ignore: …)`** into `application.rb`, both rejected by Rails 7.0 (`rails aborted! Unknown version "8.0"` and `NoMethodError: undefined method 'autoload_lib'` on the first **`bundle exec rails dartsass:install`**), so app generation aborted right after Dart Sass install.
|
|
84
|
+
- **Defensive `application.rb` rewrite (belt + suspenders):** even when the picked generator is Rails 8.x (e.g. no 7.0 gem available), `bin/inline_forms_installer_core.rb` rewrites **`config.load_defaults <N>.<M>`** to **`config.load_defaults 7.0`** and strips **`config.autoload_lib(…)`** post-generation so the bundled Rails 7.0 can boot.
|
|
85
|
+
|
|
86
|
+
### Changed
|
|
87
|
+
|
|
88
|
+
- **`docs/ujs-to-turbo.md`:** Step 3 marks the apartment field flow integration test (**`example_app_apartment_field_turbo_test.rb`** — open row → edit text field → save → cancel) as done; the test has been shipping since 7.4.1.
|
|
89
|
+
|
|
90
|
+
### Verified (end-to-end against the `--example` install)
|
|
91
|
+
|
|
92
|
+
- **`bundle exec rails test`** — **46 runs, 196 assertions, 0 failures, 0 errors, 0 skips** against the generated MyApp (Apartment + Photo).
|
|
93
|
+
- **curl smoke** with **`Turbo-Frame`** header: top-level row open/close (**`/apartments/1?update=apartment_1[&close=true]`**), scalar field edit/update/cancel (**`/apartments/1/edit?attribute=name&form_element=text_field&update=apartment_1_name`** + **`PUT /apartments/1`**), nested **`/photos?parent_class=Apartment&parent_id=1&update=apartment_1_photos_list`** pagination, and nested Photo row open/close (**`/photos/1?update=apartment_1_photo_1[&close=true]`**) all return **200** with the matching **`<turbo-frame id="…">`** in the body.
|
|
94
|
+
- **Browser** (devtools MCP, Drive disabled, UJS for the legacy paths): sign-in → click apartment row (Turbo open, no full-page nav) → nested photo pagination Next (Turbo) → click name field (Turbo edit-in-place) → save (in-place swap, no reload) → close X (Turbo collapse, list shows updated name). **`/apartments/name_list`** field-edit demo confirmed reachable from the **More** menu.
|
|
95
|
+
|
|
96
|
+
## [7.4.3] - 2026-05-16
|
|
97
|
+
|
|
98
|
+
### Added
|
|
99
|
+
|
|
100
|
+
- **Turbo row open/close on stock index:** each top-level list row is a **`<turbo-frame id="{model}_{id}">`**; presentation links use Turbo (**`row_show.html.erb`** / **`row_close.html.erb`**, **`close_link(..., turbo_row:)`**, **`example_app_apartment_row_turbo_test.rb`**).
|
|
101
|
+
|
|
102
|
+
### Fixed
|
|
103
|
+
|
|
104
|
+
- **Nested associated list (e.g. Apartment → Photo):** same per-row **`<turbo-frame>`** + Turbo presentation as top-level; removed **`data-turbo="false"`**, which broke nested **cancel** and other in-frame GETs. **`row_html_turbo_allowed?`** / **`nested_associated_list_row_update?`** serve **`format.html`** row **show** / **close** for **`not_accessible_through_html?`** models when **`params[:update]`** is a nested row id (e.g. **`apartment_1_photo_5`**).
|
|
105
|
+
|
|
106
|
+
### Changed
|
|
107
|
+
|
|
108
|
+
- **`docs/ujs-to-turbo.md`:** Step 2 / Step 3 checklist for row + nested Turbo.
|
|
109
|
+
- **`example_app_apartment_photos_pagination_test.rb`:** asserts nested turbo-frame rows and Photo row open/close + field cancel; drops the obsolete requirement that nested rows opt out of Turbo.
|
|
110
|
+
|
|
111
|
+
## [7.4.1] - 2026-05-15
|
|
112
|
+
|
|
113
|
+
### Added
|
|
114
|
+
|
|
115
|
+
- **Turbo field edit (Step 3, partial):** scalar fields in stock **`_show.html.erb`** are wrapped in **`<turbo-frame id="{model}_{id}_{attribute}">`**. Field **edit**, **update**, and **cancel** respond with **`format.html`** via **`field_edit.html.erb`** / **`field_show.html.erb`** and the **`turbo_rails/frame`** layout (no UJS on field links/forms). Row-level show/close remains UJS.
|
|
116
|
+
- **`inline_forms_field_cancel_link`** helper and **`inline_forms_field_show`** helper; **`link_to_inline_edit`** accepts **`turbo_frame:`** and omits **`remote: true`** on the Turbo path.
|
|
117
|
+
- **Regression tests** **`example_app_apartment_field_turbo_test.rb`** (stock panel field turbo-frame edit/update/cancel) and extended **`example_app_apartment_name_list_test.rb`** (turbo-frame contract, no **`UnknownFormat`** on cancel).
|
|
118
|
+
|
|
119
|
+
### Fixed
|
|
120
|
+
|
|
121
|
+
- **Field cancel on Turbo path:** cancel no longer triggers full-page navigation or **`UnknownFormat`** — **`format.html`** is always registered for single-attribute show; cancel uses a plain GET link with **`data-turbo-frame="_self"`** (no **`data-method`**, which conflicted with jQuery UJS).
|
|
122
|
+
- **Cancel button height:** restored **`input[type=button]`** inside a thin wrapper link (Turbo/UJS attrs on the **`<a>`**) so cancel matches the **ok** submit height; Foundation **`a.button`** was rendering much taller in collapse rows.
|
|
123
|
+
|
|
124
|
+
### Changed
|
|
125
|
+
|
|
126
|
+
- **Example name list (`--example`):** uses the same turbo-field contract as stock **`_show`** ( **`@inline_forms_turbo_field`**, **`<turbo-frame>`** wrappers), not a separate UJS path.
|
|
127
|
+
- **`docs/ujs-to-turbo.md`:** Step 3 field-level checklist items marked done for stock scalar fields and name-list regression.
|
|
128
|
+
|
|
129
|
+
## [7.4.0] - 2026-05-15
|
|
130
|
+
|
|
131
|
+
### Added
|
|
132
|
+
|
|
133
|
+
- **`--example` demo: field-level inline edit without the stock `_show` UI** (`ApartmentsController#name_list`, **`GET /apartments/name_list`**). Lists the first 10 apartments with each **`name`** rendered via **`text_field_show`** inside a wrapper `id="apartment_<id>_name"`, so edit/update use the normal polymorphic paths without opening the full inline-edit panel. Installer copies **`app/views/apartments/name_list.html.erb`**, injects the controller action (with CanCan **`skip_load_and_authorize_resource`** / **`authorize! :read, Apartment`**), and adds the route.
|
|
134
|
+
- **More menu link** in the example app only: installer overrides **`app/views/inline_forms/_header.html.erb`** with an extra item **“Apartment names (first 10)”** pointing at **`apartment_name_list_path`**.
|
|
135
|
+
- **UJS → Turbo migration checklist** at **`docs/ujs-to-turbo.md`** (Steps 1–2 done, 3–5 tracked).
|
|
136
|
+
- **Regression test** **`test/integration/example_app_apartment_name_list_test.rb`**: page render, More menu link, and UJS edit-link **`update=`** contract.
|
|
137
|
+
|
|
138
|
+
## [7.3.4] - 2026-05-15
|
|
139
|
+
|
|
140
|
+
### Changed
|
|
141
|
+
|
|
142
|
+
- **Installer Gemfile**: `devise-i18n` is taken from RubyGems (`~> 1.16`, current release **1.16.0**) instead of the obsolete `https://github.com/acesuares/devise-i18n.git` fork (which matched upstream only through 2018). `devise` is pinned to **`~> 5.0`** so it satisfies `devise-i18n` 1.16’s runtime dependency on Devise 5+.
|
|
143
|
+
|
|
144
|
+
## [7.3.3] - 2026-05-07
|
|
145
|
+
|
|
146
|
+
### Fixed
|
|
147
|
+
|
|
148
|
+
- **Session flash no longer appears inside inline-edit fields**: `_edit.html.erb` was injected into the field span via UJS and iterated the full `flash` hash, so an unconsumed Devise notice (for example after sign-in) could show up inside the Trix/rich-text editor when opening a field. The edit partial no longer renders global flash; `_new.html.erb` only shows `flash.now` keys used by `create` (`header`, `error`, `success`). **`layouts/inline_forms.html.erb`** now renders **`flash["notice"]` / `flash["alert"]`** under the header so redirect flash is shown once and consumed on normal pages.
|
|
149
|
+
- **`InlineFormsApplicationController` default layout**: `layout 'devise' if :devise_controller?` was ineffective because `:devise_controller?` is a Symbol (always truthy), so every controller defaulted to `layouts/devise`. Replaced with `layout ->(c) { c.devise_controller? ? "devise" : "inline_forms" }` so app controllers use the full **`inline_forms`** chrome unless an action overrides `render` layout.
|
|
150
|
+
- **Devise sign-in form** (`app/views/devise/sessions/_form.html.erb`): added `data-turbo="false"` on the form so a Turbo-enabled asset bundle cannot turn the POST into a non-navigational request (which would skip Devise’s `set_flash_message!` for `:signed_in`).
|
|
151
|
+
|
|
152
|
+
## [7.3.2] - 2026-05-07
|
|
153
|
+
|
|
154
|
+
### Fixed
|
|
155
|
+
|
|
156
|
+
- **Legacy `:text_area` alias no longer triggers plain-text column checks**: `:text_area` is treated as the rich-text alias path, while plain-text column enforcement remains limited to `:plain_text`, `:plain_text_area`, and `:text_area_without_ckeditor`. This prevents false `InlineForms::PlainTextColumnMissingError` when switching an ActionText-backed attribute from `:rich_text` to `:text_area`.
|
|
157
|
+
|
|
158
|
+
## [7.3.1] - 2026-05-07
|
|
159
|
+
|
|
160
|
+
### Changed
|
|
161
|
+
|
|
162
|
+
- **Long text form element naming is now explicit**: `:plain_text` is the canonical non-WYSIWYG textarea form element (backed by a DB `text` column), while `:rich_text` remains the ActionText/Trix element.
|
|
163
|
+
- **Default mapping for migration type `:text` now emits form element `:plain_text`** (instead of `:text_area`) so newly generated models use the explicit name.
|
|
164
|
+
- **Legacy aliases remain supported**: `:text_area_without_ckeditor` and `:plain_text_area` delegate to `:plain_text`; legacy `:text_area` and `:ckeditor` delegate to `:rich_text`.
|
|
165
|
+
|
|
166
|
+
### Fixed
|
|
167
|
+
|
|
168
|
+
- **Misconfigured `plain_text` attributes now fail fast with a clear error**: inline_forms now raises `InlineForms::PlainTextColumnMissingError` when a `plain_text`-style form element targets an attribute without a DB column (for example, an ActionText-only attribute such as `description` after switching from `:rich_text` to `:text_area`/`:plain_text` without adding a column).
|
|
169
|
+
- **Checks run both during app boot/reload (for loaded models) and at request runtime** (`getKlass`, `create`, `update`) to prevent late `ActiveModel::MissingAttributeError` failures.
|
|
170
|
+
- **Generated example-app tests now cover rich_text/plain_text edge cases**, including the failure path above and the reverse direction (`plain_text` -> `rich_text`) staying non-failing from inline_forms' perspective.
|
|
171
|
+
|
|
172
|
+
## [7.3.0] - 2026-05-07
|
|
173
|
+
|
|
174
|
+
### Removed
|
|
175
|
+
|
|
176
|
+
- **CKEditor**: no CDN script tags in engine layouts, no `cktext_area_tag` / `CKEDITOR` usage, no `.ckeditor_area` styles, and no `inline_forms/ckeditor/config.js` asset precompile entry. Long text uses the same plain `<textarea>` path as before when the CKEditor gem was absent.
|
|
177
|
+
|
|
178
|
+
### Changed
|
|
179
|
+
|
|
180
|
+
- **`:text_area`** always renders a plain multiline field (equivalent to the old non-CKEditor path and to **`:text_area_without_ckeditor`**).
|
|
181
|
+
- **`:ckeditor`** remains a valid generator/model type name but now delegates to **`:text_area`** behavior (plain text); migrate to **`:text_area`** or **`:rich_text`** when convenient.
|
|
182
|
+
|
|
7
183
|
## [7.2.11] - 2026-05-07
|
|
8
184
|
|
|
9
185
|
### Changed
|
data/README.rdoc
CHANGED
|
@@ -30,9 +30,9 @@ You can install the example application manually if you like:
|
|
|
30
30
|
|
|
31
31
|
inline_forms create MyApp
|
|
32
32
|
cd MyApp
|
|
33
|
-
rails g inline_forms Picture name:string caption:string image:image_field description:
|
|
33
|
+
rails g inline_forms Picture name:string caption:string image:image_field description:plain_text apartment:belongs_to _presentation:'#{name}'
|
|
34
34
|
rails generate uploader Image
|
|
35
|
-
rails g inline_forms Apartment name:string title:string description:
|
|
35
|
+
rails g inline_forms Apartment name:string title:string description:rich_text pictures:has_many pictures:associated _enabled:yes _presentation:'#{name}'
|
|
36
36
|
bundle exec rake db:migrate
|
|
37
37
|
rails s
|
|
38
38
|
|
|
@@ -48,6 +48,8 @@ The +:image_field+ form element uses CarrierWave. Generated apps depend on +carr
|
|
|
48
48
|
|
|
49
49
|
To switch to S3, add +carrierwave-aws+ (or use the bundled fog backend) and configure a +CarrierWave.configure+ block in +config/initializers/carrierwave.rb+; nothing in inline_forms hard-codes local storage.
|
|
50
50
|
|
|
51
|
+
For long text fields, use +:plain_text+ for a plain textarea backed by a DB +text+ column, or +:rich_text+ for ActionText/Trix content. +:plain_text+ requires an actual column on the model table; if the column is missing, inline_forms now raises +InlineForms::PlainTextColumnMissingError+ during controller boot/runtime checks.
|
|
52
|
+
|
|
51
53
|
Note: generated apps also depend on ActiveStorage transitively because the +:rich_text+ form element uses ActionText (+active_storage:install+ runs during +inline_forms create+). Image uploads still go through CarrierWave; ActiveStorage is only there to back ActionText embeds.
|
|
52
54
|
|
|
53
55
|
= Build a vagrant virtualbox box for easier development
|
|
@@ -37,3 +37,26 @@ $(function(){ $(document).foundation(); });
|
|
|
37
37
|
$(this).attr('title', '');
|
|
38
38
|
});
|
|
39
39
|
});
|
|
40
|
+
|
|
41
|
+
// Re-bind jQuery UI widgets and Trix after Turbo Frame swaps (Step 3).
|
|
42
|
+
document.addEventListener("turbo:frame-load", function(event) {
|
|
43
|
+
var root = event.target;
|
|
44
|
+
if (!root || !root.querySelectorAll) { return; }
|
|
45
|
+
|
|
46
|
+
$(root).find("input.datepicker").each(function() {
|
|
47
|
+
var $el = $(this);
|
|
48
|
+
if (!$el.hasClass("hasDatepicker")) { $el.datepicker(); }
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
$(root).find("input.timepicker").each(function() {
|
|
52
|
+
var $el = $(this);
|
|
53
|
+
if (!$el.data("timepicker")) { $el.timepicker(); }
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
$(root).find("trix-editor").each(function() {
|
|
57
|
+
if (window.Trix && this.editor) { return; }
|
|
58
|
+
if (window.Trix && typeof Trix.Editor === "function") {
|
|
59
|
+
new Trix.Editor(this);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -223,6 +223,14 @@ select:hover, select:focus {
|
|
|
223
223
|
font-weight: bold;
|
|
224
224
|
font-size: 110%;
|
|
225
225
|
}
|
|
226
|
+
// Custom elements default to `display: inline`, which collapses the row layout
|
|
227
|
+
// of an empty/just-mounted top-level `<turbo-frame id="apartments_list">` and
|
|
228
|
+
// hides its rows under the fixed top bar. Force block layout so frames behave
|
|
229
|
+
// like the legacy `<div class="list_container">` and `<div class="row">` they
|
|
230
|
+
// replaced (see app/views/inline_forms/_list.html.erb).
|
|
231
|
+
turbo-frame {
|
|
232
|
+
display: block;
|
|
233
|
+
}
|
|
226
234
|
.list_container {
|
|
227
235
|
.row {
|
|
228
236
|
font-size: 1.2rem;
|
|
@@ -258,6 +266,30 @@ select:hover, select:focus {
|
|
|
258
266
|
}
|
|
259
267
|
}
|
|
260
268
|
|
|
269
|
+
// Field edit cancel: outer <a> carries Turbo/UJS; inner input[type=button] matches ok height.
|
|
270
|
+
.edit_form .row.collapse {
|
|
271
|
+
input[type="submit"].postfix.button,
|
|
272
|
+
a.inline_forms-field-cancel input[type="button"].postfix.button {
|
|
273
|
+
margin: 2px 0 !important;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.edit_form a.inline_forms-field-cancel {
|
|
278
|
+
display: inline-block;
|
|
279
|
+
padding: 0;
|
|
280
|
+
border: 0;
|
|
281
|
+
background: transparent;
|
|
282
|
+
line-height: 0;
|
|
283
|
+
vertical-align: top;
|
|
284
|
+
text-decoration: none;
|
|
285
|
+
|
|
286
|
+
input[type="button"] {
|
|
287
|
+
pointer-events: none;
|
|
288
|
+
cursor: pointer;
|
|
289
|
+
width: auto;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
261
293
|
.object_presentation {
|
|
262
294
|
background-color: #B94C32;
|
|
263
295
|
color: white;
|
|
@@ -434,22 +466,6 @@ select:hover, select:focus {
|
|
|
434
466
|
margin-bottom: 0.5em;
|
|
435
467
|
}
|
|
436
468
|
|
|
437
|
-
.ckeditor_area {
|
|
438
|
-
position: relative;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
.ckeditor_area .glass_plate {
|
|
442
|
-
position: absolute;
|
|
443
|
-
top: -1px;
|
|
444
|
-
width: 98%;
|
|
445
|
-
height: 232px;
|
|
446
|
-
border: 0;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
.ckeditor_area .cke_top, .ckeditor_area .cke_bottom, .ckeditor_area .cke_border {
|
|
450
|
-
display: none;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
469
|
/* jQuery ui Slider 8 */
|
|
454
470
|
.slider {
|
|
455
471
|
width: 300px;
|
|
@@ -11,11 +11,12 @@ module VersionsConcern
|
|
|
11
11
|
close = params[:close] || false
|
|
12
12
|
if close
|
|
13
13
|
respond_to do |format|
|
|
14
|
+
format.html { render "inline_forms/versions_panel", layout: "turbo_rails/frame" }
|
|
14
15
|
format.js { render :versions }
|
|
15
16
|
end
|
|
16
17
|
else
|
|
17
18
|
respond_to do |format|
|
|
18
|
-
format.html {
|
|
19
|
+
format.html { render "inline_forms/versions_list_panel", layout: "turbo_rails/frame" }
|
|
19
20
|
format.js { render :versions_list }
|
|
20
21
|
end
|
|
21
22
|
end
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
|
2
2
|
class InlineFormsApplicationController < ActionController::Base
|
|
3
3
|
protect_from_forgery
|
|
4
|
-
layout 'devise' if :devise_controller
|
|
4
|
+
# `layout 'devise' if :devise_controller?` was wrong: `:devise_controller?` is a
|
|
5
|
+
# Symbol (always truthy), so every controller used the Devise layout. Use a
|
|
6
|
+
# callable so only Devise controllers get `layouts/devise`; everything else
|
|
7
|
+
# defaults to `layouts/inline_forms` (actions may still override via `render`).
|
|
8
|
+
layout ->(controller) { controller.devise_controller? ? "devise" : "inline_forms" }
|
|
5
9
|
|
|
6
10
|
# limit available locales by setting this. Override in applicaton_controller.
|
|
7
11
|
I18n.available_locales = [ :en, :nl, :pp ]
|
|
@@ -72,12 +72,17 @@ class InlineFormsController < ApplicationController
|
|
|
72
72
|
if @Klass.not_accessible_through_html?
|
|
73
73
|
format.html do
|
|
74
74
|
if @parent_class.present?
|
|
75
|
-
|
|
76
|
-
render "inline_forms/_list", layout: frame_layout
|
|
75
|
+
render_nested_associated_list_html
|
|
77
76
|
end
|
|
78
77
|
end
|
|
79
78
|
else
|
|
80
|
-
format.html
|
|
79
|
+
format.html do
|
|
80
|
+
if @parent_class.present?
|
|
81
|
+
render_nested_associated_list_html
|
|
82
|
+
else
|
|
83
|
+
render "inline_forms/_list", layout: "inline_forms"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
81
86
|
end
|
|
82
87
|
format.js { render :list }
|
|
83
88
|
end
|
|
@@ -98,7 +103,7 @@ class InlineFormsController < ApplicationController
|
|
|
98
103
|
|
|
99
104
|
@object.inline_forms_attribute_list = @inline_forms_attribute_list if @inline_forms_attribute_list
|
|
100
105
|
respond_to do |format|
|
|
101
|
-
format.html {
|
|
106
|
+
format.html { render_turbo_new } if associated_list_html_allowed? || !@Klass.not_accessible_through_html?
|
|
102
107
|
format.js { }
|
|
103
108
|
end
|
|
104
109
|
end
|
|
@@ -111,8 +116,7 @@ class InlineFormsController < ApplicationController
|
|
|
111
116
|
@sub_id = params[:sub_id]
|
|
112
117
|
@update_span = params[:update]
|
|
113
118
|
respond_to do |format|
|
|
114
|
-
format.html { }
|
|
115
|
-
format.js { }
|
|
119
|
+
format.html { render_turbo_field(:field_edit) }
|
|
116
120
|
end
|
|
117
121
|
end
|
|
118
122
|
|
|
@@ -123,6 +127,7 @@ class InlineFormsController < ApplicationController
|
|
|
123
127
|
@update_span = params[:update]
|
|
124
128
|
attributes = @inline_forms_attribute_list || @object.inline_forms_attribute_list
|
|
125
129
|
attributes.each do | attribute, name, form_element |
|
|
130
|
+
InlineForms.assert_plain_text_column!(object: @object, attribute: attribute, form_element: form_element)
|
|
126
131
|
send("#{form_element.to_s}_update", @object, attribute) unless form_element == :tree || form_element == :associated || (cancan_enabled? && cannot?(:read, @object, attribute))
|
|
127
132
|
end
|
|
128
133
|
@parent_class = params[:parent_class]
|
|
@@ -145,14 +150,16 @@ class InlineFormsController < ApplicationController
|
|
|
145
150
|
@objects = @objects.where(conditions).paginate(:page => params[:page])
|
|
146
151
|
@object = nil
|
|
147
152
|
respond_to do |format|
|
|
148
|
-
format.
|
|
153
|
+
format.html { render_associated_list_frame } if associated_list_html_allowed?
|
|
154
|
+
format.js { render :list }
|
|
149
155
|
end
|
|
150
156
|
else
|
|
151
157
|
flash.now[:header] = ["Kan #{@object.class.to_s.underscore} niet aanmaken."]
|
|
152
158
|
flash.now[:error] = @object.errors.to_a
|
|
153
159
|
respond_to do |format|
|
|
154
160
|
@object.inline_forms_attribute_list = attributes
|
|
155
|
-
format.
|
|
161
|
+
format.html { render_turbo_new } if associated_list_html_allowed? || !@Klass.not_accessible_through_html?
|
|
162
|
+
format.js { render :new }
|
|
156
163
|
end
|
|
157
164
|
end
|
|
158
165
|
end
|
|
@@ -164,11 +171,11 @@ class InlineFormsController < ApplicationController
|
|
|
164
171
|
@form_element = params[:form_element]
|
|
165
172
|
@sub_id = params[:sub_id]
|
|
166
173
|
@update_span = params[:update]
|
|
174
|
+
InlineForms.assert_plain_text_column!(object: @object, attribute: @attribute, form_element: @form_element)
|
|
167
175
|
send("#{@form_element.to_s}_update", @object, @attribute)
|
|
168
176
|
@object.save
|
|
169
177
|
respond_to do |format|
|
|
170
|
-
format.html {
|
|
171
|
-
format.js { }
|
|
178
|
+
format.html { render_turbo_field(:field_show, turbo_field_show: true) }
|
|
172
179
|
end
|
|
173
180
|
end
|
|
174
181
|
|
|
@@ -195,15 +202,16 @@ class InlineFormsController < ApplicationController
|
|
|
195
202
|
respond_to do |format|
|
|
196
203
|
@attributes = @object.inline_forms_attribute_list
|
|
197
204
|
if close
|
|
205
|
+
format.html { render_row_turbo(:close) } if row_html_turbo_allowed?
|
|
198
206
|
format.js { render :close }
|
|
199
207
|
else
|
|
200
|
-
format.
|
|
208
|
+
format.html { render_row_turbo(:show) } if row_html_turbo_allowed?
|
|
209
|
+
format.js { render :show }
|
|
201
210
|
end
|
|
202
211
|
end
|
|
203
212
|
else
|
|
204
213
|
respond_to do |format|
|
|
205
|
-
format.html {
|
|
206
|
-
format.js { render :show_element }
|
|
214
|
+
format.html { render_turbo_field(:field_show, turbo_field_show: true) }
|
|
207
215
|
end
|
|
208
216
|
end
|
|
209
217
|
end
|
|
@@ -212,10 +220,9 @@ class InlineFormsController < ApplicationController
|
|
|
212
220
|
def soft_delete
|
|
213
221
|
@update_span = params[:update]
|
|
214
222
|
@object = referenced_object
|
|
215
|
-
# destroy the object
|
|
216
223
|
@object.soft_delete(current_user)
|
|
217
224
|
respond_to do |format|
|
|
218
|
-
format.html { }
|
|
225
|
+
format.html { render_row_turbo(:close) } if row_html_turbo_allowed?
|
|
219
226
|
format.js { render :close }
|
|
220
227
|
end
|
|
221
228
|
end
|
|
@@ -224,10 +231,9 @@ class InlineFormsController < ApplicationController
|
|
|
224
231
|
def soft_restore
|
|
225
232
|
@update_span = params[:update]
|
|
226
233
|
@object = referenced_object
|
|
227
|
-
# restore the object
|
|
228
234
|
@object.soft_restore
|
|
229
235
|
respond_to do |format|
|
|
230
|
-
format.html { }
|
|
236
|
+
format.html { render_row_turbo(:close) } if row_html_turbo_allowed?
|
|
231
237
|
format.js { render :close }
|
|
232
238
|
end
|
|
233
239
|
end
|
|
@@ -237,11 +243,10 @@ class InlineFormsController < ApplicationController
|
|
|
237
243
|
@update_span = params[:update]
|
|
238
244
|
@object = referenced_object
|
|
239
245
|
if current_user.role? :superadmin
|
|
240
|
-
|
|
241
|
-
@undo_object = @object.versions.last
|
|
246
|
+
@undo_version = @object.versions.last
|
|
242
247
|
@object.destroy
|
|
243
248
|
respond_to do |format|
|
|
244
|
-
format.html { }
|
|
249
|
+
format.html { render_row_turbo_destroyed } if row_html_turbo_allowed?
|
|
245
250
|
format.js { render :record_destroyed }
|
|
246
251
|
end
|
|
247
252
|
end
|
|
@@ -251,14 +256,13 @@ class InlineFormsController < ApplicationController
|
|
|
251
256
|
# Thanks Ryan Bates: http://railscasts.com/episodes/255-undo-with-paper-trail
|
|
252
257
|
def revert
|
|
253
258
|
@update_span = params[:update]
|
|
254
|
-
@object = referenced_object
|
|
255
259
|
if current_user.role? :superadmin
|
|
256
260
|
@version = PaperTrail::Version.find(params[:id])
|
|
257
|
-
@version.reify
|
|
258
|
-
@object
|
|
261
|
+
@object = @version.reify
|
|
262
|
+
@object.save!
|
|
259
263
|
authorize!(:revert, @object) if cancan_enabled?
|
|
260
264
|
respond_to do |format|
|
|
261
|
-
format.html { }
|
|
265
|
+
format.html { render_row_turbo(:close) } if row_html_turbo_allowed?
|
|
262
266
|
format.js { render :close }
|
|
263
267
|
end
|
|
264
268
|
end
|
|
@@ -277,11 +281,103 @@ class InlineFormsController < ApplicationController
|
|
|
277
281
|
end
|
|
278
282
|
|
|
279
283
|
private
|
|
284
|
+
|
|
285
|
+
# HTML field edit/show inside a +<turbo-frame>+ (Step 3). Scalar fields no longer
|
|
286
|
+
# use UJS; +format.html+ is always registered for edit/update/single-attribute show.
|
|
287
|
+
#
|
|
288
|
+
# +@inline_forms_turbo_field+ tells +link_to_inline_edit+ (and the per-+form_element+
|
|
289
|
+
# +*_show+ helpers it wraps) to emit Turbo data attributes. The flag is set in
|
|
290
|
+
# +_show.html.erb+ when a row first opens, but bare +field_show+ / +field_edit+
|
|
291
|
+
# responses (on +cancel+ / +update+) do not re-render +_show+. Without setting
|
|
292
|
+
# it here the link in the swapped frame falls back to +remote: true+, which the
|
|
293
|
+
# legacy +jquery_ujs+ bundle intercepts as a JS request -- the controller only
|
|
294
|
+
# registers +format.html+, so the click silently fails (no swap, no edit form).
|
|
295
|
+
def render_turbo_field(template, turbo_field_show: false)
|
|
296
|
+
@turbo_frame = true if template == :field_edit
|
|
297
|
+
@turbo_field_show_turbo_frame = turbo_field_show
|
|
298
|
+
@inline_forms_turbo_field = true
|
|
299
|
+
render "inline_forms/#{template}", layout: "turbo_rails/frame"
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# Top-level list row open/close (Step 3): full `_show` / `_close` inside
|
|
303
|
+
# `<turbo-frame id="…">` matching `params[:update]`.
|
|
304
|
+
def render_row_turbo(mode)
|
|
305
|
+
@inline_forms_turbo_row = true
|
|
306
|
+
template = (mode == :close) ? "inline_forms/row_close" : "inline_forms/row_show"
|
|
307
|
+
layout = turbo_frame_request? ? "turbo_rails/frame" : "inline_forms"
|
|
308
|
+
render template, layout: layout
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def render_row_turbo_destroyed
|
|
312
|
+
@inline_forms_turbo_row = true
|
|
313
|
+
layout = turbo_frame_request? ? "turbo_rails/frame" : "inline_forms"
|
|
314
|
+
render "inline_forms/row_destroyed", layout: layout
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
# Nested has_many +new+ / cancel / +create+ inside a parent +<turbo-frame>+ (e.g. Apartment → Photo).
|
|
318
|
+
def associated_list_html_allowed?
|
|
319
|
+
@parent_class.present? && params[:update].present?
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def associated_list_frame_layout
|
|
323
|
+
# Use full inline_forms chrome so the swapped frame is styled; Turbo extracts
|
|
324
|
+
# the matching <turbo-frame id="…"> from the response body.
|
|
325
|
+
"inline_forms"
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def render_turbo_new
|
|
329
|
+
@turbo_frame = true
|
|
330
|
+
render "inline_forms/new_record", layout: associated_list_frame_layout
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# Nested +index+ / cancel / +create+ HTML inside a parent-associated +<turbo-frame>+.
|
|
334
|
+
def render_nested_associated_list_html
|
|
335
|
+
if turbo_frame_request? && nested_list_frame_id?(params[:update])
|
|
336
|
+
# Pagination and other swaps targeting the inner +…_photos_list+ frame: minimal layout.
|
|
337
|
+
@ul_needed = true
|
|
338
|
+
render "inline_forms/_list", layout: "turbo_rails/frame"
|
|
339
|
+
elsif turbo_frame_request? && params[:update].present?
|
|
340
|
+
# Cancel / +create+ targeting the outer +apartment_<id>_photos+ frame: styled full layout.
|
|
341
|
+
render_associated_list_frame
|
|
342
|
+
else
|
|
343
|
+
frame_layout = turbo_frame_request? ? "turbo_rails/frame" : "inline_forms"
|
|
344
|
+
render "inline_forms/_list", layout: frame_layout
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
# +apartment_1_photos_list+ (inner list) vs +apartment_1_photos+ (outer associated container).
|
|
349
|
+
def nested_list_frame_id?(update)
|
|
350
|
+
update.to_s.end_with?("_list")
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
# After nested +create+ / cancel; restores list inside the outer associated frame.
|
|
354
|
+
def render_associated_list_frame
|
|
355
|
+
@ul_needed = true
|
|
356
|
+
render "inline_forms/create_list_frame", layout: associated_list_frame_layout
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
# HTML row open/close is allowed for normal models, and for +not_accessible_through_html?+
|
|
360
|
+
# models (e.g. Photo) when the request targets a nested associated list row
|
|
361
|
+
# (+params[:update]+ like +apartment_1_photo_5+), not bare top-level CRUD.
|
|
362
|
+
def row_html_turbo_allowed?
|
|
363
|
+
return true unless @Klass.not_accessible_through_html?
|
|
364
|
+
nested_associated_list_row_update?(params[:update])
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
# +apartment_1_photo_5+ → +["apartment","1","photo","5"]+ (≥4 segments, trailing id).
|
|
368
|
+
# Differs from field spans (+apartment_1_photo_5_name+ ends with letters) and
|
|
369
|
+
# top-level rows (+apartment_1+ — too few segments).
|
|
370
|
+
def nested_associated_list_row_update?(update)
|
|
371
|
+
parts = update.to_s.split("_")
|
|
372
|
+
parts.length >= 4 && parts.last.match?(/\A\d+\z/)
|
|
373
|
+
end
|
|
374
|
+
|
|
280
375
|
# Get the class from the controller name.
|
|
281
376
|
# CountryController < InlineFormsController, so what class are we?
|
|
282
377
|
# TODO think about this a bit more.
|
|
283
378
|
def getKlass #:doc:
|
|
284
379
|
@Klass = self.controller_name.classify.constantize
|
|
380
|
+
InlineForms.validate_plain_text_configuration_for!(@Klass)
|
|
285
381
|
@Klass
|
|
286
382
|
end
|
|
287
383
|
|
|
@@ -1,41 +1,15 @@
|
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
|
2
|
+
# Legacy type name: CKEditor is removed; behaves like :rich_text.
|
|
2
3
|
InlineForms::SPECIAL_COLUMN_TYPES[:ckeditor]=:text
|
|
3
4
|
|
|
4
5
|
def ckeditor_show(object, attribute)
|
|
5
|
-
|
|
6
|
-
attribute,
|
|
7
|
-
'<div class="ckeditor_area">'.html_safe +
|
|
8
|
-
cktext_area_tag(
|
|
9
|
-
attribute,
|
|
10
|
-
object[attribute],
|
|
11
|
-
:id => "textarea_#{object.class.name.underscore}_#{object.id}_#{attribute.to_s}",
|
|
12
|
-
:ckeditor => { :width => '100%',
|
|
13
|
-
:height => '200px',
|
|
14
|
-
:toolbar => "None",
|
|
15
|
-
:readOnly => "true",
|
|
16
|
-
:resize_enabled => "false",
|
|
17
|
-
:toolbarCanCollapse => "false"
|
|
18
|
-
}
|
|
19
|
-
) +
|
|
20
|
-
image_tag( 'inline_forms/glass_plate.gif',
|
|
21
|
-
:class => "glass_plate",
|
|
22
|
-
:title => '' ) +
|
|
23
|
-
"<script>delete CKEDITOR.instances['textarea_#{object.class.name.underscore}_#{object.id}_#{attribute.to_s}']</script>".html_safe +
|
|
24
|
-
'</div>'.html_safe,
|
|
25
|
-
from_callee: __callee__
|
|
6
|
+
rich_text_show(object, attribute)
|
|
26
7
|
end
|
|
27
8
|
|
|
28
9
|
def ckeditor_edit(object, attribute)
|
|
29
|
-
|
|
30
|
-
object[attribute],
|
|
31
|
-
:id => "textarea_#{object.class.name.underscore}_#{object.id}_#{attribute.to_s}",
|
|
32
|
-
:ckeditor => { :width => '100%',
|
|
33
|
-
:height => '200px'
|
|
34
|
-
}
|
|
35
|
-
) +
|
|
36
|
-
"<script>delete CKEDITOR.instances['textarea_#{object.class.name.underscore}_#{object.id}_#{attribute.to_s}']</script>".html_safe
|
|
10
|
+
rich_text_edit(object, attribute)
|
|
37
11
|
end
|
|
38
12
|
|
|
39
13
|
def ckeditor_update(object, attribute)
|
|
40
|
-
object
|
|
14
|
+
rich_text_update(object, attribute)
|
|
41
15
|
end
|