Skip to content

Commit 635d3de

Browse files
authored
Merge pull request #756 from maykinmedia/fix/1707-remove-double-search-bar
[#1707] Remove double search bar from search page
2 parents 4cde0cb + b768920 commit 635d3de

File tree

24 files changed

+432
-166
lines changed

24 files changed

+432
-166
lines changed

.github/workflows/ci.yml

+13-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ env:
1616
jobs:
1717
#
1818
# Unit and integration tests
19-
#
19+
#
2020
tests:
2121
name: Run the Django test suite
2222
runs-on: ubuntu-latest
@@ -29,7 +29,7 @@ jobs:
2929
ports:
3030
- 5432:5432
3131
# needed because the postgres container does not provide a healthcheck
32-
options:
32+
options:
3333
--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
3434
--name postgres
3535

@@ -64,7 +64,7 @@ jobs:
6464
--parallel \
6565
--exclude-tag=e2e \
6666
--exclude-tag=elastic
67-
coverage run src/manage.py test src --tag=elastic
67+
coverage run src/manage.py test src --tag=elastic --exclude-tag=e2e
6868
coverage combine
6969
7070
env:
@@ -104,6 +104,16 @@ jobs:
104104
options:
105105
--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
106106
--name postgres
107+
108+
elasticsearch:
109+
image: docker.elastic.co/elasticsearch/elasticsearch:7.9.2
110+
env:
111+
discovery.type: single-node
112+
ES_JAVA_OPTS: '-Xms512m -Xmx512m'
113+
ports:
114+
- 9200:9200
115+
- 9300:9300
116+
107117
steps:
108118
- uses: actions/checkout@v3
109119
- name: Set up backend environment

requirements/base.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ glom==20.11.0
320320
# via
321321
# -r requirements/base.in
322322
# mozilla-django-oidc-db
323-
greenlet==2.0.1
323+
greenlet==2.0.2
324324
# via playwright
325325
html5lib==1.1
326326
# via
@@ -391,7 +391,7 @@ pillow==9.0.1
391391
# easy-thumbnails
392392
# reportlab
393393
# weasyprint
394-
playwright==1.28.0
394+
playwright==1.38.0
395395
# via -r requirements/base.in
396396
polib==1.1.1
397397
# via django-rosetta

requirements/ci.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ glom==20.11.0
537537
# -c requirements/base.txt
538538
# -r requirements/base.txt
539539
# mozilla-django-oidc-db
540-
greenlet==2.0.1
540+
greenlet==2.0.2
541541
# via
542542
# -c requirements/base.txt
543543
# -r requirements/base.txt
@@ -691,7 +691,7 @@ pillow==9.0.1
691691
# weasyprint
692692
platformdirs==2.4.0
693693
# via pylint
694-
playwright==1.28.0
694+
playwright==1.38.0
695695
# via
696696
# -c requirements/base.txt
697697
# -r requirements/base.txt

requirements/dev.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ glom==20.11.0
582582
# -c requirements/ci.txt
583583
# -r requirements/ci.txt
584584
# mozilla-django-oidc-db
585-
greenlet==2.0.1
585+
greenlet==2.0.2
586586
# via
587587
# -c requirements/ci.txt
588588
# -r requirements/ci.txt
@@ -771,7 +771,7 @@ platformdirs==2.4.0
771771
# -r requirements/ci.txt
772772
# black
773773
# pylint
774-
playwright==1.28.0
774+
playwright==1.38.0
775775
# via
776776
# -c requirements/ci.txt
777777
# -r requirements/ci.txt

src/open_inwoner/cms/cases/tests/test_htmx.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ def test_cases(self, m):
450450
contact_form = page.locator("#contact-form")
451451
expect(contact_form).to_be_visible()
452452

453-
question_text_area = page.get_by_label(_("Vraag"))
453+
question_text_area = page.get_by_role("textbox", name=_("Vraag"))
454454
expect(question_text_area).to_be_visible()
455455

456456
question_text_area.fill("a question")

src/open_inwoner/components/templates/components/Button/Button.html

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
aria-label="{% firstof title text %}"
3131
{% as_attributes extra_attributes %}
3232
{% if id %} id="{{ id }}" {% endif %}
33+
{% if form_id %} form="{{ form_id }}"{% endif %}
3334
{% if ariaExpanded %} aria-expanded="{{ ariaExpanded }}" {% endif %}
3435
>
3536
{% if icon %}{% icon icon=icon outlined=icon_outlined %}{% endif %}

src/open_inwoner/components/templates/components/Filter/Filter.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</legend>
99
<div class="filter__list">
1010
{% for option in field.field.choices %}
11-
{% choice_checkbox choice=option name=field.name data=field.data index=forloop.counter %}
11+
{% choice_checkbox choice=option name=field.name data=field.data index=forloop.counter form_id=form_id %}
1212
{% endfor %}
1313
</div>
1414
</fieldset>

src/open_inwoner/components/templates/components/Form/ChoiceCheckbox.html

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
name="{{ name }}"
88
value="{{ choice.0|unlocalize }}"
99
id="id_{{ name }}_{{ index }}"
10+
{% if form_id %}form="{{ form_id }}"{% endif %}
1011
{% if choice.0 in data or choice.0|add:0 in data %}checked="checked"{% endif %}
1112
/>
1213
<label class="checkbox__label" for="id_{{ name }}_{{ index }}">{{ choice.1 }}</label>
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{% load button_tags %}
22
<div class="form__actions {% if single %}form__actions--single{% endif %}">
3-
{% if secondary_text %}{% button href=secondary_href secondary=secondary text=secondary_text icon=secondary_icon icon_position=secondary_icon_position %}{% endif %}
4-
{% if secondary_name %}{% button name=secondary_name type="submit" secondary=secondary text=secondary_text icon=secondary_icon icon_position=secondary_icon_position %}{% endif %}
5-
{% if secondary_value %}{% button name=secondary_name value=secondary_value type="submit" secondary=secondary text=secondary_text icon=secondary_icon icon_position=secondary_icon_position %}{% endif %}
6-
{% button text=primary_text icon=primary_icon primary=primary type="submit" icon_position="after" hide_text=hide_primary_text transparent=transparent %}
3+
{% if secondary_text %}{% button href=secondary_href secondary=secondary text=secondary_text icon=secondary_icon icon_position=secondary_icon_position form_id=form_id %}{% endif %}
4+
{% if secondary_name %}{% button name=secondary_name type="submit" secondary=secondary text=secondary_text icon=secondary_icon icon_position=secondary_icon_position form_id=form_id %}{% endif %}
5+
{% if secondary_value %}{% button name=secondary_name value=secondary_value type="submit" secondary=secondary text=secondary_text icon=secondary_icon icon_position=secondary_icon_position form_id=form_id %}{% endif %}
6+
{% button text=primary_text icon=primary_icon primary=primary type="submit" icon_position="after" hide_text=hide_primary_text transparent=transparent form_id=form_id %}
77
</div>

src/open_inwoner/components/templates/components/Form/Input.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
{{ field.label }}
88
{% if field.field.required %}<span class="label__label--required"> * </span>{% endif %}
99
</span>
10-
{{ field|addclass:"input" }}
10+
{% field_as_widget field "input" form_id %}
1111
{% if field.help_text and not no_help %}
1212
<p class="p">{{ field.help_text }}</p>
1313
{% endif %}

src/open_inwoner/components/templates/components/Header/Header.html

+21-30
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,13 @@
3131
{# end of mobile header-menu with logo #}
3232

3333
<div class="header__submenu">
34-
{% if cms_apps.products %}
35-
{% if request.user.is_authenticated or not config.hide_search_from_anonymous_users %}
34+
{% if cms_apps.products and request.user.is_authenticated or not config.hide_search_from_anonymous_users %}
3635
<nav class="header__actions header__actions--open" aria-label="Zoek navigatie mobiel">
37-
{% url 'search:search' as search_url %}
38-
{% render_form form=search_form method="GET" form_action=search_url inline=True spaceless=False %}
39-
{% input search_form.query no_label=True %}
40-
{% form_actions primary_icon="search" primary_text=_("Zoeken") hide_primary_text=True %}
41-
{% endrender_form %}
36+
<form id="search-form-mobile-open" class="search-form-delegate form form--inline">
37+
{% input search_form.query no_label=True %}
38+
{% form_actions primary_icon="search" primary_text=_("Zoeken") hide_primary_text=True %}
39+
</form>
4240
</nav>
43-
{% endif %}
4441
{% endif %}
4542

4643
<nav class="primary-navigation" aria-label="Hoofd navigatie">
@@ -111,33 +108,27 @@
111108

112109
{% include "components/Header/PrimaryNavigation.html" %}
113110

114-
{% if cms_apps.products %}
115-
{% if request.user.is_authenticated or not config.hide_search_from_anonymous_users %}
116-
<nav class="header__actions" aria-label="Zoek navigatie desktop">
117-
{% url 'search:search' as search_url %}
118-
{% render_form form=search_form method="GET" form_action=search_url inline=True spaceless=True %}
119-
{% input search_form.query no_label=True %}
120-
{% form_actions primary_icon="search" primary_text=_("Zoeken") hide_primary_text=True %}
121-
{% endrender_form %}
122-
</nav>
123-
{% endif %}
111+
{% if cms_apps.products and request.user.is_authenticated or not config.hide_search_from_anonymous_users %}
112+
<nav class="header__actions" aria-label="Zoek navigatie desktop">
113+
<form id="search-form-desktop" class="search-form-delegate form form--spaceless form--inline">
114+
{% input search_form.query no_label=True %}
115+
{% form_actions primary_icon="search" primary_text=_("Zoeken") hide_primary_text=True %}
116+
</form>
117+
</nav>
124118
{% endif %}
125119

126120
{% include "components/Header/NavigationAuthenticated.html" %}
127121
</div>
128122
{# end of header container #}
129123
</header>
130124

131-
{% if cms_apps.products %}
132-
{% if request.user.is_authenticated or not config.hide_search_from_anonymous_users %}
133-
<section class="search search__mobile search__mobile--closed">
134-
<nav class="search__actions " aria-label="Zoek navigatie mobiel">
135-
{% url 'search:search' as search_url %}
136-
{% render_form form=search_form method="GET" form_action=search_url inline=True spaceless=False %}
137-
{% input search_form.query no_label=True %}
138-
{% form_actions primary_icon="search" primary_text=_("Zoeken") hide_primary_text=True %}
139-
{% endrender_form %}
140-
</nav>
141-
</section>
142-
{% endif %}
125+
{% if cms_apps.products and request.user.is_authenticated or not config.hide_search_from_anonymous_users %}
126+
<section class="search search__mobile search__mobile--closed">
127+
<nav class="search__actions " aria-label="Zoek navigatie mobiel">
128+
<form id="search-form-mobile-closed" class="search-form-delegate form form--inline">
129+
{% input search_form.query no_label=True %}
130+
{% form_actions primary_icon="search" primary_text=_("Zoeken") hide_primary_text=True %}
131+
</form>
132+
</nav>
133+
</section>
143134
{% endif %}

src/open_inwoner/components/templatetags/button_tags.py

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ def button(text, **kwargs):
4343
Variables:
4444
+ text: string | this will be the button text.
4545
- class: str | Additional classes.
46+
- form_id: str | ID of parent form, sets 'form' attribute.
4647
- hide_text: bool | whether to hide the text and use aria attribute instead.
4748
- href: url or string | where the link links to (can be url name).
4849
- uuid: string | if href is an url name, pk for reverse can be passed.

src/open_inwoner/components/templatetags/filter_tags.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55

66
@register.inclusion_tag("components/Filter/Filter.html")
7-
def filter(field, **kwargs):
7+
def filters(field, **kwargs):
88
"""
99
Building the filter options for the search page.
1010
1111
Usage:
12-
{% filter field=field %}
12+
{% filters field=field %}
1313
1414
Variables:
1515
+ field: Field | This is a form field.

src/open_inwoner/components/templatetags/form_tags.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,9 @@ def hidden(field, **kwargs):
356356

357357

358358
@register.inclusion_tag("components/Form/FormActions.html")
359-
def form_actions(primary_text="", primary_icon=None, secondary=True, **kwargs):
359+
def form_actions(
360+
primary_text="", primary_icon=None, secondary=True, form_id=None, **kwargs
361+
):
360362
"""
361363
Rendering the form actions. This may contain a primary and or secondary button.
362364
@@ -393,6 +395,7 @@ def form_actions(primary_text="", primary_icon=None, secondary=True, **kwargs):
393395
"primary_icon": primary_icon,
394396
"primary": primary,
395397
"secondary": secondary,
398+
"form_id": form_id,
396399
}
397400

398401

@@ -411,6 +414,19 @@ def addclass(field, class_string):
411414
return field.as_widget(attrs={"class": class_string})
412415

413416

417+
@register.simple_tag()
418+
def field_as_widget(field, class_string, form_id):
419+
"""
420+
Clone of addclass-filter but with more atributes
421+
"""
422+
attrs = {}
423+
if class_string:
424+
attrs["class"] = class_string
425+
if form_id:
426+
attrs["form"] = form_id
427+
return field.as_widget(attrs=attrs)
428+
429+
414430
@register.simple_tag(takes_context=True)
415431
def initial_match(context):
416432
initial = context.get("initial")

src/open_inwoner/js/components/search/filter-mobile.js

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ export class FilterMobile {
99

1010
toggleOpen(event) {
1111
event.preventDefault()
12-
console.log('this is mobile')
1312
const filterParent = this.node.parentElement
1413
if (filterParent) {
1514
filterParent.classList.toggle('filter--open')
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,7 @@
1-
const radioButtons = document.querySelectorAll(
2-
'.feedback__options .button-radio__input'
3-
)
4-
5-
;[...radioButtons].forEach((radioButton) => {
6-
radioButton.addEventListener('click', (event) => {
7-
const feedbackRemarks = document.querySelectorAll('.feedback__remark')
8-
;[...feedbackRemarks].forEach((feedbackRemark) =>
9-
feedbackRemark.classList.add('feedback__remark--show')
10-
)
11-
})
12-
})
13-
14-
let timerId = null
15-
161
const searchForm = document.getElementById('search-form')
172

18-
const filterButtons = document.querySelectorAll('.filter .checkbox__input')
19-
;[...filterButtons].forEach((checkbox) => {
3+
document.querySelectorAll('.filter .checkbox__input').forEach((checkbox) => {
204
checkbox.addEventListener('change', (event) => {
21-
clearTimeout(timerId)
22-
23-
// Set a new interval
24-
timerId = setTimeout(() => {
25-
searchForm.submit()
26-
}, 250)
5+
searchForm.submit()
276
})
287
})
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,34 @@
11
import './filter-mobile'
22
import './filter-options'
3+
4+
const searchForm = document.getElementById('search-form')
5+
6+
// connect multiple search boxes to centralized hidden form
7+
document.querySelectorAll('.search-form-delegate').forEach((form) => {
8+
console.log(['connecting .search-form-delegate', form, 'to', searchForm])
9+
// make sure all forms have same query
10+
form.query.value = searchForm.query.value
11+
12+
// setup to copy the query and submit the actual search form instead of the delegate
13+
form.addEventListener('submit', (event) => {
14+
event.preventDefault()
15+
const query = event.target.query.value.trim()
16+
if (query !== '') {
17+
searchForm.query.value = query
18+
searchForm.submit()
19+
}
20+
})
21+
})
22+
23+
// connect search feedback
24+
document
25+
.querySelectorAll('.feedback__options .button-radio__input')
26+
.forEach((radioButton) => {
27+
radioButton.addEventListener('click', (event) => {
28+
document
29+
.querySelectorAll('.feedback__remark')
30+
.forEach((feedbackRemark) =>
31+
feedbackRemark.classList.add('feedback__remark--show')
32+
)
33+
})
34+
})

src/open_inwoner/scss/components/Form/Form.scss

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
gap: 0;
1818
}
1919

20+
&--hidden {
21+
display: none;
22+
}
23+
2024
&--horizontal {
2125
.form__control > .label {
2226
flex-direction: row;

src/open_inwoner/search/results.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from collections import OrderedDict
22
from dataclasses import dataclass
3+
from operator import attrgetter
34
from typing import List, Type
45

56
from django.db import models
@@ -21,7 +22,6 @@ class FacetBucket:
2122

2223
@property
2324
def label(self) -> str:
24-
"""display in the label"""
2525
return f"{self.name} ({self.count})"
2626

2727

@@ -81,6 +81,12 @@ def total_buckets(self) -> List[FacetBucket]:
8181
def choices(self) -> list:
8282
return [(b.slug, b.label) for b in self.buckets]
8383

84+
def total_choices(self) -> list:
85+
return [
86+
(b.slug, b.label)
87+
for b in sorted(self.total_buckets, key=attrgetter("slug"))
88+
]
89+
8490

8591
@dataclass()
8692
class ProductSearchResult:

0 commit comments

Comments
 (0)