From f153d0da40c1b99ec8fac3a7c2b3ee525df1f769 Mon Sep 17 00:00:00 2001 From: Simon Oliver Tveit Date: Wed, 15 Jan 2025 02:40:50 +0100 Subject: [PATCH] WIP implement --- src/argus/htmx/destination/forms.py | 92 ++++++++--------------------- src/argus/htmx/destination/views.py | 27 ++++----- 2 files changed, 37 insertions(+), 82 deletions(-) diff --git a/src/argus/htmx/destination/forms.py b/src/argus/htmx/destination/forms.py index fb50ac073..76626bbf3 100644 --- a/src/argus/htmx/destination/forms.py +++ b/src/argus/htmx/destination/forms.py @@ -2,7 +2,6 @@ from django.forms import ModelForm from argus.notificationprofile.models import DestinationConfig, Media -from argus.notificationprofile.serializers import RequestDestinationConfigSerializer from argus.notificationprofile.media import api_safely_get_medium_object @@ -10,8 +9,8 @@ class DestinationFormCreate(ModelForm): settings = forms.CharField(required=True) def __init__(self, *args, **kwargs): - # Serializer request the request object - self.request = kwargs.pop("request", None) + # Serializer needs the request object + self.user = kwargs.pop("user", None) super().__init__(*args, **kwargs) class Meta: @@ -26,54 +25,29 @@ class Meta: def clean(self): super().clean() + media = self.cleaned_data["media"] + medium = api_safely_get_medium_object(media.slug)() settings_key = _get_settings_key_for_media(self.cleaned_data["media"]) # Convert settings value (e.g. email address) to be compatible with JSONField self.cleaned_data["settings"] = {settings_key: self.cleaned_data["settings"]} - self._init_serializer() - return self._validate_serializer() + + # Update form needs to set instance.settings back to the json dict form before validating + + form = self._validate(medium) + return form.cleaned_data def save(self): - # self.serializer should be initiated and validated in clean() before save() is called - self.serializer.save(user=self.request.user) - - def _init_serializer(self): - serializer = RequestDestinationConfigSerializer( - data={ - "media": self.cleaned_data["media"], - "label": self.cleaned_data.get("label", ""), - "settings": self.cleaned_data["settings"], - }, - context={"request": self.request}, + # Manual save to include user since the form itself does not have a user field + new_destination = DestinationConfig( + user=self.cleaned_data["user"], + media=self.cleaned_data["media"], + label=self.cleaned_data.get("label", ""), + settings=self.cleaned_data["settings"], ) - self.serializer = serializer + new_destination.save() - def _validate_serializer(self): - media = self.cleaned_data["media"] - settings_key = _get_settings_key_for_media(media) - - # Add error messages from serializer to form - if not self.serializer.is_valid(): - for error_name, error_detail in self.serializer.errors.items(): - if error_name in ["media", "label", settings_key]: - if error_name == settings_key: - error_name = "settings" - self.add_error(error_name, error_detail) - # Serializer might add more data to the JSON dict - if settings := self.serializer.data.get("settings"): - self.cleaned_data["settings"] = settings - else: - # Serializer might add more data to the JSON dict - if settings := self.serializer.validated_data.get("settings"): - self.cleaned_data["settings"] = settings - - if label := self.cleaned_data.get("label"): - destination_filter = DestinationConfig.objects.filter(label=label, media=media) - if self.instance: - destination_filter = destination_filter.exclude(pk=self.instance.pk) - if destination_filter.exists(): - self.add_error("label", "Name must be unique per media") - - return self.cleaned_data + def _validate(self, medium): + return medium.validate(data=self.cleaned_data, user=self.user) class DestinationFormUpdate(DestinationFormCreate): @@ -94,28 +68,14 @@ class Meta: "media": forms.HiddenInput(), } - def _init_serializer(self): - # self.instance is modified in __init__, - # so get unmodified version here for the serializer - destination = DestinationConfig.objects.get(pk=self.instance.pk) - settings_key = _get_settings_key_for_media(destination.media) - data = {} - - if "label" in self.cleaned_data: - label = self.cleaned_data["label"] - if label != destination.label: - data["label"] = label - - settings = self.cleaned_data["settings"] - if settings.get(settings_key) != destination.settings.get(settings_key): - data["settings"] = settings - - self.serializer = RequestDestinationConfigSerializer( - destination, - data=data, - context={"request": self.request}, - partial=True, - ) + def save(self): + self.instance.settings = self.cleaned_data["settings"] + self.instance.label = self.cleaned_data.get("label", "") + self.instance.save() + + def _validate(self, medium): + # raise ValueError(str(self.cleaned_data["media"]) == self.instance.media.slug) + return medium.validate(data=self.cleaned_data, user=self.user, instance=self.instance) def _get_settings_key_for_media(media: Media) -> str: diff --git a/src/argus/htmx/destination/views.py b/src/argus/htmx/destination/views.py index fdd4cd489..e27d5684c 100644 --- a/src/argus/htmx/destination/views.py +++ b/src/argus/htmx/destination/views.py @@ -18,7 +18,7 @@ def destination_list(request): @require_http_methods(["POST"]) def create_htmx(request) -> HttpResponse: - form = DestinationFormCreate(request.POST or None, request=request) + form = DestinationFormCreate(request.POST or None, user=request.user) template = "htmx/destination/_content.html" if form.is_valid(): form.save() @@ -52,22 +52,17 @@ def delete_htmx(request, pk: int) -> HttpResponse: @require_http_methods(["POST"]) def update_htmx(request, pk: int) -> HttpResponse: destination = DestinationConfig.objects.get(pk=pk) - media = destination.media - form = DestinationFormUpdate(request.POST or None, instance=destination, request=request) - if is_valid := form.is_valid(): + form = DestinationFormUpdate(request.POST or None, instance=destination, request=request.user) + template = "htmx/destination/_form_list.html" + if form.is_valid(): form.save() - - update_forms = _get_update_forms(request.user, media=media) - - if not is_valid: - update_forms = _replace_form_in_list(update_forms, form) - - context = { - "error_msg": None, - "forms": update_forms, - "media": media, - } - return render(request, "htmx/destination/_collapse_with_forms.html", context=context) + return _render_destination_list(request, template=template) + update_forms = _get_update_forms(request.user) + for index, update_form in enumerate(update_forms): + if update_form.instance.pk == pk: + update_forms[index] = form + break + return _render_destination_list(request, update_forms=update_forms, template=template) def _render_destination_list(