From ee077e20941ac7b5cca62c256e6d6f9f6e2824dd Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Wed, 9 Apr 2025 10:06:07 -0600 Subject: [PATCH 01/21] Version 4.32.1 --- lib/effective_datatables/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/effective_datatables/version.rb b/lib/effective_datatables/version.rb index dc7e702..454698d 100644 --- a/lib/effective_datatables/version.rb +++ b/lib/effective_datatables/version.rb @@ -1,3 +1,3 @@ module EffectiveDatatables - VERSION = '4.32.0'.freeze + VERSION = '4.32.1'.freeze end From 4f32e59e62961ca54f5607494a788dbfa6a2e4eb Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Thu, 10 Apr 2025 09:48:14 -0600 Subject: [PATCH 02/21] Add btn-success for inline new button --- app/helpers/effective_datatables_private_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/helpers/effective_datatables_private_helper.rb b/app/helpers/effective_datatables_private_helper.rb index 4bacb71..ab94521 100644 --- a/app/helpers/effective_datatables_private_helper.rb +++ b/app/helpers/effective_datatables_private_helper.rb @@ -44,7 +44,8 @@ def datatable_length_menu(datatable) def datatable_new_resource_button(datatable, name, column) return unless datatable.inline? && (column[:actions][:new] != false) - action = { action: :new, class: ['btn', column[:btn_class].presence].compact.join(' '), 'data-remote': true } + # Override the default btn_class and use this one + action = { action: :new, class: 'btn btn-sm btn-success', 'data-remote': true } if column[:actions][:new].kind_of?(Hash) # This might be active_record_array_collection? actions = action.merge(column[:actions][:new]) From f28913d9b223673118b5925eb790981dc0469476 Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Thu, 10 Apr 2025 09:50:27 -0600 Subject: [PATCH 03/21] Version 4.32.2 --- lib/effective_datatables/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/effective_datatables/version.rb b/lib/effective_datatables/version.rb index 454698d..03810d2 100644 --- a/lib/effective_datatables/version.rb +++ b/lib/effective_datatables/version.rb @@ -1,3 +1,3 @@ module EffectiveDatatables - VERSION = '4.32.1'.freeze + VERSION = '4.32.2'.freeze end From d9c27be26dfcd2528b12437f9ca900d1a54af198 Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Tue, 22 Apr 2025 15:55:09 -0600 Subject: [PATCH 04/21] Use search: :string for visible: false columns unless explicitly given --- app/models/effective/effective_datatable/resource.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/models/effective/effective_datatable/resource.rb b/app/models/effective/effective_datatable/resource.rb index b08b6cb..1c1e85c 100644 --- a/app/models/effective/effective_datatable/resource.rb +++ b/app/models/effective/effective_datatable/resource.rb @@ -201,13 +201,15 @@ def load_resource_search! # Nothing to do. We're just a string search. elsif search[:as] == :select && search[:collection].kind_of?(Array) # Nothing to do. We already loaded the custom parameterized collection above. - elsif array_collection? && opts[:resource].present? + elsif opts[:visible] && array_collection? && opts[:resource].present? # Assigns { as: :select, collection: [...] } search.reverse_merge!(search_resource.search_form_field(name, collection.first[opts[:index]])) - else + elsif opts[:visible] # Load the defaults from effective_resources # Assigns { as: :string } or { as: :select, collection: [...] } search.reverse_merge!(search_resource.search_form_field(name, opts[:as])) + else + search.reverse_merge!({ as: :string }) end # Assign default search operation From 3d1f4f7c129e55bb79b7bebdd2944e564d1fd03c Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Tue, 22 Apr 2025 15:55:22 -0600 Subject: [PATCH 05/21] Version 4.32.3 --- lib/effective_datatables/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/effective_datatables/version.rb b/lib/effective_datatables/version.rb index 03810d2..3346d6c 100644 --- a/lib/effective_datatables/version.rb +++ b/lib/effective_datatables/version.rb @@ -1,3 +1,3 @@ module EffectiveDatatables - VERSION = '4.32.2'.freeze + VERSION = '4.32.3'.freeze end From 7f450d55f6f00099144566b8966f9f7937dc8fc7 Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Thu, 24 Apr 2025 14:19:26 -0600 Subject: [PATCH 06/21] Revert "Use search: :string for visible: false columns unless explicitly given" This reverts commit d9c27be26dfcd2528b12437f9ca900d1a54af198. --- app/models/effective/effective_datatable/resource.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/models/effective/effective_datatable/resource.rb b/app/models/effective/effective_datatable/resource.rb index 1c1e85c..b08b6cb 100644 --- a/app/models/effective/effective_datatable/resource.rb +++ b/app/models/effective/effective_datatable/resource.rb @@ -201,15 +201,13 @@ def load_resource_search! # Nothing to do. We're just a string search. elsif search[:as] == :select && search[:collection].kind_of?(Array) # Nothing to do. We already loaded the custom parameterized collection above. - elsif opts[:visible] && array_collection? && opts[:resource].present? + elsif array_collection? && opts[:resource].present? # Assigns { as: :select, collection: [...] } search.reverse_merge!(search_resource.search_form_field(name, collection.first[opts[:index]])) - elsif opts[:visible] + else # Load the defaults from effective_resources # Assigns { as: :string } or { as: :select, collection: [...] } search.reverse_merge!(search_resource.search_form_field(name, opts[:as])) - else - search.reverse_merge!({ as: :string }) end # Assign default search operation From 3e90de4e8a8b664411a25551698c79ca0798b3c6 Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Thu, 24 Apr 2025 14:40:32 -0600 Subject: [PATCH 07/21] Only load search collection for associations when as: :select --- app/models/effective/effective_datatable/resource.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/models/effective/effective_datatable/resource.rb b/app/models/effective/effective_datatable/resource.rb index b08b6cb..d4930a9 100644 --- a/app/models/effective/effective_datatable/resource.rb +++ b/app/models/effective/effective_datatable/resource.rb @@ -201,9 +201,16 @@ def load_resource_search! # Nothing to do. We're just a string search. elsif search[:as] == :select && search[:collection].kind_of?(Array) # Nothing to do. We already loaded the custom parameterized collection above. - elsif array_collection? && opts[:resource].present? + elsif search[:as] == :select && search[:collection].blank? && array_collection? && opts[:resource].present? # Assigns { as: :select, collection: [...] } search.reverse_merge!(search_resource.search_form_field(name, collection.first[opts[:index]])) + elsif search[:as] == :select && search[:collection].blank? + # Load the defaults from effective_resources + # Assigns { as: :string } or { as: :select, collection: [...] } + search.reverse_merge!(search_resource.search_form_field(name, opts[:as])) + elsif [:belongs_to, :belongs_to_polymorphic, :has_and_belongs_to_many, :has_many, :has_one].include?(opts[:as]) + # Do not eager load the collection. Treat this as a string search. + search.reverse_merge!({ as: :string }) else # Load the defaults from effective_resources # Assigns { as: :string } or { as: :select, collection: [...] } From 1a0d6c3c5c661efcd70ce1905ee780a2b2f044ab Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Thu, 24 Apr 2025 14:40:58 -0600 Subject: [PATCH 08/21] Version 4.33.0 --- lib/effective_datatables/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/effective_datatables/version.rb b/lib/effective_datatables/version.rb index 3346d6c..d70166d 100644 --- a/lib/effective_datatables/version.rb +++ b/lib/effective_datatables/version.rb @@ -1,3 +1,3 @@ module EffectiveDatatables - VERSION = '4.32.3'.freeze + VERSION = '4.33.0'.freeze end From 9a0a288f068ab369ac9961adc1b91b4177615c27 Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Fri, 25 Apr 2025 08:59:29 -0600 Subject: [PATCH 09/21] Tweak resource search --- .../effective/effective_datatable/resource.rb | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/app/models/effective/effective_datatable/resource.rb b/app/models/effective/effective_datatable/resource.rb index d4930a9..ecfccce 100644 --- a/app/models/effective/effective_datatable/resource.rb +++ b/app/models/effective/effective_datatable/resource.rb @@ -160,9 +160,12 @@ def load_resource_search! columns.each do |name, opts| # Normalize the given opts[:search] into a Hash # Take special note of the opts[:search] as we need to collapse it when an ActiveRecord::Relation - case opts[:search] - when false + + if opts[:search] == false || attributes[:searchable] == false opts[:search] = { as: :null }; next + end + + case opts[:search] when Symbol opts[:search] = { as: opts[:search] } when Array, ActiveRecord::Relation @@ -176,10 +179,12 @@ def load_resource_search! # Now lets deal with the opts[:search] hash itself search = opts[:search] + # Adjust based on shorthand search: :select syntax + search[:as] ||= :select if search.key?(:collection) + search[:value] ||= search.delete(:selected) if search.key?(:selected) + # Parameterize collection - if attributes[:searchable] == false - # Nothing to do - elsif search[:collection].kind_of?(ActiveRecord::Relation) + if search[:collection].kind_of?(ActiveRecord::Relation) search[:collection] = search[:collection].map { |obj| [obj.to_s, obj.id] } elsif search[:collection].kind_of?(Array) && search[:collection].first.kind_of?(ActiveRecord::Base) search[:collection] = search[:collection].map { |obj| [obj.to_s, obj.id] } @@ -187,17 +192,11 @@ def load_resource_search! search[:collection] = search[:collection] end - search[:as] ||= :select if search.key?(:collection) - search[:value] ||= search.delete(:selected) if search.key?(:selected) - # Merge with defaults search_resource = [opts[:resource], effective_resource, fallback_effective_resource].compact search_resource = search_resource.find { |res| res.klass.present? } || search_resource.first - # Assign search collections from effective_resources - if attributes[:searchable] == false - # Nothing to do - elsif search[:as] == :string + if search[:as] == :string # Nothing to do. We're just a string search. elsif search[:as] == :select && search[:collection].kind_of?(Array) # Nothing to do. We already loaded the custom parameterized collection above. From 97a2ae6fcc15ea96638a5568541809d55d065ecf Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Fri, 25 Apr 2025 08:59:42 -0600 Subject: [PATCH 10/21] Version 4.33.1 --- lib/effective_datatables/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/effective_datatables/version.rb b/lib/effective_datatables/version.rb index d70166d..a7bcc7c 100644 --- a/lib/effective_datatables/version.rb +++ b/lib/effective_datatables/version.rb @@ -1,3 +1,3 @@ module EffectiveDatatables - VERSION = '4.33.0'.freeze + VERSION = '4.33.1'.freeze end From 80c462fb394460edd0deb87c8bd2794e5194acf2 Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Tue, 29 Apr 2025 10:38:13 -0600 Subject: [PATCH 11/21] Add boolean column formatting with bootstrap colors --- app/models/effective/effective_datatable/format.rb | 4 +++- config/effective_datatables.rb | 4 ++++ lib/effective_datatables.rb | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/models/effective/effective_datatable/format.rb b/app/models/effective/effective_datatable/format.rb index 88b715d..e3eb8e8 100644 --- a/app/models/effective/effective_datatable/format.rb +++ b/app/models/effective/effective_datatable/format.rb @@ -117,7 +117,9 @@ def format_column(value, column, as: nil, csv: false) when :actions raise("please use actions_col instead of col(#{name}, as: :actions)") when :boolean - view.t("effective_datatables.boolean_#{value}") + label = view.t("effective_datatables.boolean_#{value}") + color = value ? EffectiveDatatables.format_true : EffectiveDatatables.format_false + color.present? ? view.badge(label, color) : label when :currency view.number_to_currency(value) when :date diff --git a/config/effective_datatables.rb b/config/effective_datatables.rb index fab211a..2f51a8d 100644 --- a/config/effective_datatables.rb +++ b/config/effective_datatables.rb @@ -46,6 +46,10 @@ config.format_date = '%F' config.format_time = '%H:%M' + # Boolean formatting. When present will render booleans as badges with this bootstrap color + config.format_true = 'success' + config.format_false = 'danger' + # Enable the Download button which serves a CSV of your collection config.download = false diff --git a/lib/effective_datatables.rb b/lib/effective_datatables.rb index 17df712..5e64cc0 100644 --- a/lib/effective_datatables.rb +++ b/lib/effective_datatables.rb @@ -22,6 +22,9 @@ module EffectiveDatatables mattr_accessor :format_date mattr_accessor :format_time + mattr_accessor :format_true + mattr_accessor :format_false + mattr_accessor :debug mattr_accessor :download From 1afb8d86272cb8f925fe218498d63e4e83f501f7 Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Tue, 29 Apr 2025 10:38:24 -0600 Subject: [PATCH 12/21] Version 4.34.0 --- lib/effective_datatables/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/effective_datatables/version.rb b/lib/effective_datatables/version.rb index a7bcc7c..bf69b11 100644 --- a/lib/effective_datatables/version.rb +++ b/lib/effective_datatables/version.rb @@ -1,3 +1,3 @@ module EffectiveDatatables - VERSION = '4.33.1'.freeze + VERSION = '4.34.0'.freeze end From f6e38f059c50441d6c92f4e892379cf10dfc531c Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Tue, 6 May 2025 13:28:12 -0600 Subject: [PATCH 13/21] Add nested_datatable_action --- .../effective_datatables/initialize.js.coffee | 4 ++++ .../effective_datatables/inline_crud.js.coffee | 1 + .../javascripts/effective_datatables/nested.js.coffee | 5 +++++ .../effective_datatables/_overrides.bootstrap4.scss | 9 +++++++++ app/helpers/effective_datatables_helper.rb | 11 ++++++++++- app/models/effective/effective_datatable/dsl.rb | 5 ++++- 6 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 app/assets/javascripts/effective_datatables/nested.js.coffee diff --git a/app/assets/javascripts/effective_datatables/initialize.js.coffee b/app/assets/javascripts/effective_datatables/initialize.js.coffee index 4c7c01e..6e89dcc 100644 --- a/app/assets/javascripts/effective_datatables/initialize.js.coffee +++ b/app/assets/javascripts/effective_datatables/initialize.js.coffee @@ -3,6 +3,7 @@ initializeDataTables = (target) -> datatable = $(this) options = datatable.data('options') || {} buttons_export_columns = options['buttons_export_columns'] || ':not(.col-actions)' + nested = datatable.data('nested') reorder = datatable.data('reorder') if datatable.data('inline') && datatable.closest('form').length > 0 @@ -178,6 +179,9 @@ initializeDataTables = (target) -> if reorder table.DataTable().on('row-reorder', (event, diff, edit) -> $(event.target).DataTable().reorder(event, diff, edit)) + if nested + table.closest('.dataTables_wrapper').addClass('dataTables_wrapper_nested') + table.addClass('initialized') table.children('thead').trigger('effective-bootstrap:initialize') table.children('thead').find('input[autofocus]').first().focus() diff --git a/app/assets/javascripts/effective_datatables/inline_crud.js.coffee b/app/assets/javascripts/effective_datatables/inline_crud.js.coffee index 2089f7c..fb28ab3 100644 --- a/app/assets/javascripts/effective_datatables/inline_crud.js.coffee +++ b/app/assets/javascripts/effective_datatables/inline_crud.js.coffee @@ -9,6 +9,7 @@ $(document).on 'ajax:before', '.dataTables_wrapper .col-actions', (event) -> $table = $(event.target).closest('table') return true if ('' + $action.data('inline')) == 'false' + return true if ('' + $action.data('nested-datatable-action')) == 'true' $params = $.param( { diff --git a/app/assets/javascripts/effective_datatables/nested.js.coffee b/app/assets/javascripts/effective_datatables/nested.js.coffee new file mode 100644 index 0000000..5cdcb0a --- /dev/null +++ b/app/assets/javascripts/effective_datatables/nested.js.coffee @@ -0,0 +1,5 @@ +# Make all links for nested datatables open in new tabs +$(document).on 'click', '.dataTables_wrapper_nested a', (event) -> + $link = $(event.currentTarget) + $link.attr('target', '_blank') + true diff --git a/app/assets/stylesheets/effective_datatables/_overrides.bootstrap4.scss b/app/assets/stylesheets/effective_datatables/_overrides.bootstrap4.scss index 80c64d0..9c1314c 100644 --- a/app/assets/stylesheets/effective_datatables/_overrides.bootstrap4.scss +++ b/app/assets/stylesheets/effective_datatables/_overrides.bootstrap4.scss @@ -103,6 +103,15 @@ table.dataTable thead { } } +// When Inline Expanded with Nested +.dataTables_wrapper.effective-datatables-inline-expanded { + .dataTables_wrapper_nested { + .dt-buttons { opacity: inherit; } + .dataTables_entries { opacity: inherit; } + .dataTables_paginate { opacity: inherit; } + } +} + table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:before, table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control:before { color: #0275d8; diff --git a/app/helpers/effective_datatables_helper.rb b/app/helpers/effective_datatables_helper.rb index 3d61e0a..9fe1cc6 100644 --- a/app/helpers/effective_datatables_helper.rb +++ b/app/helpers/effective_datatables_helper.rb @@ -2,7 +2,7 @@ # These are expected to be called by a developer. They are part of the datatables DSL. module EffectiveDatatablesHelper - def render_datatable(datatable, input_js: {}, buttons: true, charts: true, download: nil, entries: true, filters: true, inline: false, namespace: nil, pagination: true, search: true, simple: false, short: false, sort: true) + def render_datatable(datatable, input_js: {}, buttons: true, charts: true, download: nil, entries: true, filters: true, inline: false, namespace: nil, nested: false, pagination: true, search: true, simple: false, short: false, sort: true) raise 'expected datatable to be present' unless datatable raise 'expected input_js to be a Hash' unless input_js.kind_of?(Hash) @@ -19,6 +19,7 @@ def render_datatable(datatable, input_js: {}, buttons: true, charts: true, downl end datatable.attributes[:inline] = true if inline + datatable.attributes[:nested] = true if nested datatable.attributes[:sortable] = false unless sort datatable.attributes[:searchable] = false unless search datatable.attributes[:downloadable] = false unless download @@ -68,6 +69,7 @@ def render_datatable(datatable, input_js: {}, buttons: true, charts: true, downl 'inline' => inline.to_s, 'language' => EffectiveDatatables.language(I18n.locale), 'length-menu' => datatable_length_menu(datatable), + 'nested' => nested.to_s, 'options' => input_js.to_json, 'reorder' => datatable.reorder?.to_s, 'reorder-index' => (datatable.columns[:_reorder][:index] if datatable.reorder?).to_s, @@ -133,4 +135,11 @@ def inline_datatable @_inline_datatable ||= datatable end + def nested_datatable_link_to(title, path, options = {}) + options[:class] ||= 'btn btn-sm btn-link' + options['data-remote'] = true + options['data-nested-datatable-action'] = true + + link_to(title, path, options) + end end diff --git a/app/models/effective/effective_datatable/dsl.rb b/app/models/effective/effective_datatable/dsl.rb index e4a574d..cd50fb5 100644 --- a/app/models/effective/effective_datatable/dsl.rb +++ b/app/models/effective/effective_datatable/dsl.rb @@ -5,7 +5,10 @@ module EffectiveDatatable module Dsl def bulk_actions(&block) - define_method('initialize_bulk_actions') { dsl_tool.instance_exec(&block); dsl_tool.bulk_actions_col } + define_method('initialize_bulk_actions') do + actions = dsl_tool.instance_exec(&block) + dsl_tool.bulk_actions_col if actions.present? + end end def charts(&block) From dd492b6c1cf7b428fa5e5b1e700ba044af2672fb Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Tue, 6 May 2025 13:28:22 -0600 Subject: [PATCH 14/21] Version 4.35.0 --- lib/effective_datatables/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/effective_datatables/version.rb b/lib/effective_datatables/version.rb index bf69b11..e069ddf 100644 --- a/lib/effective_datatables/version.rb +++ b/lib/effective_datatables/version.rb @@ -1,3 +1,3 @@ module EffectiveDatatables - VERSION = '4.34.0'.freeze + VERSION = '4.35.0'.freeze end From 471d2c3ce1a0835bfd91af65ee1ab005d1de1b62 Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Wed, 7 May 2025 11:35:13 -0600 Subject: [PATCH 15/21] Admin UX glitches --- .../effective_datatables/inline_crud.js.coffee | 14 ++++++++++++-- .../_overrides.bootstrap4.scss | 17 ++++++++++++++++- app/helpers/effective_datatables_helper.rb | 2 +- .../effective/datatables/_filters.html.haml | 2 +- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/effective_datatables/inline_crud.js.coffee b/app/assets/javascripts/effective_datatables/inline_crud.js.coffee index fb28ab3..e06a994 100644 --- a/app/assets/javascripts/effective_datatables/inline_crud.js.coffee +++ b/app/assets/javascripts/effective_datatables/inline_crud.js.coffee @@ -9,7 +9,7 @@ $(document).on 'ajax:before', '.dataTables_wrapper .col-actions', (event) -> $table = $(event.target).closest('table') return true if ('' + $action.data('inline')) == 'false' - return true if ('' + $action.data('nested-datatable-action')) == 'true' + return true if ('' + $action.data('nested')) == 'true' $params = $.param( { @@ -156,8 +156,12 @@ beforeEdit = ($action) -> afterEdit = ($action) -> $tr = $action.closest('tr') $table = $tr.closest('table') + nested = $tr.find('a').data('nested') - html = buildRow($tr.children('td').length, EffectiveForm.remote_form_payload) + html = if nested + buildNestedDatatableRow($tr.children('td').length, EffectiveForm.remote_form_payload) + else + buildRow($tr.children('td').length, EffectiveForm.remote_form_payload) $tr.data('inline-form-original-html', $tr.children().detach()) $tr.html(html) @@ -201,6 +205,12 @@ buildRow = (length, payload) -> "Cancel" + "" +buildNestedDatatableRow = (length, payload) -> + "
#{payload}
" + + "" + + "Cancel" + + "" + expand = ($table) -> $wrapper = $table.closest('.dataTables_wrapper').addClass('effective-datatables-inline-expanded') $table.on 'draw.dt', (event) -> diff --git a/app/assets/stylesheets/effective_datatables/_overrides.bootstrap4.scss b/app/assets/stylesheets/effective_datatables/_overrides.bootstrap4.scss index 9c1314c..0682b37 100644 --- a/app/assets/stylesheets/effective_datatables/_overrides.bootstrap4.scss +++ b/app/assets/stylesheets/effective_datatables/_overrides.bootstrap4.scss @@ -72,7 +72,7 @@ table.dataTable > thead .sorting_desc { table.dataTable thead { th.col-actions { text-align: right; - span { display: block; height: 1.25em; } + span { display: block; } } } @@ -184,6 +184,10 @@ table.dataTable > thead { p { margin-bottom: 0; } } +.form-group.datatables-filters-present { + margin-top: 1.75em; +} + // Processing div div.dataTables_wrapper div.dataTables_processing { margin: -26px 25% 0px 25%; @@ -321,3 +325,14 @@ div.dt-button-collection .dt-button-active:after { right: auto; left: 0.5rem; } + +// Nested Datatables +.nested-datatable-container-parent { + padding-left: 0.25em; + padding-right: 0.25em; + container-type: inline-size; +} + +.nested-datatable-container { + width: 100%; +} diff --git a/app/helpers/effective_datatables_helper.rb b/app/helpers/effective_datatables_helper.rb index 9fe1cc6..57d5481 100644 --- a/app/helpers/effective_datatables_helper.rb +++ b/app/helpers/effective_datatables_helper.rb @@ -138,7 +138,7 @@ def inline_datatable def nested_datatable_link_to(title, path, options = {}) options[:class] ||= 'btn btn-sm btn-link' options['data-remote'] = true - options['data-nested-datatable-action'] = true + options['data-nested'] = true link_to(title, path, options) end diff --git a/app/views/effective/datatables/_filters.html.haml b/app/views/effective/datatables/_filters.html.haml index 198437c..f4fc230 100644 --- a/app/views/effective/datatables/_filters.html.haml +++ b/app/views/effective/datatables/_filters.html.haml @@ -11,7 +11,7 @@ - else = datatable_filter_tag(form, datatable, name, opts) - .form-group.col-auto + .form-group.col-auto{class: (datatable._filters.present? ? 'datatables-filters-present' : 'datatables-filters-blank')} - if datatable._filters_form_required? = form.save t('effective_datatables.apply'), 'data-disable-with': t('effective_datatables.applying'), class: 'btn btn-sm btn-secondary' - else From 525f41c2a83f17a2ae3118927baa385bc1662f3a Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Wed, 7 May 2025 11:51:44 -0600 Subject: [PATCH 16/21] Nested datatable fixes --- .../effective_datatables/inline_crud.js.coffee | 13 +++++++------ app/helpers/effective_datatables_helper.rb | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/effective_datatables/inline_crud.js.coffee b/app/assets/javascripts/effective_datatables/inline_crud.js.coffee index e06a994..7b438d7 100644 --- a/app/assets/javascripts/effective_datatables/inline_crud.js.coffee +++ b/app/assets/javascripts/effective_datatables/inline_crud.js.coffee @@ -9,7 +9,7 @@ $(document).on 'ajax:before', '.dataTables_wrapper .col-actions', (event) -> $table = $(event.target).closest('table') return true if ('' + $action.data('inline')) == 'false' - return true if ('' + $action.data('nested')) == 'true' + return true if ('' + $action.data('nested-datatable')) == 'true' $params = $.param( { @@ -156,10 +156,11 @@ beforeEdit = ($action) -> afterEdit = ($action) -> $tr = $action.closest('tr') $table = $tr.closest('table') - nested = $tr.find('a').data('nested') - html = if nested - buildNestedDatatableRow($tr.children('td').length, EffectiveForm.remote_form_payload) + nestedDatatableAction = $tr.find('a[data-nested-datatable]') + + html = if nestedDatatableAction.length > 0 + buildNestedDatatableRow($tr.children('td').length, EffectiveForm.remote_form_payload, nestedDatatableAction.attr('title')) else buildRow($tr.children('td').length, EffectiveForm.remote_form_payload) @@ -205,8 +206,8 @@ buildRow = (length, payload) -> "Cancel" + "" -buildNestedDatatableRow = (length, payload) -> - "
#{payload}
" + +buildNestedDatatableRow = (length, payload, title) -> + "
#{title || ''}
#{payload}
" + "" + "Cancel" + "" diff --git a/app/helpers/effective_datatables_helper.rb b/app/helpers/effective_datatables_helper.rb index 57d5481..c5d2732 100644 --- a/app/helpers/effective_datatables_helper.rb +++ b/app/helpers/effective_datatables_helper.rb @@ -138,7 +138,7 @@ def inline_datatable def nested_datatable_link_to(title, path, options = {}) options[:class] ||= 'btn btn-sm btn-link' options['data-remote'] = true - options['data-nested'] = true + options['data-nested-datatable'] = true link_to(title, path, options) end From f98af232e0afdf44e7db2a04fbbb7fa66e394300 Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Wed, 7 May 2025 11:55:52 -0600 Subject: [PATCH 17/21] Version 4.35.1 --- lib/effective_datatables/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/effective_datatables/version.rb b/lib/effective_datatables/version.rb index e069ddf..0bac39c 100644 --- a/lib/effective_datatables/version.rb +++ b/lib/effective_datatables/version.rb @@ -1,3 +1,3 @@ module EffectiveDatatables - VERSION = '4.35.0'.freeze + VERSION = '4.35.1'.freeze end From 3048a11ffe6035b58f07ded8679709208837d384 Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Tue, 29 Jul 2025 09:27:11 -0600 Subject: [PATCH 18/21] Strip HTML from boolean columns during csv download --- app/models/effective/effective_datatable/format.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/models/effective/effective_datatable/format.rb b/app/models/effective/effective_datatable/format.rb index e3eb8e8..dd428a2 100644 --- a/app/models/effective/effective_datatable/format.rb +++ b/app/models/effective/effective_datatable/format.rb @@ -118,8 +118,13 @@ def format_column(value, column, as: nil, csv: false) raise("please use actions_col instead of col(#{name}, as: :actions)") when :boolean label = view.t("effective_datatables.boolean_#{value}") - color = value ? EffectiveDatatables.format_true : EffectiveDatatables.format_false - color.present? ? view.badge(label, color) : label + + if csv + label.to_s + else + color = value ? EffectiveDatatables.format_true : EffectiveDatatables.format_false + color.present? ? view.badge(label, color) : label + end when :currency view.number_to_currency(value) when :date From 272b0cea8a47258577504dc942dd31883fd9aabd Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Tue, 29 Jul 2025 09:27:23 -0600 Subject: [PATCH 19/21] Version 4.35.2 --- lib/effective_datatables/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/effective_datatables/version.rb b/lib/effective_datatables/version.rb index 0bac39c..7c62d94 100644 --- a/lib/effective_datatables/version.rb +++ b/lib/effective_datatables/version.rb @@ -1,3 +1,3 @@ module EffectiveDatatables - VERSION = '4.35.1'.freeze + VERSION = '4.35.2'.freeze end From 38559974c570b5e52c68a3c31a9155aad67102ed Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Tue, 29 Jul 2025 09:51:22 -0600 Subject: [PATCH 20/21] Add CSV dependency --- effective_datatables.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/effective_datatables.gemspec b/effective_datatables.gemspec index f6e6ebd..b24bd18 100644 --- a/effective_datatables.gemspec +++ b/effective_datatables.gemspec @@ -18,6 +18,7 @@ Gem::Specification.new do |s| s.add_dependency 'rails', '>= 3.2.0' s.add_dependency 'coffee-rails' + s.add_dependency 'csv' s.add_dependency 'effective_bootstrap' s.add_dependency 'effective_resources' s.add_dependency 'sassc' From 52a352e04d0bb6646e96ecdec40f092accf7f0d2 Mon Sep 17 00:00:00 2001 From: Matt Riemer Date: Tue, 29 Jul 2025 09:51:33 -0600 Subject: [PATCH 21/21] Version 4.35.3 --- lib/effective_datatables/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/effective_datatables/version.rb b/lib/effective_datatables/version.rb index 7c62d94..c6139a7 100644 --- a/lib/effective_datatables/version.rb +++ b/lib/effective_datatables/version.rb @@ -1,3 +1,3 @@ module EffectiveDatatables - VERSION = '4.35.2'.freeze + VERSION = '4.35.3'.freeze end