Skip to content

Commit

Permalink
Merge branch 'main' of github.com:bogdan/datagrid
Browse files Browse the repository at this point in the history
  • Loading branch information
bogdan committed Jan 27, 2025
2 parents 6577577 + a47950d commit 287e677
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 8 deletions.
17 changes: 13 additions & 4 deletions lib/datagrid/columns.rb
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ module Datagrid
#
# self.default_column_options = { order: false }
#
# It can also accept a proc with the column instance as an argument:
#
# self.default_column_options = ->(column) { { order: column.name == :id } }
#
# ## Columns Visibility
#
# Columns can be dynamically shown or hidden based on the grid's `column_names` accessor.
Expand Down Expand Up @@ -201,15 +205,19 @@ module Datagrid
# end
module Columns
# @!method default_column_options=(value)
# @param [Hash] value default options passed to {#column} method call
# @return [Hash] default options passed to {#column} method call
# @param [Hash,Proc] value default options passed to {#column} method call.
# When a proc is passed, it will be called with the column instance as an argument,
# and expected to produce the options hash.
# @return [Hash,Proc] default options passed to {#column} method call, or a proc that returns them.
# @example Disable default order
# self.default_column_options = { order: false }
# @example Makes entire report HTML
# self.default_column_options = { html: true }
# @example Set the default header for all columns
# self.default_column_options = ->(column) { { header: I18n.t(column.name, scope: 'my_scope.columns') } }

# @!method default_column_options
# @return [Hash] default options passed to {#column} method call
# @return [Hash,Proc] default options passed to {#column} method call, or a proc that returns them.
# @see #default_column_options=

# @!method batch_size=(value)
Expand Down Expand Up @@ -368,9 +376,10 @@ def define_column(columns, name, query = nil, **options, &block)
block ||= lambda do |model|
model.public_send(name)
end

position = Datagrid::Utils.extract_position_from_options(columns, options)
column = Datagrid::Columns::Column.new(
self, name, query, default_column_options.merge(options), &block
self, name, query, options, &block
)
columns.insert(position, column)
column
Expand Down
2 changes: 1 addition & 1 deletion lib/datagrid/columns/column.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def initialize(grid_class, name, query, options = {}, &block)
@grid_class = grid_class
@name = name.to_sym
@query = query
@options = options
@options = Datagrid::Utils.callable(grid_class.default_column_options, self).merge(options)

if options[:class]
Datagrid::Utils.warn_once(
Expand Down
1 change: 1 addition & 0 deletions lib/datagrid/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def self.included(base)
class_attribute :datagrid_attributes, instance_writer: false, default: []
class_attribute :dynamic_block, instance_writer: false
class_attribute :forbidden_attributes_protection, instance_writer: false, default: false
class_attribute :default_filter_options, default: {}
end
end

Expand Down
23 changes: 23 additions & 0 deletions lib/datagrid/filters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,35 @@ module Datagrid
# filter(:id, :integer, header: "Identifier")
# filter(:created_at, :date, range: true, default: proc { 1.month.ago.to_date..Date.today })
#
# ## Default Filter Options
#
# Default options for all filters in a grid can be set using `default_filter_options`.
#
# self.default_filter_options = { header: "" }
#
# It can also accept a proc with the filter instance as an argument:
#
# self.default_filter_options = ->(filter) { { header: I18n.t(filter.name, scope: 'filters') } }
#
# # Localization
#
# Filter labels can be localized or specified via the `:header` option:
#
# filter(:created_at, :date, header: "Creation date")
# filter(:created_at, :date, header: proc { I18n.t("creation_date") })
module Filters
# @!method default_filter_options=(value)
# @param [Hash,Proc] value default options passed to {#filter} method call.
# When a proc is passed, it will be called with the filter instance as an argument,
# and expected to produce the options hash.
# @return [Hash,Proc] default options passed to {#filter} method call, or a proc that returns them.
# @example Set the default header for all filters
# self.default_filter_options = ->(filter) { { header: I18n.t(filter.name, scope: 'my_scope.filters') } }

# @!method default_filter_options
# @return [Hash,Proc] default options passed to {#filter} method call, or a proc that returns them.
# @see #default_filter_options=

require "datagrid/filters/base_filter"
require "datagrid/filters/enum_filter"
require "datagrid/filters/extended_boolean_filter"
Expand Down Expand Up @@ -163,6 +185,7 @@ module Filters

included do
include Datagrid::Core
class_attribute :default_filter_options, instance_writer: false, default: {}
class_attribute :filters_array, default: []
end

Expand Down
2 changes: 1 addition & 1 deletion lib/datagrid/filters/base_filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class BaseFilter
def initialize(grid_class, name, **options, &block)
self.grid_class = grid_class
self.name = name.to_sym
self.options = options
self.options = Datagrid::Utils.callable(grid_class.default_filter_options, self).merge(options)
self.block = block
end

Expand Down
4 changes: 2 additions & 2 deletions lib/datagrid/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ def process_availability(grid, if_option, unless_option)
!property_availability(grid, unless_option, false)
end

def callable(value)
value.respond_to?(:call) ? value.call : value
def callable(value, *arguments)
value.respond_to?(:call) ? value.call(*arguments) : value
end

protected
Expand Down
41 changes: 41 additions & 0 deletions spec/datagrid/columns_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,30 @@ class Report27 < Datagrid::Base
expect(Report27.new.header.first).to eq("Nombre")
end
end

it "uses configured default header" do
grid = test_grid do
self.default_column_options = ->(column) { { header: -> { I18n.t(column.name, scope: "other.location") } } }

scope { Entry }
column(:name)
end

store_translations(:en, other: { location: { name: "Nosaukums" } }) do
expect(grid.header.first).to eq("Nosaukums")
end
end

it "prefers column-specific header over default" do
grid = test_grid do
self.default_column_options = { header: -> { "Global Header" } }

scope { Entry }
column(:name, header: "Column Specific Header")
end

expect(grid.header.first).to eq("Column Specific Header")
end
end

it "returns html_columns" do
Expand Down Expand Up @@ -311,6 +335,23 @@ def show?
report.attributes = { order: :name, descending: true }
expect(report.assets).to eq([second, first])
end

it "accepts proc as default column options" do
report = test_grid do
scope { Entry }
self.default_column_options = ->(column) { { order: column.name == :name ? "name" : false } }
column(:id)
column(:name)
end
first = Entry.create(name: "1st")
second = Entry.create(name: "2nd")
expect do
report.attributes = { order: :id }
report.assets
end.to raise_error(Datagrid::OrderUnsupported)
report.attributes = { order: :name, descending: true }
expect(report.assets).to eq([second, first])
end
end

describe "fetching data in batches" do
Expand Down
50 changes: 50 additions & 0 deletions spec/datagrid/filters_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,30 @@ class InheritedReport < TranslatedReport
expect(grid.filters.map(&:header)).to eq(["Navn"])
end
end

it "translates filter using configured default header" do
grid = test_grid do
self.default_filter_options = ->(filter) { { header: -> { I18n.t(filter.name, scope: "other.location") } } }

scope { Entry }
filter(:name)
end

store_translations(:en, other: { location: { name: "Nosaukums" } }) do
expect(grid.filters.map(&:header)).to eq(["Nosaukums"])
end
end

it "prefers filter-specific header over default" do
grid = test_grid do
self.default_filter_options = { header: -> { "Global Header" } }

scope { Entry }
filter(:name, header: "Filter Specific Header")
end

expect(grid.filters.map(&:header)).to eq(["Filter Specific Header"])
end
end

describe "#select_options" do
Expand Down Expand Up @@ -304,4 +328,30 @@ class TestGrid8728 < Datagrid::Base
end
end
end

describe ".default_filter_options" do
it "passes default options to each filter definition" do
grid = test_grid do
scope { Entry }
self.default_filter_options = { header: "Guess!" }
filter(:id, :integer)
filter(:name, :string)
end

expect(grid.filters.map(&:header)).to eq(["Guess!", "Guess!"])
end

it "accepts proc as default filter options" do
grid = test_grid do
scope { Entry }
self.default_filter_options = lambda { |filter|
{ header: filter.name == :id ? "Identification!" : filter.name.to_s }
}
filter(:id, :integer)
filter(:name, :string)
end

expect(grid.filters.map(&:header)).to eq(["Identification!", "name"])
end
end
end

0 comments on commit 287e677

Please sign in to comment.