""" 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)