* refactors AbstractRecordModalForm * refactors recording view for ema, intervention and eco account
378 lines
12 KiB
Python
378 lines
12 KiB
Python
"""
|
|
Author: Michel Peltriaux
|
|
Created on: 15.10.25
|
|
|
|
"""
|
|
from abc import abstractmethod
|
|
|
|
from bootstrap_modal_forms.mixins import is_ajax
|
|
from django.contrib import messages
|
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
from django.http import HttpRequest, JsonResponse, HttpResponseRedirect
|
|
from django.shortcuts import render, redirect, get_object_or_404
|
|
from django.urls import reverse
|
|
from django.views import View
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from konova.contexts import BaseContext
|
|
from konova.forms import BaseForm, SimpleGeomForm
|
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
|
from konova.utils.general import check_user_is_in_any_group, check_id_is_valid_uuid
|
|
from konova.utils.message_templates import MISSING_GROUP_PERMISSION, DATA_UNSHARED, IDENTIFIER_REPLACED, \
|
|
GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE, RECORDED_BLOCKS_EDIT, FORM_INVALID
|
|
|
|
|
|
class BaseView(View):
|
|
_TEMPLATE: str = "CHANGE_ME"
|
|
_TAB_TITLE: str = "CHANGE_ME"
|
|
_REDIRECT_URL: str = "CHANGE_ME"
|
|
_REDIRECT_URL_ERROR: str = "home"
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
request = check_user_is_in_any_group(request)
|
|
|
|
if not self._user_has_permission(request.user):
|
|
messages.info(request, MISSING_GROUP_PERMISSION)
|
|
return redirect(reverse(self._REDIRECT_URL_ERROR))
|
|
|
|
if not self._user_has_shared_access(request.user, **kwargs):
|
|
messages.info(request, DATA_UNSHARED)
|
|
return redirect(reverse(self._REDIRECT_URL_ERROR))
|
|
|
|
return super().dispatch(request, *args, **kwargs)
|
|
|
|
def _user_has_permission(self, user):
|
|
""" Has to be implemented properly by inheriting classes
|
|
|
|
Args:
|
|
user ():
|
|
|
|
Returns:
|
|
|
|
"""
|
|
return False
|
|
|
|
def _user_has_shared_access(self, user, **kwargs):
|
|
""" Has to be implemented properly by inheriting classes
|
|
|
|
Args:
|
|
user ():
|
|
|
|
Returns:
|
|
|
|
"""
|
|
return False
|
|
|
|
def _get_redirect_url(self, *args, **kwargs):
|
|
return self._REDIRECT_URL
|
|
|
|
def _get_redirect_url_error(self, *args, **kwargs):
|
|
return self._REDIRECT_URL_ERROR
|
|
|
|
class BaseModalFormView(BaseView):
|
|
_TEMPLATE = "modal/modal_form.html"
|
|
_MODEL_CLS = None
|
|
_FORM_CLS = None
|
|
_TAB_TITLE = None
|
|
_MSG_SUCCESS = None
|
|
_MSG_ERROR = None
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
def _user_has_shared_access(self, user, **kwargs):
|
|
obj = get_object_or_404(self._MODEL_CLS, id=kwargs.get("id"))
|
|
return obj.is_shared_with(user)
|
|
|
|
def get(self, request: HttpRequest, id: str, *args, **kwargs):
|
|
obj = self._MODEL_CLS.objects.get(id=id)
|
|
form = self._FORM_CLS(request.POST or None, instance=obj, request=request, **kwargs)
|
|
context = {
|
|
"form": form,
|
|
}
|
|
context = BaseContext(request, context).context
|
|
return render(request, self._TEMPLATE, context)
|
|
|
|
def post(self, request: HttpRequest, id: str, *args, **kwargs):
|
|
obj = self._MODEL_CLS.objects.get(id=id)
|
|
form = self._FORM_CLS(request.POST or None, instance=obj, request=request, **kwargs)
|
|
redirect_url = self._get_redirect_url(obj=obj)
|
|
if form.is_valid():
|
|
if not is_ajax(request.META):
|
|
# Modal forms send one POST for checking on data validity. This can be used to return possible errors
|
|
# on the form. A second POST (if no errors occured) is sent afterwards and needs to process the
|
|
# saving/commiting of the data to the database. is_ajax() performs this check. The first request is
|
|
# an ajax call, the second is a regular form POST.
|
|
form.save()
|
|
messages.success(
|
|
request,
|
|
self._get_msg_success(obj=obj)
|
|
)
|
|
return HttpResponseRedirect(redirect_url)
|
|
else:
|
|
context = {
|
|
"form": form,
|
|
}
|
|
context = BaseContext(request, context).context
|
|
return render(request, self._TEMPLATE, context)
|
|
|
|
def _get_redirect_url(self, *args, **kwargs):
|
|
obj = kwargs.get("obj", None)
|
|
assert obj is not None
|
|
return reverse(self._REDIRECT_URL, args=(obj.id,))
|
|
|
|
def _get_msg_success(self, *args, **kwargs):
|
|
return self._MSG_SUCCESS
|
|
|
|
class BaseIndexView(BaseView):
|
|
""" Base class for index views
|
|
|
|
"""
|
|
_TEMPLATE = "generic_index.html"
|
|
_INDEX_TABLE_CLS = None
|
|
_REDIRECT_URL = "home"
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
def get(self, request: HttpRequest):
|
|
qs = self._get_queryset()
|
|
table = self._INDEX_TABLE_CLS(
|
|
request=request,
|
|
queryset=qs
|
|
)
|
|
context = {
|
|
"table": table,
|
|
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
|
}
|
|
context = BaseContext(request, context).context
|
|
return render(request, self._TEMPLATE, context)
|
|
|
|
@abstractmethod
|
|
def _get_queryset(self):
|
|
raise NotImplementedError
|
|
|
|
def _user_has_permission(self, user):
|
|
# No specific permissions needed for opening base index view
|
|
return True
|
|
|
|
def _user_has_shared_access(self, user, **kwargs):
|
|
# No specific constraints for shared access of index views
|
|
return True
|
|
|
|
|
|
class BaseIdentifierGeneratorView(BaseView):
|
|
_MODEL_CLS = None
|
|
_REDIRECT_URL: str = "home"
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
def get(self, request: HttpRequest):
|
|
tmp_obj = self._MODEL_CLS()
|
|
identifier = tmp_obj.generate_new_identifier()
|
|
while self._MODEL_CLS.objects.filter(identifier=identifier).exists():
|
|
identifier = tmp_obj.generate_new_identifier()
|
|
return JsonResponse(
|
|
data={
|
|
"gen_data": identifier
|
|
}
|
|
)
|
|
|
|
def _user_has_permission(self, user):
|
|
""" Should be overwritten in inheriting classes!
|
|
|
|
Args:
|
|
user ():
|
|
|
|
Returns:
|
|
|
|
"""
|
|
return user.is_default_user()
|
|
|
|
def _user_has_shared_access(self, user, **kwargs):
|
|
# No specific constraints for shared access
|
|
return True
|
|
|
|
|
|
class BaseFormView(BaseView):
|
|
_MODEL_CLS = None
|
|
_FORM_CLS = None
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
def _get_additional_context(self, **kwargs):
|
|
"""
|
|
|
|
Args:
|
|
**kwargs ():
|
|
|
|
Returns:
|
|
|
|
"""
|
|
return {}
|
|
|
|
|
|
class BaseSpatialLocatedObjectFormView(LoginRequiredMixin, BaseFormView):
|
|
_GEOMETRY_FORM_CLS = SimpleGeomForm
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
|
|
class BaseNewSpatialLocatedObjectFormView(BaseSpatialLocatedObjectFormView):
|
|
|
|
def _user_has_permission(self, user):
|
|
# User has to have default privilege to call this endpoint
|
|
return user.is_default_user()
|
|
|
|
def _user_has_shared_access(self, user, **kwargs):
|
|
# There is no shared access control since nothing exists yet
|
|
return True
|
|
|
|
def get(self, request: HttpRequest, **kwargs):
|
|
form: BaseForm = self._FORM_CLS(None, **kwargs, user=request.user)
|
|
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(None, user=request.user, read_only=False)
|
|
|
|
context = self._get_additional_context()
|
|
context = BaseContext(request, additional_context=context).context
|
|
context.update(
|
|
{
|
|
"form": form,
|
|
"geom_form": geom_form,
|
|
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
|
}
|
|
)
|
|
return render(request, self._TEMPLATE, context)
|
|
|
|
def post(self, request: HttpRequest, **kwargs):
|
|
form: BaseForm = self._FORM_CLS(request.POST or None, **kwargs, user=request.user)
|
|
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(request.POST or None, user=request.user, read_only=False)
|
|
|
|
if form.is_valid() and geom_form.is_valid():
|
|
obj = form.save(request.user, geom_form)
|
|
obj_redirect_url = reverse(self._REDIRECT_URL, args=(obj.id,))
|
|
|
|
generated_identifier = form.cleaned_data.get("identifier", None)
|
|
|
|
if generated_identifier != obj.identifier:
|
|
messages.info(
|
|
request,
|
|
IDENTIFIER_REPLACED.format(
|
|
generated_identifier,
|
|
obj.identifier
|
|
)
|
|
)
|
|
messages.success(request, _("{} added").format(obj.identifier))
|
|
if geom_form.has_geometry_simplified():
|
|
messages.info(
|
|
request,
|
|
GEOMETRY_SIMPLIFIED
|
|
)
|
|
|
|
num_ignored_geometries = geom_form.get_num_geometries_ignored()
|
|
if num_ignored_geometries > 0:
|
|
messages.info(
|
|
request,
|
|
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
|
|
)
|
|
|
|
return redirect(obj_redirect_url)
|
|
else:
|
|
context = self._get_additional_context()
|
|
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
|
|
|
context = BaseContext(request, additional_context=context).context
|
|
context.update(
|
|
{
|
|
"form": form,
|
|
"geom_form": geom_form,
|
|
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
|
}
|
|
)
|
|
return render(request, self._TEMPLATE, context)
|
|
|
|
|
|
class BaseEditSpatialLocatedObjectFormView(BaseSpatialLocatedObjectFormView):
|
|
_TAB_TITLE = _("Edit {}")
|
|
|
|
def get(self, request: HttpRequest, id: str):
|
|
obj = get_object_or_404(
|
|
self._MODEL_CLS,
|
|
id=id
|
|
)
|
|
obj_redirect_url = reverse(self._REDIRECT_URL, args=(obj.id,))
|
|
|
|
if obj.is_recorded:
|
|
messages.info(
|
|
request,
|
|
RECORDED_BLOCKS_EDIT
|
|
)
|
|
return redirect(obj_redirect_url)
|
|
|
|
form: BaseForm = self._FORM_CLS(None, instance=obj, user=request.user)
|
|
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(None, instance=obj, read_only=False)
|
|
|
|
context = self._get_additional_context()
|
|
context = BaseContext(request, additional_context=context).context
|
|
context.update(
|
|
{
|
|
"form": form,
|
|
"geom_form": geom_form,
|
|
TAB_TITLE_IDENTIFIER: self._TAB_TITLE.format(obj.identifier),
|
|
}
|
|
)
|
|
return render(request, self._TEMPLATE, context)
|
|
|
|
def post(self, request: HttpRequest, id: str):
|
|
obj = get_object_or_404(
|
|
self._MODEL_CLS,
|
|
id=id
|
|
)
|
|
obj_redirect_url = reverse(self._REDIRECT_URL, args=(obj.id,))
|
|
|
|
form: BaseForm = self._FORM_CLS(request.POST or None, instance=obj, user=request.user)
|
|
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(request.POST or None, instance=obj, read_only=False)
|
|
|
|
if form.is_valid() and geom_form.is_valid():
|
|
obj = form.save(request.user, geom_form)
|
|
messages.success(request, _("{} edited").format(obj.identifier))
|
|
|
|
if geom_form.has_geometry_simplified():
|
|
messages.info(
|
|
request,
|
|
GEOMETRY_SIMPLIFIED
|
|
)
|
|
|
|
num_ignored_geometries = geom_form.get_num_geometries_ignored()
|
|
if num_ignored_geometries > 0:
|
|
messages.info(
|
|
request,
|
|
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
|
|
)
|
|
|
|
return redirect(obj_redirect_url)
|
|
else:
|
|
context = self._get_additional_context()
|
|
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
|
|
|
context = BaseContext(request, additional_context=context).context
|
|
context.update(
|
|
{
|
|
"form": form,
|
|
"geom_form": geom_form,
|
|
TAB_TITLE_IDENTIFIER: self._TAB_TITLE.format(obj.identifier),
|
|
}
|
|
)
|
|
return render(request, self._TEMPLATE, context)
|
|
|
|
def _user_has_shared_access(self, user, **kwargs):
|
|
obj = get_object_or_404(self._MODEL_CLS, id=kwargs.get('id', None))
|
|
return obj.is_shared_with(user)
|
|
|
|
def _user_has_permission(self, user):
|
|
return user.is_default_user() |