From b57a26953f5278a1a650d35333dd173f58ccf645 Mon Sep 17 00:00:00 2001
From: "Edgar P. Burkhart" <git@edgarpierre.fr>
Date: Wed, 12 Jun 2024 17:54:11 +0200
Subject: [PATCH] Add form page

---
 .../migrations/0003_formpage_formfield.py     | 162 ++++++++++++++++++
 lps/base/models.py                            |  55 ++++++
 lps/base/templates/base/form_page.html        |  13 ++
 .../templates/base/form_page_landing.html     |  11 ++
 lps/lps/templates/base.html                   |   2 +-
 5 files changed, 242 insertions(+), 1 deletion(-)
 create mode 100644 lps/base/migrations/0003_formpage_formfield.py
 create mode 100644 lps/base/models.py
 create mode 100644 lps/base/templates/base/form_page.html
 create mode 100644 lps/base/templates/base/form_page_landing.html

diff --git a/lps/base/migrations/0003_formpage_formfield.py b/lps/base/migrations/0003_formpage_formfield.py
new file mode 100644
index 0000000..895bec3
--- /dev/null
+++ b/lps/base/migrations/0003_formpage_formfield.py
@@ -0,0 +1,162 @@
+# Generated by Django 5.0.6 on 2024-06-12 15:10
+
+import django.db.models.deletion
+import modelcluster.fields
+import wagtail.contrib.forms.models
+import wagtail.fields
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("base", "0002_alter_navigationsettings_phone"),
+        ("wagtailcore", "0093_uploadedfile"),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name="FormPage",
+            fields=[
+                (
+                    "page_ptr",
+                    models.OneToOneField(
+                        auto_created=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        parent_link=True,
+                        primary_key=True,
+                        serialize=False,
+                        to="wagtailcore.page",
+                    ),
+                ),
+                (
+                    "to_address",
+                    models.CharField(
+                        blank=True,
+                        help_text="Optional - form submissions will be emailed to these addresses. Separate multiple addresses by comma.",
+                        max_length=255,
+                        validators=[wagtail.contrib.forms.models.validate_to_address],
+                        verbose_name="to address",
+                    ),
+                ),
+                (
+                    "from_address",
+                    models.EmailField(
+                        blank=True, max_length=255, verbose_name="from address"
+                    ),
+                ),
+                (
+                    "subject",
+                    models.CharField(
+                        blank=True, max_length=255, verbose_name="subject"
+                    ),
+                ),
+                ("intro", wagtail.fields.RichTextField(blank=True)),
+                ("thank_you_text", wagtail.fields.RichTextField(blank=True)),
+            ],
+            options={
+                "abstract": False,
+            },
+            bases=(
+                wagtail.contrib.forms.models.FormMixin,
+                "wagtailcore.page",
+                models.Model,
+            ),
+        ),
+        migrations.CreateModel(
+            name="FormField",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "sort_order",
+                    models.IntegerField(blank=True, editable=False, null=True),
+                ),
+                (
+                    "clean_name",
+                    models.CharField(
+                        blank=True,
+                        default="",
+                        help_text="Safe name of the form field, the label converted to ascii_snake_case",
+                        max_length=255,
+                        verbose_name="name",
+                    ),
+                ),
+                (
+                    "label",
+                    models.CharField(
+                        help_text="The label of the form field",
+                        max_length=255,
+                        verbose_name="label",
+                    ),
+                ),
+                (
+                    "field_type",
+                    models.CharField(
+                        choices=[
+                            ("singleline", "Single line text"),
+                            ("multiline", "Multi-line text"),
+                            ("email", "Email"),
+                            ("number", "Number"),
+                            ("url", "URL"),
+                            ("checkbox", "Checkbox"),
+                            ("checkboxes", "Checkboxes"),
+                            ("dropdown", "Drop down"),
+                            ("multiselect", "Multiple select"),
+                            ("radio", "Radio buttons"),
+                            ("date", "Date"),
+                            ("datetime", "Date/time"),
+                            ("hidden", "Hidden field"),
+                        ],
+                        max_length=16,
+                        verbose_name="field type",
+                    ),
+                ),
+                (
+                    "required",
+                    models.BooleanField(default=True, verbose_name="required"),
+                ),
+                (
+                    "choices",
+                    models.TextField(
+                        blank=True,
+                        help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
+                        verbose_name="choices",
+                    ),
+                ),
+                (
+                    "default_value",
+                    models.TextField(
+                        blank=True,
+                        help_text="Default value. Comma or new line separated values supported for checkboxes.",
+                        verbose_name="default value",
+                    ),
+                ),
+                (
+                    "help_text",
+                    models.CharField(
+                        blank=True, max_length=255, verbose_name="help text"
+                    ),
+                ),
+                (
+                    "page",
+                    modelcluster.fields.ParentalKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="form_fields",
+                        to="base.formpage",
+                    ),
+                ),
+            ],
+            options={
+                "ordering": ["sort_order"],
+                "abstract": False,
+            },
+        ),
+    ]
diff --git a/lps/base/models.py b/lps/base/models.py
new file mode 100644
index 0000000..f373a41
--- /dev/null
+++ b/lps/base/models.py
@@ -0,0 +1,55 @@
+from django.db import models
+from modelcluster.fields import ParentalKey
+from wagtail.admin.panels import FieldPanel, FieldRowPanel, InlinePanel, MultiFieldPanel
+from wagtail.contrib.forms.models import AbstractEmailForm, AbstractFormField
+from wagtail.contrib.forms.panels import FormSubmissionsPanel
+from wagtail.contrib.settings.models import BaseGenericSetting, register_setting
+from wagtail.fields import RichTextField
+
+
+@register_setting
+class NavigationSettings(BaseGenericSetting):
+    address = models.CharField(max_length=256, verbose_name="Adresse", blank=True)
+    phone = models.CharField(
+        max_length=32, verbose_name="Numéro de téléphone", blank=True
+    )
+    email = models.EmailField(verbose_name="Adresse de courriel", blank=True)
+
+    panels = [
+        MultiFieldPanel(
+            [
+                FieldPanel("address"),
+                FieldPanel("phone"),
+                FieldPanel("email"),
+            ],
+            "Informations de contact",
+        )
+    ]
+
+
+class FormField(AbstractFormField):
+    page = ParentalKey("FormPage", on_delete=models.CASCADE, related_name="form_fields")
+
+
+class FormPage(AbstractEmailForm):
+    intro = RichTextField(blank=True)
+    thank_you_text = RichTextField(blank=True)
+
+    content_panels = AbstractEmailForm.content_panels + [
+        FormSubmissionsPanel(),
+        FieldPanel("intro"),
+        InlinePanel("form_fields", label="Champs de formulaire"),
+        FieldPanel("thank_you_text"),
+        MultiFieldPanel(
+            [
+                FieldRowPanel(
+                    [
+                        FieldPanel("from_address"),
+                        FieldPanel("to_address"),
+                    ]
+                ),
+                FieldPanel("subject"),
+            ],
+            "Email",
+        ),
+    ]
diff --git a/lps/base/templates/base/form_page.html b/lps/base/templates/base/form_page.html
new file mode 100644
index 0000000..8526083
--- /dev/null
+++ b/lps/base/templates/base/form_page.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+{% load wagtailcore_tags %}
+{% block content %}
+    <h1>{{ page.title }}</h1>
+    <section>
+        {{ page.intro|richtext }}
+    </section>
+    <form action="{% pageurl page %}" method="POST">
+        {% csrf_token %}
+        {{ form.as_p }}
+        <input type="submit" />
+    </form>
+{% endblock content %}
diff --git a/lps/base/templates/base/form_page_landing.html b/lps/base/templates/base/form_page_landing.html
new file mode 100644
index 0000000..6ad130f
--- /dev/null
+++ b/lps/base/templates/base/form_page_landing.html
@@ -0,0 +1,11 @@
+{% extends "base.html" %}
+{% load wagtailcore_tags %}
+{% block content %}
+    <h1>{{ page.title }}</h1>
+    <section>
+        {{ page.thank_you_text|richtext }}
+    </section>
+		<section>
+			<a href="">Retour</a>
+		</section>
+{% endblock content %}
diff --git a/lps/lps/templates/base.html b/lps/lps/templates/base.html
index dd3a8aa..26865ad 100644
--- a/lps/lps/templates/base.html
+++ b/lps/lps/templates/base.html
@@ -29,7 +29,7 @@
         <link rel="stylesheet" type="text/css" href="{% static 'css/lps.css' %}">
         {% block extra_css %}{# Override this in templates to add extra stylesheets #}{% endblock %}
     </head>
-    <body class="{% block body_class %}{% endblock %}">
+    <body>
         {% wagtailuserbar %}
         <header>
             {% include "nav.html" %}
