Skip to content

Commit

Permalink
Merge pull request #136 from springload/feature/search-filters
Browse files Browse the repository at this point in the history
Support content-type search filters
  • Loading branch information
sarahframe authored Jul 8, 2024
2 parents c3139d4 + 0a8289f commit 626f92f
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 66 deletions.
50 changes: 40 additions & 10 deletions cdhweb/pages/forms.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,44 @@
from django import forms
from django.db import models
from wagtail.models import Page

from cdhweb.blog.models import BlogPost
from cdhweb.events.models import Event
from cdhweb.people.models import Profile
from cdhweb.projects.models import Project


class SiteSearchFilters(models.TextChoices):
EVERYTHING = "everything", "Everything"
PEOPLE = "people", "People"
UPDATES = "updates", "Blogs & news"
PROJECTS = "projects", "Projects"
EVENTS = "events", "Events"

def model_class(self):
mapping = {
"everything": Page,
"people": Profile,
"updates": BlogPost,
"projects": Project,
"events": Event,
}
return mapping[self.value]

def icon(self):
mapping = {
"everything": "doc",
"people": "person",
"updates": "blog",
"projects": "folder",
"events": "cal",
}
return mapping[self.value]


class SiteSearchForm(forms.Form):
"""Search form for finding pages across the site."""

# page filter options — currently not implemented in UI
FILTER_CHOICES = (
("everything", "everything"),
("people", "people"),
("updates", "updates"),
("projects", "projects"),
("events", "events"),
)

# keyword query
q = forms.CharField(
required=False,
Expand All @@ -25,4 +51,8 @@ class SiteSearchForm(forms.Form):
)

# filter to different page types
# filter = forms.ChoiceField(choices=FILTER_CHOICES)
filter = forms.ChoiceField(choices=SiteSearchFilters.choices, required=False)

@staticmethod
def filter_choices():
return SiteSearchFilters
11 changes: 6 additions & 5 deletions cdhweb/pages/templatetags/core_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,25 @@ def site_footer(context):
"contact_links", "useful_links", "imprint_links"
)

data = {
"request": context["request"],
"site_search": context["site_search"],
}
if footers.exists():
contact_links = footers.first().contact_links.all()
social_media_links = footers.first().social_media_links.all()
physical_address = footers.first().address
useful_links = footers.first().useful_links.all()
imprint_links = footers.first().imprint_links.all()

data = {
data |= {
"contact_links": contact_links,
"social_media_links": social_media_links,
"physical_address": physical_address,
"useful_links": useful_links,
"imprint_links": imprint_links,
"request": context["request"],
}
return data
else:
return None
return data


def _minor_menu_item_to_dict(item):
Expand Down
18 changes: 15 additions & 3 deletions cdhweb/pages/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from wagtail.models import Page
from wagtail.search.utils import parse_query_string

from cdhweb.pages.forms import SiteSearchForm
from cdhweb.pages.forms import SiteSearchFilters, SiteSearchForm


class LastModifiedMixin(View):
Expand Down Expand Up @@ -70,16 +70,28 @@ class SiteSearchView(ListView, FormMixin):
template_name = "cdhpages/search.html"

def get_queryset(self):
queryset = self.model.objects.live().public()
form = self.get_form()

if not form.is_valid():
print(form.errors)
return queryset.none()

# get keyword query; support filters & phrase matching with double quotes
# see https://docs.wagtail.io/en/stable/topics/search/searching.html#query-string-parsing
q = self.request.GET.get("q", "")
q = form.cleaned_data.get("q", "")
_filters, query = parse_query_string(q) # not using these filters yet
query.operator = "or" # set query operator to OR (default is AND)

type_filter = form.cleaned_data.get("filter", "")
if type_filter:
filter_class = SiteSearchFilters(type_filter).model_class()
queryset = queryset.type(filter_class)

# execute search; exclude unpublished pages.
# NOTE results sorted by relevance by default; to override sort the QS
# first and then pass order_by_relevance=false to .search()
return self.model.objects.live().search(query)
return queryset.search(query)

def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
Expand Down
31 changes: 24 additions & 7 deletions cdhweb/static_src/components/SearchForm/SearchForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,54 @@ const SearchForm = ({ searchUrl, extraClasses }: Props): JSX.Element => {
type="radio"
name="filter"
id={`${uniqueId}_everything`}
value="everything"
checked
/>
<label htmlFor={`${uniqueId}_everything`}>Everything</label>
</div>
</div>
<div className="search-form__radio">
<div className="radio">
<input type="radio" name="filter" id={`${uniqueId}_people`} />
<input
type="radio"
name="filter"
id={`${uniqueId}_people`}
value="people"
/>
<label htmlFor={`${uniqueId}_people`}>People</label>
</div>
</div>
<div className="search-form__radio">
<div className="radio">
<input type="radio" name="filter" id={`${uniqueId}_projects`} />
<label htmlFor={`${uniqueId}_projects`}>Projects</label>
<input
type="radio"
name="filter"
id={`${uniqueId}_blogs-and-news"`}
value="updates"
/>
<label htmlFor={`${uniqueId}_blogs-and-news"`}>Blogs & news</label>
</div>
</div>
<div className="search-form__radio">
<div className="radio">
<input type="radio" name="filter" id={`${uniqueId}_events`} />
<label htmlFor={`${uniqueId}_events`}>Events</label>
<input
type="radio"
name="filter"
id={`${uniqueId}_projects`}
value="projects"
/>
<label htmlFor={`${uniqueId}_projects`}>Projects</label>
</div>
</div>
<div className="search-form__radio">
<div className="radio">
<input
type="radio"
name="filter"
id={`${uniqueId}_blogs-and-news"`}
id={`${uniqueId}_events`}
value="events"
/>
<label htmlFor={`${uniqueId}_blogs-and-news"`}>Blogs & news</label>
<label htmlFor={`${uniqueId}_events`}>Events</label>
</div>
</div>
</fieldset>
Expand Down
46 changes: 10 additions & 36 deletions templates/includes/search_form.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{% load core_tags %}

{% comment %}
{% comment %}
This form will appear in more than one place on the page (main nav (though that's a tsx version), footer, and on the search page).
So `uniqueID` is used to prefix IDs (and their `for`s), so we don't get duplicate IDs in the markup.
{% endcomment %}
Expand All @@ -12,40 +12,14 @@
</div>
<fieldset class="search-form__filters">
<legend class="sr-only">Filter search results by</legend>
<div class="radio">
<div class="search-form__radio">
<input type="radio" name="filter" id="{{ uniqueID }}_everything" checked />
<label for="{{ uniqueID }}_everything">Everything</label>
{% include 'includes/svg.html' with sprite="two-tone" svg="doc" %}
{% for filter_option in site_search.filter_choices %}
<div class="radio">
<div class="search-form__radio">
<input type="radio" name="filter" value="{{ filter_option.value }}" id="{{ uniqueID }}_{{ filter_option.value }}" {% if form.filter.value == filter_option.value %}checked{% endif %}/>
<label for="{{ uniqueID }}_{{ filter_option.value }}">{{ filter_option.label }}</label>
{% include 'includes/svg.html' with sprite="two-tone" svg=filter_option.icon %}
</div>
</div>
</div>
<div class="radio">
<div class="search-form__radio">
<input type="radio" name="filter" id="{{ uniqueID }}_people" />
<label for="{{ uniqueID }}_people">People</label>
{% include 'includes/svg.html' with sprite="two-tone" svg="person" %}
</div>
</div>
<div class="radio">
<div class="search-form__radio">
<input type="radio" name="filter" id="{{ uniqueID }}_projects" />
<label for="{{ uniqueID }}_projects">Projects</label>
{% include 'includes/svg.html' with sprite="two-tone" svg="folder" %}
</div>
</div>
<div class="radio">
<div class="search-form__radio">
<input type="radio" name="filter" id="{{ uniqueID }}_events" />
<label for="{{ uniqueID }}_events">Events</label>
{% include 'includes/svg.html' with sprite="two-tone" svg="cal" %}
</div>
</div>
<div class="radio">
<div class="search-form__radio">
<input type="radio" name="filter" id="{{ uniqueID }}_blogs-and-news" />
<label for="{{ uniqueID }}_blogs-and-news">Blogs & news</label>
{% include 'includes/svg.html' with sprite="two-tone" svg="blog" %}
</div>
</div>
{% endfor %}
</fieldset>
</form>
</form>
8 changes: 3 additions & 5 deletions templates/includes/search_result.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
{# Single search result on site search page #}

{% spaceless %}
{% autoescape off %}
<li class="{{ page.get_url|url_to_icon }}">

{# Show relevant icon. Falls back to "doc" icon #}
{% comment %}
TODO: would prefer to do this conditional:
Expand All @@ -15,7 +14,7 @@
{% include 'includes/svg.html' with sprite="two-tone" svg=page.get_url|url_to_icon %}
{% else %}
{% include 'includes/svg.html' with sprite="two-tone" svg="doc" %}
{% endif %}
{% endif %}
<div>
<h3>
<a href="{% pageurl page %}">{{ page.title }}</a>
Expand All @@ -29,5 +28,4 @@ <h3>
</p>
</div>
</li>
{% endautoescape %}
{% endspaceless %}
{% endspaceless %}

0 comments on commit 626f92f

Please sign in to comment.