Skip to content

Add search and filters to the RL experiments overview - #76

Merged
jjroelofs merged 3 commits into
1.xfrom
jur/1.x/reports-filter-search
Nov 11, 2026
Merged

jjroelofs merged 3 commits into
1.xfrom
jur/1.x/reports-filter-search

Conversation

@jjroelofs

@jjroelofs jjroelofs commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

/admin/reports/rl now has a search box and two filters above the experiments table.

  • Name or ID: case-insensitive match on the displayed name or the experiment ID.
  • Source: the module that registered the experiment (options come from the registry).
  • Activity: experiments with impressions, or without impressions yet.

The filters combine, and a "Showing X of Y experiments" line and a Reset button appear while one is active.

How it works

  • A small ExperimentsFilterForm posts and redirects to the overview with search, source and activity in the URL (post-redirect-get). Filtered lists can be bookmarked and shared, and the pager and sort links keep them. A new filter starts on page one and keeps the chosen sort.
  • ExperimentsOverviewForm filters the rows before sorting and paging, so counts, sort order and the 50-per-page pager all stay consistent.
  • The bulk delete confirmation page, its Cancel link and the redirect after deleting return to the filtered list. The per-row Delete links already do through destination. Submitted selections are still retained from the full registry, so a checked row cannot be rejected because live statistics moved it out of the filtered set.
  • The route now uses the existing ReportsController::experimentsOverview() to render the page: Add experiment button and intro text, then the filter form, then the table form. HTML cannot nest forms, so the filters are their own form; the button and intro moved from the table form to the page so the filters sit between them and the table.

Edge cases handled

  • A search for 0 counts as a real filter (a plain array_filter() would drop it; caught while testing).
  • Unknown source or activity values are ignored, and the filter form then shows "- Any -" so it matches the list.
  • Array-style parameters such as ?search[]=x do not break the page.
  • No new @phpstan-ignore: the new form is final, so new static needs no suppression.

Testing

Run against the local DXPR CMS sandbox with 62 experiments (five sources, 55 of them in one source to force a second page):

  • 25 HTTP checks as a logged-in admin: search (name, ID, case, whitespace, 0, no match), source, activity, every combination, paging with a filter, page beyond the end, sort plus filter, malformed and unknown parameters.
  • Bulk delete in a filtered view: selection, confirmation page, Cancel link and the redirect after deleting all return to the filtered list.
  • Added scripts/e2e/test-experiments-overview.sh (23 assertions in the existing drush e2e style; it renders both forms through a real request with test experiments it creates and deletes). I ran it against the sandbox through the DRUSH variable and confirmed it fails when the 0 handling is broken. The Docker e2e job is what runs it in CI.
  • Checked in the browser: submitting a search, the filter row, the Reset button and the summary line, with measured positions (labels, fields and buttons share one baseline, also when the row wraps). The empty state was checked over HTTP only.

Docs page and changelog are updated.

/admin/reports/rl gets a Name or ID search plus Source and Activity filters
above the list. The filter form redirects to the overview with the values in
the URL, so filtered lists can be bookmarked, sorted and paged. The bulk
delete confirmation and its cancel link keep the filters.

A search for "0" counts as a filter, and unknown or malformed parameters are
ignored. The Add experiment button and intro text move from the table form to
the page so the filters sit between them and the table.
The inline form layout floated each item, so the search label sat higher
than the select labels and the Filter and Reset buttons aligned to the
label row instead of the fields. The filter now uses a small flex layout
that bottom-aligns every field and button and keeps the rows aligned when
the form wraps on narrow screens.
@jjroelofs

Copy link
Copy Markdown
Contributor Author

Pushed 42cd54e: fixes the alignment of the filter row.

The inline form floated each item, so the "Name or ID" label sat higher than the select labels and the Filter and Reset buttons lined up with the label row instead of the fields. The filter now uses a small flex layout (css/experiments-filter.css, attached only by the filter form). Measured in the browser: all labels share one top, and the text field, both selects and both buttons share the same top, bottom and 40 px height. When the row wraps, each wrapped row stays aligned.

No PHP behaviour changed. I removed the cosmetic note from the description.

The changelog file is being removed from the module in a separate change.
@jjroelofs jjroelofs mentioned this pull request Nov 11, 2026
@jjroelofs
jjroelofs merged commit e66b09a into 1.x Nov 11, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant