From a50a809d02aa2c9cff850ca7653cd2d520bf77c2 Mon Sep 17 00:00:00 2001 From: Stefan R <109965488+stefrado@users.noreply.github.com> Date: Mon, 25 Nov 2024 12:56:49 +0100 Subject: [PATCH] :sparkles: 990 Implement new header (#1006) --- src/sdg/conf/base.py | 1 + src/sdg/organisaties/views/notificaties.py | 12 ++- src/sdg/organisaties/views/roles.py | 9 ++ .../migrations/0059_notificationviewed.py | 38 +++++++ ...ter_notificationviewed_last_viewed_date.py | 18 ++++ src/sdg/producten/models/__init__.py | 1 + src/sdg/producten/models/notification.py | 12 +++ src/sdg/scss/components/_header.scss | 80 ++------------ src/sdg/scss/components/_index.scss | 2 + src/sdg/scss/components/_nav.scss | 31 ++++++ src/sdg/scss/components/_user-dropdown.scss | 86 +++++++++++++++ .../templates/core/_municipality_switch.html | 7 -- src/sdg/templates/core/base_home.html | 69 +----------- src/sdg/templates/core/index.html | 6 -- src/sdg/templates/navigation/nav_item.html | 11 ++ src/sdg/templates/navigation/navigation.html | 39 +++++++ .../templates/navigation/user_dropdown.html | 23 ++++ .../templates/organisaties/roles/update.html | 7 +- src/sdg/utils/context_processors.py | 35 ++++++ src/sdg/utils/templatetags/utils.py | 101 +++++++++++++++++- 20 files changed, 431 insertions(+), 157 deletions(-) create mode 100644 src/sdg/producten/migrations/0059_notificationviewed.py create mode 100644 src/sdg/producten/migrations/0060_alter_notificationviewed_last_viewed_date.py create mode 100644 src/sdg/producten/models/notification.py create mode 100644 src/sdg/scss/components/_nav.scss create mode 100644 src/sdg/scss/components/_user-dropdown.scss delete mode 100644 src/sdg/templates/core/_municipality_switch.html create mode 100644 src/sdg/templates/navigation/nav_item.html create mode 100644 src/sdg/templates/navigation/navigation.html create mode 100644 src/sdg/templates/navigation/user_dropdown.html diff --git a/src/sdg/conf/base.py b/src/sdg/conf/base.py index 273c856ca..ec8240f97 100644 --- a/src/sdg/conf/base.py +++ b/src/sdg/conf/base.py @@ -183,6 +183,7 @@ "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", "sdg.utils.context_processors.settings", + "sdg.utils.context_processors.has_new_notifications", ], "loaders": TEMPLATE_LOADERS, }, diff --git a/src/sdg/organisaties/views/notificaties.py b/src/sdg/organisaties/views/notificaties.py index 208dd12a9..5138ad5ce 100644 --- a/src/sdg/organisaties/views/notificaties.py +++ b/src/sdg/organisaties/views/notificaties.py @@ -1,4 +1,5 @@ from django.contrib.auth.mixins import LoginRequiredMixin +from django.utils import timezone from django.utils.timezone import now from django.utils.translation import gettext as _ from django.views.generic import ListView @@ -6,7 +7,7 @@ from dateutil.relativedelta import relativedelta from sdg.core.views.mixins import BreadcrumbsMixin -from sdg.producten.models import ProductVersie +from sdg.producten.models import NotificationViewed, ProductVersie class ProductVersieListView( @@ -41,3 +42,12 @@ def get_queryset(self): .published() .order_by("-gewijzigd_op")[: self.limit] ) + + def get(self, request, *args, **kwargs): + # Call the parent class's get method to fetch the queryset + response = super().get(request, *args, **kwargs) + + # Update or create the NotificationViewed instance for the current user + NotificationViewed.objects.update_or_create(gebruiker=request.user) + + return response diff --git a/src/sdg/organisaties/views/roles.py b/src/sdg/organisaties/views/roles.py index cfcabd969..705622a08 100644 --- a/src/sdg/organisaties/views/roles.py +++ b/src/sdg/organisaties/views/roles.py @@ -79,6 +79,15 @@ def get_form_class(self): raise PermissionDenied() + def get_success_url(self): + # Stay on the same page if the user is editing own settings and is not an admin. + if ( + self.request.user.email == self.object.user.email + and self.object.is_beheerder is not True + ): + return self.request.get_full_path() + return super().get_success_url() + def form_valid(self, form, *args, **kwargs): response = super().form_valid(form) diff --git a/src/sdg/producten/migrations/0059_notificationviewed.py b/src/sdg/producten/migrations/0059_notificationviewed.py new file mode 100644 index 000000000..6e1e12807 --- /dev/null +++ b/src/sdg/producten/migrations/0059_notificationviewed.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.23 on 2024-10-21 14:12 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("producten", "0058_alter_localizedproduct_decentrale_procedure_link"), + ] + + operations = [ + migrations.CreateModel( + name="NotificationViewed", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("last_viewed_date", models.DateTimeField(blank=True, null=True)), + ( + "gebruiker", + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + ] diff --git a/src/sdg/producten/migrations/0060_alter_notificationviewed_last_viewed_date.py b/src/sdg/producten/migrations/0060_alter_notificationviewed_last_viewed_date.py new file mode 100644 index 000000000..a91b7a576 --- /dev/null +++ b/src/sdg/producten/migrations/0060_alter_notificationviewed_last_viewed_date.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.23 on 2024-11-15 16:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("producten", "0059_notificationviewed"), + ] + + operations = [ + migrations.AlterField( + model_name="notificationviewed", + name="last_viewed_date", + field=models.DateTimeField(auto_now=True), + ), + ] diff --git a/src/sdg/producten/models/__init__.py b/src/sdg/producten/models/__init__.py index 43ffa6f41..9e2a1778b 100644 --- a/src/sdg/producten/models/__init__.py +++ b/src/sdg/producten/models/__init__.py @@ -1,2 +1,3 @@ from .localized import * # noqa +from .notification import * # noqa from .product import * # noqa diff --git a/src/sdg/producten/models/notification.py b/src/sdg/producten/models/notification.py new file mode 100644 index 000000000..c1286e92e --- /dev/null +++ b/src/sdg/producten/models/notification.py @@ -0,0 +1,12 @@ +from django.contrib.auth import get_user_model +from django.db import models + +User = get_user_model() + + +class NotificationViewed(models.Model): + gebruiker = models.OneToOneField(User, on_delete=models.CASCADE) + last_viewed_date = models.DateTimeField(auto_now=True) + + def __str__(self): + return f"User: {self.gebruiker_id} - Notification last viewed on: {self.last_viewed_date}" diff --git a/src/sdg/scss/components/_header.scss b/src/sdg/scss/components/_header.scss index a1259c019..0cafe1cc1 100644 --- a/src/sdg/scss/components/_header.scss +++ b/src/sdg/scss/components/_header.scss @@ -1,48 +1,24 @@ -@import 'colors'; +@import "colors"; .header { - --shadow-color: rgba(0, 0, 0, 0.121722); - width: 100%; background: rgb(57, 106, 136); - background: linear-gradient(353.15deg, var(--org-theme-bg-darkest) -68.3%, var(--org-theme-bg) 179.94%); + background: linear-gradient( + 353.15deg, + var(--org-theme-bg-darkest) -68.3%, + var(--org-theme-bg) 179.94% + ); padding: 24px 0 0; justify-content: space-between; display: flex; flex-direction: column; - &.header--inset { - padding-bottom: 88px; - } - - .header__top { + &__top { justify-content: space-between; display: flex; flex-direction: row; } - .header__user { - display: flex; - align-items: center; - - & > .svg-inline--fa { - height: 50px; - width: 50px; - border-radius: 50%; - background-color: $color_primary_lightest; - color: $color_primary; - padding-top: 4px; - overflow: hidden; - margin-right: 8px; - border: 3px solid $color_secondary_dark; - z-index: 1; - - path { - color: $color_primary; - } - } - } - .header__username { background-color: var(--org-theme-bg-darker); border: 1px solid transparent; @@ -59,36 +35,10 @@ color: #000; } - .header__title { - color: $color_secondary_dark; - font-size: 40px; - - .switch-icon { - color: $color_accent; - margin-left: 8px; - } - - a:hover svg { - color: $color_accent_dark; - transition: all 0.3s ease-in-out; - } - - } - - .header__subtitle { - color: $color_secondary_darker; - font-size: 14px; - margin-bottom: 8px; - } - .header__dropdown { position: relative; padding: 12px; color: #fff; - - .svg-inline--fa:hover { - transform: scale(1.05); - } } .header__dropdown *:hover ~ .header__dropdown-list, @@ -126,20 +76,4 @@ text-decoration: underline; } } - - .header__dropdown-action .svg-inline--fa { - float: left; - margin-top: 2px; - margin-right: 8px; - width: 1em; - } - - .header__dropdown-text { - padding: 12px; - color: #000; - display: block; - text-align: left; - text-decoration: none; - margin-right: 8px; - } } diff --git a/src/sdg/scss/components/_index.scss b/src/sdg/scss/components/_index.scss index d86e35bd3..e41a6574a 100644 --- a/src/sdg/scss/components/_index.scss +++ b/src/sdg/scss/components/_index.scss @@ -34,3 +34,5 @@ @import 'url_label_field'; @import 'choices'; @import 'publications'; +@import 'nav'; +@import 'user-dropdown'; diff --git a/src/sdg/scss/components/_nav.scss b/src/sdg/scss/components/_nav.scss new file mode 100644 index 000000000..bbac36c81 --- /dev/null +++ b/src/sdg/scss/components/_nav.scss @@ -0,0 +1,31 @@ +.nav { + display: flex; + justify-content: space-between; + + &__list { + display: flex; + list-style: none; + font-size: 1rem; + color: $color-white; + margin: 0; + gap: $grid-margin-3; + } + + &__item { + color: $color-white; + } + + &__item--active &__link { + color: $color_accent; + text-decoration: underline; + } + + &__link { + color: $color-white; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } +} diff --git a/src/sdg/scss/components/_user-dropdown.scss b/src/sdg/scss/components/_user-dropdown.scss new file mode 100644 index 000000000..f3e48b54f --- /dev/null +++ b/src/sdg/scss/components/_user-dropdown.scss @@ -0,0 +1,86 @@ +.user-dropdown { + --shadow-color: rgba(0, 0, 0, 0.121722); + --border-color: #{$color_grey_dark}; + + align-items: center; + background-color: var(--org-theme-bg-darker); + border: 1px solid transparent; + border-radius: 9999px; + color: $color-white; + display: flex; + gap: $grid-margin-0; + height: 40px; + text-decoration: none; + padding-right: $grid-margin-2; + position: relative; + transition: all 0.3s ease-in-out; + + &:hover &__list, + & > *:hover ~ &__list, + &__list:hover { + opacity: 1; + transition-delay: 0s; + visibility: visible; + } + + &:hover { + background-color: $color_grey_light; + border-color: var(--border-color); + color: #212121; + } + + &__icon { + background-color: $color_primary_lightest; + border: 2px solid var(--border-color); + border-radius: 50%; + color: $color_primary; + flex-shrink: 0; + height: 50px; + left: -4px; + overflow: hidden; + padding-top: 4px; + position: relative; + width: 50px; + + > .svg-inline--fa { + color: $color_primary; + height: 100%; + width: 100%; + } + } + + &__list { + background-color: $color_grey_light; + border: 1px solid var(--border-color); + border-radius: 10px; + box-shadow: 1px 1px 4px var(--shadow-color); + color: #fff; + left: 0; + opacity: 0; + position: absolute; + right: 0; + top: calc(100% + 1rem); + transition: all 0.3s ease-in-out; + transition-delay: 0s; + visibility: hidden; + z-index: 20; + } + + &__action { + align-items: center; + color: $color_primary_dark; + display: flex; + gap: 0.5rem; + padding: 12px; + text-align: left; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + + hr { + border: 0.5px solid var(--border-color); + } +} diff --git a/src/sdg/templates/core/_municipality_switch.html b/src/sdg/templates/core/_municipality_switch.html deleted file mode 100644 index 7c8cc7597..000000000 --- a/src/sdg/templates/core/_municipality_switch.html +++ /dev/null @@ -1,7 +0,0 @@ -{% load i18n %} - -{% if user.roles.count > 1 %} - - - -{% endif %} diff --git a/src/sdg/templates/core/base_home.html b/src/sdg/templates/core/base_home.html index 136df1b56..81be3c80a 100644 --- a/src/sdg/templates/core/base_home.html +++ b/src/sdg/templates/core/base_home.html @@ -17,75 +17,10 @@
{% block container_subtitle %}{% endblock container_subtitle %}
-- {% block container_title %} - {% if lokaleoverheid %} - {{ lokaleoverheid }} - {% include "core/_municipality_switch.html" %} - {% else %} -
{{ request.user }}
+ +