Skip to content

Commit

Permalink
evol:add or/and separator field for text field
Browse files Browse the repository at this point in the history
  • Loading branch information
Quent1Pr committed Dec 7, 2021
1 parent 578f3e5 commit 53834af
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 8 deletions.
22 changes: 22 additions & 0 deletions app/assets/javascripts/rails_admin/ra.filter-box.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@
var field_name = options["name"];
var field_type = options["type"];
var field_value = options["value"];
var field_separator = options["separator"];
var field_operator = options["operator"];
var select_options = options["select_options"];
var required = options["required"];
var index = options["index"];
var value_name = "f[" + field_name + "][" + index + "][v]";
var operator_name = "f[" + field_name + "][" + index + "][o]";
var separator_filter_name = "f[" + field_name + "][" + index + "][s]";
var control = null;
var separator_control = null;
var additional_control = null;

switch (field_type) {
Expand Down Expand Up @@ -168,6 +171,23 @@
case "string":
case "text":
case "belongs_to_association":
if ($("#filters_box").find("p").length > 0) {
separator_control = $(
'<select class="input-sm form-control"></select>'
)
.prop("name", separator_filter_name)
.append(
$('<option value="or"></option>')
.prop("selected", field_separator == "or")
.text(RailsAdmin.I18n.t("or"))
)
.append(
$('<option value="and"></option>')
.prop("selected", field_separator == "and")
.text(RailsAdmin.I18n.t("and"))
);
}

control = $(
'<select class="switch-additional-fieldsets input-sm form-control"></select>'
)
Expand Down Expand Up @@ -314,6 +334,8 @@
var $content = $("<p>")
.attr("id", filterContainerId)
.addClass("filter form-search")
.append(separator_control)
.append("&nbsp;")
.append(
$(
'<button type="button" class="btn btn-info btn-sm delete"></button>'
Expand Down
16 changes: 13 additions & 3 deletions lib/rails_admin/adapters/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,14 @@ def build
scope = scope.references(*@tables.uniq) if @tables.any?
scope
end

def build_with_separator(initial_scope, separator)
scope = @scope.where(@statements.join, *@values)
initial_scope = initial_scope.references(*@tables.uniq) if @tables.any?
scope = @scope.or(initial_scope.where(@statements.join, *@values)) if separator == 'or'
scope = scope.references(*@tables.uniq) if @tables.any?
scope
end
end

def query_scope(scope, query, fields = config.list.fields.select(&:queryable?))
Expand All @@ -143,15 +151,17 @@ def query_scope(scope, query, fields = config.list.fields.select(&:queryable?))
# filters example => {"string_field"=>{"0055"=>{"o"=>"like", "v"=>"test_value"}}, ...}
# "0055" is the filter index, no use here. o is the operator, v the value
def filter_scope(scope, filters, fields = config.list.fields.select(&:filterable?))
initial_scope = scope
filters.each_pair do |field_name, filters_dump|
field = fields.detect { |f| f.name.to_s == field_name }
filters_dump.each do |_, filter_dump|
wb = WhereBuilder.new(scope)
field = fields.detect { |f| f.name.to_s == field_name }

value = parse_field_value(field, filter_dump[:v])

wb.add(field, value, (filter_dump[:o] || RailsAdmin::Config.default_search_operator))
# AND current filter statements to other filter statements
scope = wb.build
scope = wb.build_with_separator(initial_scope, filter_dump[:s]) if filter_dump[:s] == 'or'
scope = wb.build unless filter_dump[:s] == 'or'
end
end
scope
Expand Down
18 changes: 13 additions & 5 deletions lib/rails_admin/adapters/mongoid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,14 @@ def query_scope(scope, query, fields = config.list.fields.select(&:queryable?))
# filters example => {"string_field"=>{"0055"=>{"o"=>"like", "v"=>"test_value"}}, ...}
# "0055" is the filter index, no use here. o is the operator, v the value
def filter_scope(scope, filters, fields = config.list.fields.select(&:filterable?))
statements = []

initial_scope = scope
filters.each_pair do |field_name, filters_dump|
field = fields.detect { |f| f.name.to_s == field_name }

filters_dump.each do |_, filter_dump|
field = fields.detect { |f| f.name.to_s == field_name }
next unless field

statements = []
value = parse_field_value(field, filter_dump[:v])
conditions_per_collection = make_field_conditions(field, value, (filter_dump[:o] || 'default'))
field_statements = make_condition_for_current_collection(field, conditions_per_collection)
Expand All @@ -162,10 +163,17 @@ def filter_scope(scope, filters, fields = config.list.fields.select(&:filterable
elsif field_statements.any?
statements << field_statements.first
end
separator = '$and'
is_separator_or_input = filter_dump[:s].present? && filter_dump[:s] == 'or'
scope =
if is_separator_or_input
scope.or(initial_scope.where(statements.any? ? {separator => statements} : {}))
else
scope.where(statements.any? ? {separator => statements} : {})
end
end
end

scope.where(statements.any? ? {'$and' => statements} : {})
scope
end

def parse_collection_name(column)
Expand Down
19 changes: 19 additions & 0 deletions spec/integration/actions/index_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,25 @@
end
end

it 'allows to query the same attribute with or' do
RailsAdmin.config Player do
list do
field :name
field :team
field :injured
field :retired
end
end

visit index_path(model_name: 'player',
f: {name: {'1' => {v: @players[0].name}, '2' => {v: @players[1].name, s: 'or'}}})
is_expected.to have_content(@players[0].name)
is_expected.to have_content(@players[1].name)
(2..3).each do |i|
is_expected.to have_no_content(@players[i].name)
end
end

it 'allows to filter on one attribute' do
RailsAdmin.config Player do
list do
Expand Down

0 comments on commit 53834af

Please sign in to comment.