Skip to content

Commit 331746f

Browse files
committed
Include search sort and filter in URL
1 parent 95baecd commit 331746f

File tree

2 files changed

+106
-2
lines changed

2 files changed

+106
-2
lines changed

pytest_mpl/summary/templates/extra.js

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ var options = {
1717
'rms-value', 'baseline-hash-value', 'result-hash-value']
1818
};
1919
var resultsList = new List('results', options);
20-
resultsList.sort('status-sort', {order: "desc"});
2120

2221
var filterClasses = [];
2322
var filterElements = document.getElementById('filterForm').getElementsByClassName('filter');
@@ -26,19 +25,121 @@ for (var i = 0, elem; elem = filterElements[i++];) {
2625
}
2726
countClasses();
2827

28+
// Get and apply initial search parameters from URL
29+
var searchParams = new URLSearchParams(window.location.search);
30+
if (window.location.search.length > 0) {
31+
applyURL();
32+
} else { // If no parameters, apply default but don't update the URL
33+
resultsList.sort('status-sort', {order: "desc"});
34+
}
35+
36+
// Record URL parameters after new sort (but do not update URL yet)
37+
resultsList.on('sortComplete', function updateSortURL() {
38+
var sortElements = document.getElementsByClassName('sort');
39+
for (var i = 0, elem; elem = sortElements[i++];) {
40+
if (elem.checked) {
41+
searchParams.set('sort', elem.dataset['sort']);
42+
searchParams.set('order', getSortOrder(elem));
43+
break;
44+
}
45+
}
46+
})
47+
48+
// Update URL when filter sidebar is hidden
49+
var filterOffcanvas = document.getElementById('offcanvasFilter');
50+
filterOffcanvas.addEventListener('hide.bs.offcanvas', function () {
51+
updateURL();
52+
})
53+
54+
// Update URL when search bar is clicked away from
55+
function searchComplete() {
56+
var q = document.getElementsByClassName('search')[0].value;
57+
if (q.length > 0) { // Include query in URL if active query
58+
searchParams.set('q', q);
59+
} else {
60+
searchParams.delete('q');
61+
}
62+
updateURL();
63+
}
64+
65+
// Search, sort and filter by the current URL parameters
66+
function applyURL() {
67+
// Get and apply sort
68+
var sort = searchParams.get('sort');
69+
if (sort) {
70+
document.getElementsByName('sort').forEach(
71+
function selectSort(elem) {
72+
if (elem.dataset['sort'] == sort) {
73+
elem.checked = true;
74+
}
75+
}
76+
)
77+
resultsList.sort(sort, {order: searchParams.get('order')});
78+
}
79+
// Get and apply filters
80+
var filters = searchParams.getAll('f');
81+
if (filters.length > 0) {
82+
var cond = searchParams.get('c');
83+
if (cond === 'and') {
84+
document.getElementById('conditionand').checked = true;
85+
} else if (cond === 'or') {
86+
document.getElementById('conditionor').checked = true;
87+
}
88+
for (var i = 0, f; f = filters[i++];) {
89+
document.getElementById(f).checked = true;
90+
}
91+
applyFilters();
92+
}
93+
// Get and apply search
94+
var query = searchParams.get('q');
95+
if (query) {
96+
document.getElementsByClassName('search')[0].value = query;
97+
resultsList.search(query);
98+
}
99+
}
100+
101+
// Update the URL with the current search parameters
102+
function updateURL() {
103+
var query = searchParams.toString();
104+
if (query.length > 0) { // Don't end the URL with '?'
105+
query = '?' + query;
106+
}
107+
if (window.location.search != query) { // Update URL if changed
108+
history.replaceState(null, '', window.location.pathname + query);
109+
}
110+
}
111+
112+
// Get the current sorting order from an active sort radio button
113+
function getSortOrder(elem) {
114+
var fixedOrder = elem.dataset['order'];
115+
if (fixedOrder == 'asc' || fixedOrder == 'desc') {
116+
return fixedOrder;
117+
} else if (elem.classList.contains('desc')) {
118+
return 'desc';
119+
} else if (elem.classList.contains('asc')) {
120+
return 'asc';
121+
} else {
122+
return 'asc';
123+
}
124+
}
125+
29126
function applyFilters() {
127+
searchParams.delete('f');
128+
searchParams.delete('c');
30129
var cond_and = document.getElementById('filterForm').elements['conditionand'].checked;
31130
var filters = [];
32131
var filterElements = document.getElementById('filterForm').getElementsByClassName('filter');
33132
for (var i = 0, elem; elem = filterElements[i++];) {
34133
if (elem.checked) {
35134
filters.push(elem.id);
135+
searchParams.append('f', elem.id);
36136
}
37137
}
38138
if (filters.length == 0) {
39139
resultsList.filter(); // Show all if nothing selected
40140
return countClasses();
41141
}
142+
searchParams.set('c', (cond_and) ? 'and' : 'or');
42143
resultsList.filter(function (item) {
43144
var inc = false;
44145
for (var i = 0, filt; filt = filters[i++];) {
@@ -62,6 +163,8 @@ function resetFilters() {
62163
resultsList.filter();
63164
document.getElementById("filterForm").reset();
64165
countClasses();
166+
searchParams.delete('f');
167+
searchParams.delete('c');
65168
}
66169

67170
function countClasses() {

pytest_mpl/summary/templates/navbar.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
</a>
66
<div class="d-flex nav-filtertools">
77
<div class="spacer"></div>
8-
<input class="form-control me-2 search" type="search" placeholder="Search" aria-label="Search">
98
<form class="me-2 nav-searchbar" onsubmit="return false">
9+
<input class="form-control me-2 search" type="search" onblur="searchComplete()" placeholder="Search"
10+
aria-label="Search">
1011
</form>
1112
<button class="btn btn-outline-primary" aria-label="Filter" type="button" data-bs-toggle="offcanvas"
1213
data-bs-target="#offcanvasFilter" aria-controls="offcanvasFilter">

0 commit comments

Comments
 (0)