# User view refactoring
* refactors majority of user views into class based views * introduces BaseModalFormView and BaseView for even more generic usage * renames url identifier user:index into user:detail for more clarity
This commit is contained in:
parent
be9f6f1b7e
commit
afbdf221c3
@ -17,12 +17,24 @@ from konova.utils.general import check_user_is_in_any_group
|
|||||||
from konova.utils.message_templates import MISSING_GROUP_PERMISSION
|
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
|
""" Base class for index views
|
||||||
|
|
||||||
"""
|
"""
|
||||||
_TEMPLATE: str = 'generic_index.html'
|
_TEMPLATE = "generic_index.html"
|
||||||
_TAB_TITLE: str = "CHANGE_ME"
|
|
||||||
_INDEX_TABLE_CLS = None
|
_INDEX_TABLE_CLS = None
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@ -56,7 +56,7 @@
|
|||||||
{% if user.is_staff or user.is_superuser %}
|
{% if user.is_staff or user.is_superuser %}
|
||||||
<a class="dropdown-item" target="_blank" href="{% url 'admin:index' %}">{% fa5_icon 'tools' %} {% trans 'Admin' %}</a>
|
<a class="dropdown-item" target="_blank" href="{% url 'admin:index' %}">{% fa5_icon 'tools' %} {% trans 'Admin' %}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a class="dropdown-item" href="{% url 'user:index' %}">{% fa5_icon 'cogs' %} {% trans 'Settings' %}</a>
|
<a class="dropdown-item" href="{% url 'user:detail' %}">{% fa5_icon 'cogs' %} {% trans 'Settings' %}</a>
|
||||||
<a class="dropdown-item" href="{% url 'logout' %}">{% fa5_icon 'sign-out-alt' %} {% trans 'Logout' %}</a>
|
<a class="dropdown-item" href="{% url 'logout' %}">{% fa5_icon 'sign-out-alt' %} {% trans 'Logout' %}</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@ -38,7 +38,7 @@ class UserNotificationForm(BaseForm):
|
|||||||
self.form_title = _("Edit notifications")
|
self.form_title = _("Edit notifications")
|
||||||
self.form_caption = _("")
|
self.form_caption = _("")
|
||||||
self.action_url = reverse("user:notifications")
|
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
|
# Insert all notifications into form field by creating choices as tuples
|
||||||
notifications = UserNotification.objects.filter(
|
notifications = UserNotification.objects.filter(
|
||||||
|
|||||||
@ -26,7 +26,7 @@ class UserViewTestCase(BaseViewTestCase):
|
|||||||
self.team.users.add(self.superuser)
|
self.team.users.add(self.superuser)
|
||||||
self.team.admins.add(self.superuser)
|
self.team.admins.add(self.superuser)
|
||||||
# Prepare urls
|
# Prepare urls
|
||||||
self.index_url = reverse("user:index", args=())
|
self.index_url = reverse("user:detail", args=())
|
||||||
self.notification_url = reverse("user:notifications", args=())
|
self.notification_url = reverse("user:notifications", args=())
|
||||||
self.api_token_url = reverse("user:api-token", args=())
|
self.api_token_url = reverse("user:api-token", args=())
|
||||||
self.contact_url = reverse("user:contact", args=(self.superuser.id,))
|
self.contact_url = reverse("user:contact", args=(self.superuser.id,))
|
||||||
|
|||||||
@ -233,7 +233,7 @@ class UserNotificationFormTestCase(BaseTestCase):
|
|||||||
self.assertEqual(form.form_title, str(_("Edit notifications")))
|
self.assertEqual(form.form_title, str(_("Edit notifications")))
|
||||||
self.assertEqual(form.form_caption, "")
|
self.assertEqual(form.form_caption, "")
|
||||||
self.assertEqual(form.action_url, reverse("user:notifications"))
|
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):
|
def test_save(self):
|
||||||
selected_notification = UserNotification.objects.first()
|
selected_notification = UserNotification.objects.first()
|
||||||
|
|||||||
10
user/urls.py
10
user/urls.py
@ -15,15 +15,15 @@ from user.views.views import *
|
|||||||
|
|
||||||
app_name = "user"
|
app_name = "user"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", index_view, name="index"),
|
path("", UserDetailView.as_view(), name="detail"),
|
||||||
path("propagate/", PropagateUserView.as_view(), name="propagate"),
|
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", APITokenView.as_view(), name="api-token"),
|
||||||
path("token/api/new", new_api_token_view, name="api-token-new"),
|
path("token/api/new", new_api_token_view, name="api-token-new"),
|
||||||
path("contact/<id>", contact_view, name="contact"),
|
path("contact/<id>", ContactView.as_view(), name="contact"),
|
||||||
path("team/", index_team_view, name="team-index"),
|
path("team/", TeamIndexView.as_view(), name="team-index"),
|
||||||
path("team/new", new_team_view, name="team-new"),
|
path("team/new", new_team_view, name="team-new"),
|
||||||
path("team/<id>", data_team_view, name="team-data"),
|
path("team/<id>", TeamDetailModalView.as_view(), name="team-data"),
|
||||||
path("team/<id>/edit", edit_team_view, name="team-edit"),
|
path("team/<id>/edit", edit_team_view, name="team-edit"),
|
||||||
path("team/<id>/remove", remove_team_view, name="team-remove"),
|
path("team/<id>/remove", remove_team_view, name="team-remove"),
|
||||||
path("team/<id>/leave", leave_team_view, name="team-leave"),
|
path("team/<id>/leave", leave_team_view, name="team-leave"),
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
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.team import NewTeamModalForm, EditTeamModalForm, RemoveTeamModalForm, LeaveTeamModalForm
|
||||||
from user.forms.modals.user import UserContactForm
|
from user.forms.modals.user import UserContactForm
|
||||||
from user.forms.team import TeamDataForm
|
from user.forms.team import TeamDataForm
|
||||||
@ -13,70 +15,58 @@ from django.shortcuts import render, redirect, get_object_or_404
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from konova.contexts import BaseContext
|
from konova.contexts import BaseContext
|
||||||
from konova.decorators import any_group_check, login_required_modal
|
from konova.decorators import login_required_modal
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class UserDetailView(LoginRequiredMixin, BaseView):
|
||||||
@any_group_check
|
_TAB_TITLE = _("User settings")
|
||||||
def index_view(request: HttpRequest):
|
_TEMPLATE = "user/index.html"
|
||||||
""" Renders the user's data index view
|
|
||||||
|
|
||||||
Args:
|
def get(self, request: HttpRequest):
|
||||||
request ():
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
template = "user/index.html"
|
|
||||||
context = {
|
context = {
|
||||||
"user": request.user,
|
"user": request.user,
|
||||||
TAB_TITLE_IDENTIFIER: _("User settings"),
|
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||||
}
|
}
|
||||||
context = BaseContext(request, context).context
|
context = BaseContext(request, context).context
|
||||||
return render(request, template, context)
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class NotificationsView(LoginRequiredMixin, BaseView):
|
||||||
@any_group_check
|
_TEMPLATE = "user/notifications.html"
|
||||||
def notifications_view(request: HttpRequest):
|
_TAB_TITLE = _("User notifications")
|
||||||
""" Renders the notifications settings view
|
|
||||||
|
|
||||||
Args:
|
def get(self, request: HttpRequest):
|
||||||
request ():
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
template = "user/notifications.html"
|
|
||||||
user = request.user
|
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)
|
||||||
|
|
||||||
form = UserNotificationForm(user=user, data=request.POST or None)
|
def post(self, request: HttpRequest):
|
||||||
if request.method == "POST":
|
user = request.user
|
||||||
|
form = UserNotificationForm(user=user, data=request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
form.save()
|
form.save()
|
||||||
messages.success(
|
messages.success(
|
||||||
request,
|
request,
|
||||||
_("Notifications edited")
|
_("Notifications edited")
|
||||||
)
|
)
|
||||||
return redirect("user:index")
|
return redirect("user:detail")
|
||||||
elif request.method == "GET":
|
|
||||||
# Implicit
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"user": user,
|
"user": user,
|
||||||
"form": form,
|
"form": form,
|
||||||
TAB_TITLE_IDENTIFIER: _("User notifications"),
|
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||||
}
|
}
|
||||||
context = BaseContext(request, context).context
|
context = BaseContext(request, context).context
|
||||||
return render(request, template, context)
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
|
||||||
@login_required_modal
|
class ContactView(LoginRequiredMixin, BaseModalFormView):
|
||||||
@login_required
|
def get(self, request: HttpRequest, id: str):
|
||||||
def contact_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders contact modal view of a users contact data
|
""" Renders contact modal view of a users contact data
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -88,21 +78,15 @@ def contact_view(request: HttpRequest, id: str):
|
|||||||
"""
|
"""
|
||||||
user = get_object_or_404(User, id=id)
|
user = get_object_or_404(User, id=id)
|
||||||
form = UserContactForm(request.POST or None, instance=user, request=request)
|
form = UserContactForm(request.POST or None, instance=user, request=request)
|
||||||
template = "modal/modal_form.html"
|
|
||||||
context = {
|
context = {
|
||||||
"form": form,
|
"form": form,
|
||||||
}
|
}
|
||||||
context = BaseContext(request, context).context
|
context = BaseContext(request, context).context
|
||||||
return render(
|
return render(request, self._TEMPLATE, context)
|
||||||
request,
|
|
||||||
template,
|
|
||||||
context
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required_modal
|
class TeamDetailModalView(LoginRequiredMixin, BaseModalFormView):
|
||||||
@login_required
|
def get(self, request: HttpRequest, id: str):
|
||||||
def data_team_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders team data
|
""" Renders team data
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -114,28 +98,25 @@ def data_team_view(request: HttpRequest, id: str):
|
|||||||
"""
|
"""
|
||||||
team = get_object_or_404(Team, id=id)
|
team = get_object_or_404(Team, id=id)
|
||||||
form = TeamDataForm(request.POST or None, instance=team, request=request)
|
form = TeamDataForm(request.POST or None, instance=team, request=request)
|
||||||
template = "modal/modal_form.html"
|
|
||||||
context = {
|
context = {
|
||||||
"form": form,
|
"form": form,
|
||||||
}
|
}
|
||||||
context = BaseContext(request, context).context
|
context = BaseContext(request, context).context
|
||||||
return render(
|
return render(request, self._TEMPLATE, context)
|
||||||
request,
|
|
||||||
template,
|
|
||||||
context
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class TeamIndexView(LoginRequiredMixin, BaseView):
|
||||||
def index_team_view(request: HttpRequest):
|
_TEMPLATE = "user/team/index.html"
|
||||||
template = "user/team/index.html"
|
_TAB_TITLE = _("Teams")
|
||||||
|
|
||||||
|
def get(self, request: HttpRequest):
|
||||||
user = request.user
|
user = request.user
|
||||||
context = {
|
context = {
|
||||||
"teams": user.shared_teams,
|
"teams": user.shared_teams,
|
||||||
"tab_title": _("Teams"),
|
"tab_title": self._TAB_TITLE,
|
||||||
}
|
}
|
||||||
context = BaseContext(request, context).context
|
context = BaseContext(request, context).context
|
||||||
return render(request, template, context)
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
|
||||||
@login_required_modal
|
@login_required_modal
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user