diff --git a/peachjam/migrations/0182_peachjamsettings_allow_save_searches.py b/peachjam/migrations/0182_peachjamsettings_allow_save_searches.py new file mode 100644 index 000000000..bd5bbc4ff --- /dev/null +++ b/peachjam/migrations/0182_peachjamsettings_allow_save_searches.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.15 on 2024-11-22 07:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("peachjam", "0181_taxonomy_path_name"), + ] + + operations = [ + migrations.AddField( + model_name="peachjamsettings", + name="allow_save_searches", + field=models.BooleanField( + default=False, + help_text="Allow searches to be saved.", + verbose_name="allow save searches", + ), + ), + ] diff --git a/peachjam/models/settings.py b/peachjam/models/settings.py index 68241bfab..5224569ff 100644 --- a/peachjam/models/settings.py +++ b/peachjam/models/settings.py @@ -144,6 +144,11 @@ class PeachJamSettings(SingletonModel): default=False, help_text=_("Allow documents to be saved."), ) + allow_save_searches = models.BooleanField( + verbose_name=_("allow save searches"), + default=False, + help_text=_("Allow searches to be saved."), + ) robots_txt = models.TextField( null=True, blank=True, help_text=_("Additional robots.txt rules.") ) diff --git a/peachjam/templates/peachjam/_header.html b/peachjam/templates/peachjam/_header.html index c4ef100a3..9b6bcd401 100644 --- a/peachjam/templates/peachjam/_header.html +++ b/peachjam/templates/peachjam/_header.html @@ -70,12 +70,23 @@ diff --git a/peachjam/templates/user_account/_tabs.html b/peachjam/templates/user_account/_tabs.html index 6cf79a969..a1a22cce3 100644 --- a/peachjam/templates/user_account/_tabs.html +++ b/peachjam/templates/user_account/_tabs.html @@ -28,18 +28,22 @@ {% endif %} - - + {% if PEACHJAM_SETTINGS.allow_save_documents %} + + {% endif %} + {% if PEACHJAM_SETTINGS.allow_save_searches %} + + {% endif %} {% endblock %} diff --git a/peachjam_search/templates/peachjam_search/saved_search_button.html b/peachjam_search/templates/peachjam_search/saved_search_button.html index 1b56a9c2b..2ef89158d 100644 --- a/peachjam_search/templates/peachjam_search/saved_search_button.html +++ b/peachjam_search/templates/peachjam_search/saved_search_button.html @@ -1,15 +1,20 @@ {% load i18n %} -{% if request.user.is_authenticated %} -
- - +
+ {% if request.user.is_authenticated %} + + + + {% endif %} - {% if request.user.is_authenticated %}{% endif %} - {% include 'peachjam_search/_saved_search_modal.html' %} +
+{% include 'peachjam_search/_saved_search_modal.html' %} diff --git a/peachjam_search/views.py b/peachjam_search/views.py index 93a98cd0a..59b69365b 100644 --- a/peachjam_search/views.py +++ b/peachjam_search/views.py @@ -3,12 +3,11 @@ from django.conf import settings from django.contrib import messages -from django.contrib.auth.mixins import PermissionRequiredMixin +from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin from django.core.exceptions import ValidationError from django.http import HttpResponseRedirect, QueryDict -from django.http.response import JsonResponse +from django.http.response import Http404, JsonResponse from django.shortcuts import redirect, reverse -from django.urls import reverse_lazy from django.utils.decorators import method_decorator from django.utils.functional import cached_property from django.utils.timezone import now @@ -769,10 +768,18 @@ def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) def has_permission(self): - return self.request.user.is_authenticated and self.request.user.is_staff + return self.request.user.is_authenticated and self.request.user.is_staffo + + +class AllowSavedSearchesMixin: + def dispatch(self, *args, **kwargs): + if not pj_settings().allow_save_searches: + raise Http404("Saving searches is not allowed.") + return super().dispatch(*args, **kwargs) -class SavedSearchButtonView(TemplateView): + +class SavedSearchButtonView(AllowSavedSearchesMixin, TemplateView): template_name = "peachjam_search/saved_search_button.html" def get(self, *args, **kwargs): @@ -810,10 +817,27 @@ def get(self, *args, **kwargs): return super().get(*args, **kwargs) -class SavedSearchCreateView(CreateView): +class BaseSavedSearchFormView( + AllowSavedSearchesMixin, LoginRequiredMixin, PermissionRequiredMixin +): + model = SavedSearch + context_object_name = "saved_search" + + def get_queryset(self): + return self.request.user.saved_searches.all() + + def get_success_url(self): + return reverse( + "search:saved_search_update", + kwargs={ + "pk": self.object.pk, + }, + ) + + +class SavedSearchCreateView(BaseSavedSearchFormView, CreateView): permission_required = "peachjam_search.add_savedsearch" template_name = "peachjam_search/saved_search_form.html" - model = SavedSearch form_class = SavedSearchCreateForm def get_form_kwargs(self): @@ -827,41 +851,21 @@ def get_form_kwargs(self): kwargs["instance"] = instance return kwargs - def get_success_url(self): - return reverse("search:saved_search_update", kwargs={"pk": self.object.pk}) - -class SavedSearchUpdateView(UpdateView): +class SavedSearchUpdateView(BaseSavedSearchFormView, UpdateView): permission_required = "peachjam_search.change_savedsearch" template_name = "peachjam_search/saved_search_form.html" - model = SavedSearch form_class = SavedSearchUpdateForm - context_object_name = "saved_search" - - def get_queryset(self): - return self.request.user.saved_searches.all() - - def get_success_url(self): - return reverse("search:saved_search_update", kwargs={"pk": self.object.pk}) -class SavedSearchListView(ListView): +class SavedSearchListView(BaseSavedSearchFormView, ListView): permission_required = "peachjam_search.view_savedsearch" template_name = "peachjam_search/saved_search_list.html" - model = SavedSearch context_object_name = "saved_searches" - def get_queryset(self): - return self.request.user.saved_searches.all() - -class SavedSearchDeleteView(DeleteView): +class SavedSearchDeleteView(BaseSavedSearchFormView, DeleteView): permission_required = "peachjam_search.delete_savedsearch" - model = SavedSearch - success_url = reverse_lazy("search:saved_search_list") - - def get_queryset(self): - return self.request.user.saved_searches.all() def get_success_url(self): return self.request.GET.get("next", None) or reverse("search:saved_search_list")