cafe_car 0.2.1 → 0.3.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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/.claude-plugin/marketplace.json +23 -0
  3. data/README.md +417 -29
  4. data/Rakefile +2 -2
  5. data/app/assets/stylesheets/cafe_car/chart.css +41 -0
  6. data/app/assets/stylesheets/cafe_car/dashboard.css +43 -0
  7. data/app/assets/stylesheets/cafe_car/filters.css +50 -0
  8. data/app/assets/stylesheets/cafe_car/themes/cool2.css +2 -0
  9. data/app/assets/stylesheets/cafe_car/themes/warm.css +30 -0
  10. data/app/assets/stylesheets/cafe_car/tooltips.css +1 -1
  11. data/app/assets/stylesheets/cafe_car.css +14 -4
  12. data/app/assets/stylesheets/tom-select.css +95 -0
  13. data/app/assets/stylesheets/ui/Button.css +7 -5
  14. data/app/assets/stylesheets/ui/Input.css +92 -1
  15. data/app/assets/stylesheets/ui/Page.css +7 -0
  16. data/app/assets/stylesheets/ui/Table.css +25 -0
  17. data/app/controllers/cafe_car/dashboards_controller.rb +29 -0
  18. data/app/javascript/cafe_car.js +68 -0
  19. data/app/javascript/tom-select.complete.min.js +444 -0
  20. data/app/policies/cafe_car/application_policy.rb +1 -1
  21. data/app/presenters/cafe_car/active_storage/attachment_presenter.rb +4 -1
  22. data/app/presenters/cafe_car/presenter.rb +2 -2
  23. data/app/views/application/_actions.html.haml +9 -0
  24. data/app/views/application/_active_filters.html.haml +15 -0
  25. data/app/views/application/_belongs_to_filter.html.haml +6 -0
  26. data/app/views/application/_boolean_filter.html.haml +4 -0
  27. data/app/views/application/_bulk_actions.html.haml +9 -0
  28. data/app/views/application/_chart.html.haml +18 -0
  29. data/app/views/application/_controls.html.haml +8 -0
  30. data/app/views/application/_enum_filter.html.haml +5 -0
  31. data/app/views/application/_filter.html.haml +4 -0
  32. data/app/views/application/_filters.html.haml +13 -4
  33. data/app/views/application/_has_many_filter.html.haml +7 -0
  34. data/app/views/application/_head.html.haml +1 -0
  35. data/app/views/application/_index.html.haml +3 -1
  36. data/app/views/application/_index_actions.html.haml +12 -3
  37. data/app/views/application/_navigation.html.haml +5 -0
  38. data/app/views/application/_nested_field.html.haml +1 -1
  39. data/app/views/application/_range_filter.html.haml +8 -0
  40. data/app/views/application/_scope_filter.html.haml +5 -0
  41. data/app/views/application/_string_filter.html.haml +4 -0
  42. data/app/views/application/_table.html.haml +8 -6
  43. data/app/views/application/_text_filter.html.haml +1 -0
  44. data/app/views/cafe_car/application/index.html.haml +5 -2
  45. data/app/views/cafe_car/dashboard/_chart.html.haml +11 -0
  46. data/app/views/cafe_car/dashboard/_metric.html.haml +4 -0
  47. data/config/brakeman.ignore +0 -48
  48. data/config/importmap.rb +1 -0
  49. data/config/locales/en.yml +60 -0
  50. data/config/routes.rb +15 -2
  51. data/lib/cafe_car/attributes.rb +40 -12
  52. data/lib/cafe_car/chart_builder.rb +217 -0
  53. data/lib/cafe_car/controller/filtering.rb +108 -6
  54. data/lib/cafe_car/controller.rb +220 -11
  55. data/lib/cafe_car/engine.rb +2 -2
  56. data/lib/cafe_car/field_info.rb +14 -4
  57. data/lib/cafe_car/filter/field_info.rb +56 -7
  58. data/lib/cafe_car/filter/form_builder.rb +57 -7
  59. data/lib/cafe_car/filter_builder.rb +14 -1
  60. data/lib/cafe_car/form_builder.rb +61 -6
  61. data/lib/cafe_car/helpers.rb +196 -0
  62. data/lib/cafe_car/inputs/association_input.rb +11 -0
  63. data/lib/cafe_car/inputs/base_input.rb +56 -7
  64. data/lib/cafe_car/inputs/boolean_input.rb +9 -0
  65. data/lib/cafe_car/inputs/date_input.rb +8 -0
  66. data/lib/cafe_car/inputs/datetime_input.rb +8 -0
  67. data/lib/cafe_car/inputs/file_input.rb +11 -0
  68. data/lib/cafe_car/inputs/nested_input.rb +10 -0
  69. data/lib/cafe_car/inputs/number_input.rb +9 -0
  70. data/lib/cafe_car/inputs/password_input.rb +4 -2
  71. data/lib/cafe_car/inputs/rich_text_input.rb +9 -0
  72. data/lib/cafe_car/inputs/select_input.rb +10 -0
  73. data/lib/cafe_car/inputs/string_input.rb +3 -1
  74. data/lib/cafe_car/inputs/text_area_input.rb +9 -0
  75. data/lib/cafe_car/link_builder.rb +11 -0
  76. data/lib/cafe_car/model.rb +37 -8
  77. data/lib/cafe_car/navigation.rb +10 -0
  78. data/lib/cafe_car/policy.rb +85 -15
  79. data/lib/cafe_car/query_builder.rb +22 -0
  80. data/lib/cafe_car/routing.rb +26 -2
  81. data/lib/cafe_car/table/builder.rb +1 -1
  82. data/lib/cafe_car/table/foot_builder.rb +1 -0
  83. data/lib/cafe_car/table/head_builder.rb +6 -0
  84. data/lib/cafe_car/table/row_builder.rb +7 -0
  85. data/lib/cafe_car/version.rb +1 -1
  86. data/lib/cafe_car.rb +32 -2
  87. data/lib/generators/cafe_car/agents/USAGE +13 -0
  88. data/lib/generators/cafe_car/agents/agents_generator.rb +49 -0
  89. data/lib/generators/cafe_car/resource/resource_generator.rb +12 -1
  90. data/lib/tasks/demo.rake +9 -0
  91. data/llms.txt +25 -0
  92. data/skills/cafe_car/SKILL.md +135 -0
  93. data/skills/cafe_car/references/components.md +93 -0
  94. data/skills/cafe_car/references/controllers.md +106 -0
  95. data/skills/cafe_car/references/filtering.md +102 -0
  96. data/skills/cafe_car/references/forms.md +84 -0
  97. data/skills/cafe_car/references/locales.md +74 -0
  98. data/skills/cafe_car/references/navigation.md +67 -0
  99. data/skills/cafe_car/references/policies.md +112 -0
  100. data/skills/cafe_car/references/presenters.md +76 -0
  101. data/skills/cafe_car/references/turbo.md +53 -0
  102. data/skills/cafe_car/references/views.md +96 -0
  103. metadata +59 -16
  104. data/app/assets/stylesheets/cafe_car/themes/warm-dark.css +0 -29
  105. data/app/views/application/_search.html.haml +0 -6
  106. data/lib/cafe_car/auto_resolver.rb +0 -49
  107. data/lib/cafe_car/inputs/association_builder.rb +0 -6
  108. data/lib/cafe_car/inputs/belongs_to_builder.rb +0 -6
  109. data/lib/tasks/holdco_tasks.rake +0 -532
  110. data/lib/tasks/templates/tasks_header.md +0 -37
@@ -0,0 +1,76 @@
1
+ # Presenters — how values render
2
+
3
+ Source: `app/presenters/cafe_car/presenter.rb` in the gem, plus per-type presenters
4
+ alongside it (`CurrencyPresenter`, `DatePresenter`, `RecordPresenter`,
5
+ `ActiveRecord::RelationPresenter`, `ActiveStorage::AttachmentPresenter`, …).
6
+
7
+ `present(value)` (aliased `p` in views) wraps anything in a presenter and returns
8
+ an html-safe object. Records render as a linked preview (logo + title); dates,
9
+ currency, rich text, attachments, and collections each render through their type's
10
+ presenter.
11
+
12
+ ## How a presenter is chosen
13
+
14
+ The value's ancestor chain is walked and the first `<Ancestor>Presenter` constant
15
+ found wins — a host `InvoicePresenter` beats the gem's `RecordPresenter` by
16
+ existing; nothing is registered. Force a type with `as:`:
17
+
18
+ ```ruby
19
+ present(@invoice) # InvoicePresenter, else RecordPresenter
20
+ present(record.total, as: :currency) # CurrencyPresenter
21
+ ```
22
+
23
+ Note: constants the gem defines under `CafeCar::` (e.g. `CafeCar::StringPresenter`)
24
+ resolve engine-first — a same-named top-level constant does *not* shadow them.
25
+ Override per model (`ProductPresenter`) or per ancestor the gem doesn't claim.
26
+
27
+ ## Writing one
28
+
29
+ ```ruby
30
+ # app/presenters/invoice_presenter.rb
31
+ class InvoicePresenter < CafeCar::Presenter
32
+ show :total, as: :currency # render this attribute through a type
33
+ show :number, -> { "#%03d" % _1 } # or through a lambda
34
+
35
+ def title = show(:number) # what links/cards/breadcrumbs call this record
36
+ end
37
+ ```
38
+
39
+ `show` class macros set per-attribute rendering defaults used everywhere the
40
+ attribute appears — tables, show pages, cards.
41
+
42
+ ## The instance API (used inside overridden views)
43
+
44
+ In view code, `present(@article)` (or the `object` local in `_grid_item`) gives:
45
+
46
+ ```ruby
47
+ p = present(@article)
48
+ p.title # policy.title_attribute, rendered
49
+ p.logo(size: :icon) # policy.logo_attribute as an image
50
+ p.show(:author) # one attribute's value, presented
51
+ p.attribute(:author) # labeled Field (label + value)
52
+ p.attributes(:a, :b) # several labeled fields; no args = all displayable
53
+ p.remaining_attributes # displayable minus already-shown
54
+ p.associations # labeled fields for displayable associations
55
+ p.timestamps # created_at/updated_at etc.
56
+ p.controls # the show/edit/delete control links
57
+ p.href # canonical path, nil if not routable
58
+ p.object # the underlying record (for url helpers etc.)
59
+ ```
60
+
61
+ ## Linking to related objects
62
+
63
+ `show`/`preview` of an associated record is already a link to it. For explicit
64
+ links use the helpers:
65
+
66
+ ```ruby
67
+ href_for(record) # path to the record in the current namespace
68
+ link(record).show # LinkBuilder: policy-aware link (disabled when denied)
69
+ link(record).edit
70
+ link(record).destroy # turbo DELETE with locale-driven confirm
71
+ link(model).index
72
+ link(model.new).new
73
+ ```
74
+
75
+ `link(...)` renders disabled-with-tooltip when the policy denies the action —
76
+ prefer it over hand-written `link_to` so authorization stays visible in the UI.
@@ -0,0 +1,53 @@
1
+ # Turbo Streams and live sync
2
+
3
+ Source: `app/views/cafe_car/application/*.turbo_stream.haml` and
4
+ `app/views/application/_head.html.haml` (in the gem).
5
+
6
+ This is a big reason not to hand-roll admin pages: the defaults carry Turbo 8
7
+ morph behavior you'd otherwise rebuild.
8
+
9
+ ## What ships by default
10
+
11
+ - Every CafeCar page sets `turbo-refresh-method: morph` and
12
+ `turbo-refresh-scroll: preserve` (the `_head` partial), so refreshes patch the
13
+ DOM in place — scroll position, open popovers, and form state survive.
14
+ - Create/update/destroy respond to `turbo_stream` with a page refresh
15
+ (`turbo_stream.refresh`), which morphs. Update also removes the record's modal
16
+ if it was edited in one.
17
+ - Every show page subscribes to its record: `turbo_stream_from(object)` is in the
18
+ default show template.
19
+
20
+ ## Cross-client live sync is a one-line host opt-in
21
+
22
+ The subscription is only useful if the model broadcasts. Add Rails'
23
+ `broadcasts_refreshes` to the model:
24
+
25
+ ```ruby
26
+ class Invoice < ApplicationRecord
27
+ broadcasts_refreshes
28
+ end
29
+ ```
30
+
31
+ Now any save/destroy — from another browser, a job, the console — morph-refreshes
32
+ every open show page for that record. Requires a working ActionCable/Solid Cable
33
+ setup in the host, as with any Turbo broadcast.
34
+
35
+ ## Customizing
36
+
37
+ Override the turbo_stream response per resource like any view
38
+ ([views.md](views.md)):
39
+
40
+ ```haml
41
+ -# app/views/admin/products/update.turbo_stream.haml
42
+ = turbo_stream.refresh request_id: nil
43
+ = turbo_stream.append "audit_log", partial: "audit_entry", locals: { product: @product }
44
+ ```
45
+
46
+ Keep the `refresh` line unless you're deliberately replacing morphing with targeted
47
+ streams.
48
+
49
+ ## Don't break it
50
+
51
+ When writing custom views for a CafeCar resource, keep `turbo_stream_from(object)`
52
+ on detail pages and don't strip the `_head` meta tags — hand-rolled pages that drop
53
+ these are how admins lose live updates.
@@ -0,0 +1,96 @@
1
+ # Views and the override system
2
+
3
+ This is the crux of CafeCar: the gem ships default templates; a host replaces any
4
+ one of them by dropping a same-named file. You delete view files, you don't write
5
+ folders of them.
6
+
7
+ ## The two engine view roots
8
+
9
+ - `app/views/application/` (in the gem) — **shared partials**: `_table`, `_grid`,
10
+ `_form`, `_show`, `_search`, `_navigation`, … Resolved through normal controller
11
+ prefix fallback (every host controller inherits `ApplicationController`).
12
+ - `app/views/cafe_car/application/` (in the gem) — **action templates and
13
+ turbo_stream responses**: `index.html.haml`, `show.html.haml`, `new`, `edit`,
14
+ `create/update/destroy.turbo_stream.haml`.
15
+
16
+ ## Precedence (first match wins)
17
+
18
+ 1. `app/views/<controller_path>/…` in the host — one resource
19
+ (e.g. `app/views/admin/products/_grid_item.html.haml`)
20
+ 2. `app/views/application/…` in the host — app-wide partial override
21
+ 3. `app/views/cafe_car/application/…` in the host — app-wide action-template override
22
+ 4. the gem's defaults
23
+
24
+ Start by copying the gem's default (`cd "$(bundle show cafe_car)"`) and trimming.
25
+ Most defaults are 1–10 lines — the composition happens in helpers and policies, so
26
+ overrides stay small.
27
+
28
+ ## The key overridable partials
29
+
30
+ | Partial | Renders |
31
+ |---|---|
32
+ | `_index` | index body: toolbar (search + bulk bar), the current view, pagination |
33
+ | `_table` | the table: `table_for` with select/logo/title/remaining/timestamps/controls columns |
34
+ | `_grid` / `_grid_item` | card grid; `_grid_item` is one card |
35
+ | `_show` | show-page body: remaining attributes + associations |
36
+ | `_form` / `_fields` | the form card; `_fields` is just `f.remaining_fields` |
37
+ | `_field`, `_<type>_field` | one form field (see [forms.md](forms.md)) |
38
+ | `_controls` | the show/edit/delete link cluster on rows and cards |
39
+ | `_search` | the index search box |
40
+ | `_bulk_actions` | the bulk-action button bar (defaults to looping the policy's list) |
41
+ | `_navigation`, `_navigation_links` | the sidebar (see [navigation.md](navigation.md)) |
42
+ | `_index_actions` | index toolbar right side: view toggles, CSV, New button |
43
+ | `_head` | the `<head>`: meta, stylesheets, importmap |
44
+ | `_alerts`, `_errors`, `_empty`, `_submit` | flash messages, form errors, empty state, submit row |
45
+
46
+ ## Worked example: buttons on the grid cards
47
+
48
+ The gem's whole `_grid_item.html.haml`:
49
+
50
+ ```haml
51
+ = Card title: object.title, image: object.logo(href: object), actions: object.controls
52
+ ```
53
+
54
+ `object` is a presenter. To add a field and a custom button for one resource:
55
+
56
+ ```haml
57
+ -# app/views/admin/products/_grid_item.html.haml
58
+ = Card title: object.title, image: object.logo(href: object), actions: object.controls do |card|
59
+ = card.Section object.show(:price)
60
+ = card.Foot do
61
+ = button_to t(:restock), restock_admin_product_path(object.object), class: ui.Button(:primary).class_name
62
+ ```
63
+
64
+ (`object.object` is the record; a custom member action needs its own route +
65
+ controller action today. The button label goes in the locale.) Drop the same file
66
+ in `app/views/application/` to change every resource's card.
67
+
68
+ ## Worked example: a bespoke index
69
+
70
+ ```haml
71
+ -# app/views/articles/index.html.haml — replaces the whole action template
72
+ = Page :slim, :center do |page|
73
+ = page.Body do
74
+ - @articles.each do |article|
75
+ %article
76
+ %h2= p article
77
+ %p= article.summary
78
+ = paginate @articles
79
+ ```
80
+
81
+ Full control, and you keep the layout, filtering, pagination, and helpers. Prefer
82
+ overriding the smallest partial that's wrong (`_grid_item`, not `index`).
83
+
84
+ ## Turbo_stream templates
85
+
86
+ Per-resource turbo responses override the same way:
87
+ `app/views/admin/products/update.turbo_stream.haml` replaces the default
88
+ morph-refresh response for that resource. See [turbo.md](turbo.md).
89
+
90
+ ## Design rules (owner-set, hold to them)
91
+
92
+ - Configuration happens **in views and partials** (plus the policy) — never invent
93
+ a config DSL or initializer registry.
94
+ - **All copy in locales** — no hardcoded UI strings in templates
95
+ ([locales.md](locales.md)).
96
+ - **No global CSS** — styles belong to components ([components.md](components.md)).
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cafe_car
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Peterson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-07-01 00:00:00.000000000 Z
11
+ date: 2026-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -192,17 +192,20 @@ dependencies:
192
192
  - - ">="
193
193
  - !ruby/object:Gem::Version
194
194
  version: '4.0'
195
- description: CafeCar is a Rails engine that extends the view layer to render complete
196
- index, show, new, and edit interfaces straight from your models, with no boilerplate
197
- required. Sensible defaults cover authorization, presenters, filtering, sorting,
198
- pagination, and Hotwire-ready forms, and every default can be overridden application-wide
199
- or per model. Batteries included for admin panels, internal tools, and rapid prototyping.
195
+ description: 'CafeCar is a composable view extension for Rails: it renders complete
196
+ index, show, new, and edit interfaces straight from your models, with no DSL and
197
+ no boilerplate. Every index ships with keyword search, URL-based filtering and sorting,
198
+ pagination, and one-click CSV export. Authorization runs on Pundit with attribute-level
199
+ permissions; forms and Turbo Stream (Hotwire) responses render automatically. Every
200
+ default can be overridden application-wide or per model with ordinary Rails. It
201
+ makes admin panels, internal tools, and back-office apps on Rails 8 trivial.'
200
202
  email:
201
203
  - jeff@yak.sh
202
204
  executables: []
203
205
  extensions: []
204
206
  extra_rdoc_files: []
205
207
  files:
208
+ - ".claude-plugin/marketplace.json"
206
209
  - MIT-LICENSE
207
210
  - README.md
208
211
  - Rakefile
@@ -212,18 +215,21 @@ files:
212
215
  - app/assets/stylesheets/actiontext.css
213
216
  - app/assets/stylesheets/application.css
214
217
  - app/assets/stylesheets/cafe_car.css
218
+ - app/assets/stylesheets/cafe_car/chart.css
215
219
  - app/assets/stylesheets/cafe_car/code/base16-dark.css
216
220
  - app/assets/stylesheets/cafe_car/code/base16-light.css
221
+ - app/assets/stylesheets/cafe_car/dashboard.css
222
+ - app/assets/stylesheets/cafe_car/filters.css
217
223
  - app/assets/stylesheets/cafe_car/pagination.css
218
224
  - app/assets/stylesheets/cafe_car/themes/cool.css
219
225
  - app/assets/stylesheets/cafe_car/themes/cool2.css
220
226
  - app/assets/stylesheets/cafe_car/themes/defaults.css
221
- - app/assets/stylesheets/cafe_car/themes/warm-dark.css
222
227
  - app/assets/stylesheets/cafe_car/themes/warm.css
223
228
  - app/assets/stylesheets/cafe_car/tooltips.css
224
229
  - app/assets/stylesheets/cafe_car/trix.css
225
230
  - app/assets/stylesheets/cafe_car/utility.css
226
231
  - app/assets/stylesheets/iconoir.css
232
+ - app/assets/stylesheets/tom-select.css
227
233
  - app/assets/stylesheets/ui/Alert.css
228
234
  - app/assets/stylesheets/ui/Article.css
229
235
  - app/assets/stylesheets/ui/Button.css
@@ -250,11 +256,13 @@ files:
250
256
  - app/assets/stylesheets/ui/Table.css
251
257
  - app/assets/stylesheets/ui/components.css
252
258
  - app/controllers/cafe_car/application_controller.rb
259
+ - app/controllers/cafe_car/dashboards_controller.rb
253
260
  - app/controllers/cafe_car/examples_controller.rb
254
261
  - app/controllers/cafe_car/sessions_controller.rb
255
262
  - app/controllers/concerns/cafe_car/authentication.rb
256
263
  - app/javascript/application.js
257
264
  - app/javascript/cafe_car.js
265
+ - app/javascript/tom-select.complete.min.js
258
266
  - app/models/cafe_car/session.rb
259
267
  - app/policies/cafe_car/application_policy.rb
260
268
  - app/policies/cafe_car/session_policy.rb
@@ -286,20 +294,28 @@ files:
286
294
  - app/ui/cafe_car/ui/layout.rb
287
295
  - app/ui/cafe_car/ui/page.rb
288
296
  - app/views/application/_actions.html.haml
297
+ - app/views/application/_active_filters.html.haml
289
298
  - app/views/application/_alerts.html.haml
290
299
  - app/views/application/_aside.html.haml
300
+ - app/views/application/_belongs_to_filter.html.haml
291
301
  - app/views/application/_body.html.haml
302
+ - app/views/application/_boolean_filter.html.haml
303
+ - app/views/application/_bulk_actions.html.haml
304
+ - app/views/application/_chart.html.haml
292
305
  - app/views/application/_controls.html.haml
293
306
  - app/views/application/_debug.html.haml
294
307
  - app/views/application/_empty.html.haml
308
+ - app/views/application/_enum_filter.html.haml
295
309
  - app/views/application/_errors.html.haml
296
310
  - app/views/application/_field.html.haml
297
311
  - app/views/application/_fields.html.haml
312
+ - app/views/application/_filter.html.haml
298
313
  - app/views/application/_filters.html.haml
299
314
  - app/views/application/_footer.html.haml
300
315
  - app/views/application/_form.html.haml
301
316
  - app/views/application/_grid.html.haml
302
317
  - app/views/application/_grid_item.html.haml
318
+ - app/views/application/_has_many_filter.html.haml
303
319
  - app/views/application/_head.html.haml
304
320
  - app/views/application/_index.html.haml
305
321
  - app/views/application/_index_actions.html.haml
@@ -308,10 +324,13 @@ files:
308
324
  - app/views/application/_nested_field.html.haml
309
325
  - app/views/application/_notes.html.haml
310
326
  - app/views/application/_popup.html.haml
311
- - app/views/application/_search.html.haml
327
+ - app/views/application/_range_filter.html.haml
328
+ - app/views/application/_scope_filter.html.haml
312
329
  - app/views/application/_show.html.haml
330
+ - app/views/application/_string_filter.html.haml
313
331
  - app/views/application/_submit.html.haml
314
332
  - app/views/application/_table.html.haml
333
+ - app/views/application/_text_filter.html.haml
315
334
  - app/views/cafe_car/application/create.turbo_stream.haml
316
335
  - app/views/cafe_car/application/destroy.turbo_stream.haml
317
336
  - app/views/cafe_car/application/edit.html.haml
@@ -321,6 +340,8 @@ files:
321
340
  - app/views/cafe_car/application/new.turbo_stream.haml
322
341
  - app/views/cafe_car/application/show.html.haml
323
342
  - app/views/cafe_car/application/update.turbo_stream.haml
343
+ - app/views/cafe_car/dashboard/_chart.html.haml
344
+ - app/views/cafe_car/dashboard/_metric.html.haml
324
345
  - app/views/cafe_car/examples/_example.html.haml
325
346
  - app/views/cafe_car/examples/_index.html.haml
326
347
  - app/views/cafe_car/examples/_index_actions.html.haml
@@ -362,8 +383,8 @@ files:
362
383
  - lib/cafe_car/active_record.rb
363
384
  - lib/cafe_car/application_responder.rb
364
385
  - lib/cafe_car/attributes.rb
365
- - lib/cafe_car/auto_resolver.rb
366
386
  - lib/cafe_car/caching.rb
387
+ - lib/cafe_car/chart_builder.rb
367
388
  - lib/cafe_car/component.rb
368
389
  - lib/cafe_car/context.rb
369
390
  - lib/cafe_car/controller.rb
@@ -388,11 +409,19 @@ files:
388
409
  - lib/cafe_car/href_builder.rb
389
410
  - lib/cafe_car/informable.rb
390
411
  - lib/cafe_car/input_builder.rb
391
- - lib/cafe_car/inputs/association_builder.rb
412
+ - lib/cafe_car/inputs/association_input.rb
392
413
  - lib/cafe_car/inputs/base_input.rb
393
- - lib/cafe_car/inputs/belongs_to_builder.rb
414
+ - lib/cafe_car/inputs/boolean_input.rb
415
+ - lib/cafe_car/inputs/date_input.rb
416
+ - lib/cafe_car/inputs/datetime_input.rb
417
+ - lib/cafe_car/inputs/file_input.rb
418
+ - lib/cafe_car/inputs/nested_input.rb
419
+ - lib/cafe_car/inputs/number_input.rb
394
420
  - lib/cafe_car/inputs/password_input.rb
421
+ - lib/cafe_car/inputs/rich_text_input.rb
422
+ - lib/cafe_car/inputs/select_input.rb
395
423
  - lib/cafe_car/inputs/string_input.rb
424
+ - lib/cafe_car/inputs/text_area_input.rb
396
425
  - lib/cafe_car/link_builder.rb
397
426
  - lib/cafe_car/model.rb
398
427
  - lib/cafe_car/model_info.rb
@@ -419,6 +448,8 @@ files:
419
448
  - lib/cafe_car/ui.rb
420
449
  - lib/cafe_car/version.rb
421
450
  - lib/cafe_car/visitors.rb
451
+ - lib/generators/cafe_car/agents/USAGE
452
+ - lib/generators/cafe_car/agents/agents_generator.rb
422
453
  - lib/generators/cafe_car/controller/USAGE
423
454
  - lib/generators/cafe_car/controller/controller_generator.rb
424
455
  - lib/generators/cafe_car/controller/templates/controller.rb.tt
@@ -439,8 +470,19 @@ files:
439
470
  - lib/generators/cafe_car/sessions/sessions_generator.rb
440
471
  - lib/generators/cafe_car/sessions/templates/create_sessions.rb.tt
441
472
  - lib/tasks/cafe_car_tasks.rake
442
- - lib/tasks/holdco_tasks.rake
443
- - lib/tasks/templates/tasks_header.md
473
+ - lib/tasks/demo.rake
474
+ - llms.txt
475
+ - skills/cafe_car/SKILL.md
476
+ - skills/cafe_car/references/components.md
477
+ - skills/cafe_car/references/controllers.md
478
+ - skills/cafe_car/references/filtering.md
479
+ - skills/cafe_car/references/forms.md
480
+ - skills/cafe_car/references/locales.md
481
+ - skills/cafe_car/references/navigation.md
482
+ - skills/cafe_car/references/policies.md
483
+ - skills/cafe_car/references/presenters.md
484
+ - skills/cafe_car/references/turbo.md
485
+ - skills/cafe_car/references/views.md
444
486
  homepage: https://craft-concept.github.io/cafe_car
445
487
  licenses:
446
488
  - MIT
@@ -468,6 +510,7 @@ requirements: []
468
510
  rubygems_version: 3.5.22
469
511
  signing_key:
470
512
  specification_version: 4
471
- summary: Auto-generate CRUD admin UI for your Rails models, with sensible overridable
472
- defaults.
513
+ summary: A composable view extension for Rails — render index, show, new, and edit
514
+ straight from your models, with keyword search, filtering, CSV export, and Pundit
515
+ authorization, then override any default with ordinary Rails.
473
516
  test_files: []
@@ -1,29 +0,0 @@
1
- @import url(defaults.css);
2
-
3
- :root {
4
- --blue: rgb(35, 175, 208);
5
-
6
- --input: #1e1e1d;
7
- --background: #191918;
8
- --button: #333;
9
-
10
- --color: #e7e3dc;
11
- --dim: #6c7a91;
12
-
13
- --card: #222221;
14
- --border: #2A2A28;
15
- --hover: rgb(42, 42, 40);
16
- --shadow: rgba(0, 0, 0, 0.2);
17
- }
18
-
19
- body {
20
- scrollbar-color: rgb(73, 72, 70) rgb(25, 25, 24);
21
- }
22
-
23
- .Card, .Table {
24
- border: 0;
25
- }
26
-
27
- .Table_Head {
28
- background-color: var(--card);
29
- }
@@ -1,6 +0,0 @@
1
- = form_with url: "", method: :get, class: "search" do |f|
2
- - dot_params.each do |key, value|
3
- = hidden_field_tag key, value
4
- = hidden_field_tag :sort, params[:sort] if params[:sort].present?
5
- = f.search_field :q, value: search_term, placeholder: t(:search, scope: :helpers, default: "Search")
6
- = f.button "Search", name: nil
@@ -1,49 +0,0 @@
1
- module CafeCar
2
- module AutoResolver
3
- def auto_resolve!(mod)
4
- mod.instance_eval <<~RUBY, __FILE__, __LINE__
5
- def const_missing(name)
6
- super
7
- rescue NameError
8
- CafeCar.define(self, name) or raise
9
- end
10
- RUBY
11
- end
12
-
13
- def define(mod, name)
14
- case name.to_s
15
- when /^\w+Controller$/
16
- TOPLEVEL_BINDING.eval <<~RUBY, __FILE__, __LINE__
17
- class #{mod.name}::#{name} < CafeCar[:ApplicationController]
18
- include CafeCar::Controller
19
- cafe_car
20
- self
21
- end
22
- RUBY
23
- when /^\w+Policy$/
24
- TOPLEVEL_BINDING.eval <<~RUBY, __FILE__, __LINE__
25
- class #{mod.name}::#{name} < CafeCar[:ApplicationPolicy]
26
- def admin? = Rails.env.development?
27
-
28
- def index? = admin?
29
- def show? = admin?
30
- def create? = admin?
31
- def update? = admin?
32
- def destroy? = admin?
33
-
34
- def permitted_attributes
35
- model.info.fields.names.then do |names|
36
- [*model.primary_key].reverse.map(&:to_sym) & names | names
37
- end
38
- end
39
-
40
- class Scope < Scope
41
- def resolve = scope.all
42
- end
43
- self
44
- end
45
- RUBY
46
- end
47
- end
48
- end
49
- end
@@ -1,6 +0,0 @@
1
- module CafeCar
2
- module Inputs
3
- class AssociationBuilder < InputBuilder
4
- end
5
- end
6
- end
@@ -1,6 +0,0 @@
1
- module CafeCar
2
- module Inputs
3
- class BelongsToBuilder < AssociationBuilder
4
- end
5
- end
6
- end