Allow saving search preferences (#540)

* Add indicator for modified filters

* Rename shared filter values

* Add update search preferences handler

* Separate search and preferences forms

* Properly initialize bookmark search from get or post

* Add tests for applying search preferences

* Implement saving search preferences

* Remove bookmark search query alias

* Use search preferences as default

* Only show save button for authenticated users

* Only show modified indicator if preferences are modified

* Fix overriding search preferences

* Add missing migration
This commit is contained in:
Sascha Ißbrücker
2023-10-01 21:22:44 +02:00
committed by GitHub
parent 4a2642f16c
commit 41f79e35a0
22 changed files with 1094 additions and 442 deletions

View File

@@ -1,13 +1,16 @@
{% load widget_tweaks %}
<form id="search" action="" method="get" role="search">
<div class="input-group">
<div class="search-container">
<form id="search" class="input-group" action="" method="get" role="search">
<input type="search" class="form-input" name="q" placeholder="Search for words or #tags"
value="{{ search.query }}">
value="{{ search.q }}">
<input type="submit" value="Search" class="btn input-group-btn">
</div>
{% for hidden_field in search_form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
</form>
<div class="search-options dropdown dropdown-right">
<button type="button" class="btn dropdown-toggle">
<button type="button" class="btn dropdown-toggle{% if search.has_modified_preferences %} badge{% endif %}">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" stroke-width="2"
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
@@ -23,40 +26,54 @@
</svg>
</button>
<div class="menu text-sm" tabindex="0">
<div class="form-group">
<label for="{{ form.sort.id_for_label }}" class="form-label">Sort by</label>
{{ form.sort|add_class:"form-select select-sm" }}
</div>
<div class="form-group radio-group">
<div class="form-label">Shared filter</div>
{% for radio in form.shared %}
<label for="{{ radio.id_for_label }}" class="form-radio form-inline">
{{ radio.tag }}
<i class="form-icon"></i>
{{ radio.choice_label }}
</label>
<form id="search_preferences" action="" method="post">
{% csrf_token %}
{% if 'sort' in preferences_form.editable_fields %}
<div class="form-group">
<label for="{{ preferences_form.sort.id_for_label }}"
class="form-label{% if 'sort' in search.modified_params %} text-bold{% endif %}">Sort by</label>
{{ preferences_form.sort|add_class:"form-select select-sm" }}
</div>
{% endif %}
{% if 'shared' in preferences_form.editable_fields %}
<div class="form-group radio-group">
<div class="form-label{% if 'shared' in search.modified_params %} text-bold{% endif %}">Shared filter</div>
{% for radio in preferences_form.shared %}
<label for="{{ radio.id_for_label }}" class="form-radio form-inline">
{{ radio.tag }}
<i class="form-icon"></i>
{{ radio.choice_label }}
</label>
{% endfor %}
</div>
{% endif %}
{% if 'unread' in preferences_form.editable_fields %}
<div class="form-group radio-group">
<div class="form-label{% if 'unread' in search.modified_params %} text-bold{% endif %}">Unread filter</div>
{% for radio in preferences_form.unread %}
<label for="{{ radio.id_for_label }}" class="form-radio form-inline">
{{ radio.tag }}
<i class="form-icon"></i>
{{ radio.choice_label }}
</label>
{% endfor %}
</div>
{% endif %}
<div class="actions">
<button type="submit" class="btn btn-sm btn-primary" name="apply">Apply</button>
{% if request.user.is_authenticated %}
<button type="submit" class="btn btn-sm" name="save">Save as default</button>
{% endif %}
</div>
{% for hidden_field in preferences_form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
</div>
<div class="form-group radio-group">
<div class="form-label">Unread filter</div>
{% for radio in form.unread %}
<label for="{{ radio.id_for_label }}" class="form-radio form-inline">
{{ radio.tag }}
<i class="form-icon"></i>
{{ radio.choice_label }}
</label>
{% endfor %}
</div>
<div class="actions">
<button type="submit" class="btn btn-sm btn-primary">Apply</button>
</div>
</form>
</div>
</div>
</div>
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
</form>
{# Replace search input with auto-complete component #}
<script type="application/javascript">
@@ -65,7 +82,7 @@
const currentTags = currentTagsString.split(' ');
const uniqueTags = [...new Set(currentTags)]
const search = {
q: '{{ search.query }}',
q: '{{ search.q }}',
user: '{{ search.user }}',
shared: '{{ search.shared }}',
unread: '{{ search.unread }}',
@@ -78,7 +95,7 @@
props: {
name: 'q',
placeholder: 'Search for words or #tags',
value: '{{ search.query|safe }}',
value: '{{ search.q|safe }}',
tags: uniqueTags,
mode: '{{ mode }}',
linkTarget: '{{ request.user_profile.bookmark_link_target }}',