infotable 1.4.1 β 1.6.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.
- checksums.yaml +4 -4
- data/README.md +179 -11
- data/app/assets/javascripts/infotable/controllers/drawer_controller.js +74 -378
- data/app/assets/javascripts/infotable/controllers/table_controller.js +112 -120
- data/app/assets/javascripts/infotable/vendor/sortable.esm.js +3363 -0
- data/app/controllers/infotable/tables_controller.rb +16 -5
- data/app/helpers/infotable/tables_helper.rb +10 -48
- data/app/views/infotable/tables/_column_visibility.html.erb +4 -4
- data/app/views/infotable/tables/_end_indicator.html.erb +8 -0
- data/app/views/infotable/tables/_filter_drawer.html.erb +6 -6
- data/app/views/infotable/tables/_next_page_frame.html.erb +1 -9
- data/app/views/infotable/tables/_pagination.html.erb +4 -7
- data/app/views/infotable/tables/_table.html.erb +1 -1
- data/app/views/infotable/tables/_table_rows.html.erb +9 -2
- data/app/views/infotable/tables/filters/_boolean.html.erb +1 -1
- data/app/views/infotable/tables/filters/_range.html.erb +1 -1
- data/app/views/infotable/tables/filters/_select.html.erb +2 -2
- data/app/views/infotable/tables/filters/_text.html.erb +2 -2
- data/app/views/infotable/tables/show.html.erb +2 -2
- data/config/importmap.rb +2 -2
- data/config/locales/de.yml +126 -0
- data/config/locales/el.yml +126 -0
- data/config/locales/en.yml +18 -4
- data/config/locales/es.yml +126 -0
- data/config/locales/fr.yml +126 -0
- data/config/locales/it.yml +126 -0
- data/config/locales/pl.yml +18 -4
- data/exe/infotable-mcp +13 -0
- data/lib/generators/infotable/install/templates/initializer.rb +5 -3
- data/lib/generators/infotable/table/table_generator.rb +23 -1
- data/lib/generators/infotable/table/templates/table.rb.tt +8 -1
- data/lib/infotable/base.rb +62 -4
- data/lib/infotable/configuration.rb +1 -1
- data/lib/infotable/engine.rb +1 -8
- data/lib/infotable/filter_processor.rb +10 -1
- data/lib/infotable/formatters/boolean_formatter.rb +4 -4
- data/lib/infotable/formatters/currency_formatter.rb +4 -12
- data/lib/infotable/formatters/date_formatter.rb +3 -9
- data/lib/infotable/formatters/duration_formatter.rb +51 -0
- data/lib/infotable/formatters/filesize_formatter.rb +14 -0
- data/lib/infotable/formatters/image_formatter.rb +31 -0
- data/lib/infotable/formatters/number_formatter.rb +46 -0
- data/lib/infotable/formatters/tags_formatter.rb +44 -0
- data/lib/infotable/formatters/truncate_formatter.rb +19 -0
- data/lib/infotable/mcp/introspection.rb +94 -0
- data/lib/infotable/mcp/server.rb +26 -0
- data/lib/infotable/mcp/table_checker.rb +80 -0
- data/lib/infotable/mcp/table_writer.rb +66 -0
- data/lib/infotable/mcp/tools.rb +122 -0
- data/lib/infotable/mcp.rb +30 -0
- data/lib/infotable/table_resolver.rb +9 -0
- data/lib/infotable/version.rb +1 -1
- data/lib/infotable.rb +22 -0
- metadata +53 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 31096b54bd71fb8799c287dbd43f91c2e05a3a5d5c8a652bd89f84e97c9fa5ed
|
|
4
|
+
data.tar.gz: 4cec84bed5d53f7599753fa30183e667833278aa4ebd89484cc2495ace2b7262
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fa78ae7189b9c5ed8363ecd04c9abe444ed51ba3fcf231644fb14b624d5f7aa776811335efafc8ba521b99cfb9d8724ceccec647e3f3398e27377f5bc0ebaec6
|
|
7
|
+
data.tar.gz: 6bdaf90359935c4a3a1bad5575748b0dd40c47ce01ebd2fc7f8c10c6604d3b7720f9edde5fa387cd5e16868ce48165cc24183d6eeba1474b01b337621bd3829b
|
data/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Modern, flexible datatable engine for Rails 8+ with Hotwire. Build beautiful, in
|
|
|
12
12
|
- π§ **Highly customizable** - Easy to override defaults and add custom formatters
|
|
13
13
|
- π¦ **Works with any bundler** - Importmap, esbuild, webpack, viteβwe support them all
|
|
14
14
|
- π **Rails 8+ ready** - Built for modern Rails applications
|
|
15
|
-
- π **i18n Support** - English and
|
|
15
|
+
- π **i18n Support** - English, Polish, German, French, Spanish, Greek and Italian translations included
|
|
16
16
|
- π― **Advanced Features** - Infinite scroll, column pinning, drag-to-reorder, row links, and more
|
|
17
17
|
|
|
18
18
|
## Quick Start
|
|
@@ -129,6 +129,15 @@ Infotable.configure do |config|
|
|
|
129
129
|
end
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
+
### Security
|
|
133
|
+
|
|
134
|
+
Tables are served by the engine at `/infotable/tables/:name/{data,export,ids}`. A table without an
|
|
135
|
+
`authorize { |controller| ... }` block is readable (and exportable as CSV) by **everyone who can reach the
|
|
136
|
+
route**, unless the engine controllers inherit your app's authentication. The installer therefore sets
|
|
137
|
+
`config.parent_controller = "ApplicationController"`; keep it (or point it at a controller with your
|
|
138
|
+
`before_action :authenticate_user!`) and add `authorize` to tables with restricted data. The engine's own
|
|
139
|
+
default (`ActionController::Base`) applies no authentication at all.
|
|
140
|
+
|
|
132
141
|
### Available Global Options
|
|
133
142
|
|
|
134
143
|
| Option | Type | Default | Description |
|
|
@@ -137,7 +146,8 @@ end
|
|
|
137
146
|
| `per_page_options` | Array | `[10, 25, 50, 100]` | Available rows per page options |
|
|
138
147
|
| `drawer_position` | Symbol | `:right` | Position of filter/column drawer (`:left` or `:right`) |
|
|
139
148
|
| `drawer_width` | String | `"26rem"` | Width of the drawer (`px`, `rem`, `em`, `vw` or `%`; anything else falls back to the default) |
|
|
140
|
-
| `parent_controller` | String | `"ActionController::Base"` | Controller the engine's controllers inherit from. Set it to `"ApplicationController"` to reuse your authentication |
|
|
149
|
+
| `parent_controller` | String | `"ActionController::Base"` (the installer sets `"ApplicationController"`) | Controller the engine's controllers inherit from. Set it to `"ApplicationController"` to reuse your authentication |
|
|
150
|
+
| `max_select_all` | Integer, nil | `4000` | "Select all N matching" collects at most this many ids (each is sent as `ids[]`; Rack accepts 4096 parameters per request) |
|
|
141
151
|
| `table_min_height` | String | `"400px"` | Minimum table height |
|
|
142
152
|
| `table_max_height` | String | `"600px"` | Maximum table height (enables scrolling) |
|
|
143
153
|
| `autofilter` | Boolean | `true` | Auto-apply filters on change (debounced) vs manual apply |
|
|
@@ -155,6 +165,8 @@ Generate a starting point from a model's columns:
|
|
|
155
165
|
```bash
|
|
156
166
|
rails generate infotable:table User
|
|
157
167
|
rails generate infotable:table Admin::Order --only=id number status # or --skip=notes
|
|
168
|
+
rails generate infotable:table Order --per-page=50 --sort=placed_at:desc --toolbar=rail --checkbox \
|
|
169
|
+
--authorize="controller.current_user&.admin?" # also --row-click --infinite-scroll --countless
|
|
158
170
|
```
|
|
159
171
|
|
|
160
172
|
It writes `app/infotable/users_table.rb` with a column per attribute (types and filters inferred, enums become select filters, passwords/tokens and foreign keys are left out, `belongs_to` associations come as commented hints).
|
|
@@ -448,6 +460,30 @@ Features:
|
|
|
448
460
|
- Cmd/Ctrl+Click to open in new tab
|
|
449
461
|
- Ignores clicks on buttons, links, and inputs
|
|
450
462
|
|
|
463
|
+
#### Row click, classes and data attributes
|
|
464
|
+
|
|
465
|
+
```ruby
|
|
466
|
+
# Style rows by their data (write the Tailwind classes out in full so they are generated)
|
|
467
|
+
row_class ->(order) { "bg-red-50" if order.overdue? }
|
|
468
|
+
|
|
469
|
+
# data-* attributes on the <tr>, e.g. for your own Stimulus controller
|
|
470
|
+
row_data ->(post) { { post_id: post.id, status: post.status } } # data-post-id, data-status
|
|
471
|
+
|
|
472
|
+
# Rows fire a cancelable `infotable:row-click` event (needs no row_link)
|
|
473
|
+
row_click
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
Every row also gets `id="<dom_id>"` (`order_42`), so Turbo Streams can target it (`turbo_stream.replace dom_id(order)`, `broadcasts_to`). Rows without a record id are left without one.
|
|
477
|
+
|
|
478
|
+
Clicking a row (not a link, button or input inside it) first dispatches `infotable:row-click` on the `<tr>`, with `detail: { id, url, data, originalEvent }`. If nothing calls `preventDefault()` and the table has a `row_link`, the click then falls back to following it, so the two compose:
|
|
479
|
+
|
|
480
|
+
```js
|
|
481
|
+
document.addEventListener("infotable:row-click", event => {
|
|
482
|
+
if (event.detail.data.status === "locked") event.preventDefault() // no navigation for locked rows
|
|
483
|
+
else openPreview(event.detail.data.postId) // ...or handle it yourself
|
|
484
|
+
})
|
|
485
|
+
```
|
|
486
|
+
|
|
451
487
|
#### Row Size
|
|
452
488
|
|
|
453
489
|
Control table row padding and text size with three options:
|
|
@@ -566,6 +602,100 @@ column :actions,
|
|
|
566
602
|
|
|
567
603
|
`method:` and `confirm:` use Turbo (`data-turbo-method`, `data-turbo-confirm`). Labels are HTML-escaped.
|
|
568
604
|
|
|
605
|
+
#### 6. Link Formatter (`:link`)
|
|
606
|
+
|
|
607
|
+
```ruby
|
|
608
|
+
column :website, formatter: :link, formatter_options: { external: true } # the value is the URL
|
|
609
|
+
|
|
610
|
+
column :email,
|
|
611
|
+
formatter: :link,
|
|
612
|
+
formatter_options: { url: ->(record) { "mailto:#{record.email}" } } # email / phone: mailto: and tel:
|
|
613
|
+
|
|
614
|
+
column :name,
|
|
615
|
+
formatter: :link,
|
|
616
|
+
formatter_options: { url: ->(record) { user_path(record) } } # Proc (run in the view), Symbol or String
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
Only relative URLs, `http(s)`, `mailto` and `tel` are linked (`javascript:` and friends render as plain text). Options: `url`, `label`, `external` (`target="_blank"` + `rel="noopener noreferrer"`), `class`.
|
|
620
|
+
|
|
621
|
+
#### 7. Avatar Formatter (`:avatar`)
|
|
622
|
+
|
|
623
|
+
```ruby
|
|
624
|
+
column :avatar_url,
|
|
625
|
+
formatter: :avatar,
|
|
626
|
+
formatter_options: { name: ->(record) { record.name }, size: :md } # :sm, :md, :lg
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
The value is the image URL; without one, the initials of `name` are shown on a coloured disc. `label: false` hides the name next to the picture.
|
|
630
|
+
|
|
631
|
+
#### 8. Percent Formatter (`:percent`)
|
|
632
|
+
|
|
633
|
+
```ruby
|
|
634
|
+
column :completion, formatter: :percent, formatter_options: { precision: 1, bar: true }
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
Options: `precision` (default 0), `scale: :percent` (0-100, default) or `:ratio` (0-1), `bar` (small progress bar).
|
|
638
|
+
|
|
639
|
+
#### 9. Number Formatter (`:number`)
|
|
640
|
+
|
|
641
|
+
```ruby
|
|
642
|
+
column :views_count, formatter: :number, formatter_options: { compact: true } # 1.5k, 3.4M
|
|
643
|
+
column :latency, formatter: :number, formatter_options: { unit: "ms", precision: 1 }
|
|
644
|
+
column :stock, formatter: :number, formatter_options: { zero: "-" }
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
Options: `precision`, `delimiter` (`","`), `separator` (`"."`), `unit` (appended), `compact`, `zero` (shown instead of 0).
|
|
648
|
+
|
|
649
|
+
#### 10. Tags Formatter (`:tags`, alias `:list`)
|
|
650
|
+
|
|
651
|
+
```ruby
|
|
652
|
+
column :roles,
|
|
653
|
+
formatter: :tags,
|
|
654
|
+
formatter_options: { limit: 3, colors: { "admin" => "red" } }
|
|
655
|
+
|
|
656
|
+
# several values in a cell that is not an attribute: use `value:`
|
|
657
|
+
column :labels, value: ->(post) { post.tags.map(&:name) }, formatter: :tags, formatter_options: { limit: 2 }
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
The value is an Array, a relation or a comma separated string; each item is a small badge. `limit` shows N items and "+M" (the rest is in its tooltip), `label: ->(item) { item.name }` picks the text, `colors` maps item to badge colour (as in `:badge`), `separator: ", "` renders plain text instead of badges. The CSV export joins the items with `", "`.
|
|
661
|
+
|
|
662
|
+
#### 11. Truncate Formatter (`:truncate`)
|
|
663
|
+
|
|
664
|
+
```ruby
|
|
665
|
+
column :description, formatter: :truncate, formatter_options: { length: 80 }
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
Long text is cut to `length` (default 60, `omission` default `"β¦"`); the full text is in the cell's tooltip.
|
|
669
|
+
|
|
670
|
+
#### 12. Image Formatter (`:image`)
|
|
671
|
+
|
|
672
|
+
```ruby
|
|
673
|
+
column :photo_url,
|
|
674
|
+
formatter: :image,
|
|
675
|
+
formatter_options: { size: :md, alt: ->(record) { record.name }, link: true } # :sm (32px), :md (48px), :lg (64px)
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
A square thumbnail (use `:avatar` for round pictures). Only http(s) and relative URLs are rendered. `link: true` opens the full image in a new tab.
|
|
679
|
+
|
|
680
|
+
#### 13. Filesize Formatter (`:filesize`)
|
|
681
|
+
|
|
682
|
+
```ruby
|
|
683
|
+
column :byte_size, formatter: :filesize # 1536 => "1.5 KB"
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
`precision` is the number of significant digits (default 2).
|
|
687
|
+
|
|
688
|
+
#### 14. Duration Formatter (`:duration`)
|
|
689
|
+
|
|
690
|
+
```ruby
|
|
691
|
+
column :duration_seconds, formatter: :duration # 3900 => "1h 05m"
|
|
692
|
+
column :duration_seconds, formatter: :duration, formatter_options: { format: :long } # "1 hour 5 minutes"
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
The value is in seconds. `parts` limits how many units are shown (default 2). Translated through `infotable.formatters.duration` (Polish plural forms work out of the box).
|
|
696
|
+
|
|
697
|
+
The Date formatter's `format: :relative` keeps the exact time in a tooltip, and the Currency formatter takes `unit`, `precision`, `delimiter` and `separator` from your locale (`number.currency.format`) for whatever you do not pass.
|
|
698
|
+
|
|
569
699
|
### Custom Formatters
|
|
570
700
|
|
|
571
701
|
#### Lambda/Proc Formatter
|
|
@@ -713,7 +843,7 @@ config.autofilter = false # Require "Apply Filters" button click
|
|
|
713
843
|
|
|
714
844
|
## Internationalization (i18n)
|
|
715
845
|
|
|
716
|
-
InfoTable includes English and
|
|
846
|
+
InfoTable includes English, Polish, German, French, Spanish, Greek and Italian translations. Any key can be overridden in your app.
|
|
717
847
|
|
|
718
848
|
### Set Locale
|
|
719
849
|
|
|
@@ -735,7 +865,7 @@ end
|
|
|
735
865
|
### Available Languages
|
|
736
866
|
|
|
737
867
|
- English (`:en`) - Default
|
|
738
|
-
- Polish (`:pl`)
|
|
868
|
+
- Polish (`:pl`), German (`:de`), French (`:fr`), Spanish (`:es`), Greek (`:el`), Italian (`:it`)
|
|
739
869
|
|
|
740
870
|
### Customize Translations
|
|
741
871
|
|
|
@@ -750,11 +880,11 @@ en:
|
|
|
750
880
|
export_csv: "Download CSV"
|
|
751
881
|
```
|
|
752
882
|
|
|
753
|
-
### Add
|
|
883
|
+
### Add Another Language
|
|
754
884
|
|
|
755
885
|
```yaml
|
|
756
|
-
# config/locales/infotable.
|
|
757
|
-
|
|
886
|
+
# config/locales/infotable.pt.yml
|
|
887
|
+
pt:
|
|
758
888
|
infotable:
|
|
759
889
|
table:
|
|
760
890
|
buttons:
|
|
@@ -804,6 +934,48 @@ Built-in CSV export with:
|
|
|
804
934
|
|
|
805
935
|
---
|
|
806
936
|
|
|
937
|
+
## MCP Server (AI assistants)
|
|
938
|
+
|
|
939
|
+
The gem ships an [MCP](https://modelcontextprotocol.io) server, so an AI assistant (Claude Code, Cursor, ...) can create tables in your app: it reads your models, asks you how the table should look, generates `app/infotable/*_table.rb` and checks that it works. It talks to your app over stdio on your machine, no port is opened.
|
|
940
|
+
|
|
941
|
+
Add the `mcp` gem to the app (it is not a dependency of infotable):
|
|
942
|
+
|
|
943
|
+
```ruby
|
|
944
|
+
# Gemfile
|
|
945
|
+
gem "mcp", group: :development
|
|
946
|
+
```
|
|
947
|
+
|
|
948
|
+
Register the server in the client, from the app's root. For Claude Code:
|
|
949
|
+
|
|
950
|
+
```bash
|
|
951
|
+
claude mcp add infotable -- bundle exec infotable-mcp
|
|
952
|
+
```
|
|
953
|
+
|
|
954
|
+
or commit a `.mcp.json` (Cursor: `.cursor/mcp.json`):
|
|
955
|
+
|
|
956
|
+
```json
|
|
957
|
+
{
|
|
958
|
+
"mcpServers": {
|
|
959
|
+
"infotable": { "command": "bundle", "args": ["exec", "infotable-mcp"] }
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
```
|
|
963
|
+
|
|
964
|
+
Then ask: *"create an InfoTable table for Order"*. Or use the `new_table` prompt, which makes the assistant ask for the settings first.
|
|
965
|
+
|
|
966
|
+
| Tool | What it does |
|
|
967
|
+
|------|--------------|
|
|
968
|
+
| `list_models` | Models with column types, enums and associations |
|
|
969
|
+
| `list_tables` | Tables that already exist, with their settings (the house style) |
|
|
970
|
+
| `describe_dsl` | Column options, types, filters, formatters and settings of the installed version |
|
|
971
|
+
| `table_options` | Questions about a new table (columns, sort, per page, toolbar, selection, authorization...) with defaults proposed from the model |
|
|
972
|
+
| `generate_table` | Renders the table with the `infotable:table` generator. Only shows the code; `write: true` saves it, an existing file is replaced only with `overwrite: true` |
|
|
973
|
+
| `validate_table` | Loads a table by name or from source and reports missing columns, a bad `default_sort`, a failing query or a missing `authorize`; `preview: 5` returns the first rows |
|
|
974
|
+
|
|
975
|
+
The full README is available to the assistant as the `infotable://readme` resource.
|
|
976
|
+
|
|
977
|
+
Notes: the server boots your app (development environment unless `RAILS_ENV` is set) and reads the development database; it writes only to `app/infotable/`. Tables are generated without `authorize` unless you give one, and `validate_table` warns about that (see [Security](#security)).
|
|
978
|
+
|
|
807
979
|
## Examples
|
|
808
980
|
|
|
809
981
|
### Basic Table
|
|
@@ -1046,10 +1218,6 @@ end
|
|
|
1046
1218
|
## Roadmap
|
|
1047
1219
|
|
|
1048
1220
|
- [ ] Server-side persistence of column settings
|
|
1049
|
-
- [ ] Table state in the URL
|
|
1050
|
-
- [ ] More formatters (link, avatar, percent)
|
|
1051
|
-
- [ ] `infotable:table` generator
|
|
1052
|
-
- [ ] Tailwind v3 support
|
|
1053
1221
|
|
|
1054
1222
|
---
|
|
1055
1223
|
|