Fix interaction between Filters::FilterForm and the WorkPackage Query

This commit is contained in:
Klaus Zanders
2026-05-29 13:38:58 +02:00
parent ff20cffd49
commit 78abead8b4
9 changed files with 139 additions and 59 deletions
@@ -130,10 +130,7 @@ form forwards it as `appendTo` to every autocompleter it renders.
| You want… | Use |
|----------------------------------------------------------|---------------------------|
| The standard OpenProject filter panel on an index page | `Filter::FilterComponent` |
| Filters inside a dialog or a non-filter form | `Filters::FilterForm` |
| Coordination with a quick filter input in a sub-header | `Filter::FilterComponent` (the sub-header attaches the controller) |
| The serialized filter string in `params` on submit | `Filters::FilterForm` + `hidden_input_name:` |
| Autocompleter dropdowns to escape a clipping container | `Filters::FilterForm` + `autocomplete_append_to:` |
| Filters inside a dialog or a non-filter form | `Filters::FilterForm` + `hidden_input_name:` |
## Stimulus controller placement
@@ -164,6 +161,8 @@ default.
with the same signature, so passing a `Query` (or any of its subclasses)
to `FilterForm` works exactly like passing a `BaseQuery` subclass.
<%= embed OpenProject::Filter::FilterFormPreview, :for_a_work_package_query, panels: %i[preview source] %>
What `FilterForm` does *not* do for you on the legacy side: parsing the
form submission back into a `Query#filters` collection. The work-package
filter pipeline still uses its own serialization (URL `filters=[...]`
@@ -33,12 +33,14 @@ module OpenProject
# @logical_path OpenProject/Filter
class FilterFormPreview < Lookbook::Preview
# @display min_height 600px
# Using the `UserQuery` as an example.
def default
render_with_template(locals: { query: UserQuery.new })
end
# @display min_height 600px
# @label With an active filter
# Using the `UserQuery` as an example.
def with_active_filter
query = UserQuery.new
query.where(:login, "~", ["admin"])
@@ -48,6 +50,7 @@ module OpenProject
# @display min_height 600px
# @label Hidden input mode
# @param output_format [Symbol] select [json, params]
# Using the `UserQuery` as an example.
# This also renders a field that shows the value of the hidden input to show the different serialization formats.
def with_hidden_input(output_format: :json)
render_with_template(locals: { query: UserQuery.new, output_format: output_format.to_sym })
@@ -55,9 +58,20 @@ module OpenProject
# @display min_height 600px
# @label Combined with other inputs
# Using the `UserQuery` as an example
def combined_with_other_inputs
render_with_template(locals: { query: UserQuery.new })
end
# @display min_height 600px
# @label Work package query (legacy `Query`)
# Renders against the legacy work-package `Query` (the one that # predates `Queries::BaseQuery`).
def for_a_work_package_query
query = ::Query.new
query.add_filter(:status_id, "o", [])
query.add_filter(:due_date, "=d", [Date.current.end_of_year.iso8601])
render_with_template(locals: { query: query })
end
end
end
end
@@ -0,0 +1,17 @@
<%# `Query` is the legacy work-package query model. `Filters::FilterForm` %>
<%# works against it the same way it does against `Queries::BaseQuery` %>
<%# subclasses — the only requirement is `available_advanced_filters`, %>
<%# `filters`, and `find_active_filter(name)`, all of which `Query` %>
<%# exposes (the last one was mirrored from `BaseQuery` to bring the %>
<%# legacy query in line with the new form). %>
<%= primer_form_with(url: "/foo", method: :post) do |f| %>
<%=
render(
Filters::FilterForm.new(
f,
query: query,
wrap_with_controller: true
)
)
%>
<% end %>