Compare commits

..

No commits in common. "ca485978b93b8997bdbe774127503dcdc1765e9f" and "a5d46b696f5b8a9aacecd277b1e9c397e28b9cb8" have entirely different histories.

8 changed files with 34 additions and 32 deletions

View file

@ -560,7 +560,7 @@ class CustomFormMixin(FormGeneratorMixin):
field = self.fields[field_name] field = self.fields[field_name]
field_type = field_config.get("type") field_type = field_config.get("type")
field.label = field_config.get("label", field_name) field.label = field_config.get("label", field_config["name"])
field.help_text = field_config.get("help_text", "") field.help_text = field_config.get("help_text", "")
field.required = field_config.get("required", False) field.required = field_config.get("required", False)

View file

@ -192,7 +192,7 @@ class ServiceDefinitionAdminForm(forms.ModelForm):
schema = None schema = None
try: try:
schema = crd.resource_schema schema = crd.resource_schema
except Exception: except Exception as e:
pass pass
if not schema or not (spec_schema := schema.get("properties", {}).get("spec")): if not schema or not (spec_schema := schema.get("properties", {}).get("spec")):

View file

@ -15,11 +15,7 @@ class Migration(migrations.Migration):
name="form_config", name="form_config",
field=models.JSONField( field=models.JSONField(
blank=True, blank=True,
help_text=( help_text='Optional custom form configuration. When provided, this configuration will be used to render the service form instead of auto-generating it from the OpenAPI spec. Format: {"fieldsets": [{"title": "Section", "fields": [{...}]}]}',
"Optional custom form configuration. When provided, this configuration will "
"be used to render the service form instead of auto-generating it from the OpenAPI spec. "
'Format: {"fieldsets": [{"title": "Section", "fields": [{...}]}]}'
),
null=True, null=True,
verbose_name="Form Configuration", verbose_name="Form Configuration",
), ),

View file

@ -23,8 +23,13 @@
"minItems": 1, "minItems": 1,
"items": { "items": {
"type": "object", "type": "object",
"required": ["type", "label", "controlplane_field_mapping"], "required": ["name", "type", "label", "controlplane_field_mapping"],
"properties": { "properties": {
"name": {
"type": "string",
"description": "Unique field name/identifier",
"pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$"
},
"type": { "type": {
"type": "string", "type": "string",
"description": "Field type", "description": "Field type",
@ -92,6 +97,14 @@
"type": "string", "type": "string",
"enum": ["email", "fqdn", "url", "ipv4", "ipv6"] "enum": ["email", "fqdn", "url", "ipv4", "ipv6"]
} }
},
"generators": {
"type": "array",
"description": "Array of generator function names (for future use)",
"items": {
"type": "string",
"enum": ["suggest_fqdn_from_name"]
}
} }
} }
} }

View file

@ -31,9 +31,7 @@
</div> </div>
{% for provider in socialaccount_providers %} {% for provider in socialaccount_providers %}
{% provider_login_url provider process=process scope=scope auth_params=auth_params as href %} {% provider_login_url provider process=process scope=scope auth_params=auth_params as href %}
<form method="post" <form method="post" action="{{ href }}" class="d-flex justify-content-center">
action="{{ href }}"
class="d-flex justify-content-center">
{% csrf_token %} {% csrf_token %}
{{ redirect_field }} {{ redirect_field }}
<button type="submit" <button type="submit"

View file

@ -42,9 +42,7 @@
<i class="bi bi-exclamation-triangle-fill me-2"></i> <i class="bi bi-exclamation-triangle-fill me-2"></i>
<div> <div>
<strong>{% translate "Service Unavailable" %}</strong> <strong>{% translate "Service Unavailable" %}</strong>
<p class="mb-0"> <p class="mb-0">{% translate "We currently cannot offer this service. Please check back later or contact support for more information." %}</p>
{% translate "We currently cannot offer this service. Please check back later or contact support for more information." %}
</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -4,7 +4,9 @@
{% for info in control_plane.user_info %} {% for info in control_plane.user_info %}
<div class="info-item mb-3"> <div class="info-item mb-3">
<div class="d-flex align-items-center mb-1"> <div class="d-flex align-items-center mb-1">
<small class="text-muted fw-semibold">{{ info.title }}</small> <small class="text-muted fw-semibold">
{{ info.title }}
</small>
{% if info.help_text %} {% if info.help_text %}
<i class="bi bi-info-circle ms-1 text-muted" <i class="bi bi-info-circle ms-1 text-muted"
data-bs-toggle="popover" data-bs-toggle="popover"
@ -12,7 +14,7 @@
data-bs-placement="top" data-bs-placement="top"
data-bs-content="{{ info.help_text }}" data-bs-content="{{ info.help_text }}"
style="cursor: help; style="cursor: help;
font-size: 0.875rem"></i> font-size: 0.875rem;"></i>
{% endif %} {% endif %}
</div> </div>
<div class="bg-light-subtle p-2 rounded"> <div class="bg-light-subtle p-2 rounded">

View file

@ -15,8 +15,7 @@
</button> </button>
</div> </div>
{% endif %} {% endif %}
<div id="custom-form-container" <div id="custom-form-container" class="{% if form %}custom-crd-form{% else %}expert-crd-form{% endif %}">
class="{% if form %}custom-crd-form{% else %}expert-crd-form{% endif %}">
{% if form and form.context %}{{ form.context }}{% endif %} {% if form and form.context %}{{ form.context }}{% endif %}
{% if form and form.get_fieldsets|length == 1 %} {% if form and form.get_fieldsets|length == 1 %}
{# Single fieldset - render without tabs #} {# Single fieldset - render without tabs #}
@ -42,7 +41,8 @@
<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 %}
<li class="nav-item" role="presentation"> <li class="nav-item"
role="presentation">
<button class="nav-link {% if forloop.first %}active{% endif %}{% if fieldset.has_mandatory %} has-mandatory{% endif %}" <button class="nav-link {% if forloop.first %}active{% endif %}{% if fieldset.has_mandatory %} has-mandatory{% endif %}"
id="{{ fieldset.title|slugify }}-tab" id="{{ fieldset.title|slugify }}-tab"
data-bs-toggle="tab" data-bs-toggle="tab"
@ -83,13 +83,12 @@
{% endif %} {% endif %}
</div> </div>
{% if form and expert_form %} {% if form and expert_form %}
<div id="expert-form-container" <div id="expert-form-container" class="expert-crd-form" style="display:none;">
class="expert-crd-form"
style="display:none">
<ul class="nav nav-tabs" id="expertTab" role="tablist"> <ul class="nav nav-tabs" id="expertTab" role="tablist">
{% for fieldset in expert_form.get_fieldsets %} {% for fieldset in expert_form.get_fieldsets %}
{% if not fieldset.hidden %} {% if not fieldset.hidden %}
<li class="nav-item" role="presentation"> <li class="nav-item"
role="presentation">
<button class="nav-link {% if forloop.first %}active{% endif %}{% if fieldset.has_mandatory %} has-mandatory{% endif %}" <button class="nav-link {% if forloop.first %}active{% endif %}{% if fieldset.has_mandatory %} has-mandatory{% endif %}"
id="expert-{{ fieldset.title|slugify }}-tab" id="expert-{{ fieldset.title|slugify }}-tab"
data-bs-toggle="tab" data-bs-toggle="tab"
@ -130,17 +129,13 @@
</div> </div>
{% endif %} {% endif %}
{% if form %} {% if form %}
<input type="hidden" <input type="hidden" name="active_form" id="active-form-input" value="custom">
name="active_form"
id="active-form-input"
value="custom">
{% endif %} {% endif %}
<div class="col-sm-12 d-flex justify-content-end"> <div class="col-sm-12 d-flex justify-content-end">
{# browser form validation fails when there are fields missing/invalid that are hidden #} <input class="btn btn-primary me-1 mb-1" type="submit"
<input class="btn btn-primary me-1 mb-1" {% if form and expert_form %}formnovalidate {% endif %} {# browser form validation fails when there are fields missing/invalid that are hidden #}
type="submit" value="{% if form_submit_label %}{{ form_submit_label }}{% else %}{% translate "Save" %}{% endif %}"
{% if form and expert_form %}formnovalidate{% endif %} >
value="{% if form_submit_label %}{{ form_submit_label }}{% else %}{% translate "Save" %}{% endif %}" />
</div> </div>
</form> </form>
{% if form %} {% if form %}