mensa 0.6.10 → 0.6.12

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer-lock.json +34 -0
  3. data/.devcontainer/devcontainer.json +16 -19
  4. data/.devcontainer/docker-compose.yml +35 -0
  5. data/.devcontainer/postStart.sh +9 -5
  6. data/.prettierrc.json +3 -0
  7. data/.shipkit.yml +2 -0
  8. data/.vscode/settings.json +8 -0
  9. data/.vscode/tasks.json +47 -0
  10. data/CHANGELOG.md +18 -0
  11. data/Gemfile +4 -0
  12. data/Gemfile.lock +8 -2
  13. data/README.md +32 -0
  14. data/app/components/mensa/column_customizer/component.html.erb +1 -0
  15. data/app/components/mensa/column_customizer/component_controller.js +8 -3
  16. data/app/components/mensa/control_bar/component.html.erb +2 -2
  17. data/app/components/mensa/filter_pill_list/component.html.erb +1 -0
  18. data/app/components/mensa/filter_pill_list/component_controller.js +15 -9
  19. data/app/components/mensa/header/component.html.erb +1 -1
  20. data/app/components/mensa/table/component.html.erb +3 -3
  21. data/app/components/mensa/table/component_controller.js +9 -5
  22. data/app/components/mensa/view/component.html.erb +1 -1
  23. data/app/components/mensa/view/paging.css +40 -40
  24. data/app/components/mensa/views/component.html.erb +1 -1
  25. data/app/components/mensa/views/component_controller.js +2 -2
  26. data/app/controllers/mensa/tables/batch_actions_controller.rb +1 -1
  27. data/app/controllers/mensa/tables/exports_controller.rb +31 -12
  28. data/app/controllers/mensa/tables/filters_controller.rb +2 -2
  29. data/app/controllers/mensa/tables/views_controller.rb +8 -3
  30. data/app/javascript/mensa/controllers/application_controller.js +8 -0
  31. data/app/jobs/mensa/export_job.rb +5 -5
  32. data/app/models/mensa/export.rb +42 -25
  33. data/app/tables/mensa/base.rb +37 -1
  34. data/app/tables/mensa/column.rb +23 -1
  35. data/app/tables/mensa/filter.rb +37 -2
  36. data/app/tables/mensa/row.rb +18 -1
  37. data/app/tables/mensa/scope.rb +57 -2
  38. data/app/tables/mensa/table_params.rb +44 -0
  39. data/app/views/mensa/exports/_badge.html.erb +3 -2
  40. data/app/views/mensa/exports/_dialog.html.erb +2 -2
  41. data/app/views/mensa/exports/_list.html.erb +1 -1
  42. data/config/locales/en.yml +1 -0
  43. data/config/locales/nl.yml +1 -0
  44. data/lib/generators/mensa/templates/config/initializers/mensa.rb +6 -0
  45. data/lib/mensa/configuration.rb +30 -1
  46. data/lib/mensa/version.rb +1 -1
  47. metadata +9 -4
  48. data/.devcontainer/compose.yaml +0 -49
  49. data/.devcontainer/postCreate.sh +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14b28a5dcb74e6d3bfccaa9180f0ba2299b1c5bff0adc6e9bbd2a17ff2d91c19
4
- data.tar.gz: 552b80421e290566218fe4e7e495785f7208ffa8f397fd88859b4e4ad20d6a21
3
+ metadata.gz: 72a11ca0b316e616b3705f54523e4fe6f6ae408f7e767f9a130db02d1afc088f
4
+ data.tar.gz: ae13275d6ead1adece9e27ea3f82143c3dc88bb1aa7f443ad8aaf8dca251eff1
5
5
  SHA512:
6
- metadata.gz: 4848da1b5f33354d6dc79a8b6f76ed68e43744706ce34b808910186de399ae19d49e85409a561d11d74376c3a067f411697432664d2274c28a869e83136fdde9
7
- data.tar.gz: 400e3c6400043dea964f3958a27704ae1b56dd7c475de8ba4f20a16b3b3b4682582e3229589d285b3f62377db326ff56b0ac17160544aa38369a11f6f4cc92ca
6
+ metadata.gz: 1a5f0d0e105762e8542af697c8bc1af5816ac2d628b9ba1e22bab262828ddf47ffbfe5e8f8a9d03ca78990caa8cf6b313748199eaa2f2eae0658cf6a2ad0c8f0
7
+ data.tar.gz: 8ba1ab12c0c48b03f4b425cc933614bbc5880fed150fbf70f2e32e39dd90307eca0a530c2cf43e81450708ba094fcab9dfe6dd81258b2cb77a72818f4f48fed9
@@ -0,0 +1,34 @@
1
+ {
2
+ "features": {
3
+ "ghcr.io/devcontainers/features/common-utils:2": {
4
+ "version": "2.5.9",
5
+ "resolved": "ghcr.io/devcontainers/features/common-utils@sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a",
6
+ "integrity": "sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a"
7
+ },
8
+ "ghcr.io/devcontainers/features/docker-in-docker:2": {
9
+ "version": "2.17.0",
10
+ "resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c",
11
+ "integrity": "sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c"
12
+ },
13
+ "ghcr.io/devcontainers/features/github-cli:1": {
14
+ "version": "1.1.0",
15
+ "resolved": "ghcr.io/devcontainers/features/github-cli@sha256:d22f50b70ed75339b4eed1ba9ecde3a1791f90e88d37936517e3bace0bbad671",
16
+ "integrity": "sha256:d22f50b70ed75339b4eed1ba9ecde3a1791f90e88d37936517e3bace0bbad671"
17
+ },
18
+ "ghcr.io/devcontainers/features/node:2": {
19
+ "version": "2.1.0",
20
+ "resolved": "ghcr.io/devcontainers/features/node@sha256:586c9a6f7dd40bd3ba2cd41e7f2f88dcc31fbe5d1442afcbf07ffbc66b686857",
21
+ "integrity": "sha256:586c9a6f7dd40bd3ba2cd41e7f2f88dcc31fbe5d1442afcbf07ffbc66b686857"
22
+ },
23
+ "ghcr.io/rails/devcontainer/features/activestorage": {
24
+ "version": "1.1.1",
25
+ "resolved": "ghcr.io/rails/devcontainer/features/activestorage@sha256:7fa8fff898ac33076ebf65631d3c6c902dc9bad87de3e5dfa645f3e2d7a35c07",
26
+ "integrity": "sha256:7fa8fff898ac33076ebf65631d3c6c902dc9bad87de3e5dfa645f3e2d7a35c07"
27
+ },
28
+ "ghcr.io/rails/devcontainer/features/postgres-client": {
29
+ "version": "1.2.0",
30
+ "resolved": "ghcr.io/rails/devcontainer/features/postgres-client@sha256:7e6b118646d6e0d82a9ec06e81ad1b5406f7042f0279d35fff3a7a612be7a050",
31
+ "integrity": "sha256:7e6b118646d6e0d82a9ec06e81ad1b5406f7042f0279d35fff3a7a612be7a050"
32
+ }
33
+ }
34
+ }
@@ -1,37 +1,34 @@
1
1
  // For format details, see https://aka.ms/devcontainer.json. For config options, see the
2
- // README at: https://github.com/devcontainers/templates/tree/main/src/ruby
2
+ // README at: https://github.com/devcontainers/templates/tree/main/src/ruby-rails-postgres
3
3
  {
4
4
  "name": "mensa",
5
- "dockerComposeFile": "compose.yaml",
5
+ "dockerComposeFile": "docker-compose.yml",
6
6
  "service": "app",
7
- "workspaceFolder": "/workspaces/mensa",
8
- // Features to add to the dev container. More info: https://containers.dev/features.
9
7
  "features": {
10
- "ghcr.io/devcontainers/features/github-cli:1": {},
8
+ "ghcr.io/devcontainers/features/node:2": {},
9
+ "ghcr.io/devcontainers/features/common-utils:2": {
10
+ "configureZshAsDefaultShell": true,
11
+ "installOhMyZsh": false,
12
+ "installOhMyZshConfig": false
13
+ },
11
14
  "ghcr.io/rails/devcontainer/features/activestorage": {},
12
15
  "ghcr.io/rails/devcontainer/features/postgres-client": {
13
- "version": "17"
16
+ "version": "18"
14
17
  },
15
- "ghcr.io/devcontainers/features/node:1": {},
16
- "ghcr.io/duduribeiro/devcontainer-features/tmux:1": {}
18
+ "ghcr.io/devcontainers/features/github-cli:1": {},
19
+ "ghcr.io/devcontainers/features/docker-in-docker:2": {
20
+ "moby": false
21
+ }
17
22
  },
18
23
  "mounts": [
19
- "source=/run/host-services/ssh-auth.sock,target=/ssh-agent,type=bind",
24
+ "source=/run/host-services/ssh-auth.sock,target=/ssh-agent,type=bind,consistency=cached",
20
25
  "source=${localEnv:HOME}/.gitconfig,target=/home/vscode/.gitconfig,type=bind,consistency=cached"
21
26
  ],
22
- "postCreateCommand": ".devcontainer/postCreate.sh",
23
27
  "postStartCommand": ".devcontainer/postStart.sh",
24
28
  "containerEnv": {
25
- "CAPYBARA_SERVER_PORT": "45678",
26
- "SELENIUM_URL": "http://host.docker.internal:4444/",
27
29
  "VISUAL": "vi",
28
- "DB_HOST": "postgres",
29
30
  "SSH_AUTH_SOCK": "/ssh-agent"
30
31
  },
31
- "build": {
32
- "args": {
33
- "RUBY_VERSION": "3.4.7"
34
- },
35
- "dockerfile": "./devcontainer/Dockerfile"
36
- }
32
+ "customizations": {},
33
+ "workspaceFolder": "/workspaces/mensa"
37
34
  }
@@ -0,0 +1,35 @@
1
+ name: mensa
2
+
3
+ services:
4
+ app:
5
+ image: ghcr.io/rails/devcontainer/images/ruby:4.0.5
6
+
7
+ volumes:
8
+ - ../..:/workspaces
9
+
10
+ # Overrides default command so things don't shut down after the process ends.
11
+ command: sleep infinity
12
+
13
+ depends_on:
14
+ - postgres
15
+ - redis
16
+
17
+ postgres:
18
+ image: postgres:18
19
+ restart: unless-stopped
20
+ volumes:
21
+ - postgres-data:/var/lib/postgresql/18/docker
22
+ environment:
23
+ POSTGRES_USER: postgres
24
+ POSTGRES_PASSWORD: postgres
25
+
26
+ redis:
27
+ image: valkey/valkey:8
28
+ restart: unless-stopped
29
+
30
+ selenium:
31
+ image: selenium/standalone-firefox
32
+ restart: unless-stopped
33
+
34
+ volumes:
35
+ postgres-data:
@@ -1,9 +1,13 @@
1
1
  #!/usr/bin/env bash
2
2
  set -e
3
3
 
4
- MISE=$(which mise)
5
- eval "$($MISE activate bash)"
4
+ MISE="$HOME/.local/bin/mise"
5
+ eval "$("$MISE" activate bash)"
6
+ "$MISE" trust
7
+ "$MISE" install
8
+ sudo chmod 666 /ssh-agent
6
9
 
7
- npm install
8
- bundle install
9
- rake db:prepare
10
+ "$MISE" exec -- npm install
11
+ "$MISE" exec -- bundle install
12
+ "$MISE" exec --cd test/dummy -- rake db:prepare
13
+ "$MISE" exec --cd test/dummy -- rake tailwindcss:config
data/.prettierrc.json ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "semi": false
3
+ }
data/.shipkit.yml ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ previous_version: 0.6.11
@@ -0,0 +1,8 @@
1
+ {
2
+ "i18n-ally-next.localesPaths": [
3
+ "config/locales/**"
4
+ ],
5
+ "i18n-ally-next.displayLanguage": "nl",
6
+ "i18n-ally-next.annotationMaxLength": 60,
7
+ "i18n-ally-next.keystyle": "nested",
8
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
3
+ // for the documentation about the tasks.json format
4
+ "version": "2.0.0",
5
+ "tasks": [
6
+ {
7
+ "label": "server",
8
+ "type": "shell",
9
+ "command": "if [ -f tmp/pids/server.pid ]; then pid=$(cat tmp/pids/server.pid); kill \"$pid\" 2>/dev/null || true; rm -f tmp/pids/server.pid; fi; mise exec -- bin/rails server -p 3000 -b 0.0.0.0",
10
+ "presentation": {
11
+ "reveal": "always",
12
+ "panel": "new"
13
+ },
14
+ "isBackground": true,
15
+ "problemMatcher": [],
16
+ "icon": {
17
+ "id": "server"
18
+ }
19
+ },
20
+ {
21
+ "label": "css",
22
+ "type": "shell",
23
+ "command": "cd test/dummy && mise exec -- bin/rails tailwindcss:config && mise exec -- bin/rails tailwindcss:watch",
24
+ "presentation": {
25
+ "reveal": "always",
26
+ "panel": "new"
27
+ },
28
+ "isBackground": true,
29
+ "problemMatcher": [],
30
+ "icon": {
31
+ "id": "json"
32
+ }
33
+ },
34
+ {
35
+ "label": "start all",
36
+ "dependsOn": [
37
+ "server",
38
+ "css"
39
+ ],
40
+ "problemMatcher": [],
41
+ "presentation": {
42
+ "reveal": "always",
43
+ "panel": "new"
44
+ }
45
+ }
46
+ ]
47
+ }
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.12
4
+
5
+ - Tables built with `params` (`table :name, params: {...}`) now work in filters,
6
+ views, batch actions and exports. The params are sent to these endpoints as
7
+ `params[...]` query parameters and stored on `Mensa::Export#config`, so
8
+ `Mensa::ExportJob` (and recurring exports) rebuild the table with them.
9
+ Host apps can remove their FiltersController, ExportsController and
10
+ Table::Component patches for this.
11
+ - The export list, badge and Turbo stream are scoped per table params, so
12
+ exports of e.g. two different queries on the same table are no longer mixed.
13
+ - Browser state (filters, search, order, column order, hidden columns) is
14
+ stored per table params. Unknown column names in `column_order`,
15
+ `hidden_columns`, `order` and `filters` are ignored instead of raising.
16
+ - The export completed callback is now `export_completed`, as documented in the
17
+ generated initializer. The old `export_complete` name still works. Unknown
18
+ callback names are logged as a warning.
19
+ - `selected_scope` only selects `id` when the relation has an `id` column.
20
+
3
21
  ## 0.2.4
4
22
 
5
23
  - Renames the data column on table_views to config
data/Gemfile CHANGED
@@ -22,3 +22,7 @@ group :development, :test do
22
22
  gem "ruby-lsp", require: false
23
23
  gem "ruby-lsp-rails", require: false
24
24
  end
25
+
26
+ source "https://rubygems.pkg.github.com/entdec" do
27
+ gem "shipkit"
28
+ end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mensa (0.6.9)
4
+ mensa (0.6.11)
5
5
  csv
6
6
  importmap-rails
7
7
  pagy (>= 43)
@@ -366,6 +366,11 @@ GEM
366
366
  yaml (0.4.0)
367
367
  zeitwerk (2.8.2)
368
368
 
369
+ GEM
370
+ remote: https://rubygems.pkg.github.com/entdec/
371
+ specs:
372
+ shipkit (0.1.2)
373
+
369
374
  PLATFORMS
370
375
  aarch64-linux-gnu
371
376
  aarch64-linux-musl
@@ -391,8 +396,9 @@ DEPENDENCIES
391
396
  ruby-lsp
392
397
  ruby-lsp-rails
393
398
  selenium-webdriver (~> 4.17)
399
+ shipkit!
394
400
  sprockets-rails
395
401
  standard
396
402
 
397
403
  BUNDLED WITH
398
- 2.6.2
404
+ 2.6.9
data/README.md CHANGED
@@ -186,12 +186,44 @@ Next you can run the generator to generate a table:
186
186
  $ rails g mensa:table:generate <model_name>
187
187
  ```
188
188
 
189
+ ### Table params
190
+
191
+ A table can be built with extra params, for example when its scope or columns
192
+ depend on a record:
193
+
194
+ ```erb
195
+ <%= table :query_results, params: {query_id: @query.id} %>
196
+ ```
197
+
198
+ They are available as `params` inside the table (e.g. `params[:query_id]`) and
199
+ are sent along whenever Mensa rebuilds the table: paging, filters, views, batch
200
+ actions and exports (including recurring exports, which store them on the
201
+ `Mensa::Export`). Exports and the state the browser remembers (filters, order,
202
+ columns) are kept per table *and* params.
203
+
189
204
  ### Exports
190
205
 
191
206
  Exporting is built into the table's control bar. Clicking the export button opens
192
207
  a dialog that lists the user's previous downloads and lets them request a new
193
208
  export (scope and CSV format).
194
209
 
210
+ #### Export callbacks
211
+
212
+ Configure callbacks in your Mensa initializer to act on exports, for example to
213
+ email the user once their download is ready:
214
+
215
+ ```ruby
216
+ Mensa.setup do |config|
217
+ config.callbacks = {
218
+ export_started: ->(export) {},
219
+ export_completed: ->(export) { ExportMailer.with(export: export).ready.deliver_later }
220
+ }
221
+ end
222
+ ```
223
+
224
+ `export_completed` was called `export_complete` before 0.6.12; that name still
225
+ works. Unknown callback names are logged as a warning.
226
+
195
227
  #### Repeating exports
196
228
 
197
229
  The user can choose to export a table on a regular basis (daily, weekly, monthly, quarterly, bi-yearly, yearly).
@@ -1,6 +1,7 @@
1
1
  <div class="relative"
2
2
  data-controller="mensa-column-customizer"
3
3
  data-mensa-column-customizer-table-name-value="<%= table.name %>"
4
+ data-mensa-column-customizer-storage-key-value="<%= table.storage_key %>"
4
5
  data-mensa-column-customizer-turbo-frame-id-value="<%= table.table_id %>"
5
6
  data-mensa-column-customizer-mensa-table-outlet="#table-<%= table.table_id %>">
6
7
  <button class="mensa-table__control_bar__button" type="button" data-action="click->mensa-column-customizer#toggle">
@@ -3,7 +3,7 @@ import ApplicationController from "mensa/controllers/application_controller";
3
3
  export default class ColumnCustomizerController extends ApplicationController {
4
4
  static outlets = ["mensa-table"];
5
5
  static targets = ["popover", "columnRow"];
6
- static values = { turboFrameId: String, tableName: String };
6
+ static values = { turboFrameId: String, tableName: String, storageKey: String };
7
7
 
8
8
  connect() {
9
9
  super.connect();
@@ -340,12 +340,17 @@ export default class ColumnCustomizerController extends ApplicationController {
340
340
  if (view) url.searchParams.set("table_view_id", view);
341
341
  }
342
342
 
343
+ // Tables built with different params keep separate browser state.
344
+ get storageName() {
345
+ return this.storageKeyValue || this.tableNameValue;
346
+ }
347
+
343
348
  get _columnOrderKey() {
344
- return `mensa:column_order:${this.tableNameValue}`;
349
+ return `mensa:column_order:${this.storageName}`;
345
350
  }
346
351
 
347
352
  get _hiddenColumnsKey() {
348
- return `mensa:hidden_columns:${this.tableNameValue}`;
353
+ return `mensa:hidden_columns:${this.storageName}`;
349
354
  }
350
355
 
351
356
  _writeStorage(key, value) {
@@ -45,13 +45,13 @@
45
45
  <% if table.exportable? %>
46
46
  <button class="mensa-table__control_bar__button relative" type="button" data-action="mensa-table#export">
47
47
  <i data-mensa-table-target="exportIcon" class="<%= Mensa.config.icons[:control_bar_export] %>"></i>
48
- <%= helpers.render partial: "mensa/exports/badge", locals: {table_name: table.name, user: table.current_user} %>
48
+ <%= helpers.render partial: "mensa/exports/badge", locals: {table_name: table.name, user: table.current_user, table_params: table.params} %>
49
49
  </button>
50
50
  <% end %>
51
51
  </div>
52
52
 
53
53
  <% if table.exportable? %>
54
- <%= helpers.turbo_stream_from Mensa::Export.stream_name(table.name, table.current_user) %>
54
+ <%= helpers.turbo_stream_from Mensa::Export.stream_name(table.name, table.current_user, params: table.params) %>
55
55
  <%= helpers.render partial: "mensa/exports/dialog", locals: {table: table} %>
56
56
  <% end %>
57
57
  </div>
@@ -4,6 +4,7 @@
4
4
  data-controller="mensa-filter-pill-list"
5
5
  data-mensa-table-target="filterList"
6
6
  data-mensa-filter-pill-list-table-name-value="<%= table.name %>"
7
+ data-mensa-filter-pill-list-storage-key-value="<%= table.storage_key %>"
7
8
  data-mensa-filter-pill-list-mensa-table-outlet=".mensa-table#table-<%= table.table_id %>"
8
9
  data-mensa-filter-pill-list-mensa-filter-pill-outlet=".mensa-filter-pill"
9
10
  data-mensa-filter-pill-list-mensa-add-filter-outlet="[data-controller=mensa-add-filter]">
@@ -8,6 +8,7 @@ export default class FilterPillListComponentController extends ApplicationContro
8
8
  static values = {
9
9
  supportsViews: Boolean,
10
10
  tableName: String,
11
+ storageKey: String,
11
12
  };
12
13
 
13
14
  connect() {
@@ -567,8 +568,8 @@ export default class FilterPillListComponentController extends ApplicationContro
567
568
  this.writeStorage(this.filtersStorageKey, null);
568
569
  this.writeStorage(this.searchStorageKey, null);
569
570
  this.writeStorage(this.orderStorageKey, null);
570
- this.writeStorage(`mensa:column_order:${this.tableNameValue}`, null);
571
- this.writeStorage(`mensa:hidden_columns:${this.tableNameValue}`, null);
571
+ this.writeStorage(`mensa:column_order:${this.storageName}`, null);
572
+ this.writeStorage(`mensa:hidden_columns:${this.storageName}`, null);
572
573
  }
573
574
 
574
575
  // Keep these for backward-compatibility with other controllers that look up
@@ -698,7 +699,7 @@ export default class FilterPillListComponentController extends ApplicationContro
698
699
  return (
699
700
  JSON.parse(
700
701
  this.readStorage(
701
- `mensa:column_order:${this.tableNameValue}`,
702
+ `mensa:column_order:${this.storageName}`,
702
703
  ),
703
704
  ) || []
704
705
  );
@@ -712,7 +713,7 @@ export default class FilterPillListComponentController extends ApplicationContro
712
713
  return (
713
714
  JSON.parse(
714
715
  this.readStorage(
715
- `mensa:hidden_columns:${this.tableNameValue}`,
716
+ `mensa:hidden_columns:${this.storageName}`,
716
717
  ),
717
718
  ) || []
718
719
  );
@@ -721,20 +722,25 @@ export default class FilterPillListComponentController extends ApplicationContro
721
722
  }
722
723
  }
723
724
 
725
+ // Tables built with different params keep separate browser state.
726
+ get storageName() {
727
+ return this.storageKeyValue || this.tableNameValue;
728
+ }
729
+
724
730
  get filtersStorageKey() {
725
- return `mensa:filters:${this.tableNameValue}`;
731
+ return `mensa:filters:${this.storageName}`;
726
732
  }
727
733
  get searchStorageKey() {
728
- return `mensa:search:${this.tableNameValue}`;
734
+ return `mensa:search:${this.storageName}`;
729
735
  }
730
736
  get viewStorageKey() {
731
- return `mensa:view:${this.tableNameValue}`;
737
+ return `mensa:view:${this.storageName}`;
732
738
  }
733
739
  get pageStorageKey() {
734
- return `mensa:page:${this.tableNameValue}`;
740
+ return `mensa:page:${this.storageName}`;
735
741
  }
736
742
  get orderStorageKey() {
737
- return `mensa:order:${this.tableNameValue}`;
743
+ return `mensa:order:${this.storageName}`;
738
744
  }
739
745
 
740
746
  get ourUrl() {
@@ -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["header_order_indicator#{column.sort_direction.to_s.present? ? "_#{column.sort_direction}" : ""}".to_sym] %>"></i>
5
+ <i class="<%= Mensa.config.icons[column.sort_indicator_icon_key.to_sym] %>"></i>
6
6
  <% end %>
7
7
  <% else %>
8
8
  <div class="container">
@@ -2,9 +2,9 @@
2
2
  id="table-<%= table.table_id %>"
3
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
- data-mensa-table-save-view-url-value="<%= helpers.mensa.table_views_path(table.name) %>"
6
- data-mensa-table-views-url-value="<%= helpers.mensa.table_views_path(table.name) %>"
7
- data-mensa-table-exports-url-value="<%= helpers.mensa.table_exports_path(table.name) %>"
5
+ data-mensa-table-save-view-url-value="<%= table.path_with_params(helpers.mensa.table_views_path(table.name)) %>"
6
+ data-mensa-table-views-url-value="<%= table.path_with_params(helpers.mensa.table_views_path(table.name)) %>"
7
+ data-mensa-table-exports-url-value="<%= table.path_with_params(helpers.mensa.table_exports_path(table.name)) %>"
8
8
  data-controller="mensa-table"
9
9
  data-action="click@document->mensa-table#saveDropdownOutsideHandler"
10
10
  data-mensa-table-mensa-filter-pill-outlet="[data-controller='mensa-filter-pill']"
@@ -255,7 +255,7 @@ export default class TableComponentController extends ApplicationController {
255
255
  const state = this.currentViewState();
256
256
  this.hideSaveReset();
257
257
 
258
- const response = await patch(`${this.saveViewUrlValue}/${viewId}`, {
258
+ const response = await patch(this.memberUrl(this.saveViewUrlValue, viewId), {
259
259
  body: JSON.stringify({
260
260
  query: state.query,
261
261
  filters: state.filters,
@@ -439,17 +439,21 @@ export default class TableComponentController extends ApplicationController {
439
439
  // --- View filter visibility persistence ---
440
440
 
441
441
  _viewFiltersStorageKey() {
442
- return `mensa:view-filters-visible:${this._tableName()}`;
442
+ return `mensa:view-filters-visible:${this._storageName()}`;
443
443
  }
444
444
 
445
- _tableName() {
445
+ _storageName() {
446
446
  if (this.hasMensaFilterPillListOutlet) {
447
- return this.mensaFilterPillListOutlet.tableNameValue;
447
+ return this.mensaFilterPillListOutlet.storageName;
448
448
  }
449
449
  const el = this.element.querySelector(
450
450
  "[data-mensa-filter-pill-list-table-name-value]",
451
451
  );
452
- return el?.dataset?.mensaFilterPillListTableNameValue || "";
452
+ return (
453
+ el?.dataset?.mensaFilterPillListStorageKeyValue ||
454
+ el?.dataset?.mensaFilterPillListTableNameValue ||
455
+ ""
456
+ );
453
457
  }
454
458
 
455
459
  _loadViewFiltersVisible() {
@@ -2,7 +2,7 @@
2
2
  <div class="overflow-y-auto relative"
3
3
  data-mensa-table-target="scrollContainer"
4
4
  data-controller="mensa-selection"
5
- data-mensa-selection-batch-url-value="<%= table.batch_actions? ? helpers.mensa.table_batch_actions_path(table.name) : "" %>">
5
+ data-mensa-selection-batch-url-value="<%= table.batch_actions? ? table.path_with_params(helpers.mensa.table_batch_actions_path(table.name)) : "" %>">
6
6
  <% if table.batch_actions? %>
7
7
  <div class="mensa-batch-bar hidden" data-mensa-selection-target="batchBar">
8
8
  <div class="mensa-batch-bar__content">
@@ -1,44 +1,44 @@
1
1
  .mensa-table {
2
- .paging {
3
- @apply flex items-center justify-between border-t border-gray-100 dark:border-gray-700 bg-white dark:bg-gray-800 px-4 py-3 sm:px-6 text-sm;
4
-
5
- .pagy {
6
- @apply isolate inline-flex -space-x-px text-gray-500 dark:text-gray-400;
7
-
8
- a:not(.gap) {
9
- @apply relative inline-flex items-center px-4 py-1.5 text-gray-500 dark:text-gray-400 bg-gray-100 dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:z-20 no-underline;
10
-
11
- &:first-child {
12
- border-top-left-radius: 4px;
13
- border-bottom-left-radius: 4px;
14
- }
15
-
16
- &:last-child {
17
- border-top-right-radius: 4px;
18
- border-bottom-right-radius: 4px;
19
- }
20
-
21
- &:hover {
22
- @apply bg-gray-300 dark:bg-gray-600;
23
- }
24
-
25
- &:not([href]) {
26
- /* disabled links */
27
- @apply bg-gray-100 dark:bg-gray-800 hover:bg-gray-100 hover:dark:bg-gray-800 text-gray-700 dark:text-gray-100 text-opacity-25 dark:text-opacity-50 cursor-default;
28
- }
29
-
30
- &.current {
31
- @apply z-10 bg-primary-200 dark:bg-primary-800 hover:bg-primary-200 hover:dark:bg-primary-400 text-opacity-75 dark:text-opacity-75 border-none;
32
- }
33
- }
34
-
35
- label {
36
- @apply inline-block whitespace-nowrap bg-gray-200 dark:bg-gray-600 rounded-lg px-4 py-1.5;
37
-
38
- input {
39
- @apply bg-gray-100 dark:bg-gray-700 border-none rounded-md;
2
+ .paging {
3
+ @apply flex items-center justify-between border-t border-gray-100 dark:border-gray-700 bg-white dark:bg-gray-800 px-4 py-3 sm:px-6 text-sm;
4
+
5
+ .pagy {
6
+ @apply isolate inline-flex -space-x-px text-gray-500 dark:text-gray-400;
7
+
8
+ a:not(.gap) {
9
+ @apply relative inline-flex items-center px-4 py-1.5 text-gray-500 dark:text-gray-400 bg-gray-100 dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:z-20 no-underline;
10
+
11
+ &:first-child {
12
+ border-top-left-radius: 4px;
13
+ border-bottom-left-radius: 4px;
14
+ }
15
+
16
+ &:last-child {
17
+ border-top-right-radius: 4px;
18
+ border-bottom-right-radius: 4px;
19
+ }
20
+
21
+ &:hover {
22
+ @apply bg-gray-300 dark:bg-gray-600;
23
+ }
24
+
25
+ &:not([href]) {
26
+ /* disabled links */
27
+ @apply bg-gray-100 dark:bg-gray-800 hover:bg-gray-100 hover:dark:bg-gray-800 text-gray-700 dark:text-gray-100 text-opacity-25 dark:text-opacity-50 cursor-default;
28
+ }
29
+
30
+ &[aria-current="page"] {
31
+ @apply z-10 bg-primary-200 dark:bg-primary-800 hover:bg-primary-200 hover:dark:bg-primary-800 text-gray-900 dark:text-white text-opacity-100 dark:text-opacity-100 border-none font-semibold;
32
+ }
33
+ }
34
+
35
+ label {
36
+ @apply inline-block whitespace-nowrap bg-gray-200 dark:bg-gray-600 rounded-lg px-4 py-1.5;
37
+
38
+ input {
39
+ @apply bg-gray-100 dark:bg-gray-700 border-none rounded-md;
40
+ }
41
+ }
40
42
  }
41
- }
42
43
  }
43
- }
44
44
  }
@@ -8,7 +8,7 @@
8
8
  data-controller="mensa-views"
9
9
  data-mensa-views-mensa-filter-pill-list-outlet="#mensa-filter-pill-list-<%= table.table_id %>"
10
10
  data-mensa-views-table-id-value="<%= table.table_id %>"
11
- data-mensa-views-views-url-value="<%= helpers.mensa.table_views_path(table.name) %>">
11
+ data-mensa-views-views-url-value="<%= table.path_with_params(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
14
  <i class="<%= Mensa.config.icons[:views_trigger] %> mensa-table__views__trigger-icon"></i>