Skip to content

Conversation

@phycodurus
Copy link
Member

@phycodurus phycodurus commented Jan 22, 2026

Addresses

Changes:

  • Adds tom_targets/tables.py to define the django-tables2.Table subclass
  • Updates tom_targets/filters.py to update the TargetFilterSet to
    • add htmx elements
    • defined FilterSet layout in _form.helper.Layout
  • Updates the TargetListView to
    • handle htmx request and provide the appropriate template
    • add skymap_object to context to keep skymap in sync with table
  • adds partials for the table and a wrappers for the skymap (for side-loading).

Things that should work:

  • general search box
  • filters on target type and target group
  • checkboxes for merging and grouping
  • cone searches (try M31 and radius 4 for Messier objects)
  • pagination

Because this story was time-boxed, the following issues have been created

Here's how Copilot summarized this PR:

This pull request introduces major improvements to the target filtering and table display system, focusing on enhanced user experience with AJAX-powered (HTMX) interactions and more flexible filter forms. The changes include replacing the old TargetFilter with a new, extensible TargetFilterSet, adding a TargetTable class using django-tables2, and updating the UI with dynamic features such as sorting arrows and progress indicators. These updates enable more interactive and responsive filtering and table rendering for target data.

Target filtering improvements:

  • Replaced TargetFilter with TargetFilterSet, which now supports advanced filter layouts using crispy forms, AJAX (HTMX) integration for instant updates, and a new universal search field. Additional filter fields and widgets have been enhanced for better usability and dynamic behavior. [1] [2] [3] [4] [5] [6]
  • Updated all usages of the old TargetFilter to use the new TargetFilterSet in api_views.py and groups.py. [1] [2] [3] [4] [5] [6]

Table rendering and UI enhancements:

  • Added a new TargetTable class using django-tables2, with support for row selection, linkified names, and HTMX attributes for AJAX-based sorting and pagination.
  • Updated CSS to add up/down sorting arrows on table headers and a progress bar indicator for AJAX requests, improving visual feedback during filtering and sorting. [1] [2]

Dependency and configuration updates:

  • Added django-tables2 to the project dependencies and to the list of installed apps in settings.py. [1] [2]

phycodurus and others added 30 commits January 8, 2026 17:24
we've only set the Meta.{model, fields, template_name} properties
and the partial that renders only the table
(vs. whole page with table)
also store table-rendering partial in class to allow this
to be overridden. (This might be removed in the future if
if is not useful).
If the request came from HTMX, just load the partial (the table),
not the whole page.
Merge (sorting) sub-issue in to (htmx table widget) parent-issue
also add type column to table so we can sort on it later
We re-defining the default ChoiceFilter to add htmx attributes
to it's widget. (forms.Select is the default widget, but we have to
make it explicite in order to add htmx attributes to it).
this class was mis-named: it's a FilterSet subclass for Targets.
Also django_filter defines XXXFilter (e.g. ChoiceFilter) classes
which correspond to form fields. TargetFilter would thus be a
type of Filter, not a FilterSet. So, TargetFilterSet better
reflects what this class actually is.
hx-include of "closest form" collects all the form data from the
TargetFilterSet and sends it to the {% url 'tom_targets:list' %}
as specificed in the target_list.html as query parameters.

Without this only most recently used filter is honored. With this,
all the filters are honored.
the problem at the moment is that this work alone, but
doesn not play nicely with the other filters. (We need
to honor the request parameters as we construct the db Q's).
We don't need to send an AJAX request for every single
keystroke. Wait until they stop/pause typing before sending
the request.
The queryset argument is the result of the previous filters in the
filter chain. We must furter filter this queryset with
queryset.filter(Q), not start over with Target.objects.filter(Q)!
Also, don't propagate the checkbox click to the header or else
the header will thing we're trying to sort on that column.
directly. There's no hidden button connected to the form anymore.
The FilterSet change triggers the update to both the table and
Aladin. This is an htmx triggered AJAX call that does an out-of-band
swap (i.e. the Aladin part of the DOM is "side-loaded" (updated) away
from the HTML element that generated the AJAX call).
and refer to it in the <table> element HTMX attributes defined
in tables.py. The sorting and pagination AJAX call, which are
generated by the <table> element need to know about the request
parameters from the <form> element. The id in the <form> ID
hx-include in the <table> make that happen.
The hx-boost=True attr on the <table> element is needed so that
the sorting and pagination requests are HTMX table-only reloads.
For the linkified 'name' table.Column, we need to turn off the
hx-boost so that clicking on the name brings up the TargetDetail
page as a full page reload.
phycodurus and others added 8 commits January 20, 2026 10:57
Since we removed the submit button, need to make these fields
submit requests triggered by Return key-up.
We were already "side-loading" the skymap when the table page
contents changed, but we weren't loading the exact targets in the
table. This does that. We needed to create the object list (called
skymap_objects in the context) in the View.get_context_data. This is
then specified as the object_list sent to the table and skymap partials.
The Filter subclass instance and their methods remain as
examples. We may move this to the documentation.
@phycodurus phycodurus requested a review from jchate6 January 22, 2026 22:50
@phycodurus phycodurus linked an issue Jan 22, 2026 that may be closed by this pull request
8 tasks
@phycodurus phycodurus removed a link to an issue Jan 22, 2026
8 tasks
@phycodurus phycodurus requested a review from Fingel January 22, 2026 22:57
@jchate6 jchate6 moved this to Needs Review in TOM Toolkit Jan 22, 2026
@jchate6
Copy link
Contributor

jchate6 commented Jan 22, 2026

@phycodurus would you like me to start reviewing now, or would you like to get the tests working first?

The tom_targets.tests.tests.test_search_one_result_unauthorized
was failing because the render_table include was only rendering
the table (and the alert message was missing). We added the empty
table alerts to the partial. So, including it and having it render
the table (and add the alerts, as appropriate) satisfies the test.
@phycodurus
Copy link
Member Author

@phycodurus would you like me to start reviewing now, or would you like to get the tests working first?

tests are passing and the PR is ready to review.

I'll fix the codacy complaints in main.css. They are all minor code style complaints).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Needs Review

Development

Successfully merging this pull request may close these issues.

3 participants