refactor: add ajax filter functionality#3489
Conversation
There was a problem hiding this comment.
Sorry @ViRUS-0-0, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
There was a problem hiding this comment.
Pull request overview
This PR implements AJAX-based filter application/clearing (to avoid full page reloads) by adding a shared frontend script, wiring it into the common/control base templates, and tagging the shared filter “clear” action so it can be intercepted.
Changes:
- Added
ajax-filter.jsto fetch filtered HTML via GET and replace the table + pagination in-place. - Updated the shared filter actions template to mark the clear action with a dedicated class and adjust button grouping.
- Loaded the new script globally in both
eventyay_commonandpretixcontrolbase templates.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| app/eventyay/static/eventyay-common/js/ajax-filter.js | Adds AJAX interception for filter submit/clear/pagination and DOM replacement logic. |
| app/eventyay/eventyay_common/templates/eventyay_common/filter_actions.html | Adds btn-clear-filter hook and changes the filter actions wrapper classes. |
| app/eventyay/eventyay_common/templates/eventyay_common/base.html | Loads the new AJAX filter script for eventyay_common pages. |
| app/eventyay/control/templates/pretixcontrol/base.html | Loads the new AJAX filter script for pretixcontrol pages. |
| // Find the relevant form | ||
| var $form = $('form').filter(function() { | ||
| return $(this).hasClass('filter-form') || $(this).find('.filter-form').length > 0 || $(this).closest('.filter-form').length > 0; | ||
| }).first(); |
| // Find the relevant form | ||
| var $form = $('form').filter(function() { | ||
| return $(this).hasClass('filter-form') || $(this).find('.filter-form').length > 0 || $(this).closest('.filter-form').length > 0; | ||
| }).first(); | ||
|
|
||
| // Find the target table or container | ||
| var $tableContainer = $('.table-responsive'); | ||
| if ($tableContainer.length === 0) { | ||
| $tableContainer = $('table.table').first(); | ||
| } | ||
|
|
||
| if ($form.length === 0 || $tableContainer.length === 0) { | ||
| return; | ||
| } | ||
|
|
||
| function fetchAndReplace(url, replaceUrlParams) { | ||
| var $paginationContainer = $('.pagination'); | ||
|
|
| var $paginationContainer = $('.pagination'); | ||
|
|
||
| $tableContainer.css('opacity', '0.5'); | ||
| if ($paginationContainer.length) { | ||
| $paginationContainer.css('opacity', '0.5'); | ||
| } | ||
|
|
||
| $.ajax({ | ||
| url: url, | ||
| type: 'GET', | ||
| success: function(data) { | ||
| var doc = new DOMParser().parseFromString(data, 'text/html'); | ||
| var $newDoc = $(doc); | ||
|
|
||
| // Replace table or container content | ||
| var newTableContainer = $newDoc.find('.table-responsive'); | ||
| if (newTableContainer.length === 0) { | ||
| newTableContainer = $newDoc.find('table.table').first(); | ||
| } | ||
|
|
||
| if (newTableContainer.length) { | ||
| // If we're replacing the table directly (no wrapper), use replaceWith | ||
| if ($tableContainer.is('table')) { | ||
| $tableContainer.replaceWith(newTableContainer); | ||
| $tableContainer = newTableContainer; // Update reference | ||
| } else { | ||
| $tableContainer.html(newTableContainer.html()); | ||
| } | ||
| } | ||
|
|
||
| // Replace pagination content or remove it if none exists | ||
| var newPagination = $newDoc.find('.pagination'); | ||
| $paginationContainer = $('.pagination'); // re-query in case it changed | ||
|
|
||
| if (newPagination.length) { | ||
| if ($paginationContainer.length) { | ||
| $paginationContainer.replaceWith(newPagination); | ||
| } else { | ||
| $tableContainer.after($('<div class="pagination text-center"></div>').html(newPagination.html())); | ||
| } | ||
| } else { | ||
| $paginationContainer.remove(); | ||
| } |
| {% load i18n %} | ||
|
|
||
| <div class="filter-actions"> | ||
| <div class="filter-actions btn-group"> |
| <script type="text/javascript" src="{% static "pretixcontrol/js/ui/popover.js" %}"></script> | ||
| <script type="text/javascript" src="{% static "utils/js/utils.js" %}"></script> | ||
| <script type="text/javascript" src="{% static "task_management/js/task_management.js" %}"></script> | ||
| <script type="text/javascript" src="{% static "eventyay-common/js/ajax-filter.js" %}"></script> |
|
@ViRUS-0-0 These are used in many other places like vouchers products etc and in some places ui is also slightly broken if i recall correctly ensure it fixes all those adding videos for all such areas is also highly appreciated |
Closes #2390
This PR refactors the original filter to AJAX filter so that the page itself doesn't reload when filtering. This solves the full HTTP call issue when applying or clearing filter and results in a seamless experience.
This PR adds a new file called
ajax-filter.jswhich takes care of the the
filter_actions.htmlfile which is used as a component to filter in many areas around the codebase.Some of the areas and along with their resolved screen recording is mentioned below.
My Events:
Screen.Recording.2026-05-08.at.12.55.15.AM.mov
My Orders :
Screen.Recording.2026-05-08.at.12.55.00.AM.mov
Orders :
Screen.Recording.2026-05-08.at.12.16.56.AM.mov
My Sessions :
Screen.Recording.2026-05-08.at.12.15.21.AM.mov