* adds modal form for adding payments * generalizes generic_table_form.html for table-form-like usage in modal_form.html * adds css enhancements for focused input fields * adds BaseModalForm as specification to BaseForm, which inherits the BSModalForm class as well * adds translations
153 lines
4.6 KiB
Python
153 lines
4.6 KiB
Python
"""
|
|
Author: Michel Peltriaux
|
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
Created on: 16.11.20
|
|
|
|
"""
|
|
|
|
from abc import abstractmethod
|
|
|
|
from bootstrap_modal_forms.forms import BSModalForm
|
|
from django import forms
|
|
from django.contrib.auth.models import User
|
|
from django.contrib.gis.forms import GeometryField, OSMWidget
|
|
from django.contrib.gis.geos import Polygon
|
|
from django.utils import timezone
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
|
class BaseForm(forms.Form):
|
|
"""
|
|
Basic form for that holds attributes needed in all other forms
|
|
"""
|
|
action_url = None
|
|
form_title = None
|
|
cancel_redirect = None
|
|
form_caption = None
|
|
instance = None # The data holding model object
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.instance = kwargs.pop("instance", None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
@abstractmethod
|
|
def save(self):
|
|
# To be implemented in subclasses!
|
|
pass
|
|
|
|
def disable_form_field(self, field: str):
|
|
"""
|
|
Disables a form field for user editing
|
|
"""
|
|
self.fields[field].widget.attrs["readonly"] = True
|
|
self.fields[field].disabled = True
|
|
self.fields[field].widget.attrs["title"] = _("Not editable")
|
|
|
|
def initialize_form_field(self, field: str, val):
|
|
"""
|
|
Initializes a form field with a value
|
|
"""
|
|
self.fields[field].initial = val
|
|
|
|
def load_initial_data(self, form_data: dict, disabled_fields: list):
|
|
""" Initializes form data from instance
|
|
|
|
Inserts instance data into form and disables form fields
|
|
|
|
Returns:
|
|
|
|
"""
|
|
if self.instance is None:
|
|
return
|
|
for k, v in form_data.items():
|
|
self.initialize_form_field(k, v)
|
|
for field in disabled_fields:
|
|
self.disable_form_field(field)
|
|
|
|
|
|
class RemoveForm(BaseForm):
|
|
check = forms.BooleanField(
|
|
label=_("Confirm"),
|
|
label_suffix=_(""),
|
|
required=True,
|
|
)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.object_to_remove = kwargs.pop("object_to_remove", None)
|
|
self.remove_post_url = kwargs.pop("remove_post_url", "")
|
|
self.cancel_url = kwargs.pop("cancel_url", "")
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
self.form_title = _("Remove")
|
|
if self.object_to_remove is not None:
|
|
self.form_caption = _("You are about to remove {} {}").format(self.object_to_remove.__class__.__name__, self.object_to_remove)
|
|
self.action_url = self.remove_post_url
|
|
self.cancel_redirect = self.cancel_url
|
|
|
|
def is_checked(self) -> bool:
|
|
return self.cleaned_data.get("check", False)
|
|
|
|
def save(self, user: User):
|
|
if self.object_to_remove is not None and self.is_checked():
|
|
self.object_to_remove.is_active = False
|
|
self.object_to_remove.deleted_on = timezone.now()
|
|
self.object_to_remove.deleted_by = user
|
|
self.object_to_remove.save()
|
|
return self.object_to_remove
|
|
|
|
|
|
class BaseModalForm(BaseForm, BSModalForm):
|
|
""" A specialzed form class for modal form handling
|
|
|
|
"""
|
|
is_modal_form = True
|
|
|
|
|
|
class SimpleGeomForm(BaseForm):
|
|
""" A geometry form for rendering geometry read-only using a widget
|
|
|
|
"""
|
|
geom = GeometryField(
|
|
required=False,
|
|
disabled=True,
|
|
widget=OSMWidget(
|
|
attrs={
|
|
"map_width": 600,
|
|
"map_height": 400,
|
|
}
|
|
)
|
|
)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# Initialize geometry
|
|
try:
|
|
geom = self.instance.geometry.geom
|
|
if geom is None:
|
|
raise AttributeError
|
|
except AttributeError:
|
|
# catches if no geometry has been added, yet. Replace with empty placeholder polygon.
|
|
geom = Polygon.from_bbox([0, 0, 0, 0])
|
|
# Zoom out to a very high level, so the user can see directly that there is no geometry for this entry
|
|
self.fields["geom"].widget.attrs["default_zoom"] = 1
|
|
self.initialize_form_field("geom", geom)
|
|
self.area = geom.area
|
|
|
|
|
|
class RemoveDocumentForm(BaseModalForm):
|
|
confirm = forms.BooleanField(
|
|
label=_("Confirm"),
|
|
label_suffix=_(""),
|
|
widget=forms.CheckboxInput(),
|
|
required=True,
|
|
)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.instance = kwargs.get("instance", None)
|
|
self.form_title = _("Remove document")
|
|
self.form_caption = _("This will remove '{}'. Are you sure?").format(self.instance.title)
|