mensa 0.5.0 → 0.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +12 -8
  4. data/README.md +4 -1
  5. data/app/components/mensa/add_filter/component.css +5 -3
  6. data/app/components/mensa/add_filter/component.html.erb +2 -2
  7. data/app/components/mensa/add_filter/component_controller.js +1 -0
  8. data/app/components/mensa/column_customizer/component.css +4 -4
  9. data/app/components/mensa/column_customizer/component.html.erb +4 -4
  10. data/app/components/mensa/control_bar/component.html.erb +9 -8
  11. data/app/components/mensa/empty_state/component.html.erb +1 -1
  12. data/app/components/mensa/filter_pill/component.html.erb +2 -2
  13. data/app/components/mensa/filter_pill_list/component.html.erb +2 -2
  14. data/app/components/mensa/header/component.html.erb +1 -1
  15. data/app/components/mensa/table/component.html.erb +7 -3
  16. data/app/components/mensa/table/component_controller.js +7 -2
  17. data/app/components/mensa/views/component.html.erb +8 -8
  18. data/app/controllers/mensa/tables_controller.rb +1 -1
  19. data/app/tables/mensa/base.rb +4 -2
  20. data/app/tables/mensa/cell.rb +8 -4
  21. data/app/tables/mensa/column.rb +5 -0
  22. data/app/tables/mensa/config/column_dsl.rb +1 -0
  23. data/app/tables/mensa/config/dsl_logic.rb +19 -1
  24. data/app/tables/mensa/config/format_dsl.rb +7 -0
  25. data/app/tables/mensa/config/table_dsl.rb +1 -5
  26. data/app/tables/mensa/filter.rb +24 -1
  27. data/app/tables/mensa/format.rb +23 -0
  28. data/app/views/mensa/exports/_dialog.html.erb +2 -2
  29. data/app/views/mensa/exports/_list.html.erb +3 -3
  30. data/app/views/mensa/tables/filters/show.turbo_stream.erb +4 -1
  31. data/app/views/mensa/tables/views/destroy.turbo_stream.erb +5 -1
  32. data/config/locales/en.yml +4 -0
  33. data/config/locales/nl.yml +4 -0
  34. data/lib/generators/mensa/templates/config/initializers/mensa.rb +29 -8
  35. data/lib/mensa/configuration.rb +59 -17
  36. data/lib/mensa/version.rb +1 -1
  37. metadata +4 -3
  38. data/app/views/mensa/tables/standard_error.html.erb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ad9a06fc13439d733db95cc8d3c0142247291057d8a5c84fce0f090f8c96a63
4
- data.tar.gz: fef0dcdcaf8b21e038af8baa90f3509016372f30998a7bdd0cb94c3050a19444
3
+ metadata.gz: 95766fa259330a818f92429d4b361853af00fee5e519d44bac2cf9c251bf4206
4
+ data.tar.gz: b58a0063b5e7331a26ebc3da30516fa901237b6f2a4901354a18929c0a83a51c
5
5
  SHA512:
6
- metadata.gz: e86a46aab67adf045e5939e9d307732e7752ccc50f3bae26b67dc9176ecb00508405b9b8c9c146fd7f0eb88a71f2aeba7f9f49fc943e3b8bb6910cbd1858e2d9
7
- data.tar.gz: 89e4d11db3e400215fdbce8cd5b031577a8c254cb92fc37f99c7ebbb726609c7d5e70c7bfb143a529f7ae6e9d5290d1bf4df314b6ca4e65384ebb20198f038dd
6
+ metadata.gz: 5c2d502c10e92c897a7ef313667772afb3e823f87ea2efd804543706b9380416b2238dbd06bd98c39d67086576d6ba4422be343c01db2afa79b6e5bee1f435bd
7
+ data.tar.gz: 70a4ac1c22e048d6a38f02e6da520bb8ffa48b2b5ca94b336aa7ee3b09a556b59c085e10b75edfc59a09c8aade640f636b89017d7868fb135420aac9df34b457
data/Gemfile CHANGED
@@ -14,6 +14,7 @@ gem "selenium-webdriver", "~> 4.17"
14
14
  gem "debug"
15
15
  gem "overmind", require: false
16
16
  gem "rack-mini-profiler"
17
+ gem "rails-i18n"
17
18
 
18
19
  group :development, :test do
19
20
  gem "standard", require: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mensa (0.4.0)
4
+ mensa (0.5.0)
5
5
  csv
6
6
  importmap-rails
7
7
  pagy (>= 43)
@@ -131,7 +131,7 @@ GEM
131
131
  prism (>= 1.3.0)
132
132
  rdoc (>= 4.0.0)
133
133
  reline (>= 0.4.2)
134
- json (2.19.8)
134
+ json (2.19.9)
135
135
  language_server-protocol (3.17.0.5)
136
136
  lint_roller (1.1.0)
137
137
  logger (1.7.0)
@@ -186,7 +186,7 @@ GEM
186
186
  json
187
187
  uri
188
188
  yaml
189
- parallel (1.28.0)
189
+ parallel (2.1.0)
190
190
  parser (3.3.11.1)
191
191
  ast (~> 2.4.1)
192
192
  racc
@@ -243,6 +243,9 @@ GEM
243
243
  rails-html-sanitizer (1.7.0)
244
244
  loofah (~> 2.25)
245
245
  nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
246
+ rails-i18n (8.1.0)
247
+ i18n (>= 0.7, < 2)
248
+ railties (>= 8.0.0, < 9)
246
249
  railties (8.1.3)
247
250
  actionpack (= 8.1.3)
248
251
  activesupport (= 8.1.3)
@@ -266,11 +269,11 @@ GEM
266
269
  reline (0.6.3)
267
270
  io-console (~> 0.5)
268
271
  rexml (3.4.4)
269
- rubocop (1.84.2)
272
+ rubocop (1.87.0)
270
273
  json (~> 2.3)
271
274
  language_server-protocol (~> 3.17.0.2)
272
275
  lint_roller (~> 1.1.0)
273
- parallel (~> 1.10)
276
+ parallel (>= 1.10)
274
277
  parser (>= 3.3.0.2)
275
278
  rainbow (>= 2.2.2, < 4.0)
276
279
  regexp_parser (>= 2.9.3, < 3.0)
@@ -284,7 +287,7 @@ GEM
284
287
  lint_roller (~> 1.1)
285
288
  rubocop (>= 1.75.0, < 2.0)
286
289
  rubocop-ast (>= 1.47.1, < 2.0)
287
- rubocop-rails (2.35.3)
290
+ rubocop-rails (2.35.4)
288
291
  activesupport (>= 4.2.0)
289
292
  lint_roller (~> 1.1)
290
293
  rack (>= 1.1)
@@ -313,10 +316,10 @@ GEM
313
316
  actionpack (>= 6.1)
314
317
  activesupport (>= 6.1)
315
318
  sprockets (>= 3.0.0)
316
- standard (1.54.0)
319
+ standard (1.55.0)
317
320
  language_server-protocol (~> 3.17.0.2)
318
321
  lint_roller (~> 1.0)
319
- rubocop (~> 1.84.0)
322
+ rubocop (~> 1.87.0)
320
323
  standard-custom (~> 1.0.0)
321
324
  standard-performance (~> 1.8)
322
325
  standard-custom (1.0.2)
@@ -383,6 +386,7 @@ DEPENDENCIES
383
386
  pry
384
387
  puma
385
388
  rack-mini-profiler
389
+ rails-i18n
386
390
  rubocop-rails
387
391
  ruby-lsp
388
392
  ruby-lsp-rails
data/README.md CHANGED
@@ -23,6 +23,9 @@ Features:
23
23
  - [X] Exports can be scheduled to run recurring (daily/weekly/monthly/quarterly/bi-yearly/yearly)
24
24
  You will have to bring your own mailer, see configuration for details.
25
25
 
26
+ TODO:
27
+ - [ ] ...
28
+
26
29
  Nice to haves:
27
30
 
28
31
  - [ ] group by
@@ -70,7 +73,7 @@ class UserTable < ApplicationTable
70
73
  end
71
74
 
72
75
  link { |user| edit_user_path(user) }
73
- supports_views true # This table supports custom views
76
+
74
77
  show_header true
75
78
  view_columns_ordering false # Disabled for now
76
79
 
@@ -64,15 +64,17 @@
64
64
  }
65
65
 
66
66
  &__clear {
67
- @apply block mt-3 text-gray-500 dark:text-gray-400 no-underline hover:text-gray-700 dark:hover:text-gray-200 cursor-pointer;
67
+ @apply flex items-center gap-2 mt-3 text-gray-500 dark:text-gray-400 no-underline hover:text-gray-700 dark:hover:text-gray-200 cursor-pointer;
68
68
  }
69
69
  }
70
70
  }
71
71
  }
72
72
 
73
- /* Show enter hint on hover or keyboard highlight — covers column list and value popover */
73
+ /* Show key hint on hover or keyboard highlight — covers column list and value popover */
74
74
  .mensa-table__add_filter li:hover .mensa-table__add_filter__enter-hint,
75
- .mensa-table__add_filter li.highlighted .mensa-table__add_filter__enter-hint {
75
+ .mensa-table__add_filter li.highlighted .mensa-table__add_filter__enter-hint,
76
+ .mensa-table__add_filter__popover_container__clear:hover
77
+ .mensa-table__add_filter__enter-hint {
76
78
  display: inline-flex;
77
79
  }
78
80
 
@@ -6,7 +6,7 @@
6
6
  type="button"
7
7
  title="<%= t("mensa.add_filter.add") %>"
8
8
  data-action="mensa-add-filter#openAllColumns">
9
- <i class="fa-solid fa-circle-plus"></i>
9
+ <i class="<%= Mensa.config.icons[:add_filter_trigger] %>"></i>
10
10
  </button>
11
11
 
12
12
  <ul class="hidden fixed z-50 max-h-96 overflow-auto rounded-lg bg-white p-2 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:bg-gray-800 sm:text-sm"
@@ -18,7 +18,7 @@
18
18
  data-filter-column-name="<%= column.name %>">
19
19
  <div class="label block flex-1 truncate font-normal"><%= column.human_name %></div>
20
20
  <div class="check hidden flex items-center text-primary-600">
21
- <div class="fal fa-check"></div>
21
+ <div class="<%= Mensa.config.icons[:add_filter_selected] %>"></div>
22
22
  </div>
23
23
  <span class="mensa-table__add_filter__enter-hint">↵ Enter</span>
24
24
  </li>
@@ -77,6 +77,7 @@ export default class AddFilterComponentController extends ApplicationController
77
77
 
78
78
  // Called by the + button — always shows all columns regardless of current filter
79
79
  openAllColumns(event) {
80
+ this._closePopover();
80
81
  this.filterColumns("");
81
82
  this.showList(event?.currentTarget);
82
83
  }
@@ -28,12 +28,12 @@
28
28
  @apply flex-none text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300 cursor-pointer;
29
29
  }
30
30
 
31
- /* Show the correct eye icon based on the row's data-visible attribute.
32
- Works with both FA CSS (i elements) and FA SVG mode (svg elements). */
33
- &__row[data-visible="true"] .fa-eye-slash {
31
+ /* Show the correct visibility icon based on the row's data-visible attribute
32
+ without depending on specific Font Awesome class names. */
33
+ &__row[data-visible="true"] [data-icon-role="hidden"] {
34
34
  display: none;
35
35
  }
36
- &__row[data-visible="false"] .fa-eye {
36
+ &__row[data-visible="false"] [data-icon-role="visible"] {
37
37
  display: none;
38
38
  }
39
39
  }
@@ -4,7 +4,7 @@
4
4
  data-mensa-column-customizer-turbo-frame-id-value="<%= table.table_id %>"
5
5
  data-mensa-column-customizer-mensa-table-outlet="#table-<%= table.table_id %>">
6
6
  <button class="mensa-table__control_bar__button" type="button" data-action="click->mensa-column-customizer#toggle">
7
- <i class="<%= Mensa.config.icons[:control_bar_edit] %>"></i>
7
+ <i class="<%= Mensa.config.icons[:column_customizer_toggle] %>"></i>
8
8
  </button>
9
9
  <div class="mensa-table__column_customizer__popover hidden" data-mensa-column-customizer-target="popover">
10
10
  <p class="mensa-table__column_customizer__heading">Columns</p>
@@ -16,13 +16,13 @@
16
16
  data-visible="<%= column.visible?.to_s %>"
17
17
  draggable="true"
18
18
  data-action="dragstart->mensa-column-customizer#dragStart dragover->mensa-column-customizer#dragOver drop->mensa-column-customizer#drop dragend->mensa-column-customizer#dragEnd">
19
- <i class="mensa-table__column_customizer__handle fa-solid fa-grip-vertical"></i>
19
+ <i class="mensa-table__column_customizer__handle <%= Mensa.config.icons[:column_customizer_handle] %>"></i>
20
20
  <span class="mensa-table__column_customizer__name<%= !column.visible? ? " mensa-table__column_customizer__name--hidden" : "" %>">
21
21
  <%= column.human_name %>
22
22
  </span>
23
23
  <button class="mensa-table__column_customizer__visibility" type="button" data-action="click->mensa-column-customizer#toggleVisibility">
24
- <i class="fa-solid fa-eye"></i>
25
- <i class="fa-solid fa-eye-slash"></i>
24
+ <i data-icon-role="visible" class="<%= Mensa.config.icons[:column_customizer_visibility_on] %>"></i>
25
+ <i data-icon-role="hidden" class="<%= Mensa.config.icons[:column_customizer_visibility_off] %>"></i>
26
26
  </button>
27
27
  </li>
28
28
  <% end %>
@@ -6,7 +6,7 @@
6
6
 
7
7
  <div class="mensa-table__save-reset hidden" data-mensa-table-target="saveResetButtons">
8
8
  <button class="mensa-table__control_bar__button" type="button" title="<%= t(".reset", default: "Reset") %>" data-action="mensa-table#cancelFiltersAndSearch">
9
- <i class="fa-solid fa-rotate-left"></i>
9
+ <i class="<%= Mensa.config.icons[:control_bar_reset] %>"></i>
10
10
  </button>
11
11
  <% if table.current_user && table.supports_custom_views? %>
12
12
  <div class="relative">
@@ -15,7 +15,7 @@
15
15
  </button>
16
16
  <button class="mensa-table__control_bar__button hidden" type="button" data-mensa-table-target="saveSplit" data-action="mensa-table#toggleSaveDropdown">
17
17
  <%= t("mensa.save") %>
18
- <i class="fa-solid fa-chevron-down text-xs"></i>
18
+ <i class="<%= Mensa.config.icons[:control_bar_save_dropdown] %> text-xs"></i>
19
19
  </button>
20
20
  <ul class="mensa-table__control_bar__save-dropdown hidden" data-mensa-table-target="saveDropdown">
21
21
  <li>
@@ -30,15 +30,16 @@
30
30
  </li>
31
31
  </ul>
32
32
  </div>
33
- <% else %>
34
- <button class="mensa-table__control_bar__button" type="button" data-action="mensa-table#saveAsNewView">
35
- <%= t("mensa.save") %>
36
- </button>
37
33
  <% end %>
38
34
  </div>
39
35
 
40
- <button class="mensa-table__control_bar__button hidden" type="button" data-mensa-table-target="eyeButton" data-action="click->mensa-table#toggleViewFilters">
41
- <i class="fa-solid fa-eye"></i>
36
+ <button class="mensa-table__control_bar__button hidden"
37
+ type="button"
38
+ data-mensa-table-target="eyeButton"
39
+ data-action="click->mensa-table#toggleViewFilters"
40
+ data-icon-visible-class="<%= Mensa.config.icons[:control_bar_view_filters_show] %>"
41
+ data-icon-hidden-class="<%= Mensa.config.icons[:control_bar_view_filters_hide] %>">
42
+ <i class="<%= Mensa.config.icons[:control_bar_view_filters_show] %>"></i>
42
43
  </button>
43
44
 
44
45
  <% if table.exportable? %>
@@ -1,6 +1,6 @@
1
1
  <div class="mensa-empty-state">
2
2
  <div class="mensa-empty-state__icon">
3
- <i class="<%= Mensa.config.icons[:search] %>"></i>
3
+ <i class="<%= Mensa.config.icons[:empty_state_icon] %>"></i>
4
4
  </div>
5
5
  <h3 class="mensa-empty-state__title"><%= t("mensa.empty_state.title", model: model_name_plural) %></h3>
6
6
  <p class="mensa-empty-state__subtitle"><%= t("mensa.empty_state.subtitle") %></p>
@@ -1,4 +1,4 @@
1
- <% formatted_value = filter.value.is_a?(Array) ? filter.value.join(", ") : filter.value %>
1
+ <% formatted_value = filter.formatted_value %>
2
2
  <div class="mensa-filter-pill"
3
3
  data-controller="mensa-filter-pill"
4
4
  data-mensa-filter-pill-mensa-filter-pill-list-outlet="#mensa-filter-pill-list-<%= filter.table.table_id %>"
@@ -15,6 +15,6 @@
15
15
  <% end %>
16
16
  </button>
17
17
  <button class="mensa-filter-pill__remove" type="button" title="Remove filter" data-action="click->mensa-filter-pill#remove">
18
- <i class="fa-solid fa-xmark"></i>
18
+ <i class="<%= Mensa.config.icons[:filter_pill_remove] %>"></i>
19
19
  </button>
20
20
  </div>
@@ -21,10 +21,10 @@
21
21
  data-mensa-filter-pill-list-target="searchInput"
22
22
  data-action="input->mensa-filter-pill-list#monitorSearch keydown.enter->mensa-filter-pill-list#search keydown.esc->mensa-filter-pill-list#resetSearch focus->mensa-filter-pill-list#searchFocused keydown.down->mensa-filter-pill-list#navigateDown keydown.up->mensa-filter-pill-list#navigateUp"
23
23
  value="<%= params[:query] %>">
24
- <i class="mensa-table__search-bar__search-icon <%= Mensa.config.icons[:search] %>"></i>
24
+ <i class="mensa-table__search-bar__search-icon <%= Mensa.config.icons[:filter_pill_list_search] %>"></i>
25
25
  </div>
26
26
  </div>
27
27
  <button class="mensa-table__search-bar__clear hidden" type="button" data-mensa-filter-pill-list-target="resetSearchButton" data-action="mensa-filter-pill-list#resetSearch">
28
- <i class="fas fa-xmark"></i>
28
+ <i class="<%= Mensa.config.icons[:filter_pill_list_clear] %>"></i>
29
29
  </button>
30
30
  </div>
@@ -2,7 +2,7 @@
2
2
  <% if column.sortable? %>
3
3
  <%= link_to table.path(order: {column.name => column.next_sort_direction}, turbo_frame_id: table.table_id), "data-turbo-frame": "_self", class: "order cursor-pointer" do %>
4
4
  <span><%= column.human_name %></span>
5
- <i class="<%= Mensa.config.icons["order_indicator#{column.sort_direction.to_s.present? ? "_#{column.sort_direction}" : ""}".to_sym] %>"></i>
5
+ <i class="<%= Mensa.config.icons["header_order_indicator#{column.sort_direction.to_s.present? ? "_#{column.sort_direction}" : ""}".to_sym] %>"></i>
6
6
  <% end %>
7
7
  <% else %>
8
8
  <div class="container">
@@ -1,6 +1,6 @@
1
1
  <div class="mensa-table"
2
2
  id="table-<%= table.table_id %>"
3
- data-mensa-table-supports-views-value="<%= table.supports_views? %>"
3
+ data-mensa-table-supports-views-value="<%= table.views? %>"
4
4
  data-mensa-table-table-url-value="<%= table.path(turbo_frame_id: table.table_id, user_params: params) %>"
5
5
  data-mensa-table-save-view-url-value="<%= helpers.mensa.table_views_path(table.name) %>"
6
6
  data-mensa-table-views-url-value="<%= helpers.mensa.table_views_path(table.name) %>"
@@ -11,8 +11,12 @@
11
11
  data-mensa-table-mensa-column-customizer-outlet="[data-controller='mensa-column-customizer']">
12
12
  <div class="mensa-table__toolbar">
13
13
  <div class="mensa-table__search-container">
14
- <% if table.supports_views? && table.show_header? %>
15
- <%= render Mensa::Views::Component.new(table: table) %>
14
+ <% if table.show_header? %>
15
+ <% if table.views? %>
16
+ <%= render Mensa::Views::Component.new(table: table) %>
17
+ <% else %>
18
+ <div id="mensa-views-<%= table.table_id %>"></div>
19
+ <% end %>
16
20
  <% end %>
17
21
  <div class="flex min-w-0 flex-1" id="filters-<%= table.table_id %>">
18
22
  <%= render Mensa::FilterPillList::Component.new(table: table) %>
@@ -375,10 +375,15 @@ export default class TableComponentController extends ApplicationController {
375
375
  const hidden = this.element.classList.contains(
376
376
  "mensa-table--view-filters-hidden",
377
377
  );
378
+ const visibleIconClass =
379
+ this.eyeButtonTarget.dataset.iconVisibleClass || "";
380
+ const hiddenIconClass =
381
+ this.eyeButtonTarget.dataset.iconHiddenClass || "";
382
+
378
383
  // Replace innerHTML so FontAwesome's MutationObserver re-processes the new <i>
379
384
  this.eyeButtonTarget.innerHTML = hidden
380
- ? '<i class="fa-solid fa-eye"></i>'
381
- : '<i class="fa-solid fa-eye-slash"></i>';
385
+ ? `<i class="${visibleIconClass}"></i>`
386
+ : `<i class="${hiddenIconClass}"></i>`;
382
387
  }
383
388
  }
384
389
 
@@ -11,26 +11,26 @@
11
11
  data-mensa-views-views-url-value="<%= helpers.mensa.table_views_path(table.name) %>">
12
12
  <button class="mensa-table__views__trigger" type="button" data-action="mensa-views#toggleDropdown" data-mensa-views-target="trigger" aria-haspopup="listbox">
13
13
  <span class="mensa-table__views__trigger-label" data-mensa-views-target="triggerLabel"><%= current_view_name %></span>
14
- <i class="fa-solid fa-sort mensa-table__views__trigger-icon"></i>
14
+ <i class="<%= Mensa.config.icons[:views_trigger] %> mensa-table__views__trigger-icon"></i>
15
15
  </button>
16
16
 
17
17
  <div class="mensa-table__views__dropdown hidden" data-mensa-views-target="dropdown">
18
18
  <ul role="listbox">
19
19
  <% table.all_views.each do |view| %>
20
20
  <% is_selected = view.id == table.table_view&.id || (view.id == :default && table.table_view.blank?) %>
21
- <% is_user_view = view.id.is_a?(String) && view.id.match?(/\A[0-9a-f-]{32,}\z/i) %>
21
+ <% is_user_view = view.is_a?(Mensa::TableView) %>
22
22
  <li class="mensa-table__views__option" role="option" data-view-id="<%= view.id %>" data-view-name="<%= view.name %>" data-mensa-views-target="view">
23
23
  <button class="mensa-table__views__option-btn" type="button" data-action="mensa-views#select" data-view-id="<%= view.id %>">
24
- <i class="mensa-table__views__option-check fa-solid fa-check<%= " invisible" unless is_selected %>"></i>
24
+ <i class="mensa-table__views__option-check <%= Mensa.config.icons[:views_option_selected] %><%= " invisible" unless is_selected %>"></i>
25
25
  <span><%= view.name %></span>
26
26
  </button>
27
27
  <% if is_user_view %>
28
28
  <button class="mensa-table__views__option-menu" type="button" data-action="mensa-views#toggleSubmenu" data-view-id="<%= view.id %>" title="View options">
29
- <i class="fa-solid fa-ellipsis"></i>
29
+ <i class="<%= Mensa.config.icons[:views_option_menu] %>"></i>
30
30
  </button>
31
31
  <% else %>
32
32
  <div class="mensa-table__views__option-system">
33
- <i class="fa-solid fa-ban"></i>
33
+ <i class="<%= Mensa.config.icons[:views_option_system] %>"></i>
34
34
  </div>
35
35
  <% end %>
36
36
  </li>
@@ -39,15 +39,15 @@
39
39
 
40
40
  <div class="mensa-table__views__submenu hidden" data-mensa-views-target="submenu">
41
41
  <button class="mensa-table__views__submenu-item" type="button" data-action="mensa-views#renameView">
42
- <i class="fa-solid fa-pencil"></i>
42
+ <i class="<%= Mensa.config.icons[:views_rename] %>"></i>
43
43
  <%= t(".rename_view", default: "Rename view") %>
44
44
  </button>
45
45
  <button class="mensa-table__views__submenu-item" type="button" data-action="mensa-views#duplicateView">
46
- <i class="fa-solid fa-copy"></i>
46
+ <i class="<%= Mensa.config.icons[:views_duplicate] %>"></i>
47
47
  <%= t(".duplicate_view", default: "Duplicate view") %>
48
48
  </button>
49
49
  <button class="mensa-table__views__submenu-item mensa-table__views__submenu-item--danger" type="button" data-action="mensa-views#deleteView">
50
- <i class="fa-solid fa-trash"></i>
50
+ <i class="<%= Mensa.config.icons[:views_delete] %>"></i>
51
51
  <%= t(".delete_view", default: "Delete view") %>
52
52
  </button>
53
53
  </div>
@@ -2,7 +2,7 @@ module Mensa
2
2
  class TablesController < ApplicationController
3
3
  def show
4
4
  config = params.permit(:format, :query, :id, :page, :table_view_id, :turbo_frame_id, order: {}, column_order: [], hidden_columns: [], params: {}).to_h
5
- config[:filters] = params[:filters]&.to_unsafe_h || {}
5
+ config[:filters] = params[:filters].to_unsafe_h if params.key?(:filters)
6
6
  config[:params] = params[:params]&.to_unsafe_h || {}
7
7
 
8
8
  if params[:table_view_id]
@@ -13,9 +13,7 @@ module Mensa
13
13
  config_reader :model
14
14
  config_reader :scope
15
15
  config_reader :link, call: false
16
- config_reader :supports_views?
17
16
  config_reader :supports_custom_views?
18
- config_reader :supports_filters?
19
17
  config_reader :view_columns_ordering?
20
18
  config_reader :show_header?
21
19
  config_reader :exportable?
@@ -143,6 +141,10 @@ module Mensa
143
141
  views
144
142
  end
145
143
 
144
+ def views?
145
+ all_views.reject{_1.id == :default}.present?
146
+ end
147
+
146
148
  # The user that owns custom views. Returns nil when the host application has
147
149
  # no current user, in which case views cannot be saved.
148
150
  def current_user
@@ -38,10 +38,14 @@ module Mensa
38
38
  content_tag(:i, "", class: "fa-solid fa-check")
39
39
  when FalseClass
40
40
  content_tag(:i, "", class: "fa-solid fa-xmark")
41
+ when Array
42
+ value.to_fs(:db)
41
43
  when Date
42
- respond_to?(:dt) ? dt(value) : value.strftime("%d.%m.%Y")
44
+ I18n.l(value.in_time_zone(column.format.time_zone), format: column.format.format)
45
+ # value.in_time_zone(column.format.time_zone).to_fs(column.format.format)
43
46
  when Time, DateTime
44
- respond_to?(:ln) ? ln(value) : value.strftime("%d-%m-%Y %H:%M:%S")
47
+ I18n.l(value.in_time_zone(column.format.time_zone), format: column.format.format)
48
+ # value.in_time_zone(column.format.time_zone).to_fs(column.format.format)
45
49
  else
46
50
  column.sanitize? ? sanitize(value.to_s) : value.to_s.html_safe
47
51
  end
@@ -54,9 +58,9 @@ module Mensa
54
58
  when TrueClass, FalseClass
55
59
  value.to_s
56
60
  when Date
57
- respond_to?(:dt) ? dt(value) : value.strftime("%d.%m.%Y")
61
+ I18n.l(value.in_time_zone(column.format.time_zone), format: column.format.format)
58
62
  when Time, DateTime
59
- respond_to?(:ln) ? ln(value) : value.strftime("%d-%m-%Y %H:%M:%S")
63
+ value.in_time_zone(column.format.time_zone).to_fs(column.format.format)
60
64
  else
61
65
  strip_tags(value.to_s)
62
66
  end
@@ -19,6 +19,7 @@ module Mensa
19
19
  config_reader :visible?
20
20
  config_reader :internal?
21
21
  config_reader :method # When a method needs to be called on the model, slow!
22
+ config_reader :format
22
23
 
23
24
  def sort_direction
24
25
  value = table.config.dig(:order, name)
@@ -88,6 +89,10 @@ module Mensa
88
89
  @filter ||= Mensa::Filter.new(column: self, config: table.config.dig(:columns, name, :filter) || {}, table: table)
89
90
  end
90
91
 
92
+ def format
93
+ @format ||= Mensa::Format.new(config: config.dig(:format).presence || {}, column: self)
94
+ end
95
+
91
96
  def human_name
92
97
  if table.model < ActiveRecord::Base
93
98
  table.model.human_attribute_name name
@@ -16,6 +16,7 @@ module Mensa::Config
16
16
  option :internal, default: false
17
17
  option :method
18
18
  option :type
19
+ option :format, default: :long, dsl_single_hash: Mensa::Config::FormatDsl, name_attribute: :format
19
20
 
20
21
  option :visible, default: true
21
22
  option :render, dsl: Mensa::Config::RenderDsl
@@ -17,11 +17,13 @@ module Mensa::Config
17
17
  class_methods do
18
18
  attr_reader :default_config
19
19
 
20
- def option(name, default: nil, config_name: nil, dsl: nil, dsl_hash: nil, dsl_array: nil)
20
+ def option(name, default: nil, config_name: nil, name_attribute: nil, dsl: nil, dsl_hash: nil, dsl_array: nil, dsl_single_hash: nil)
21
21
  if dsl
22
22
  dsl_option(name, dsl)
23
23
  elsif dsl_hash
24
24
  dsl_hash(name, dsl_hash, config_name: config_name)
25
+ elsif dsl_single_hash
26
+ dsl_single_hash(name, dsl_single_hash, name_attribute:, default: default)
25
27
  elsif dsl_array
26
28
  dsl_array(name, dsl_array, config_name: config_name)
27
29
  else
@@ -80,6 +82,22 @@ module Mensa::Config
80
82
  end
81
83
  end
82
84
 
85
+ ###
86
+ # Define a DSL that builds a single hash
87
+ # by calling option :action, dsl_single_hash: Mensa::ActionDsl
88
+ #
89
+ def dsl_single_hash(option_name, klass, name_attribute: :name, default: nil)
90
+ config_name ||= option_name.to_s.to_sym
91
+
92
+ @default_config ||= {}
93
+ @default_config[option_name.to_sym] = default.nil? ? {} : {name_attribute => default}
94
+
95
+ define_method(option_name) do |name = nil, &block|
96
+ config[config_name] = {name_attribute => name}
97
+ config[config_name].merge!(klass.new(nil, &block).config.compact)
98
+ end
99
+ end
100
+
83
101
  ###
84
102
  # Define a DSL that builds an array
85
103
  # by calling option :action, dsl_array: Mensa::ActionDsl
@@ -0,0 +1,7 @@
1
+ module Mensa::Config
2
+ class FormatDsl
3
+ include DslLogic
4
+
5
+ option :time_zone, default: -> { Time.zone }
6
+ end
7
+ end
@@ -30,8 +30,6 @@
30
30
  # order last_name: :asc
31
31
  # link { |user| edit_user_path(user) }
32
32
  #
33
- # supports_views true
34
- # supports_filters true
35
33
  #
36
34
  # action :activate do
37
35
  # link { |user| edit_user_path(user) }
@@ -76,9 +74,7 @@ module Mensa::Config
76
74
 
77
75
  option :render, dsl: Mensa::Config::RenderDsl
78
76
 
79
- option :supports_views, default: false
80
- option :supports_custom_views, default: false
81
- option :supports_filters, default: true
77
+ option :supports_custom_views, default: true
82
78
  option :show_header, default: true
83
79
  # Whether the table allows to change column ordering
84
80
  option :view_columns_ordering, default: true
@@ -60,11 +60,20 @@ module Mensa
60
60
 
61
61
  def to_s
62
62
  parts = [column.human_name, operator_label]
63
- formatted_value = value.is_a?(Array) ? value.join(", ") : value
64
63
  parts << formatted_value if formatted_value.present? && operator_with_value?
65
64
  parts.join(" ")
66
65
  end
67
66
 
67
+ def formatted_value
68
+ options = collection_options
69
+
70
+ if value.is_a?(Array)
71
+ value.map { |entry| label_for_value(entry, options) }.join(", ")
72
+ else
73
+ label_for_value(value, options)
74
+ end
75
+ end
76
+
68
77
  def filter_scope(record_scope)
69
78
  if scope
70
79
  record_scope.instance_exec(normalize(value), &scope)
@@ -140,6 +149,20 @@ module Mensa
140
149
 
141
150
  private
142
151
 
152
+ def label_for_value(selected_value, options)
153
+ option = options.find { |_label, value| value.to_s == selected_value.to_s }
154
+ option ? option.first : selected_value
155
+ end
156
+
157
+ def collection_options
158
+ collection = column.filter&.collection
159
+ return [] if collection.blank?
160
+
161
+ collection.map do |item|
162
+ item.is_a?(Array) ? [item.first.to_s, item.last.to_s] : [item.to_s, item.to_s]
163
+ end
164
+ end
165
+
143
166
  # Unused at the moment
144
167
  def normalize(query)
145
168
  query # .to_s.gsub(/\s(?![&!|])/, '\\\\ ')
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mensa
4
+ # Represents a batch action that can be applied to multiple selected records.
5
+ #
6
+ # batch :archive do
7
+ # title "Archive"
8
+ # process { |records| records.update_all(archived: true) }
9
+ # end
10
+ class Format
11
+ include ConfigReaders
12
+
13
+ defined_by Mensa::Config::FormatDsl
14
+
15
+ config_reader :format
16
+ config_reader :time_zone
17
+
18
+ def initialize(config:, column:)
19
+ @column = column
20
+ @config = self.class.definition.merge(config || {})
21
+ end
22
+ end
23
+ end
@@ -5,7 +5,7 @@
5
5
  <header class="mensa-table__export-dialog__header">
6
6
  <h2 class="mensa-table__export-dialog__title"><%= t("mensa.exports.title", default: "Export %{table}", table: table.name.to_s.humanize) %></h2>
7
7
  <button class="mensa-table__export-dialog__close" type="button" data-action="mensa-table#cancelExport" aria-label="<%= t("mensa.exports.close", default: "Close") %>">
8
- <i class="fa-solid fa-xmark"></i>
8
+ <i class="<%= Mensa.config.icons[:exports_dialog_close] %>"></i>
9
9
  </button>
10
10
  </header>
11
11
 
@@ -65,7 +65,7 @@
65
65
  <%= t("mensa.exports.cancel", default: "Cancel") %>
66
66
  </button>
67
67
  <button class="mensa-table__export-dialog__button mensa-table__export-dialog__button--primary" type="submit">
68
- <i class="fa-solid fa-file-export"></i>
68
+ <i class="<%= Mensa.config.icons[:exports_dialog_submit] %>"></i>
69
69
  <%= t("mensa.exports.submit", default: "Export") %>
70
70
  </button>
71
71
  </div>
@@ -11,7 +11,7 @@
11
11
  class: "mensa-table__export-dialog__delete",
12
12
  form_class: "mensa-table__export-dialog__delete-form",
13
13
  aria: {label: t("mensa.exports.delete", default: "Delete export") } do %>
14
- <i class="fa-solid fa-trash"></i>
14
+ <i class="<%= Mensa.config.icons[:exports_list_delete] %>"></i>
15
15
  <% end %>
16
16
 
17
17
  <div class="mensa-table__export-dialog__item-info">
@@ -24,7 +24,7 @@
24
24
  <div class="mensa-table__export-dialog__item-action">
25
25
  <% if export.downloadable? %>
26
26
  <%= link_to mensa.download_table_export_path(export.table_name, export), class: "mensa-table__export-dialog__download", data: {turbo: false} do %>
27
- <i class="fa-solid fa-download"></i>
27
+ <i class="<%= Mensa.config.icons[:exports_list_download] %>"></i>
28
28
  <%= t("mensa.exports.download", default: "Download") %>
29
29
  <% end %>
30
30
  <% elsif export.failed? %>
@@ -33,7 +33,7 @@
33
33
  <span class="mensa-table__export-dialog__status mensa-table__export-dialog__status--pending"><%= t("mensa.exports.waiting", default: "Waiting") %></span>
34
34
  <% else %>
35
35
  <span class="mensa-table__export-dialog__status mensa-table__export-dialog__status--pending">
36
- <i class="fa-solid fa-spinner fa-spin"></i>
36
+ <i class="<%= Mensa.config.icons[:exports_list_processing] %>"></i>
37
37
  <%= t("mensa.exports.processing", default: "Preparing…") %>
38
38
  </span>
39
39
  <% end %>
@@ -54,5 +54,8 @@
54
54
  <% end %>
55
55
  </ul>
56
56
  <hr class="mensa-table__add_filter__popover_container__separator">
57
- <a class="mensa-table__add_filter__popover_container__clear" href="#" data-action="click->mensa-add-filter#reset">Clear</a>
57
+ <a class="mensa-table__add_filter__popover_container__clear" href="#" data-action="click->mensa-add-filter#reset">
58
+ <span class="flex-1"><%= t('mensa.tables.filters.show.clear') %></span>
59
+ <span class="mensa-table__add_filter__enter-hint">⎋ Esc</span>
60
+ </a>
58
61
  <% end %>
@@ -1,5 +1,9 @@
1
1
  <%= turbo_stream.replace "mensa-views-#{@table.table_id}" do %>
2
- <%= render Mensa::Views::Component.new(table: @table) %>
2
+ <% if @table.views? %>
3
+ <%= render Mensa::Views::Component.new(table: @table) %>
4
+ <% else %>
5
+ <div id="mensa-views-<%= @table.table_id %>"></div>
6
+ <% end %>
3
7
  <% end %>
4
8
 
5
9
  <%= turbo_stream.update "filters-#{@table.table_id}" do %>
@@ -1,5 +1,9 @@
1
1
  en:
2
2
  mensa:
3
+ tables:
4
+ filters:
5
+ show:
6
+ clear: Cancel
3
7
  actions: Actions
4
8
  save: Save
5
9
  update_view: Update view
@@ -1,5 +1,9 @@
1
1
  nl:
2
2
  mensa:
3
+ tables:
4
+ filters:
5
+ show:
6
+ clear: Annuleren
3
7
  actions: Acties
4
8
  save: Bewaar
5
9
  update_view: Bewaar weergave
@@ -9,14 +9,35 @@ Mensa.setup do |config|
9
9
 
10
10
  # Override icons in use
11
11
  config.icons = {
12
- order_indicator_asc: "fa-solid fa-arrow-up",
13
- order_indicator_desc: "fa-solid fa-arrow-down",
14
- control_bar_search: "fa-solid fa-magnifying-glass",
15
- control_bar_filter: "fa-solid fa-filter",
16
- control_bar_edit: "fa-solid fa-table-columns",
17
- control_bar_compress: "fa-solid fa-compress",
12
+ add_filter_trigger: "fa-solid fa-circle-plus",
13
+ add_filter_selected: "fal fa-check",
14
+ column_customizer_toggle: "fa-solid fa-table-columns",
15
+ column_customizer_handle: "fa-solid fa-grip-vertical",
16
+ column_customizer_visibility_on: "fa-solid fa-eye",
17
+ column_customizer_visibility_off: "fa-solid fa-eye-slash",
18
+ control_bar_reset: "fa-solid fa-rotate-left",
19
+ control_bar_save_dropdown: "fa-solid fa-chevron-down",
20
+ control_bar_view_filters_show: "fa-solid fa-eye",
21
+ control_bar_view_filters_hide: "fa-solid fa-eye-slash",
18
22
  control_bar_export: "fa-solid fa-file-export",
19
- search: "fa-solid fa-magnifying-glass",
20
- filters_add_filter: "fa-solid fa-plus"
23
+ empty_state_icon: "fa-solid fa-magnifying-glass",
24
+ filter_pill_remove: "fa-solid fa-xmark",
25
+ filter_pill_list_search: "fa-solid fa-magnifying-glass",
26
+ filter_pill_list_clear: "fa-solid fa-xmark",
27
+ header_order_indicator_asc: "fa-solid fa-arrow-up",
28
+ header_order_indicator_desc: "fa-solid fa-arrow-down",
29
+ views_trigger: "fa-solid fa-sort",
30
+ views_option_selected: "fa-solid fa-check",
31
+ views_option_menu: "fa-solid fa-ellipsis",
32
+ views_option_system: "fa-solid fa-ban",
33
+ views_rename: "fa-solid fa-pencil",
34
+ views_duplicate: "fa-solid fa-copy",
35
+ views_delete: "fa-solid fa-trash",
36
+ exports_dialog_close: "fa-solid fa-xmark",
37
+ exports_dialog_submit: "fa-solid fa-file-export",
38
+ exports_list_delete: "fa-solid fa-trash",
39
+ exports_list_download: "fa-solid fa-download",
40
+ exports_list_processing: "fa-solid fa-spinner fa-spin",
41
+ tables_standard_error: "fa-solid fa-circle-exclamation"
21
42
  }
22
43
  end
@@ -41,29 +41,70 @@ module Mensa
41
41
  option :logger, default: Rails.logger
42
42
  option :base_controller, default: "::ApplicationController"
43
43
 
44
- # TODO: add all icons below
45
44
  option :icons, default: {
46
- order_indicator_asc: "fa-solid fa-arrow-up",
47
- order_indicator_desc: "fa-solid fa-arrow-down",
48
- control_bar_search: "fa-solid fa-magnifying-glass",
49
- control_bar_filter: "fa-solid fa-filter",
50
- control_bar_edit: "fa-solid fa-table-columns",
51
- control_bar_compress: "fa-solid fa-compress",
45
+ add_filter_trigger: "fa-solid fa-circle-plus",
46
+ add_filter_selected: "fa-solid fa-check",
47
+ column_customizer_toggle: "fa-solid fa-table-columns",
48
+ column_customizer_handle: "fa-solid fa-grip-vertical",
49
+ column_customizer_visibility_on: "fa-solid fa-eye",
50
+ column_customizer_visibility_off: "fa-solid fa-eye-slash",
51
+ control_bar_reset: "fa-solid fa-rotate-left",
52
+ control_bar_save_dropdown: "fa-solid fa-chevron-down",
53
+ control_bar_view_filters_show: "fa-solid fa-eye",
54
+ control_bar_view_filters_hide: "fa-solid fa-eye-slash",
52
55
  control_bar_export: "fa-solid fa-file-export",
53
- search: "fa-solid fa-magnifying-glass",
54
- filters_add_filter: "fa-solid fa-plus"
56
+ empty_state_icon: "fa-solid fa-magnifying-glass",
57
+ filter_pill_remove: "fa-solid fa-xmark",
58
+ filter_pill_list_search: "fa-solid fa-magnifying-glass",
59
+ filter_pill_list_clear: "fa-solid fa-xmark",
60
+ header_order_indicator_asc: "fa-solid fa-arrow-up",
61
+ header_order_indicator_desc: "fa-solid fa-arrow-down",
62
+ views_trigger: "fa-solid fa-sort",
63
+ views_option_selected: "fa-solid fa-check",
64
+ views_option_menu: "fa-solid fa-ellipsis",
65
+ views_option_system: "fa-solid fa-ban",
66
+ views_rename: "fa-solid fa-pencil",
67
+ views_duplicate: "fa-solid fa-copy",
68
+ views_delete: "fa-solid fa-trash",
69
+ exports_dialog_close: "fa-solid fa-xmark",
70
+ exports_dialog_submit: "fa-solid fa-file-export",
71
+ exports_list_delete: "fa-solid fa-trash",
72
+ exports_list_download: "fa-solid fa-download",
73
+ exports_list_processing: "fa-solid fa-spinner fa-spin",
74
+ tables_standard_error: "fa-solid fa-circle-exclamation"
55
75
  }
56
76
  # PRO
57
77
  # option :icons, default: {
58
- # order_indicator_asc: "fa-regular fa-arrow-up-short-wide",
59
- # order_indicator_desc: "fa-regular fa-arrow-down-wide-short",
60
- # order_indicator: "fa-regular fa-arrow-down-arrow-up",
61
- # control_bar_search: "fa-light fa-magnifying-glass",
62
- # control_bar_filter: "fa-light fa-bars-filter",
63
- # control_bar_edit: "fa-light fa-columns-3",
64
- # control_bar_compress: "fa-light fa-compress",
78
+ # add_filter_trigger: "fa-light fa-circle-plus",
79
+ # add_filter_selected: "fa-light fa-check",
80
+ # column_customizer_toggle: "fa-light fa-columns-3",
81
+ # column_customizer_handle: "fa-light fa-grip-vertical",
82
+ # column_customizer_visibility_on: "fa-light fa-eye",
83
+ # column_customizer_visibility_off: "fa-light fa-eye-slash",
84
+ # control_bar_reset: "fa-light fa-rotate-left",
85
+ # control_bar_save_dropdown: "fa-light fa-chevron-down",
86
+ # control_bar_view_filters_show: "fa-light fa-eye",
87
+ # control_bar_view_filters_hide: "fa-light fa-eye-slash",
65
88
  # control_bar_export: "fa-light fa-file-export",
66
- # search: "fa-light fa-magnifying-glass"
89
+ # empty_state_icon: "fa-light fa-magnifying-glass",
90
+ # filter_pill_remove: "fa-light fa-xmark",
91
+ # filter_pill_list_search: "fa-light fa-magnifying-glass",
92
+ # filter_pill_list_clear: "fa-light fa-xmark",
93
+ # header_order_indicator_asc: "fa-regular fa-arrow-up-short-wide",
94
+ # header_order_indicator_desc: "fa-regular fa-arrow-down-wide-short",
95
+ # views_trigger: "fa-light fa-sort",
96
+ # views_option_selected: "fa-light fa-check",
97
+ # views_option_menu: "fa-light fa-ellipsis",
98
+ # views_option_system: "fa-light fa-ban",
99
+ # views_rename: "fa-light fa-pencil",
100
+ # views_duplicate: "fa-light fa-copy",
101
+ # views_delete: "fa-light fa-trash",
102
+ # exports_dialog_close: "fa-light fa-xmark",
103
+ # exports_dialog_submit: "fa-light fa-file-export",
104
+ # exports_list_delete: "fa-light fa-trash",
105
+ # exports_list_download: "fa-light fa-download",
106
+ # exports_list_processing: "fa-light fa-spinner fa-spin",
107
+ # tables_standard_error: "fa-light fa-circle-exclamation"
67
108
  # }
68
109
 
69
110
  option :callbacks, default: {
@@ -81,6 +122,7 @@ module Mensa
81
122
  end
82
123
  }
83
124
 
125
+ # :front or :back (default)
84
126
  option :row_actions_position, default: :back
85
127
  # It's either :basic or :fuzzy, for fuzzy search you need to have `pg_trgm` extension installed
86
128
  option :search, default: :basic
data/lib/mensa/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mensa
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mensa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom de Grunt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-12 00:00:00.000000000 Z
11
+ date: 2026-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -262,11 +262,13 @@ files:
262
262
  - app/tables/mensa/config/column_dsl.rb
263
263
  - app/tables/mensa/config/dsl_logic.rb
264
264
  - app/tables/mensa/config/filter_dsl.rb
265
+ - app/tables/mensa/config/format_dsl.rb
265
266
  - app/tables/mensa/config/render_dsl.rb
266
267
  - app/tables/mensa/config/table_dsl.rb
267
268
  - app/tables/mensa/config/view_dsl.rb
268
269
  - app/tables/mensa/config_readers.rb
269
270
  - app/tables/mensa/filter.rb
271
+ - app/tables/mensa/format.rb
270
272
  - app/tables/mensa/row.rb
271
273
  - app/tables/mensa/scope.rb
272
274
  - app/tables/mensa/search.rb
@@ -277,7 +279,6 @@ files:
277
279
  - app/views/mensa/tables/filters/show.turbo_stream.erb
278
280
  - app/views/mensa/tables/show.html.erb
279
281
  - app/views/mensa/tables/show.turbo_stream.erb
280
- - app/views/mensa/tables/standard_error.html.erb
281
282
  - app/views/mensa/tables/views/create.turbo_stream.erb
282
283
  - app/views/mensa/tables/views/destroy.turbo_stream.erb
283
284
  - app/views/mensa/tables/views/update.turbo_stream.erb
@@ -1,9 +0,0 @@
1
- <turbo-frame id="<%= @frame_id %>">
2
- <div class="mensa-empty-state">
3
- <div class="mensa-empty-state__icon">
4
- <i class="fa-solid fa-circle-exclamation"></i>
5
- </div>
6
- <h3 class="mensa-empty-state__title">Could not load table</h3>
7
- <p class="mensa-empty-state__subtitle"><%= @error_message %></p>
8
- </div>
9
- </turbo-frame>