-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
365 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
from django import forms | ||
from django.http import QueryDict | ||
from django.urls import reverse_lazy | ||
|
||
from apps.patterns.forms import PlatformFormMixin | ||
from apps.patterns.widgets import Select | ||
|
||
from .etl.odk.client import ODKPublishClient | ||
from .http import HttpRequest | ||
|
||
|
||
class ProjectSyncForm(PlatformFormMixin, forms.Form): | ||
"""Form for syncing projects from an ODK Central server. | ||
In addition to processing the form normally, this form also handles | ||
render logic for the project field during an HTMX request. | ||
""" | ||
|
||
server = forms.ChoiceField( | ||
# The server field is populated with the available ODK Central servers | ||
# (from an environment variable) when the form is rendered. | ||
choices=[("", "Select an ODK Central server...")] | ||
+ [ | ||
(config.base_url, config.base_url) for config in ODKPublishClient.get_configs().values() | ||
], | ||
# When a server is selected, the project field below is populated with | ||
# the available projects for that server using HMTX. | ||
widget=Select( | ||
attrs={ | ||
"hx-trigger": "change", | ||
"hx-get": reverse_lazy("odk_publish:server-sync-projects"), | ||
"hx-target": "#id_project_container", | ||
"hx-swap": "innerHTML", | ||
"hx-indicator": ".loading", | ||
} | ||
), | ||
) | ||
project = forms.ChoiceField(widget=Select(attrs={"disabled": "disabled"})) | ||
|
||
def __init__(self, request: HttpRequest, data: QueryDict, *args, **kwargs): | ||
htmx_data = data.copy() if request.htmx else {} | ||
# Don't bind the form on an htmx request, otherwise we'll see "This | ||
# field is required" errors | ||
data = data if not request.htmx else None | ||
super().__init__(data, *args, **kwargs) | ||
# Set `project` field choices when a server is provided either via a | ||
# POST or HTMX request | ||
if server := htmx_data.get("server") or self.data.get("server"): | ||
self.set_project_choices(base_url=server) | ||
self.fields["project"].widget.attrs.pop("disabled", None) | ||
|
||
def set_project_choices(self, base_url: str): | ||
with ODKPublishClient(base_url=base_url) as client: | ||
self.fields["project"].choices = [ | ||
(project.id, project.name) for project in client.projects.list() | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from django.db.models import QuerySet | ||
from django.http import HttpRequest as HttpRequestBase | ||
from django_htmx.middleware import HtmxDetails | ||
|
||
from .models import Project | ||
from .nav import Breadcrumbs | ||
|
||
|
||
class HttpRequest(HttpRequestBase): | ||
"""Custom HttpRequest class for type-checking purposes.""" | ||
|
||
htmx: HtmxDetails | ||
odk_project = Project | None | ||
odk_project_tabs = Breadcrumbs | None | ||
odk_projects = QuerySet[Project] | None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{% for error in errors %} | ||
<div class="p-4 mb-4 text-sm text-brand-danger-medium rounded-lg bg-red-50 dark:bg-gray-800 dark:text-brand-danger-light" | ||
role="alert">{{ error }}</div> | ||
{% endfor %} | ||
asdfasdf | ||
{% if errors and not fields %} | ||
<div> | ||
{% for field in hidden_fields %}{{ field }}{% endfor %} | ||
</div> | ||
{% endif %} | ||
{% for field, errors in fields %} | ||
<div {% with classes=field.css_classes %} | ||
{% if classes %}classfixme="{{ classes }}"{% endif %} | ||
{% endwith %} | ||
class="mb-6" | ||
id="id_{{ field.name }}_container"> | ||
{% if field.use_fieldset %} | ||
<fieldset> | ||
{% if field.label %}{{ field.legend_tag }}{% endif %} | ||
{% else %} | ||
{% if field.label %}{{ field.label_tag }}{% endif %} | ||
{% endif %} | ||
{% if field.help_text %}<div class="helptext">{{ field.help_text|safe }}</div>{% endif %} | ||
{{ field }} | ||
{% for error in erors %} | ||
<p class="mt-2 text-sm text-brand-danger-medium dark:text-brand-danger-light">{{ error }}</p> | ||
{% endfor %} | ||
{% if field.use_fieldset %}</fieldset>{% endif %} | ||
{% if forloop.last %} | ||
{% for field in hidden_fields %}{{ field }}{% endfor %} | ||
{% endif %} | ||
</div> | ||
{% endfor %} | ||
{% if not fields and not errors %} | ||
{% for field in hidden_fields %}{{ field }}{% endfor %} | ||
{% endif %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
apps/patterns/templates/patterns/forms/widgets/select.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<select name="{{ widget.name }}" | ||
{% include "django/forms/widgets/attrs.html" %} | ||
class="{% if 'disabled' in widget.attrs %}cursor-not-allowed {% endif %}border rounded-md block w-full p-2.5 {% if not field.errors %}bg-gray-50 border border-gray-300 text-gray-900 focus:ring-2 focus:ring-primary-200 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500{% else %} bg-red-50 border-brand-danger-medium text-brand-danger-medium focus:ring-red-500 focus:border-brand-danger-medium dark:bg-brand-danger-light dark:border-brand-danger-light {% endif %} "> | ||
{% for group_name, group_choices, group_index in widget.optgroups %} | ||
{% if group_name %}<optgroup label="{{ group_name }}">{% endif %} | ||
{% for option in group_choices %} | ||
{% include option.template_name with widget=option %} | ||
{% endfor %} | ||
{% if group_name %}</optgroup>{% endif %} | ||
{% endfor %} | ||
</select> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.