""" 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 BSModalModelForm, 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.urls import reverse 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 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(BaseForm, BSModalForm): 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)