Compare commits

...

1 Commits

Author SHA1 Message Date
Jürgen Mummert ac203b37ce Persist event filter state across reload and navigation 2026-02-23 21:54:27 +01:00
@@ -124,6 +124,8 @@
const orgWidget = orgSelect?.closest('.widget-select'); const orgWidget = orgSelect?.closest('.widget-select');
const resetButton = filters.querySelector('#eventfilter-reset'); const resetButton = filters.querySelector('#eventfilter-reset');
const status = filters.querySelector('#eventfilter-status'); const status = filters.querySelector('#eventfilter-status');
const stateStorageKey = 'event-filter-state';
const stateQueryKey = 'event_filter';
const animationMs = 220; const animationMs = 220;
let hideTimers = new WeakMap(); let hideTimers = new WeakMap();
@@ -182,6 +184,109 @@
const locationTom = initTomSelect(locationSelect); const locationTom = initTomSelect(locationSelect);
const orgTom = initTomSelect(orgSelect); const orgTom = initTomSelect(orgSelect);
const hasOptionValue = (selectElement, value) => {
if (!selectElement) {
return false;
}
return Array.from(selectElement.options).some((option) => option.value === value);
};
const rawValueToFilterState = (rawValue) => {
const value = (rawValue || '').trim();
if (!value) {
return { type: 'all', value: '' };
}
if (value.startsWith('tag-') && hasOptionValue(tagSelect, value)) {
return { type: 'tag', value: value.replace('tag-', '') };
}
if (value.startsWith('location-') && hasOptionValue(locationSelect, value)) {
return { type: 'location', value: value.replace('location-', '') };
}
if (value.startsWith('org-') && hasOptionValue(orgSelect, value)) {
return { type: 'org', value: value.replace('org-', '') };
}
return { type: 'all', value: '' };
};
const filterStateToRawValue = (filterState) => {
if (!filterState.value || filterState.type === 'all') {
return '';
}
if (filterState.type === 'tag') {
return `tag-${filterState.value}`;
}
if (filterState.type === 'location') {
return `location-${filterState.value}`;
}
if (filterState.type === 'org') {
return `org-${filterState.value}`;
}
return '';
};
const readUrlState = () => {
const url = new URL(window.location.href);
return (url.searchParams.get(stateQueryKey) || '').trim();
};
const writeUrlState = (value) => {
const url = new URL(window.location.href);
if (value) {
url.searchParams.set(stateQueryKey, value);
} else {
url.searchParams.delete(stateQueryKey);
}
window.history.replaceState(window.history.state, '', url);
};
const readStoredState = () => {
try {
return (window.sessionStorage.getItem(stateStorageKey) || '').trim();
} catch (error) {
return '';
}
};
const writeStoredState = (value) => {
try {
if (value) {
window.sessionStorage.setItem(stateStorageKey, value);
} else {
window.sessionStorage.removeItem(stateStorageKey);
}
} catch (error) {
// noop
}
};
const syncState = (filterState) => {
const rawValue = filterStateToRawValue(filterState);
writeStoredState(rawValue);
writeUrlState(rawValue);
};
const applyControlState = (filterState) => {
const tagValue = filterState.type === 'tag' ? `tag-${filterState.value}` : '';
const locationValue = filterState.type === 'location' ? `location-${filterState.value}` : '';
const orgValue = filterState.type === 'org' ? `org-${filterState.value}` : '';
setSelectValue(tagSelect, tagTom, tagValue);
setSelectValue(locationSelect, locationTom, locationValue);
setSelectValue(orgSelect, orgTom, orgValue);
};
const setSelectValue = (selectElement, tomInstance, value) => { const setSelectValue = (selectElement, tomInstance, value) => {
if (!selectElement) { if (!selectElement) {
return; return;
@@ -314,6 +419,7 @@
}); });
updateStatus(filterState); updateStatus(filterState);
syncState(filterState);
}; };
tagSelect?.addEventListener('change', () => { tagSelect?.addEventListener('change', () => {
@@ -375,5 +481,16 @@
applyFilter({ type: 'all', value: '' }); applyFilter({ type: 'all', value: '' });
}); });
applyFilter(currentFilter); const urlState = readUrlState();
const storedState = readStoredState();
const initialState = rawValueToFilterState(urlState || storedState);
applyControlState(initialState);
applyFilter(initialState);
window.addEventListener('popstate', () => {
const stateFromUrl = rawValueToFilterState(readUrlState());
applyControlState(stateFromUrl);
applyFilter(stateFromUrl);
});
</script> </script>