From 6d68af40e7d8f06df476a948fb06948cdafde948 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Fri, 11 Sep 2026 14:28:12 -0400 Subject: [PATCH] Merge into current URL params instead of replacing them in Advanced Search (#58) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same root pattern as the earlier chart click-to-filter bug (#29): performAdvancedSearch() built a brand-new URLSearchParams from only the form's own fields and navigated to it, silently dropping any active filter the form doesn't represent (e.g. a category/type filter applied via a dashboard quick-filter pill or stats-widget click). populateCurrentFilters() also only read search/status back out of the URL into the form, not the date ranges/priority range/user fields the form does control. Fixed performAdvancedSearch() to start from the current URL's params and only set/clear the ones this form actually represents, leaving everything else untouched. Also fixed populateCurrentFilters() to restore all of those fields, not just search/status — without that, reopening the modal and submitting without touching anything would now silently wipe date/priority/user filters that were active but shown blank in the form (a new foot-gun the first fix alone would have introduced). Verified via jsdom: category/type/sort params not represented in the form survive a search submission; page resets to 1; and reopening the modal with an active created_from filter correctly restores it into the form and preserves it on a no-op resubmit. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01Lhz7pGMaoTfL5sdYS5XiKv --- assets/js/advanced-search.js | 43 +++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/assets/js/advanced-search.js b/assets/js/advanced-search.js index 09c42f9..4572437 100644 --- a/assets/js/advanced-search.js +++ b/assets/js/advanced-search.js @@ -61,25 +61,46 @@ function populateCurrentFilters() { const urlParams = new URLSearchParams(window.location.search); // Search text - if (urlParams.has('search')) { - document.getElementById('adv-search-text').value = urlParams.get('search'); - } + document.getElementById('adv-search-text').value = urlParams.get('search') || ''; // Status - if (urlParams.has('status')) { - const statuses = urlParams.get('status').split(','); - const statusSelect = document.getElementById('adv-status'); - Array.from(statusSelect.options).forEach(option => { - option.selected = statuses.includes(option.value); - }); - } + const statuses = urlParams.has('status') ? urlParams.get('status').split(',') : []; + const statusSelect = document.getElementById('adv-status'); + Array.from(statusSelect.options).forEach(option => { + option.selected = statuses.includes(option.value); + }); + + // Date ranges + document.getElementById('adv-created-from').value = urlParams.get('created_from') || ''; + document.getElementById('adv-created-to').value = urlParams.get('created_to') || ''; + document.getElementById('adv-updated-from').value = urlParams.get('updated_from') || ''; + document.getElementById('adv-updated-to').value = urlParams.get('updated_to') || ''; + + // Priority range + document.getElementById('adv-priority-min').value = urlParams.get('priority_min') || ''; + document.getElementById('adv-priority-max').value = urlParams.get('priority_max') || ''; + + // Users + document.getElementById('adv-created-by').value = urlParams.get('created_by') || ''; + document.getElementById('adv-assigned-to').value = urlParams.get('assigned_to') || ''; } // Perform advanced search function performAdvancedSearch(event) { event.preventDefault(); - const params = new URLSearchParams(); + // Start from the CURRENT URL's params, not a fresh set, so a filter this + // form doesn't represent (e.g. a category/type filter applied via a + // dashboard quick-filter pill or stats-widget click) isn't silently + // dropped on submit. Only the params this form actually controls are + // set/cleared below; everything else passes through untouched. + const params = new URLSearchParams(window.location.search); + const advParams = [ + 'search', 'created_from', 'created_to', 'updated_from', 'updated_to', + 'status', 'priority_min', 'priority_max', 'created_by', 'assigned_to', + ]; + advParams.forEach(key => params.delete(key)); + params.delete('page'); // filters changed — reset to page 1 // Search text const searchText = document.getElementById('adv-search-text').value.trim();