mensa 0.2.5 → 0.2.6
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/.devcontainer/Dockerfile +6 -2
- data/.devcontainer/compose.yaml +1 -1
- data/.devcontainer/devcontainer.json +31 -29
- data/.devcontainer/postCreate.sh +8 -0
- data/.devcontainer/postStart.sh +9 -0
- data/.gitignore +3 -1
- data/.zed/tasks.json +12 -0
- data/Gemfile.lock +155 -153
- data/Procfile +1 -1
- data/README.md +85 -60
- data/app/assets/stylesheets/mensa/application.css +14 -11
- data/app/components/mensa/add_filter/component.css +110 -5
- data/app/components/mensa/add_filter/component.html.slim +10 -12
- data/app/components/mensa/add_filter/component.rb +7 -1
- data/app/components/mensa/add_filter/component_controller.js +697 -83
- data/app/components/mensa/cell/component.css +9 -0
- data/app/components/mensa/column_customizer/component.css +40 -0
- data/app/components/mensa/column_customizer/component.html.slim +14 -0
- data/app/components/mensa/column_customizer/component.rb +13 -0
- data/app/components/mensa/column_customizer/component_controller.js +383 -0
- data/app/components/mensa/control_bar/component.css +127 -4
- data/app/components/mensa/control_bar/component.html.slim +41 -14
- data/app/components/mensa/control_bar/component.rb +0 -4
- data/app/components/mensa/empty_state/component.css +20 -0
- data/app/components/mensa/empty_state/component.html.slim +7 -0
- data/app/components/mensa/empty_state/component.rb +18 -0
- data/app/components/mensa/filter_pill/component.css +23 -0
- data/app/components/mensa/filter_pill/component.html.slim +9 -6
- data/app/components/mensa/filter_pill/component.rb +9 -0
- data/app/components/mensa/filter_pill/component_controller.js +50 -10
- data/app/components/mensa/filter_pill_list/component.css +58 -9
- data/app/components/mensa/filter_pill_list/component.html.slim +11 -8
- data/app/components/mensa/filter_pill_list/component_controller.js +747 -48
- data/app/components/mensa/header/component.css +41 -43
- data/app/components/mensa/header/component.html.slim +7 -7
- data/app/components/mensa/row_action/component.html.slim +2 -2
- data/app/components/mensa/search/component.css +68 -9
- data/app/components/mensa/search/component.html.slim +19 -15
- data/app/components/mensa/search/component_controller.js +39 -49
- data/app/components/mensa/selection/component_controller.js +147 -0
- data/app/components/mensa/table/component.css +28 -0
- data/app/components/mensa/table/component.html.slim +9 -6
- data/app/components/mensa/table/component.rb +1 -0
- data/app/components/mensa/table/component_controller.js +524 -88
- data/app/components/mensa/table_row/component.css +6 -0
- data/app/components/mensa/table_row/component.html.slim +8 -3
- data/app/components/mensa/view/component.css +97 -29
- data/app/components/mensa/view/component.html.slim +23 -10
- data/app/components/mensa/view/component.rb +5 -0
- data/app/components/mensa/views/component.css +106 -13
- data/app/components/mensa/views/component.html.slim +51 -17
- data/app/components/mensa/views/component_controller.js +245 -20
- data/app/controllers/mensa/tables/batch_actions_controller.rb +24 -0
- data/app/controllers/mensa/tables/exports_controller.rb +96 -0
- data/app/controllers/mensa/tables/filters_controller.rb +4 -1
- data/app/controllers/mensa/tables/views_controller.rb +108 -0
- data/app/controllers/mensa/tables_controller.rb +3 -6
- data/app/helpers/mensa/application_helper.rb +4 -0
- data/app/javascript/mensa/application.js +2 -2
- data/app/javascript/mensa/controllers/index.js +13 -4
- data/app/jobs/mensa/export_job.rb +77 -84
- data/app/models/mensa/export.rb +93 -0
- data/app/tables/mensa/base.rb +103 -12
- data/app/tables/mensa/batch_action.rb +27 -0
- data/app/tables/mensa/cell.rb +15 -0
- data/app/tables/mensa/column.rb +15 -2
- data/app/tables/mensa/config/batch_dsl.rb +13 -0
- data/app/tables/mensa/config/column_dsl.rb +1 -0
- data/app/tables/mensa/config/filter_dsl.rb +4 -1
- data/app/tables/mensa/config/render_dsl.rb +1 -1
- data/app/tables/mensa/config/table_dsl.rb +12 -5
- data/app/tables/mensa/config/view_dsl.rb +2 -0
- data/app/tables/mensa/config_readers.rb +20 -1
- data/app/tables/mensa/filter.rb +86 -3
- data/app/tables/mensa/scope.rb +24 -12
- data/app/views/mensa/exports/_badge.html.slim +5 -0
- data/app/views/mensa/exports/_dialog.html.slim +42 -0
- data/app/views/mensa/exports/_list.html.slim +29 -0
- data/app/views/mensa/tables/filters/show.turbo_stream.slim +35 -8
- data/app/views/mensa/tables/views/create.turbo_stream.slim +11 -0
- data/app/views/mensa/tables/views/destroy.turbo_stream.slim +11 -0
- data/app/views/mensa/tables/views/update.turbo_stream.slim +11 -0
- data/config/locales/en.yml +44 -0
- data/config/locales/nl.yml +45 -0
- data/config/routes.rb +7 -0
- data/db/migrate/20260604120000_create_mensa_exports.rb +25 -0
- data/docs/columns.png +0 -0
- data/docs/export.png +0 -0
- data/docs/filters.png +0 -0
- data/docs/table.png +0 -0
- data/lib/mensa/configuration.rb +33 -12
- data/lib/mensa/engine.rb +7 -2
- data/lib/mensa/version.rb +1 -1
- data/mensa.gemspec +2 -1
- data/mise.toml +8 -0
- data/package-lock.json +0 -7
- metadata +50 -8
data/Procfile
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
web: bin/rails server -p 3000 -b 0.0.0.0
|
|
2
|
-
css: cd test/dummy && bin/rails tailwindcss:watch
|
|
2
|
+
css: cd test/dummy && bin/rails tailwindcss:config && bin/rails tailwindcss:watch
|
data/README.md
CHANGED
|
@@ -4,6 +4,8 @@ Fast and awesome tables, with pagination, sorting, filtering and custom views.
|
|
|
4
4
|
|
|
5
5
|

|
|
6
6
|

|
|
7
|
+

|
|
8
|
+

|
|
7
9
|
|
|
8
10
|
Features:
|
|
9
11
|
|
|
@@ -13,86 +15,105 @@ Features:
|
|
|
13
15
|
- [x] tables without headers (and without most of the above)
|
|
14
16
|
- [x] filtering of multiple columns
|
|
15
17
|
- [X] Hide filter icon in case there are no filters
|
|
18
|
+
- [X] column ordering
|
|
19
|
+
- [X] editing of existing filters
|
|
20
|
+
- [X] view selection and exports per view
|
|
21
|
+
- [X] multiple selection of rows and batch processing
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
- [ ]
|
|
19
|
-
- [ ]
|
|
20
|
-
- [ ] view selection and exports per view
|
|
21
|
-
- [ ] multiple selection of rows
|
|
23
|
+
Todo/Fixme:
|
|
24
|
+
- [ ] exports can be mailed - daily/weekly/monthly/quarterly/bi-yearly/yearly (time configurable)
|
|
25
|
+
- [ ] Search only works on table text columns
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
Nice to haves:
|
|
24
28
|
|
|
25
29
|
- [ ] group by
|
|
26
30
|
- [ ] sum/max/min
|
|
27
31
|
- [ ] tables backed by arrays (of ActiveModel)
|
|
28
32
|
|
|
29
|
-
Todo/Fixme:
|
|
30
|
-
|
|
31
|
-
- [ ] Search only works on table text columns
|
|
32
|
-
|
|
33
33
|
## Usage
|
|
34
34
|
|
|
35
35
|
Add tables in your app/tables folder, inheriting from ApplicationTable.
|
|
36
36
|
This in turn should inherit from Mensa::Base.
|
|
37
37
|
|
|
38
|
+
You can give columns an arbitrary name, it can match the database column, translations will be taken from `activerecord.attributes.<model>.<column>`:
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
en:
|
|
42
|
+
activerecord:
|
|
43
|
+
attributes:
|
|
44
|
+
user:
|
|
45
|
+
name: Full name
|
|
46
|
+
```
|
|
47
|
+
|
|
38
48
|
```ruby
|
|
39
49
|
class UserTable < ApplicationTable
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
scope -> { where(name: ...) }
|
|
54
|
-
end
|
|
50
|
+
model User # implicit from name
|
|
51
|
+
|
|
52
|
+
order name: :desc
|
|
53
|
+
|
|
54
|
+
column(:name) do
|
|
55
|
+
attribute :name # Optional, we can deduct this from the column name
|
|
56
|
+
sortable true
|
|
57
|
+
sanitize true
|
|
58
|
+
internal false
|
|
59
|
+
visible true
|
|
60
|
+
filter do
|
|
61
|
+
collection -> { }
|
|
62
|
+
scope -> { where(name: ...) }
|
|
55
63
|
end
|
|
64
|
+
operators [:is, :isnt] # Optional, mensa tries to deduce this from the column information
|
|
65
|
+
end
|
|
56
66
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
67
|
+
column(:nr_of_roles) do
|
|
68
|
+
attribute "roles_count" # We use a database column here
|
|
69
|
+
end
|
|
60
70
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
71
|
+
# You can add one or more actions to a row
|
|
72
|
+
action :delete do
|
|
73
|
+
title "Delete row"
|
|
74
|
+
link { |user| user_path(user) }
|
|
75
|
+
icon "fa-regular fa-trash"
|
|
76
|
+
link_attributes data: {"turbo-confirm": "Are you sure you want to delete the user?", "turbo-method": :delete}
|
|
77
|
+
show ->(user) { true }
|
|
78
|
+
end
|
|
69
79
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
link { |user| edit_user_path(user) }
|
|
81
|
+
supports_views true # This table supports custom views
|
|
82
|
+
show_header true
|
|
83
|
+
view_columns_ordering false # Disabled for now
|
|
84
|
+
|
|
85
|
+
# Add system views
|
|
86
|
+
# Mensa will always create a systemview (:default) with name 'All' showing all records.
|
|
87
|
+
# If you want to rename it, for example because you don't show all records in your default scope, add it and give it a name like below.
|
|
88
|
+
view :default do
|
|
89
|
+
name "Default"
|
|
90
|
+
description "Some descriptive text"
|
|
91
|
+
end
|
|
92
|
+
view :concept do
|
|
93
|
+
name "Concept"
|
|
94
|
+
filter :state do
|
|
95
|
+
operator :is
|
|
96
|
+
value "concept"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
batch :confirm do
|
|
101
|
+
description "Confirm users"
|
|
102
|
+
process do |records|
|
|
103
|
+
ConfirmUsersJob.perform_later(records.to_a)
|
|
86
104
|
end
|
|
87
105
|
end
|
|
106
|
+
|
|
107
|
+
scope do
|
|
108
|
+
User.all
|
|
109
|
+
end
|
|
88
110
|
end
|
|
89
111
|
```
|
|
90
112
|
|
|
91
|
-
Currently mensa depends on satis, but that is something we might remove in a future version.
|
|
92
113
|
You can show your tables on the page using the following:
|
|
93
114
|
|
|
94
115
|
```slim
|
|
95
|
-
=
|
|
116
|
+
= table :users
|
|
96
117
|
```
|
|
97
118
|
|
|
98
119
|
#### Custom views
|
|
@@ -105,13 +126,12 @@ Initial support for custom-views is there, but pretty rudimentary:
|
|
|
105
126
|
|
|
106
127
|
### Fast
|
|
107
128
|
|
|
108
|
-
Mensa selects only the data it needs, based on the columns. Sometimes it needs additional columns to do it's work, but you don't want them displayed.
|
|
109
|
-
This can be done by adding `internal true` to the column definition, or shorter: use `internal` instead
|
|
129
|
+
Mensa selects only the data it needs, based on the columns. Sometimes it needs additional columns to do it's work, but you don't want them displayed. This can be done by adding `internal true` to the column definition, or shorter: use `internal` instead. If your table scope joins an association, Mensa also auto-adds the foreign key column as internal when it is needed.
|
|
110
130
|
|
|
111
131
|
```ruby
|
|
112
|
-
internal :born_on
|
|
132
|
+
internal :born_on
|
|
113
133
|
column :age do
|
|
114
|
-
attribute "EXTRACT(YEAR FROM AGE(born_on))::int"
|
|
134
|
+
attribute "EXTRACT(YEAR FROM AGE(born_on))::int" # here born_on is used internally, so we ned to select is
|
|
115
135
|
end
|
|
116
136
|
```
|
|
117
137
|
|
|
@@ -140,7 +160,7 @@ If you're not using devcontainers:
|
|
|
140
160
|
|
|
141
161
|
Using the following in your view will render Mensa::Table::Component
|
|
142
162
|
```slim
|
|
143
|
-
=
|
|
163
|
+
= table :users
|
|
144
164
|
```
|
|
145
165
|
|
|
146
166
|
The Mensa::Table::Component will render:
|
|
@@ -153,7 +173,6 @@ The Mensa::Table::Component will render:
|
|
|
153
173
|
- Mensa::ControlBar::Component
|
|
154
174
|
- search icon
|
|
155
175
|
- filter icon
|
|
156
|
-
- condensed toggle
|
|
157
176
|
- export icon
|
|
158
177
|
- turbo-frame with the actual table you see (which is rendered by Mensa::View::Component)
|
|
159
178
|
|
|
@@ -183,6 +202,12 @@ Always use `bundle` to install the gem. Next use the install generator to instal
|
|
|
183
202
|
$ bin/rails g mensa:install
|
|
184
203
|
```
|
|
185
204
|
|
|
205
|
+
### Exports
|
|
206
|
+
|
|
207
|
+
Exporting is built into the table's control bar. Clicking the export button opens
|
|
208
|
+
a dialog that lists the user's previous downloads and lets them request a new
|
|
209
|
+
export (scope and CSV format).
|
|
210
|
+
|
|
186
211
|
## Contributing
|
|
187
212
|
|
|
188
213
|
```
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
@import
|
|
2
|
-
@import
|
|
3
|
-
@import
|
|
4
|
-
@import
|
|
5
|
-
@import
|
|
6
|
-
@import
|
|
7
|
-
@import
|
|
8
|
-
@import
|
|
9
|
-
@import
|
|
10
|
-
@import
|
|
11
|
-
@import
|
|
1
|
+
@import "../../../components/mensa/add_filter/component.css";
|
|
2
|
+
@import "../../../components/mensa/column_customizer/component.css";
|
|
3
|
+
@import "../../../components/mensa/cell/component.css";
|
|
4
|
+
@import "../../../components/mensa/control_bar/component.css";
|
|
5
|
+
@import "../../../components/mensa/empty_state/component.css";
|
|
6
|
+
@import "../../../components/mensa/filter_pill/component.css";
|
|
7
|
+
@import "../../../components/mensa/filter_pill_list/component.css";
|
|
8
|
+
@import "../../../components/mensa/header/component.css";
|
|
9
|
+
@import "../../../components/mensa/row_action/component.css";
|
|
10
|
+
@import "../../../components/mensa/search/component.css";
|
|
11
|
+
@import "../../../components/mensa/table/component.css";
|
|
12
|
+
@import "../../../components/mensa/table_row/component.css";
|
|
13
|
+
@import "../../../components/mensa/view/component.css";
|
|
14
|
+
@import "../../../components/mensa/views/component.css";
|
|
@@ -1,13 +1,118 @@
|
|
|
1
|
-
.
|
|
1
|
+
.mensa-table {
|
|
2
2
|
&__add_filter {
|
|
3
|
-
@apply relative;
|
|
3
|
+
@apply relative inline-flex items-center;
|
|
4
|
+
|
|
5
|
+
&__trigger {
|
|
6
|
+
/* Hidden by default; shown via sibling selector when filter pills exist */
|
|
7
|
+
@apply hidden items-center justify-center w-5 h-5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 cursor-pointer transition-colors text-sm;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
&__enter-hint {
|
|
11
|
+
display: none;
|
|
12
|
+
@apply text-xs text-gray-400 bg-gray-100 dark:bg-gray-700 rounded px-1.5 py-0.5 whitespace-nowrap;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
&__checkbox {
|
|
16
|
+
@apply h-4 w-4 flex-none rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 inline-block;
|
|
17
|
+
|
|
18
|
+
&--checked {
|
|
19
|
+
@apply bg-gray-900 border-gray-900 dark:bg-white dark:border-white;
|
|
20
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='white'%3E%3Cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3E%3C/svg%3E");
|
|
21
|
+
background-size: 100% 100%;
|
|
22
|
+
background-repeat: no-repeat;
|
|
23
|
+
background-position: center;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
4
26
|
|
|
5
27
|
&__popover_container {
|
|
6
|
-
@apply p-
|
|
28
|
+
@apply p-4 fixed z-50 w-72 rounded-lg bg-white dark:bg-gray-800 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm;
|
|
29
|
+
|
|
30
|
+
&__heading {
|
|
31
|
+
@apply font-semibold text-gray-900 dark:text-gray-100 mb-2;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
input&__input {
|
|
35
|
+
@apply w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm text-gray-900 dark:text-gray-100 shadow-sm placeholder:text-gray-400 focus:border-primary-500 focus:ring-2 focus:ring-primary-500 focus:outline-none;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&__separator {
|
|
39
|
+
@apply border-t border-gray-200 dark:border-gray-600 my-3 -mx-4;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&__values {
|
|
43
|
+
@apply mb-2 max-h-[20rem] overflow-y-scroll;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
&__value {
|
|
47
|
+
@apply flex items-center gap-2 py-1.5 px-2 rounded-md cursor-pointer text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 select-none;
|
|
48
|
+
|
|
49
|
+
&__check {
|
|
50
|
+
@apply w-4 flex-none inline-flex items-center justify-center text-xs;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&__operators {
|
|
55
|
+
@apply mb-2;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&__operator {
|
|
59
|
+
@apply flex items-center gap-2 py-1.5 rounded-md cursor-pointer text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 select-none;
|
|
60
|
+
|
|
61
|
+
&__check {
|
|
62
|
+
@apply w-4 flex-none inline-flex items-center justify-center text-xs;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
7
65
|
|
|
8
66
|
&__clear {
|
|
9
|
-
@apply text-gray-
|
|
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;
|
|
10
68
|
}
|
|
11
69
|
}
|
|
12
70
|
}
|
|
13
|
-
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Show enter hint on hover or keyboard highlight — covers column list and value popover */
|
|
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 {
|
|
76
|
+
display: inline-flex;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Keyboard highlight background — mirrors the hover style */
|
|
80
|
+
.mensa-table__add_filter li.highlighted {
|
|
81
|
+
@apply bg-gray-100 dark:bg-gray-700;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Show + when user-added (non-view-filter) committed pills are present.
|
|
85
|
+
User pills are always visible, so no ancestor visibility check needed. */
|
|
86
|
+
.mensa-table__search-bar__pills-area:has(
|
|
87
|
+
.mensa-filter-pill:not([data-view-filter="true"]):not(
|
|
88
|
+
.mensa-filter-pill--pending
|
|
89
|
+
)
|
|
90
|
+
):not(:has(.mensa-filter-pill--pending))
|
|
91
|
+
.mensa-table__add_filter
|
|
92
|
+
.mensa-table__add_filter__trigger {
|
|
93
|
+
@apply inline-flex;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Show + when view-defined filter pills are present AND currently visible
|
|
97
|
+
(eye toggle on). Hidden view filters must not reveal the + button. */
|
|
98
|
+
.mensa-table:not(.mensa-table--view-filters-hidden)
|
|
99
|
+
.mensa-table__search-bar__pills-area:has(
|
|
100
|
+
.mensa-filter-pill[data-view-filter="true"]
|
|
101
|
+
):not(:has(.mensa-filter-pill--pending))
|
|
102
|
+
.mensa-table__add_filter
|
|
103
|
+
.mensa-table__add_filter__trigger {
|
|
104
|
+
@apply inline-flex;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* While a filter is being configured, collapse the add-filter wrapper so it
|
|
108
|
+
doesn't create an extra flex gap between the pending pill and the search input.
|
|
109
|
+
The value popover inside is position:fixed so display:contents doesn't affect it. */
|
|
110
|
+
.mensa-table__search-bar__pills-area:has(.mensa-filter-pill--pending)
|
|
111
|
+
.mensa-table__add_filter {
|
|
112
|
+
display: contents;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* Pending pill while the value popover is open — rounded on both sides (no remove button) */
|
|
116
|
+
.mensa-filter-pill--pending .mensa-filter-pill__chip {
|
|
117
|
+
@apply rounded-md opacity-70;
|
|
118
|
+
}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
.
|
|
2
|
-
button.
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
span.pointer-events-none.absolute.inset-y-0.right-0.flex.items-center.pr-2
|
|
6
|
-
div class=Mensa.config.icons[:filters_add_filter]
|
|
7
|
-
|
|
8
|
-
ul.hidden.absolute.z-10.mt-1.max-h-60.w-64.overflow-auto.rounded-md.bg-white.dark:bg-gray-800.py-1.text-base.shadow-lg.ring-1.ring-black.ring-opacity-5.focus:outline-none.sm:text-sm data-mensa-add-filter-target="filterList"
|
|
1
|
+
.mensa-table__add_filter data-controller="mensa-add-filter" data-mensa-add-filter-mensa-filter-pill-list-outlet="#mensa-filter-pill-list-#{table.table_id}" data-mensa-add-filter-operator-labels-value=operator_labels.to_json
|
|
2
|
+
button.mensa-table__add_filter__trigger[type="button" title=t("mensa.add_filter.add", default: "Add filter") data-action="mensa-add-filter#openAllColumns"]
|
|
3
|
+
i.fa-solid.fa-circle-plus
|
|
4
|
+
ul.hidden.fixed.z-50.max-h-96.overflow-auto.rounded-lg.bg-white.dark:bg-gray-800.p-2.text-base.shadow-lg.ring-1.ring-black.ring-opacity-5.focus:outline-none.sm:text-sm data-mensa-add-filter-target="filterList"
|
|
9
5
|
- table.columns.select(&:filter?).each do |column|
|
|
10
|
-
li
|
|
11
|
-
.label.font-normal.block.truncate
|
|
6
|
+
li.text-gray-900.dark:text-gray-300.hover:bg-gray-100.dark:hover:bg-gray-700.relative.cursor-default.select-none.rounded-md.py-2.px-3.flex.items-center.gap-2 data-mensa-add-filter-target="filterListItem" data-action="click->mensa-add-filter#selectColumn mouseenter->mensa-add-filter#columnItemHovered" data-filter-column-name=column.name
|
|
7
|
+
.label.font-normal.block.truncate.flex-1
|
|
12
8
|
= column.human_name
|
|
13
|
-
.check.hidden.text-primary-600.
|
|
9
|
+
.check.hidden.text-primary-600.flex.items-center
|
|
14
10
|
.fal.fa-check
|
|
11
|
+
span.mensa-table__add_filter__enter-hint
|
|
12
|
+
| ↵ Enter
|
|
15
13
|
|
|
16
|
-
div.hidden.
|
|
14
|
+
div.hidden.mensa-table__add_filter__popover_container data-mensa-add-filter-target="valuePopover" id="mensa-filter-pill-value-#{SecureRandom.base36}"
|
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
module Mensa
|
|
4
4
|
module AddFilter
|
|
5
|
-
class Component <
|
|
5
|
+
class Component < Mensa::ApplicationComponent
|
|
6
6
|
attr_reader :table
|
|
7
7
|
|
|
8
8
|
def initialize(table:)
|
|
9
9
|
@table = table
|
|
10
10
|
end
|
|
11
|
+
|
|
12
|
+
def operator_labels
|
|
13
|
+
Mensa::Filter.OPERATORS.to_h do |name, label, _requires_value|
|
|
14
|
+
[name, label]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
11
17
|
end
|
|
12
18
|
end
|
|
13
19
|
end
|