diff --git a/konova/views/base.py b/konova/views/base.py
index abffa13d..e1548a95 100644
--- a/konova/views/base.py
+++ b/konova/views/base.py
@@ -17,12 +17,24 @@ from konova.utils.general import check_user_is_in_any_group
from konova.utils.message_templates import MISSING_GROUP_PERMISSION
-class BaseIndexView(View):
+class BaseView(View):
+ _TEMPLATE: str = "CHANGE_ME"
+ _TAB_TITLE: str = "CHANGE_ME"
+
+ class Meta:
+ abstract = True
+
+
+class BaseModalFormView(BaseView):
+ _TEMPLATE = "modal/modal_form.html"
+ _TAB_TITLE = None
+
+
+class BaseIndexView(BaseView):
""" Base class for index views
"""
- _TEMPLATE: str = 'generic_index.html'
- _TAB_TITLE: str = "CHANGE_ME"
+ _TEMPLATE = "generic_index.html"
_INDEX_TABLE_CLS = None
class Meta:
diff --git a/templates/navbars/navbar.html b/templates/navbars/navbar.html
index 9d1d6859..7ba2132d 100644
--- a/templates/navbars/navbar.html
+++ b/templates/navbars/navbar.html
@@ -56,7 +56,7 @@
{% if user.is_staff or user.is_superuser %}
{% fa5_icon 'tools' %} {% trans 'Admin' %}
{% endif %}
- {% fa5_icon 'cogs' %} {% trans 'Settings' %}
+ {% fa5_icon 'cogs' %} {% trans 'Settings' %}
{% fa5_icon 'sign-out-alt' %} {% trans 'Logout' %}
diff --git a/user/forms/user.py b/user/forms/user.py
index 190ce126..0f4c4f24 100644
--- a/user/forms/user.py
+++ b/user/forms/user.py
@@ -38,7 +38,7 @@ class UserNotificationForm(BaseForm):
self.form_title = _("Edit notifications")
self.form_caption = _("")
self.action_url = reverse("user:notifications")
- self.cancel_redirect = reverse("user:index")
+ self.cancel_redirect = reverse("user:detail")
# Insert all notifications into form field by creating choices as tuples
notifications = UserNotification.objects.filter(
diff --git a/user/tests/test_views.py b/user/tests/test_views.py
index fe4c854f..7b2d2406 100644
--- a/user/tests/test_views.py
+++ b/user/tests/test_views.py
@@ -26,7 +26,7 @@ class UserViewTestCase(BaseViewTestCase):
self.team.users.add(self.superuser)
self.team.admins.add(self.superuser)
# Prepare urls
- self.index_url = reverse("user:index", args=())
+ self.index_url = reverse("user:detail", args=())
self.notification_url = reverse("user:notifications", args=())
self.api_token_url = reverse("user:api-token", args=())
self.contact_url = reverse("user:contact", args=(self.superuser.id,))
diff --git a/user/tests/unit/test_forms.py b/user/tests/unit/test_forms.py
index 20e4333c..4a86945f 100644
--- a/user/tests/unit/test_forms.py
+++ b/user/tests/unit/test_forms.py
@@ -233,7 +233,7 @@ class UserNotificationFormTestCase(BaseTestCase):
self.assertEqual(form.form_title, str(_("Edit notifications")))
self.assertEqual(form.form_caption, "")
self.assertEqual(form.action_url, reverse("user:notifications"))
- self.assertEqual(form.cancel_redirect, reverse("user:index"))
+ self.assertEqual(form.cancel_redirect, reverse("user:detail"))
def test_save(self):
selected_notification = UserNotification.objects.first()
diff --git a/user/urls.py b/user/urls.py
index c3127a1e..ce8616fd 100644
--- a/user/urls.py
+++ b/user/urls.py
@@ -15,15 +15,15 @@ from user.views.views import *
app_name = "user"
urlpatterns = [
- path("", index_view, name="index"),
+ path("", UserDetailView.as_view(), name="detail"),
path("propagate/", PropagateUserView.as_view(), name="propagate"),
- path("notifications/", notifications_view, name="notifications"),
+ path("notifications/", NotificationsView.as_view(), name="notifications"),
path("token/api", APITokenView.as_view(), name="api-token"),
path("token/api/new", new_api_token_view, name="api-token-new"),
- path("contact/", contact_view, name="contact"),
- path("team/", index_team_view, name="team-index"),
+ path("contact/", ContactView.as_view(), name="contact"),
+ path("team/", TeamIndexView.as_view(), name="team-index"),
path("team/new", new_team_view, name="team-new"),
- path("team/", data_team_view, name="team-data"),
+ path("team/", TeamDetailModalView.as_view(), name="team-data"),
path("team//edit", edit_team_view, name="team-edit"),
path("team//remove", remove_team_view, name="team-remove"),
path("team//leave", leave_team_view, name="team-leave"),
diff --git a/user/views/views.py b/user/views/views.py
index 5d773926..e639703c 100644
--- a/user/views/views.py
+++ b/user/views/views.py
@@ -1,8 +1,10 @@
from django.contrib import messages
from django.contrib.auth.decorators import login_required
+from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
+from konova.views.base import BaseView, BaseModalFormView
from user.forms.modals.team import NewTeamModalForm, EditTeamModalForm, RemoveTeamModalForm, LeaveTeamModalForm
from user.forms.modals.user import UserContactForm
from user.forms.team import TeamDataForm
@@ -13,129 +15,108 @@ from django.shortcuts import render, redirect, get_object_or_404
from django.utils.translation import gettext_lazy as _
from konova.contexts import BaseContext
-from konova.decorators import any_group_check, login_required_modal
+from konova.decorators import login_required_modal
-@login_required
-@any_group_check
-def index_view(request: HttpRequest):
- """ Renders the user's data index view
+class UserDetailView(LoginRequiredMixin, BaseView):
+ _TAB_TITLE = _("User settings")
+ _TEMPLATE = "user/index.html"
- Args:
- request ():
-
- Returns:
-
- """
- template = "user/index.html"
- context = {
- "user": request.user,
- TAB_TITLE_IDENTIFIER: _("User settings"),
- }
- context = BaseContext(request, context).context
- return render(request, template, context)
+ def get(self, request: HttpRequest):
+ context = {
+ "user": request.user,
+ TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
+ }
+ context = BaseContext(request, context).context
+ return render(request, self._TEMPLATE, context)
-@login_required
-@any_group_check
-def notifications_view(request: HttpRequest):
- """ Renders the notifications settings view
+class NotificationsView(LoginRequiredMixin, BaseView):
+ _TEMPLATE = "user/notifications.html"
+ _TAB_TITLE = _("User notifications")
- Args:
- request ():
+ def get(self, request: HttpRequest):
+ user = request.user
+ form = UserNotificationForm(user=user, data=None)
+ context = {
+ "user": user,
+ "form": form,
+ TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
+ }
+ context = BaseContext(request, context).context
+ return render(request, self._TEMPLATE, context)
- Returns:
-
- """
- template = "user/notifications.html"
- user = request.user
-
- form = UserNotificationForm(user=user, data=request.POST or None)
- if request.method == "POST":
+ def post(self, request: HttpRequest):
+ user = request.user
+ form = UserNotificationForm(user=user, data=request.POST)
if form.is_valid():
form.save()
messages.success(
request,
_("Notifications edited")
)
- return redirect("user:index")
- elif request.method == "GET":
- # Implicit
- pass
- else:
- raise NotImplementedError
-
- context = {
- "user": user,
- "form": form,
- TAB_TITLE_IDENTIFIER: _("User notifications"),
- }
- context = BaseContext(request, context).context
- return render(request, template, context)
+ return redirect("user:detail")
+ context = {
+ "user": user,
+ "form": form,
+ TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
+ }
+ context = BaseContext(request, context).context
+ return render(request, self._TEMPLATE, context)
-@login_required_modal
-@login_required
-def contact_view(request: HttpRequest, id: str):
- """ Renders contact modal view of a users contact data
+class ContactView(LoginRequiredMixin, BaseModalFormView):
+ def get(self, request: HttpRequest, id: str):
+ """ Renders contact modal view of a users contact data
- Args:
- request (HttpRequest): The incoming request
- id (str): The user's id
+ Args:
+ request (HttpRequest): The incoming request
+ id (str): The user's id
- Returns:
+ Returns:
- """
- user = get_object_or_404(User, id=id)
- form = UserContactForm(request.POST or None, instance=user, request=request)
- template = "modal/modal_form.html"
- context = {
- "form": form,
- }
- context = BaseContext(request, context).context
- return render(
- request,
- template,
- context
- )
+ """
+ user = get_object_or_404(User, id=id)
+ form = UserContactForm(request.POST or None, instance=user, request=request)
+ context = {
+ "form": form,
+ }
+ context = BaseContext(request, context).context
+ return render(request, self._TEMPLATE, context)
-@login_required_modal
-@login_required
-def data_team_view(request: HttpRequest, id: str):
- """ Renders team data
+class TeamDetailModalView(LoginRequiredMixin, BaseModalFormView):
+ def get(self, request: HttpRequest, id: str):
+ """ Renders team data
- Args:
- request (HttpRequest): The incoming request
- id (str): The team's id
+ Args:
+ request (HttpRequest): The incoming request
+ id (str): The team's id
- Returns:
+ Returns:
- """
- team = get_object_or_404(Team, id=id)
- form = TeamDataForm(request.POST or None, instance=team, request=request)
- template = "modal/modal_form.html"
- context = {
- "form": form,
- }
- context = BaseContext(request, context).context
- return render(
- request,
- template,
- context
- )
+ """
+ team = get_object_or_404(Team, id=id)
+ form = TeamDataForm(request.POST or None, instance=team, request=request)
+ context = {
+ "form": form,
+ }
+ context = BaseContext(request, context).context
+ return render(request, self._TEMPLATE, context)
-@login_required
-def index_team_view(request: HttpRequest):
- template = "user/team/index.html"
- user = request.user
- context = {
- "teams": user.shared_teams,
- "tab_title": _("Teams"),
- }
- context = BaseContext(request, context).context
- return render(request, template, context)
+class TeamIndexView(LoginRequiredMixin, BaseView):
+ _TEMPLATE = "user/team/index.html"
+ _TAB_TITLE = _("Teams")
+
+ def get(self, request: HttpRequest):
+ user = request.user
+ context = {
+ "teams": user.shared_teams,
+ "tab_title": self._TAB_TITLE,
+ }
+ context = BaseContext(request, context).context
+ return render(request, self._TEMPLATE, context)
@login_required_modal