Compare commits

..

No commits in common. "9283c38eaa5ef0f07e3b5e16d1af8c17c3d90f35" and "dabd456c996f7fc85fa494779115770fb568ad85" have entirely different histories.

4 changed files with 28 additions and 51 deletions

View file

@ -48,31 +48,18 @@ class DynamicArrayWidget(forms.Widget):
def value_from_datadict(self, data, files, name): def value_from_datadict(self, data, files, name):
value = data.get(name) value = data.get(name)
if value is None: if value:
return []
if value == "":
return []
if isinstance(value, list):
return [item for item in value if item is not None and str(item).strip()]
if isinstance(value, str):
if value.strip() == "" or value.strip().lower() == "null":
return []
try: try:
parsed = json.loads(value) parsed = json.loads(value)
if parsed is None: if parsed:
return []
if isinstance(parsed, list):
return [ return [
item item
for item in parsed for item in parsed
if item is not None and str(item).strip() if item is not None and str(item).strip()
] ]
return [parsed] if str(parsed).strip() else [] return []
except (json.JSONDecodeError, TypeError): except (json.JSONDecodeError, TypeError):
return [value] if value.strip() else [] pass
return [] return []
@ -117,17 +104,11 @@ class DynamicArrayField(forms.JSONField):
if value is None: if value is None:
return [] return []
if isinstance(value, list): if isinstance(value, list):
return [item for item in value if item is not None] return value
if isinstance(value, str): if isinstance(value, str):
if value.strip() == "" or value.strip().lower() == "null":
return []
try: try:
parsed = json.loads(value) parsed = json.loads(value)
if parsed is None: return parsed if isinstance(parsed, list) else [parsed]
return []
if isinstance(parsed, list):
return [item for item in parsed if item is not None]
return [parsed]
except (json.JSONDecodeError, TypeError): except (json.JSONDecodeError, TypeError):
return [value] if value else [] return [value] if value else []
return [str(value)] return [str(value)]
@ -136,24 +117,16 @@ class DynamicArrayField(forms.JSONField):
"""Handle bound data properly to avoid JSON parsing issues""" """Handle bound data properly to avoid JSON parsing issues"""
if data is None: if data is None:
return initial return initial
# If data is already a list (from our widget), return it as-is
if isinstance(data, list): if isinstance(data, list):
return [item for item in data if item is not None and str(item).strip()] return data
# If data is a string, try to parse it as JSON
if isinstance(data, str): if isinstance(data, str):
if data.strip() == "" or data.strip().lower() == "null":
return []
try: try:
parsed = json.loads(data) parsed = json.loads(data)
if parsed is None: return parsed if isinstance(parsed, list) else [parsed]
return []
if isinstance(parsed, list):
return [
item
for item in parsed
if item is not None and str(item).strip()
]
return [parsed] if str(parsed).strip() else []
except (json.JSONDecodeError, TypeError): except (json.JSONDecodeError, TypeError):
return [data] if data and data.strip() else [] return [data] if data else []
return data return data
def validate(self, value): def validate(self, value):

View file

@ -4,7 +4,6 @@
method="post" method="post"
{% if form_action %}action="{{ form_action }}"{% endif %}> {% if form_action %}action="{{ form_action }}"{% endif %}>
{% csrf_token %} {% csrf_token %}
{% include "frontend/forms/errors.html" %}
<ul class="nav nav-tabs" id="myTab" role="tablist"> <ul class="nav nav-tabs" id="myTab" role="tablist">
{% for fieldset in form.get_fieldsets %} {% for fieldset in form.get_fieldsets %}
{% if not fieldset.hidden %} {% if not fieldset.hidden %}

View file

@ -163,12 +163,14 @@ class ServiceOfferingDetailView(OrganizationViewMixin, HtmxViewMixin, DetailView
) )
return redirect(service_instance.urls.base) return redirect(service_instance.urls.base)
except ValidationError as e: except ValidationError as e:
form.add_error(None, e.message or str(e)) messages.error(self.request, e.message or str(e))
except Exception as e: except Exception as e:
error_message = self.organization.add_support_message( messages.error(
_(f"Error creating instance: {str(e)}.") self.request,
self.organization.add_support_message(
_(f"Error creating instance: {str(e)}.")
),
) )
form.add_error(None, error_message)
# If the form is not valid or if the service creation failed, we render it again # If the form is not valid or if the service creation failed, we render it again
context["service_form"] = form context["service_form"] = form
@ -344,6 +346,10 @@ class ServiceInstanceUpdateView(
kwargs["instance"] = self.object.spec_object kwargs["instance"] = self.object.spec_object
return kwargs return kwargs
def form_invalid(self, form):
messages.error(self.request, form.errors)
return super().form_invalid(form)
def form_valid(self, form): def form_valid(self, form):
try: try:
spec_data = form.get_nested_data().get("spec") spec_data = form.get_nested_data().get("spec")
@ -356,13 +362,15 @@ class ServiceInstanceUpdateView(
) )
return redirect(self.object.urls.base) return redirect(self.object.urls.base)
except ValidationError as e: except ValidationError as e:
form.add_error(None, e.message or str(e)) messages.error(self.request, e.message or str(e))
return self.form_invalid(form) return self.form_invalid(form)
except Exception as e: except Exception as e:
error_message = self.organization.add_support_message( messages.error(
_(f"Error updating instance: {str(e)}.") self.request,
self.organization.add_support_message(
_(f"Error updating instance: {str(e)}.")
),
) )
form.add_error(None, error_message)
return self.form_invalid(form) return self.form_invalid(form)
def get_success_url(self): def get_success_url(self):

View file

@ -19,9 +19,6 @@ const initDynamicArrayWidget = () => {
addRemoveEventListeners(container) addRemoveEventListeners(container)
addInputEventListeners(container) addInputEventListeners(container)
updateRemoveButtonVisibility(container) updateRemoveButtonVisibility(container)
// Ensure hidden input is synced with visible inputs on initialization
updateHiddenInput(container)
}) })
} }
@ -97,7 +94,7 @@ const updateHiddenInput = (container) => {
if (!hiddenInput) return if (!hiddenInput) return
const values = Array.from(inputs) const values = Array.from(inputs)
.map(input => input.value ? input.value.trim() : '') .map(input => input.value.trim())
.filter(value => value !== '') .filter(value => value !== '')
hiddenInput.value = JSON.stringify(values) hiddenInput.value = JSON.stringify(values)