mensa 0.1.0 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/gem-push.yml +11 -0
- data/.gitignore +12 -0
- data/Gemfile +10 -8
- data/Gemfile.lock +299 -0
- data/MIT-LICENSE +20 -0
- data/Procfile +2 -0
- data/README.md +76 -18
- data/Rakefile +5 -13
- data/app/assets/config/mensa_manifest.js +5 -0
- data/app/assets/images/mensa/.keep +0 -0
- data/app/assets/stylesheets/mensa/application.css +11 -0
- data/app/components/mensa/add_filter/component.css +13 -0
- data/app/components/mensa/add_filter/component.html.slim +16 -0
- data/app/components/mensa/add_filter/component.rb +13 -0
- data/app/components/mensa/add_filter/component_controller.js +84 -0
- data/app/components/mensa/application_component.rb +12 -0
- data/app/components/mensa/cell/component.css +0 -0
- data/app/components/mensa/cell/component.html.slim +1 -0
- data/app/components/mensa/cell/component.rb +15 -0
- data/app/components/mensa/control_bar/component.css +5 -0
- data/app/components/mensa/control_bar/component.html.slim +15 -0
- data/app/components/mensa/control_bar/component.rb +21 -0
- data/app/components/mensa/filters/component.css +14 -0
- data/app/components/mensa/filters/component.html.slim +14 -0
- data/app/components/mensa/filters/component.rb +13 -0
- data/app/components/mensa/filters/component_controller.js +14 -0
- data/app/components/mensa/header/component.css +54 -0
- data/app/components/mensa/header/component.html.slim +8 -0
- data/app/components/mensa/header/component.rb +19 -0
- data/app/components/mensa/row_action/component.css +0 -0
- data/app/components/mensa/row_action/component.html.slim +6 -0
- data/app/components/mensa/row_action/component.rb +19 -0
- data/app/components/mensa/search/component.css +13 -0
- data/app/components/mensa/search/component.html.slim +17 -0
- data/app/components/mensa/search/component.rb +13 -0
- data/app/components/mensa/search/component_controller.js +62 -0
- data/app/components/mensa/table/component.css +0 -0
- data/app/components/mensa/table/component.html.slim +7 -0
- data/app/components/mensa/table/component.rb +16 -0
- data/app/components/mensa/table/component_controller.js +72 -0
- data/app/components/mensa/table_row/component.css +0 -0
- data/app/components/mensa/table_row/component.html.slim +6 -0
- data/app/components/mensa/table_row/component.rb +19 -0
- data/app/components/mensa/view/component.css +82 -0
- data/app/components/mensa/view/component.html.slim +17 -0
- data/app/components/mensa/view/component.rb +16 -0
- data/app/components/mensa/views/component.css +13 -0
- data/app/components/mensa/views/component.html.slim +18 -0
- data/app/components/mensa/views/component.rb +14 -0
- data/app/controllers/concerns/.keep +0 -0
- data/app/controllers/mensa/application_controller.rb +4 -0
- data/app/controllers/mensa/tables/filters_controller.rb +29 -0
- data/app/controllers/mensa/tables_controller.rb +37 -0
- data/app/helpers/mensa/application_helper.rb +5 -0
- data/app/helpers/mensa/tables_helper.rb +5 -0
- data/app/javascript/mensa/application.js +3 -0
- data/app/javascript/mensa/controllers/alert_controller.js +7 -0
- data/app/javascript/mensa/controllers/application.js +8 -0
- data/app/javascript/mensa/controllers/application_controller.js +57 -0
- data/app/javascript/mensa/controllers/index.js +24 -0
- data/app/jobs/mensa/application_job.rb +7 -0
- data/app/jobs/mensa/export_job.rb +91 -0
- data/app/models/concerns/.keep +0 -0
- data/app/models/mensa/application_record.rb +5 -0
- data/app/models/mensa/table_view.rb +5 -0
- data/app/tables/mensa/action.rb +26 -0
- data/app/tables/mensa/base.rb +103 -0
- data/app/tables/mensa/cell.rb +50 -0
- data/app/tables/mensa/column.rb +85 -0
- data/app/tables/mensa/config/action_dsl.rb +12 -0
- data/app/tables/mensa/config/column_dsl.rb +23 -0
- data/app/tables/mensa/config/dsl_logic.rb +90 -0
- data/app/tables/mensa/config/filter_dsl.rb +8 -0
- data/app/tables/mensa/config/render_dsl.rb +8 -0
- data/app/tables/mensa/config/table_dsl.rb +71 -0
- data/app/tables/mensa/config_readers.rb +13 -0
- data/app/tables/mensa/filter.rb +31 -0
- data/app/tables/mensa/row.rb +36 -0
- data/app/tables/mensa/scope.rb +99 -0
- data/app/views/layouts/mensa/application.html.slim +11 -0
- data/app/views/mensa/tables/filters/show.turbo_stream.slim +8 -0
- data/app/views/mensa/tables/index.html.slim +93 -0
- data/app/views/mensa/tables/show.html.slim +5 -0
- data/app/views/mensa/tables/show.turbo_stream.slim +5 -0
- data/bin/importmap +4 -0
- data/bin/rails +14 -0
- data/config/importmap.rb +8 -0
- data/config/locales/en.yml +8 -0
- data/config/locales/nl.yml +11 -0
- data/config/routes.rb +7 -0
- data/db/migrate/20240201184752_create_mensa_table_views.rb +15 -0
- data/lib/generators/mensa/install_generator.rb +24 -0
- data/lib/generators/mensa/tailwind_config_generator.rb +24 -0
- data/lib/generators/mensa/templates/config/initializers/mensa.rb +22 -0
- data/lib/mensa/configuration.rb +90 -0
- data/lib/mensa/engine.rb +37 -0
- data/lib/mensa/version.rb +1 -3
- data/lib/mensa.rb +24 -5
- data/lib/tasks/mensa_tasks.rake +13 -0
- data/mensa.gemspec +42 -0
- data/package.json +10 -0
- data/vendor/javascript/@rails--request.js.js +2 -0
- data/yarn.lock +837 -0
- metadata +245 -18
- data/.rubocop.yml +0 -13
- data/CHANGELOG.md +0 -5
- data/CODE_OF_CONDUCT.md +0 -84
- data/LICENSE.txt +0 -21
- data/sig/mensa.rbs +0 -4
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mensa
|
4
|
+
class ApplicationComponent < ViewComponent::Base
|
5
|
+
include ViewComponent::Slotable
|
6
|
+
include ActionView::Helpers::TranslationHelper
|
7
|
+
include Satis::Concerns::ContextualTranslations
|
8
|
+
include Mensa::ApplicationHelper
|
9
|
+
|
10
|
+
attr_accessor :original_view_context
|
11
|
+
end
|
12
|
+
end
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
td = cell.render(:html)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mensa
|
4
|
+
class Cell
|
5
|
+
class Component < ::Mensa::ApplicationComponent
|
6
|
+
with_collection_parameter :column
|
7
|
+
|
8
|
+
attr_reader :cell
|
9
|
+
|
10
|
+
def initialize(row:, column:)
|
11
|
+
@cell = ::Mensa::Cell.new(row: row, column: column)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
.mensa-table__control_bar data-mensa-table-target="controlBar"
|
2
|
+
.flex.space-x-2.justify-right
|
3
|
+
button.flex.justify-right.cursor-pointer.py-1.5.h-full.text-gray-400 class="#{table.supports_views? ? 'w-8' : 'w-4'}" data-action="mensa-table#openFiltersAndSearch"
|
4
|
+
- if table.supports_views?
|
5
|
+
i class=Mensa.config.icons[:control_bar_search]
|
6
|
+
i class=Mensa.config.icons[:control_bar_filter]
|
7
|
+
/- if view_columns_sorting?
|
8
|
+
button.cursor-pointer.w-6.h-full.text-gray-400
|
9
|
+
i class=Mensa.config.icons[:control_bar_edit]
|
10
|
+
- if view_condensed_toggle?
|
11
|
+
button.cursor-pointer.w-6.h-full.text-gray-400 data-action="mensa-table#condenseExpand"
|
12
|
+
i data-mensa-table-target="condenseExpandIcon" class=Mensa.config.icons[:control_bar_compress]
|
13
|
+
- if table.config[:render]&.key?(:xlsx)
|
14
|
+
button.cursor-pointer.w-6.h-full.text-gray-400 data-action="mensa-table#export"
|
15
|
+
i data-mensa-table-target="exportIcon" class=Mensa.config.icons[:control_bar_export]
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mensa
|
4
|
+
module ControlBar
|
5
|
+
class Component < ::Mensa::ApplicationComponent
|
6
|
+
attr_reader :table
|
7
|
+
|
8
|
+
def initialize(table:)
|
9
|
+
@table = table
|
10
|
+
end
|
11
|
+
|
12
|
+
def view_columns_sorting?
|
13
|
+
table.view_columns_sorting?
|
14
|
+
end
|
15
|
+
|
16
|
+
def view_condensed_toggle?
|
17
|
+
table.view_condensed_toggle?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
.mensa-table {
|
2
|
+
&__filters {
|
3
|
+
@apply p-2 shadow-lg border-b dark:bg-gray-700 dark:border-gray-600;
|
4
|
+
|
5
|
+
a.filter {
|
6
|
+
@apply bg-gray-200 dark:bg-gray-500 hover:bg-gray-400 text-gray-800 rounded-md px-3 py-1.5 text-sm;
|
7
|
+
}
|
8
|
+
|
9
|
+
a.filter.selected {
|
10
|
+
@apply bg-gray-100 text-gray-600 dark:text-gray-400 hover:text-gray-800 hover:bg-gray-200;
|
11
|
+
}
|
12
|
+
|
13
|
+
}
|
14
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
.mensa-table__filters.hidden data-mensa-table-target="filters"
|
2
|
+
.block
|
3
|
+
nav
|
4
|
+
.flex.space-x-2.overflow-none.whitespace-nowrap.scroll-p-0[aria-label="Tabs"]
|
5
|
+
/ existing filters first
|
6
|
+
- table.active_filters.each do |filter|
|
7
|
+
.relative
|
8
|
+
button.relative.w-full.cursor-default.rounded-md.bg-white.dark:bg-gray-800.py-1.5.pl-3.text-left.text-gray-900.dark:text-gray-400.shadow-sm.ring-1.ring-inset.ring-gray-300.dark:ring-gray-600.focus:outline-none.focus:ring-2.focus:ring-primary-600.sm:text-sm.sm:leading-6[type="button" aria-haspopup="listbox" aria-expanded="true" aria-labelledby="listbox-label"]
|
9
|
+
span.block.truncate.pr-6
|
10
|
+
= filter
|
11
|
+
span.pointer-events-none.absolute.inset-y-0.right-0.flex.items-center.pr-2
|
12
|
+
.fal.fa-angle-down
|
13
|
+
|
14
|
+
= render Mensa::AddFilter::Component.new(table: table)
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import ApplicationController from 'mensa/controllers/application_controller'
|
2
|
+
|
3
|
+
export default class FiltersComponentController extends ApplicationController {
|
4
|
+
static targets = [
|
5
|
+
'list',
|
6
|
+
]
|
7
|
+
static values = {
|
8
|
+
supportsViews: Boolean
|
9
|
+
}
|
10
|
+
|
11
|
+
connect () {
|
12
|
+
super.connect()
|
13
|
+
}
|
14
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
.mensa-table {
|
2
|
+
thead {
|
3
|
+
tr {
|
4
|
+
@apply divide-x divide-gray-200 dark:divide-gray-600
|
5
|
+
}
|
6
|
+
|
7
|
+
th {
|
8
|
+
@apply top-0 z-10 py-3.5 pl-6 pr-6 px-6 align-bottom text-left text-xs font-medium text-gray-500 uppercase border-b border-gray-200 dark:border-gray-600;
|
9
|
+
|
10
|
+
.container {
|
11
|
+
@apply h-4 flex items-center;
|
12
|
+
}
|
13
|
+
|
14
|
+
.title {
|
15
|
+
@apply w-full pr-3;
|
16
|
+
}
|
17
|
+
|
18
|
+
.actions {
|
19
|
+
@apply pr-3 flex items-center;
|
20
|
+
|
21
|
+
.action {
|
22
|
+
@apply cursor-pointer;
|
23
|
+
/*.fa-arrow-down-arrow-up {*/
|
24
|
+
@apply opacity-0;
|
25
|
+
/*}*/
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
th:hover {
|
31
|
+
.actions {
|
32
|
+
.action {
|
33
|
+
/*.fa-arrow-down-arrow-up {*/
|
34
|
+
@apply opacity-100;
|
35
|
+
/*}*/
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
&__condensed {
|
41
|
+
thead {
|
42
|
+
th {
|
43
|
+
@apply whitespace-nowrap py-2 pl-4 pr-3 px-0;
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
&__column_edit {
|
48
|
+
thead {
|
49
|
+
th {
|
50
|
+
@apply cursor-grab;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
th
|
2
|
+
.container
|
3
|
+
.title = column.human_name
|
4
|
+
.actions
|
5
|
+
- if column.sortable?
|
6
|
+
.action
|
7
|
+
= link_to table.path(order: {column.name => column.next_sort_direction}, turbo_frame_id: table.table_id), "data-turbo-frame": "_self"
|
8
|
+
i class=Mensa.config.icons["order_indicator#{column.sort_direction.to_s.present? ? "_#{column.sort_direction.to_s}" : ""}".to_sym]
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mensa
|
4
|
+
module Header
|
5
|
+
class Component < ::Mensa::ApplicationComponent
|
6
|
+
with_collection_parameter :column
|
7
|
+
|
8
|
+
include TablesHelper
|
9
|
+
|
10
|
+
attr_reader :table
|
11
|
+
attr_reader :column
|
12
|
+
|
13
|
+
def initialize(table:, column:)
|
14
|
+
@table = table
|
15
|
+
@column = column
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
File without changes
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mensa
|
4
|
+
module RowAction
|
5
|
+
class Component < ::Mensa::ApplicationComponent
|
6
|
+
with_collection_parameter :action
|
7
|
+
|
8
|
+
attr_reader :table
|
9
|
+
attr_reader :row
|
10
|
+
attr_reader :action
|
11
|
+
|
12
|
+
def initialize(table:, row:, action:)
|
13
|
+
@table = table
|
14
|
+
@row = row
|
15
|
+
@action = action
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
.mensa-table {
|
2
|
+
&__search {
|
3
|
+
@apply dark:bg-gray-800 dark:border-gray-800 border-b p-2;
|
4
|
+
|
5
|
+
&__button {
|
6
|
+
@apply cursor-pointer w-6 h-full text-gray-400;
|
7
|
+
}
|
8
|
+
|
9
|
+
input&__input {
|
10
|
+
@apply pl-2 h-6 w-full border-0 bg-transparent pr-4 text-gray-600 dark:text-gray-400 placeholder:text-gray-400 focus:ring-0 text-sm;
|
11
|
+
}
|
12
|
+
}
|
13
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
.mensa-table__search data-mensa-table-target="search" data-controller="mensa-search" data-mensa-search-target="search" class="#{table.supports_views? ? 'hidden' : ''}" data-mensa-search-mensa-table-outlet=".mensa-table#table-#{table.table_id}"
|
2
|
+
.flex
|
3
|
+
.flex-none.w-6.h-22.text-right.text-gray-500.dark:text-gray-400
|
4
|
+
i.cursor-pointer class=Mensa.config.icons[:search]
|
5
|
+
.flex-1
|
6
|
+
input.mensa-table__search__input type="text" name="search_query" placeholder=t("search", default: "Search") data-mensa-search-target="searchInput" data-action="mensa-search#monitorSearch keydown.enter->mensa-search#search keydown.esc->mensa-search#resetSearch" value=params[:query]
|
7
|
+
.flex.space-x-2.justify-right.pr-2
|
8
|
+
button.mensa-table__search__button.hidden.pr-6 data-mensa-search-target="resetSearchButton" data-action="mensa-search#resetSearch"
|
9
|
+
i.fas.fa-xmark
|
10
|
+
.view-buttons.space-x-2.hidden data-mensa-table-target="viewButtons"
|
11
|
+
button class="rounded bg-white px-2 py-1 text-xs font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50" data-action="mensa-table#cancelFiltersAndSearch"
|
12
|
+
= t('.cancel')
|
13
|
+
button class="rounded bg-white px-2 py-1 text-xs font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50" data-action="mensa-table#saveFiltersAndSearch"
|
14
|
+
= t('.save')
|
15
|
+
- unless table.supports_views?
|
16
|
+
= render Mensa::ControlBar::Component.new(table: table)
|
17
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import ApplicationController from 'mensa/controllers/application_controller'
|
2
|
+
|
3
|
+
import { get } from '@rails/request.js'
|
4
|
+
|
5
|
+
export default class SearchComponentController extends ApplicationController {
|
6
|
+
static targets = [
|
7
|
+
'resetSearchButton',
|
8
|
+
'searchInput'
|
9
|
+
]
|
10
|
+
static outlets = [
|
11
|
+
"mensa-table"
|
12
|
+
]
|
13
|
+
connect () {
|
14
|
+
super.connect()
|
15
|
+
this.monitorSearch()
|
16
|
+
}
|
17
|
+
|
18
|
+
monitorSearch (event) {
|
19
|
+
if (this.searchInputTarget.value.length >= 1) {
|
20
|
+
this.resetSearchButtonTarget.classList.remove('hidden')
|
21
|
+
this.searchInputTarget.focus();
|
22
|
+
} else {
|
23
|
+
this.resetSearchButtonTarget.classList.add('hidden')
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
resetSearch (event) {
|
28
|
+
this.searchInputTarget.value = ''
|
29
|
+
this.searchInputTarget.focus()
|
30
|
+
this.resetSearchButtonTarget.classList.add('hidden')
|
31
|
+
|
32
|
+
let turboFrame = this.element.closest('turbo-frame')
|
33
|
+
let url = this.ourUrl
|
34
|
+
url.searchParams.delete('query')
|
35
|
+
|
36
|
+
get(url, {
|
37
|
+
responseKind: 'turbo-stream'
|
38
|
+
})
|
39
|
+
}
|
40
|
+
|
41
|
+
search (event) {
|
42
|
+
if (this.query.length < 3) {
|
43
|
+
return
|
44
|
+
}
|
45
|
+
|
46
|
+
// FIXME: This doesn't prevent searching twice on enter, the turbo-frame URL doesn't change
|
47
|
+
let url = this.ourUrl
|
48
|
+
if(url.searchParams.get('query') === this.query) {
|
49
|
+
return
|
50
|
+
}
|
51
|
+
|
52
|
+
url.searchParams.append('query', this.query)
|
53
|
+
|
54
|
+
get(url, {
|
55
|
+
responseKind: 'turbo-stream'
|
56
|
+
})
|
57
|
+
}
|
58
|
+
|
59
|
+
get query() {
|
60
|
+
return this.searchInputTarget.value
|
61
|
+
}
|
62
|
+
}
|
File without changes
|
@@ -0,0 +1,7 @@
|
|
1
|
+
.mensa-table id="table-#{table.table_id}" data-mensa-table-view-condensed-value="#{table.view_condensed?}" data-mensa-table-supports-views-value="#{table.supports_views?}" data-controller="mensa-table"
|
2
|
+
= render Mensa::Search::Component.new(table: table)
|
3
|
+
div id="filters-#{table.table_id}"
|
4
|
+
= render Mensa::Filters::Component.new(table: table)
|
5
|
+
- if table.supports_views? && table.show_header?
|
6
|
+
= render Mensa::Views::Component.new(table: table)
|
7
|
+
turbo-frame id=table.table_id src=helpers.mensa.table_path(table.name, turbo_frame_id: table.table_id) target="_top" loading="lazy" data-mensa-table-target="turboFrame"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mensa
|
4
|
+
module Table
|
5
|
+
class Component < ::Mensa::ApplicationComponent
|
6
|
+
include TablesHelper
|
7
|
+
|
8
|
+
attr_reader :table
|
9
|
+
|
10
|
+
def initialize(table_name, config = {}, **options)
|
11
|
+
@table = Mensa.for_name(table_name, config)
|
12
|
+
@table.component = self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import ApplicationController from 'mensa/controllers/application_controller'
|
2
|
+
import { get } from '@rails/request.js'
|
3
|
+
|
4
|
+
export default class TableComponentController extends ApplicationController {
|
5
|
+
static targets = [
|
6
|
+
'controlBar', // Bar with buttons
|
7
|
+
'condenseExpandIcon', // Icon
|
8
|
+
'filters', // Tabs or list of filters
|
9
|
+
'views', // Tabs or list of views
|
10
|
+
'viewButtons', // Cancel and save buttons for views
|
11
|
+
'search', // Search bar
|
12
|
+
'view', // View contains table element
|
13
|
+
'turboFrame' // The turbo-frame
|
14
|
+
]
|
15
|
+
static values = {
|
16
|
+
supportsViews: Boolean
|
17
|
+
}
|
18
|
+
|
19
|
+
connect () {
|
20
|
+
super.connect()
|
21
|
+
}
|
22
|
+
|
23
|
+
openFiltersAndSearch(event) {
|
24
|
+
if(this.supportsViewsValue) {
|
25
|
+
this.viewButtonsTarget.classList.remove('hidden')
|
26
|
+
this.searchTarget.classList.remove('hidden')
|
27
|
+
this.viewsTarget.classList.add('hidden')
|
28
|
+
this.filtersTarget.classList.remove('hidden')
|
29
|
+
} else {
|
30
|
+
this.controlBarTarget.classList.add('hidden')
|
31
|
+
this.viewButtonsTarget.classList.remove('hidden')
|
32
|
+
this.filtersTarget.classList.remove('hidden')
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
cancelFiltersAndSearch(event) {
|
37
|
+
if(this.supportsViewsValue) {
|
38
|
+
this.searchTarget.classList.add('hidden')
|
39
|
+
this.viewButtonsTarget.classList.add('hidden')
|
40
|
+
this.filtersTarget.classList.add('hidden')
|
41
|
+
this.viewsTarget.classList.remove('hidden')
|
42
|
+
} else {
|
43
|
+
this.controlBarTarget.classList.remove('hidden')
|
44
|
+
this.viewButtonsTarget.classList.add('hidden')
|
45
|
+
this.filtersTarget.classList.add('hidden')
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
saveFiltersAndSearch(event) {
|
50
|
+
|
51
|
+
}
|
52
|
+
|
53
|
+
condenseExpand (event) {
|
54
|
+
if (this.viewTarget.classList.contains('mensa-table__condensed')) {
|
55
|
+
this.viewTarget.classList.remove('mensa-table__condensed')
|
56
|
+
this.condenseExpandIconTarget.classList.add('fa-compress')
|
57
|
+
this.condenseExpandIconTarget.classList.remove('fa-expand')
|
58
|
+
} else {
|
59
|
+
this.viewTarget.classList.add('mensa-table__condensed')
|
60
|
+
this.condenseExpandIconTarget.classList.remove('fa-compress')
|
61
|
+
this.condenseExpandIconTarget.classList.add('fa-expand')
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
export(event) {
|
66
|
+
let url = this.ourUrl
|
67
|
+
url.pathname += ".xlsx"
|
68
|
+
get(url, {
|
69
|
+
}).then(() => {
|
70
|
+
})
|
71
|
+
}
|
72
|
+
}
|
File without changes
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mensa
|
4
|
+
module TableRow
|
5
|
+
class Component < ::Mensa::ApplicationComponent
|
6
|
+
with_collection_parameter :row
|
7
|
+
|
8
|
+
include TablesHelper
|
9
|
+
|
10
|
+
attr_reader :table
|
11
|
+
attr_reader :row
|
12
|
+
|
13
|
+
def initialize(table:, row:)
|
14
|
+
@table = table
|
15
|
+
@row = row
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
.mensa-table {
|
2
|
+
@apply bg-white dark:bg-gray-500 dark:border-gray-700;
|
3
|
+
|
4
|
+
.badge {
|
5
|
+
@apply bg-primary-100 text-primary-600 hidden ml-3 rounded-full text-xs font-medium md:inline-block py-0.5 px-2.5;
|
6
|
+
}
|
7
|
+
table {
|
8
|
+
@apply min-w-full divide-y divide-gray-50 dark:divide-gray-800 border-0;
|
9
|
+
|
10
|
+
thead {
|
11
|
+
@apply bg-gray-100 top-0 dark:bg-gray-700 dark:font-medium dark:text-gray-400 dark:lowercase;
|
12
|
+
|
13
|
+
/* tr and th moved to header */
|
14
|
+
}
|
15
|
+
tbody {
|
16
|
+
|
17
|
+
@apply divide-y divide-gray-200 dark:divide-gray-600;
|
18
|
+
|
19
|
+
tr {
|
20
|
+
@apply cursor-pointer bg-white dark:bg-gray-800 divide-x divide-gray-400 divide-opacity-25 hover:bg-gray-100 dark:hover:bg-gray-700;
|
21
|
+
|
22
|
+
&:nth-child(even) {
|
23
|
+
@apply bg-gray-50 dark:bg-gray-900 hover:bg-gray-200 dark:hover:bg-gray-700;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
td {
|
28
|
+
@apply px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400;
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
.paging {
|
34
|
+
@apply flex items-center justify-between border-t border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 px-4 py-3 sm:px-6;
|
35
|
+
|
36
|
+
.pagy-info {
|
37
|
+
@apply text-sm text-gray-700;
|
38
|
+
b {
|
39
|
+
@apply font-medium;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
.pagy-nav.pagination {
|
44
|
+
@apply isolate inline-flex -space-x-px rounded-md shadow-sm;
|
45
|
+
}
|
46
|
+
|
47
|
+
.page.next a {
|
48
|
+
@apply relative no-underline inline-flex items-center rounded-r-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50 focus:z-20;
|
49
|
+
}
|
50
|
+
|
51
|
+
.page.next a.disabled {
|
52
|
+
@apply relative no-underline inline-flex items-center rounded-r-md border border-gray-300 bg-slate-100 text-sm font-medium text-gray-500 hover:bg-gray-50 focus:z-20;
|
53
|
+
}
|
54
|
+
|
55
|
+
.page.prev a {
|
56
|
+
@apply relative no-underline inline-flex items-center rounded-l-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50 focus:z-20;
|
57
|
+
}
|
58
|
+
|
59
|
+
.page.prev a.disabled {
|
60
|
+
@apply relative no-underline inline-flex items-center rounded-l-md border border-gray-300 bg-slate-100 text-sm font-medium text-gray-500 hover:bg-gray-50 focus:z-20;
|
61
|
+
}
|
62
|
+
|
63
|
+
.page a, .page.gap {
|
64
|
+
@apply no-underline bg-white border-gray-300 text-gray-500 hover:bg-gray-50 relative inline-flex items-center border px-4 py-2 text-sm font-medium focus:z-20;
|
65
|
+
}
|
66
|
+
|
67
|
+
.page.active a {
|
68
|
+
@apply no-underline z-10 border-primary-500 bg-primary-50 text-primary-600 relative inline-flex items-center border text-sm font-medium focus:z-20;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
&__condensed {
|
73
|
+
table {
|
74
|
+
tbody {
|
75
|
+
td {
|
76
|
+
@apply pl-4 py-2;
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
.overflow-y-auto class=(table.view_condensed? ? "mensa-table__condensed" : "") data-mensa-table-target="view"
|
2
|
+
table.w-full
|
3
|
+
- if table.show_header?
|
4
|
+
thead
|
5
|
+
tr
|
6
|
+
= render(Mensa::Header::Component.with_collection(table.columns.select(&:visible?).reject(&:internal?), table: table))
|
7
|
+
- if table.actions?
|
8
|
+
th
|
9
|
+
|
10
|
+
tbody
|
11
|
+
= render(Mensa::TableRow::Component.with_collection(table.rows, table: table))
|
12
|
+
|
13
|
+
- if table.pagy_details&.pages > 1 || table.pagy_details.count == 0
|
14
|
+
.paging
|
15
|
+
== pagy_info(table.pagy_details)
|
16
|
+
- if table.pagy_details&.pages > 1
|
17
|
+
== pagy_nav(table.pagy_details, link_extra: 'data-turbo-frame="_self"')
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Presents a single table-view, also in use when just one table is in view
|
4
|
+
module Mensa
|
5
|
+
module View
|
6
|
+
class Component < ::Mensa::ApplicationComponent
|
7
|
+
include TablesHelper
|
8
|
+
|
9
|
+
attr_reader :table
|
10
|
+
|
11
|
+
def initialize(table)
|
12
|
+
@table = table
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
.mensa-table {
|
2
|
+
&__views {
|
3
|
+
@apply p-2 pl-4 shadow-lg border-b dark:bg-gray-700 dark:border-gray-600;
|
4
|
+
|
5
|
+
a.view {
|
6
|
+
@apply bg-gray-100 text-gray-600 dark:text-gray-400 hover:text-gray-800 hover:bg-gray-200 rounded-md px-3 py-1.5 text-sm;
|
7
|
+
}
|
8
|
+
|
9
|
+
a.view.selected {
|
10
|
+
@apply bg-gray-300 text-gray-800 dark:bg-gray-500 hover:bg-gray-400;
|
11
|
+
}
|
12
|
+
}
|
13
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
.mensa-table__views data-mensa-table-target="views"
|
2
|
+
.sm:hidden
|
3
|
+
label.sr-only[for="tabs"]
|
4
|
+
| Select a tab
|
5
|
+
select#tabs.block.w-full.rounded-md.border-gray-300.focus:border-indigo-500.focus:ring-indigo-500[name="tabs"]
|
6
|
+
- table.all_views.each.with_index do |view, index|
|
7
|
+
option = view.name
|
8
|
+
.hidden.sm:block
|
9
|
+
nav.flex.justify-between[aria-label="Tabs"]
|
10
|
+
.flex.space-x-2.overflow-x-auto.whitespace-nowrap.scroll-p-0
|
11
|
+
- table.all_views.each.with_index do |view, index|
|
12
|
+
= link_to(table.path(table_view_id: view.id, turbo_frame_id: table.table_id), "data-turbo-frame": table.table_id, class: "view #{(view == table.table_view) || (!view.persisted? && table.table_view.blank?) ? 'selected' : ''}") do
|
13
|
+
= view.name
|
14
|
+
|
15
|
+
a.text-gray-600.dark:text-gray-400.hover:text-gray-800.hover:bg-gray-200.rounded-md.px-3.py-1.5.text-sm[href="#" title=t("new_view", default: "New view")]
|
16
|
+
.fal.fa-plus
|
17
|
+
- if table.supports_views?
|
18
|
+
= render Mensa::ControlBar::Component.new(table: table)
|
File without changes
|