Skip to content

Commit

Permalink
⏪ [#2096] Re-add selected categories for users
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenbal committed Feb 19, 2024
1 parent ed038ce commit a834907
Show file tree
Hide file tree
Showing 18 changed files with 257 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/open_inwoner/accounts/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class _UserAdmin(ImageCroppingMixin, UserAdmin):
"image",
"cropping",
"phonenumber",
"selected_categories",
)
},
),
Expand Down
12 changes: 12 additions & 0 deletions src/open_inwoner/accounts/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,18 @@ def send_mail(
email_message.send()


class CategoriesForm(forms.ModelForm):
selected_categories = forms.ModelMultipleChoiceField(
queryset=Category.objects.published(),
widget=forms.widgets.CheckboxSelectMultiple,
required=False,
)

class Meta:
model = User
fields = ("selected_categories",)


class UserNotificationsForm(forms.ModelForm):
class Meta:
model = User
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 3.2.23 on 2024-02-08 13:39

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("pdc", "0066_category_access_groups"),
("accounts", "0072_merge_20240129_1610"),
]

operations = [
migrations.AddField(
model_name="user",
name="selected_categories",
field=models.ManyToManyField(
blank=True,
related_name="selected_by",
to="pdc.Category",
verbose_name="Selected categories",
),
),
]
12 changes: 12 additions & 0 deletions src/open_inwoner/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ class User(AbstractBaseUser, PermissionsMixin):
default=False,
help_text=_("Indicates if fields have been prepopulated by Haal Central API."),
)
selected_categories = models.ManyToManyField(
"pdc.Category",
verbose_name=_("Selected categories"),
related_name="selected_by",
blank=True,
)
oidc_id = models.CharField(
verbose_name=_("OpenId Connect id"),
max_length=250,
Expand Down Expand Up @@ -350,6 +356,12 @@ def get_new_messages_total(self) -> int:
def get_all_files(self):
return self.documents.order_by("-created_on")

def get_interests(self) -> list:
if not self.selected_categories.exists():
return []

return list(self.selected_categories.values_list("name", flat=True))

def get_active_notifications(self) -> str:
from open_inwoner.cms.utils.page_display import (
case_page_is_published,
Expand Down
25 changes: 25 additions & 0 deletions src/open_inwoner/accounts/tests/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from open_inwoner.accounts.models import Invite
from open_inwoner.configurations.models import SiteConfiguration
from open_inwoner.pdc.tests.factories import CategoryFactory
from open_inwoner.utils.logentry import LOG_ACTIONS

from ..choices import LoginTypeChoices, StatusChoices
Expand Down Expand Up @@ -92,6 +93,30 @@ def test_users_modification_is_logged(self):
},
)

def test_categories_modification_is_logged(self):
CategoryFactory()
CategoryFactory()
form = self.app.get(reverse("profile:categories"), user=self.user).forms[
"change-categories"
]

form.get("selected_categories", index=1).checked = True
form.submit()
log_entry = TimelineLog.objects.last()

self.assertEqual(
log_entry.timestamp.strftime("%m/%d/%Y, %H:%M:%S"), "10/18/2021, 13:00:00"
)
self.assertEqual(log_entry.content_object.id, self.user.id)
self.assertEqual(
log_entry.extra_data,
{
"message": _("categories were modified"),
"action_flag": list(LOG_ACTIONS[CHANGE]),
"content_object_repr": str(self.user),
},
)

@patch("open_inwoner.cms.utils.page_display._is_published", return_value=True)
def test_user_notifications_update_is_logged(self, mock_cms_page_display):
form = self.app.get(reverse("profile:notifications"), user=self.user).forms[
Expand Down
28 changes: 27 additions & 1 deletion src/open_inwoner/accounts/tests/test_profile_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ def test_get_empty_profile_page(self):
response = self.app.get(self.url, user=self.user)

self.assertEquals(response.status_code, 200)
self.assertContains(response, _("U heeft geen interesses gekozen."))
self.assertContains(response, _("U heeft nog geen contacten"))
self.assertContains(response, "0 acties staan open")
self.assertNotContains(response, reverse("products:questionnaire_list"))
Expand All @@ -151,11 +152,13 @@ def test_get_filled_profile_page(self):
ActionFactory(created_by=self.user)
contact = UserFactory()
self.user.user_contacts.add(contact)
CategoryFactory()
category = CategoryFactory()
self.user.selected_categories.add(category)
QuestionnaireStepFactory(published=True)

response = self.app.get(self.url, user=self.user)
self.assertEquals(response.status_code, 200)
self.assertContains(response, category.name)
self.assertContains(
response,
f"{contact.first_name} ({contact.get_contact_type_display()})",
Expand Down Expand Up @@ -881,6 +884,29 @@ def test_wrong_date_format_shows_birthday_none_brp_v_1_3(self, m):
)


@override_settings(ROOT_URLCONF="open_inwoner.cms.tests.urls")
class EditIntrestsTests(WebTest):
def setUp(self):
self.url = reverse("profile:categories")
self.user = UserFactory()

def test_login_required(self):
login_url = reverse("login")
response = self.app.get(self.url)
self.assertRedirects(response, f"{login_url}?next={self.url}")

def test_preselected_values(self):
category = CategoryFactory(name="a")
CategoryFactory(name="b")
CategoryFactory(name="c")
self.user.selected_categories.add(category)
response = self.app.get(self.url, user=self.user)
form = response.forms["change-categories"]
self.assertTrue(form.get("selected_categories", index=0).checked)
self.assertFalse(form.get("selected_categories", index=1).checked)
self.assertFalse(form.get("selected_categories", index=2).checked)


@override_settings(ROOT_URLCONF="open_inwoner.cms.tests.urls")
@patch("open_inwoner.cms.utils.page_display._is_published", return_value=True)
class EditNotificationsTests(WebTest):
Expand Down
8 changes: 7 additions & 1 deletion src/open_inwoner/accounts/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,13 @@
VerifyTokenView,
)
from .password_reset import PasswordResetView
from .profile import EditProfileView, MyDataView, MyNotificationsView, MyProfileView
from .profile import (
EditProfileView,
MyCategoriesView,
MyDataView,
MyNotificationsView,
MyProfileView,
)
from .registration import CustomRegistrationView, NecessaryFieldsUserView

__all__ = [
Expand Down
29 changes: 28 additions & 1 deletion src/open_inwoner/accounts/views/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from open_inwoner.questionnaire.models import QuestionnaireStep
from open_inwoner.utils.views import CommonPageMixin, LogMixin

from ..forms import BrpUserForm, UserForm, UserNotificationsForm
from ..forms import BrpUserForm, CategoriesForm, UserForm, UserNotificationsForm
from ..models import Action, User


Expand Down Expand Up @@ -118,6 +118,8 @@ def get_context_data(self, **kwargs):

context["files"] = user_files

context["selected_categories"] = user.get_interests()

context["questionnaire_exists"] = QuestionnaireStep.objects.filter(
published=True
).exists()
Expand Down Expand Up @@ -224,6 +226,31 @@ def get_form_kwargs(self):
return kwargs


class MyCategoriesView(
LogMixin, LoginRequiredMixin, CommonPageMixin, BaseBreadcrumbMixin, UpdateView
):
template_name = "pages/profile/categories.html"
model = User
form_class = CategoriesForm
success_url = reverse_lazy("profile:detail")

@cached_property
def crumbs(self):
return [
(_("Mijn profiel"), reverse("profile:detail")),
(_("Mijn interessegebieden"), reverse("profile:categories")),
]

def get_object(self):
return self.request.user

def form_valid(self, form):
form.save()
messages.success(self.request, _("Uw wijzigingen zijn opgeslagen"))
self.log_change(self.object, _("categories were modified"))
return HttpResponseRedirect(self.get_success_url())


class MyDataView(
LogMixin, LoginRequiredMixin, CommonPageMixin, BaseBreadcrumbMixin, TemplateView
):
Expand Down
32 changes: 19 additions & 13 deletions src/open_inwoner/cms/products/cms_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,25 @@ class CategoriesPlugin(CMSActiveAppMixin, CMSPluginBase):
def render(self, context, instance, placeholder):
config = OpenZaakConfig.get_solo()
request = context["request"]
# Show the all the highlighted categories the user has access to, as well as
# categories that are linked to ZaakTypen for which the user has Zaken within
# the specified period
visible_categories = Category.objects.published().visible_for_user(request.user)
categories = visible_categories.filter(highlighted=True)
if (
config.enable_categories_filtering_with_zaken
and request.user.is_authenticated
and (request.user.bsn or request.user.kvk)
):
categories |= visible_categories.filter_by_zaken_for_request(request)

context["categories"] = categories.order_by("path")

if request.user.is_authenticated and request.user.selected_categories.exists():
context["categories"] = request.user.selected_categories.all()
else:
# Show the all the highlighted categories the user has access to, as well as
# categories that are linked to ZaakTypen for which the user has Zaken within
# the specified period
visible_categories = Category.objects.published().visible_for_user(
request.user
)
categories = visible_categories.filter(highlighted=True)
if (
config.enable_categories_filtering_with_zaken
and request.user.is_authenticated
and (request.user.bsn or request.user.kvk)
):
categories |= visible_categories.filter_by_zaken_for_request(request)

context["categories"] = categories.order_by("path")

return context

Expand Down
16 changes: 16 additions & 0 deletions src/open_inwoner/cms/products/tests/test_plugin_categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,22 @@ def test_categories_based_on_cases(self, m):
self.assertEqual(context["categories"][1], self.category6)
self.assertEqual(context["categories"].last(), self.category7)

@requests_mock.Mocker()
def test_categories_based_on_selected_categories(self, m):
"""
If the user has selected categories, only these categories should show up on
the homepage
"""
self._setUpMocks(m)

self.user.selected_categories.set([self.category1, self.category2])

html, context = cms_tools.render_plugin(CategoriesPlugin, user=self.user)

self.assertEqual(context["categories"].count(), 2)
self.assertEqual(context["categories"].first(), self.category1)
self.assertEqual(context["categories"].last(), self.category2)

@requests_mock.Mocker()
def test_categories_based_on_cases_for_eherkenning_user(self, m):
self._setUpMocks(m)
Expand Down
1 change: 1 addition & 0 deletions src/open_inwoner/cms/profile/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class ProfileConfigAdmin(BaseAppHookConfig, admin.ModelAdmin):
def get_config_fields(self):
return (
"my_data",
"selected_categories",
"mentors",
"my_contacts",
"selfdiagnose",
Expand Down
7 changes: 7 additions & 0 deletions src/open_inwoner/cms/profile/cms_appconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ class ProfileConfig(AppHookConfig):
"Designates whether 'My data' section is rendered or not (Only for digid users)."
),
)
selected_categories = models.BooleanField(
verbose_name=_("Gekozen onderwerpen"),
default=True,
help_text=_(
"Designates whether 'selected categories' section is rendered or not."
),
)
mentors = models.BooleanField(
verbose_name=_("Begeleiders"),
default=True,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 3.2.23 on 2024-02-08 13:39

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("profile", "0006_alter_profileconfig_ssd"),
]

operations = [
migrations.AddField(
model_name="profileconfig",
name="selected_categories",
field=models.BooleanField(
default=True,
help_text="Designates whether 'selected categories' section is rendered or not.",
verbose_name="Gekozen onderwerpen",
),
),
]
2 changes: 2 additions & 0 deletions src/open_inwoner/cms/profile/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
DocumentPrivateMediaView,
EditProfileView,
InviteAcceptView,
MyCategoriesView,
MyDataView,
MyNotificationsView,
MyProfileView,
Expand Down Expand Up @@ -90,6 +91,7 @@
path("actions/", include(action_patterns)),
path("contacts/", include(contact_patterns)),
path("documenten/", include(documents_patterns)),
path("onderwerpen/", MyCategoriesView.as_view(), name="categories"),
path("notificaties/", MyNotificationsView.as_view(), name="notifications"),
path("mydata/", MyDataView.as_view(), name="data"),
path("edit/", EditProfileView.as_view(), name="edit"),
Expand Down
1 change: 1 addition & 0 deletions src/open_inwoner/conf/fixtures/profile_apphook_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"fields": {
"namespace": "profile-apphook-config",
"my_data": true,
"selected_categories": true,
"mentors": true,
"my_contacts": true,
"selfdiagnose": true,
Expand Down
13 changes: 13 additions & 0 deletions src/open_inwoner/pdc/tests/test_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,19 @@ def test_auto_redirect_to_link(self):
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "http://www.example.com")

def test_only_published_categories_exist_in_my_categories_page(self):
response = self.app.get(reverse("profile:categories"), user=self.user)
self.assertEqual(
list(response.context["form"].fields["selected_categories"].queryset.all()),
[
self.published1,
self.published2,
self.subcategory,
self.published3,
self.published4,
],
)


@override_settings(ROOT_URLCONF="open_inwoner.cms.tests.urls")
class TestHighlightedQuestionnaire(WebTest):
Expand Down
13 changes: 13 additions & 0 deletions src/open_inwoner/templates/pages/profile/categories.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{% extends 'master.html' %}
{% load i18n form_tags %}

{% block content %}
<h1 class="h1" id="title">
{% trans "Mijn Interessegebieden" %}
</h1>
<p class="p">
{% trans "Selecteer hier welke onderwerpen u interesseren, om op maat gemaakte inhoud voorgeschoteld te krijgen en nog beter te kunnen zoeken en vinden" %}
</p>

{% form form_object=form method="POST" id="change-categories" submit_text=_("Opslaan") secondary_href='profile:contact_list' secondary_text=_('Terug') secondary_icon='arrow_backward' secondary_icon_position="before" extra_classes="select-grid" %}
{% endblock content %}
Loading

0 comments on commit a834907

Please sign in to comment.