diff --git a/src/open_inwoner/components/templates/components/Filter/Filter.html b/src/open_inwoner/components/templates/components/Filter/Filter.html
index 31546f24bb..21988d56c3 100644
--- a/src/open_inwoner/components/templates/components/Filter/Filter.html
+++ b/src/open_inwoner/components/templates/components/Filter/Filter.html
@@ -1,9 +1,10 @@
-{% load i18n filter_tags icon_tags form_tags %}
+{% load i18n filter_tags icon_tags button_tags form_tags %}
-
diff --git a/src/open_inwoner/configurations/admin.py b/src/open_inwoner/configurations/admin.py
index bb69c97f62..c5e8886e71 100644
--- a/src/open_inwoner/configurations/admin.py
+++ b/src/open_inwoner/configurations/admin.py
@@ -162,6 +162,16 @@ class SiteConfigurarionAdmin(OrderedInlineModelAdminMixin, SingletonModelAdmin):
),
},
),
+ (
+ _("Search filter options"),
+ {
+ "fields": (
+ "search_filter_categories",
+ "search_filter_tags",
+ "search_filter_organizations",
+ )
+ },
+ ),
(_("Emails"), {"fields": ("email_new_message",)}),
(
_("Openid Connect"),
diff --git a/src/open_inwoner/configurations/migrations/0052_siteconfiguration_search_filters.py b/src/open_inwoner/configurations/migrations/0052_siteconfiguration_search_filters.py
new file mode 100644
index 0000000000..92b460ace0
--- /dev/null
+++ b/src/open_inwoner/configurations/migrations/0052_siteconfiguration_search_filters.py
@@ -0,0 +1,40 @@
+# Generated by Django 3.2.20 on 2023-09-18 10:09
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("configurations", "0051_merge_20230907_1800"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="siteconfiguration",
+ name="search_filter_categories",
+ field=models.BooleanField(
+ default=True,
+ help_text="Whether to show category-checkboxes in order to filter the search result.",
+ verbose_name="Add category filter for search results",
+ ),
+ ),
+ migrations.AddField(
+ model_name="siteconfiguration",
+ name="search_filter_organizations",
+ field=models.BooleanField(
+ default=True,
+ help_text="Whether to show organization-checkboxes in order to filter the search result.",
+ verbose_name="Add organization filter for search results",
+ ),
+ ),
+ migrations.AddField(
+ model_name="siteconfiguration",
+ name="search_filter_tags",
+ field=models.BooleanField(
+ default=True,
+ help_text="Whether to show tag-checkboxes in order to filter the search result.",
+ verbose_name="Add tag filter for search results",
+ ),
+ ),
+ ]
diff --git a/src/open_inwoner/configurations/models.py b/src/open_inwoner/configurations/models.py
index e9c0955ea1..ef03af5fc3 100644
--- a/src/open_inwoner/configurations/models.py
+++ b/src/open_inwoner/configurations/models.py
@@ -316,6 +316,31 @@ class SiteConfiguration(SingletonModel):
verbose_name=_("Plan help"),
help_text=_("The help text for the plan page."),
)
+
+ # search filters
+ search_filter_categories = models.BooleanField(
+ verbose_name=_("Add category filter for search results"),
+ default=True,
+ help_text=_(
+ "Whether to show category-checkboxes in order to filter the search result."
+ ),
+ )
+ search_filter_tags = models.BooleanField(
+ verbose_name=_("Add tag filter for search results"),
+ default=True,
+ help_text=_(
+ "Whether to show tag-checkboxes in order to filter the search result."
+ ),
+ )
+ search_filter_organizations = models.BooleanField(
+ verbose_name=_("Add organization filter for search results"),
+ default=True,
+ help_text=_(
+ "Whether to show organization-checkboxes in order to filter the search result."
+ ),
+ )
+
+ # email notifications
email_new_message = models.BooleanField(
verbose_name=_("Send email about a new message"),
default=True,
diff --git a/src/open_inwoner/js/components/search/filter-mobile.js b/src/open_inwoner/js/components/search/filter-mobile.js
new file mode 100644
index 0000000000..b34aeccada
--- /dev/null
+++ b/src/open_inwoner/js/components/search/filter-mobile.js
@@ -0,0 +1,34 @@
+export class FilterMobile {
+ static selector = '.filter--toggle'
+
+ constructor(node) {
+ this.node = node
+ this.node.addEventListener('click', this.toggleOpen.bind(this))
+ document.addEventListener('keydown', this.filterClosing.bind(this), false)
+ }
+
+ toggleOpen(event) {
+ event.preventDefault()
+ console.log('this is mobile')
+ const filterParent = this.node.parentElement
+ if (filterParent) {
+ filterParent.classList.toggle('filter--open')
+ }
+ }
+
+ filterClosing(event) {
+ if (event.type === 'keydown' && event.key === 'Escape') {
+ const filterParent = this.node.parentElement
+ if (filterParent) {
+ filterParent.classList.remove('filter--open')
+ }
+ }
+ }
+}
+
+/**
+ * Controls the toggling of filter lists on mobile to view more
+ */
+document
+ .querySelectorAll(FilterMobile.selector)
+ .forEach((filterToggle) => new FilterMobile(filterToggle))
diff --git a/src/open_inwoner/js/components/search/filter-options.js b/src/open_inwoner/js/components/search/filter-options.js
new file mode 100644
index 0000000000..26de0cdd6f
--- /dev/null
+++ b/src/open_inwoner/js/components/search/filter-options.js
@@ -0,0 +1,28 @@
+const radioButtons = document.querySelectorAll(
+ '.feedback__options .button-radio__input'
+)
+
+;[...radioButtons].forEach((radioButton) => {
+ radioButton.addEventListener('click', (event) => {
+ const feedbackRemarks = document.querySelectorAll('.feedback__remark')
+ ;[...feedbackRemarks].forEach((feedbackRemark) =>
+ feedbackRemark.classList.add('feedback__remark--show')
+ )
+ })
+})
+
+let timerId = null
+
+const searchForm = document.getElementById('search-form')
+
+const filterButtons = document.querySelectorAll('.filter .checkbox__input')
+;[...filterButtons].forEach((checkbox) => {
+ checkbox.addEventListener('change', (event) => {
+ clearTimeout(timerId)
+
+ // Set a new interval
+ timerId = setTimeout(() => {
+ searchForm.submit()
+ }, 250)
+ })
+})
diff --git a/src/open_inwoner/js/components/search/index.js b/src/open_inwoner/js/components/search/index.js
index 7a06c26c79..2f8febe1b3 100644
--- a/src/open_inwoner/js/components/search/index.js
+++ b/src/open_inwoner/js/components/search/index.js
@@ -1,28 +1,2 @@
-const radioButtons = document.querySelectorAll(
- '.feedback__options .button-radio__input'
-)
-
-;[...radioButtons].forEach((radioButton) => {
- radioButton.addEventListener('click', (event) => {
- const feedbackRemarks = document.querySelectorAll('.feedback__remark')
- ;[...feedbackRemarks].forEach((feedbackRemark) =>
- feedbackRemark.classList.add('feedback__remark--show')
- )
- })
-})
-
-let timerId = null
-
-const searchForm = document.getElementById('search-form')
-
-const filterButtons = document.querySelectorAll('.filter .checkbox__input')
-;[...filterButtons].forEach((checkbox) => {
- checkbox.addEventListener('change', (event) => {
- clearTimeout(timerId)
-
- // Set a new timeout
- timerId = setTimeout(() => {
- searchForm.submit()
- }, 250)
- })
-})
+import './filter-mobile'
+import './filter-options'
diff --git a/src/open_inwoner/scss/components/Divider/Divider.scss b/src/open_inwoner/scss/components/Divider/Divider.scss
index 4e785e7137..0fb79667bd 100644
--- a/src/open_inwoner/scss/components/Divider/Divider.scss
+++ b/src/open_inwoner/scss/components/Divider/Divider.scss
@@ -6,6 +6,10 @@
margin: var(--spacing-large) 0;
}
+ &--tiny {
+ margin: var(--spacing-medium) 0;
+ }
+
@media (min-width: 768px) {
margin: var(--spacing-giant) 0;
}
diff --git a/src/open_inwoner/scss/components/Filter/Filter.scss b/src/open_inwoner/scss/components/Filter/Filter.scss
index 9df009eba7..ce68df4f84 100644
--- a/src/open_inwoner/scss/components/Filter/Filter.scss
+++ b/src/open_inwoner/scss/components/Filter/Filter.scss
@@ -1,12 +1,36 @@
.filter {
border: 0 solid transparent;
+ margin: 0;
+ padding: 0;
- &--open {
- .filter__list {
+ @media (min-width: 768px) {
+ padding: 0 var(--spacing-large) var(--spacing-large) var(--spacing-large);
+ }
+
+ &__list {
+ padding-top: 0;
+ padding-bottom: var(--spacing-large);
+ display: none;
+ grid-template-columns: 1fr;
+ gap: var(--spacing-large);
+
+ @media (min-width: 768px) {
display: grid;
+ padding-top: var(--spacing-large);
+ padding-bottom: 0;
+ }
+
+ .checkbox .checkbox__label {
+ cursor: pointer;
}
}
+ .button {
+ color: var(--font-color-body);
+ font-weight: bold;
+ padding: 0;
+ }
+
&__title {
color: var(--font-color-heading-4);
font-family: var(--font-family-heading);
@@ -14,14 +38,69 @@
font-weight: bold;
letter-spacing: 0;
line-height: 21px;
- cursor: pointer;
display: flex;
}
- &__list {
- padding-top: var(--spacing-large);
- display: none;
- grid-template-columns: 1fr;
- gap: var(--spacing-large);
+ &__legend {
+ &-label {
+ display: none;
+ @media (min-width: 768px) {
+ display: inline;
+ }
+ }
+ }
+
+ .divider {
+ background-color: yellow;
+ border: red solid 5px !important;
+ &--small {
+ display: none;
+ @media (min-width: 768px) {
+ display: block;
+ }
+ }
+ &--tiny {
+ display: block;
+ @media (min-width: 768px) {
+ display: none;
+ }
+ }
+ }
+
+ &__mobile {
+ @media (min-width: 768px) {
+ display: none;
+ }
+ }
+
+ //toggling dropdows
+ &.filter--open {
+ .button {
+ color: var(--color-secondary);
+ padding: 0;
+ }
+
+ .button--textless [class*='icon'] {
+ display: inline-block;
+ right: var(--spacing-large);
+ top: 0;
+ transform: rotate(180deg);
+ transition: all 0.3s;
+ }
+
+ .filter__list {
+ display: grid;
+ }
+ }
+}
+
+.grid__filters {
+ .h2 {
+ border-bottom: 2px solid var(--color-gray-light);
+ display: block;
+ padding-bottom: var(--spacing-large);
+ @media (min-width: 768px) {
+ display: none;
+ }
}
}
diff --git a/src/open_inwoner/templates/pages/search.html b/src/open_inwoner/templates/pages/search.html
index cc3a587c3c..57e003162b 100644
--- a/src/open_inwoner/templates/pages/search.html
+++ b/src/open_inwoner/templates/pages/search.html
@@ -18,10 +18,20 @@ {% trans "Zoeken naar " %} "{{ form.query.value }}"
{# facets and results section #}
{% if paginator.count %}
-