feat: add contact form
This commit is contained in:
parent
6fd74833a3
commit
b6554fbf83
5 changed files with 129 additions and 4 deletions
52
base/migrations/0003_formpage_formfield.py
Normal file
52
base/migrations/0003_formpage_formfield.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
# Generated by Django 5.0.2 on 2024-03-01 18:28
|
||||
|
||||
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_footertext'),
|
||||
('wagtailcore', '0091_remove_revision_submitted_for_moderation'),
|
||||
]
|
||||
|
||||
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,
|
||||
},
|
||||
),
|
||||
]
|
|
@ -1,9 +1,12 @@
|
|||
from django.db import models
|
||||
from modelcluster.models import ClusterableModel
|
||||
from modelcluster.fields import ParentalKey
|
||||
|
||||
from wagtail.admin.panels import (
|
||||
FieldPanel,
|
||||
MultiFieldPanel,
|
||||
PublishingPanel
|
||||
PublishingPanel,
|
||||
FieldRowPanel,
|
||||
InlinePanel
|
||||
)
|
||||
from wagtail.fields import RichTextField
|
||||
from wagtail.models import (
|
||||
|
@ -12,13 +15,18 @@ from wagtail.models import (
|
|||
RevisionMixin,
|
||||
TranslatableMixin,
|
||||
)
|
||||
|
||||
from wagtail.contrib.forms.models import AbstractEmailForm, AbstractFormField
|
||||
|
||||
from wagtail.snippets.models import register_snippet
|
||||
from wagtail.contrib.forms.panels import FormSubmissionsPanel
|
||||
|
||||
from wagtail.contrib.settings.models import (
|
||||
BaseGenericSetting,
|
||||
register_setting,
|
||||
)
|
||||
|
||||
|
||||
@register_setting
|
||||
class NavigationSettings(BaseGenericSetting):
|
||||
linkedin_url = models.URLField(verbose_name="LinkedIn URL", blank=True)
|
||||
|
@ -36,6 +44,7 @@ class NavigationSettings(BaseGenericSetting):
|
|||
)
|
||||
]
|
||||
|
||||
|
||||
@register_snippet
|
||||
class FooterText(
|
||||
DraftStateMixin,
|
||||
|
@ -44,7 +53,6 @@ class FooterText(
|
|||
TranslatableMixin,
|
||||
models.Model,
|
||||
):
|
||||
|
||||
body = RichTextField()
|
||||
|
||||
panels = [
|
||||
|
@ -62,4 +70,27 @@ class FooterText(
|
|||
return {"footer_text": self.body}
|
||||
|
||||
class Meta(TranslatableMixin.Meta):
|
||||
verbose_name_plural = "Footer Text"
|
||||
verbose_name_plural = "Footer Text"
|
||||
|
||||
|
||||
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="Form fields"),
|
||||
FieldPanel('thank_you_text'),
|
||||
MultiFieldPanel([
|
||||
FieldRowPanel([
|
||||
FieldPanel('from_address'),
|
||||
FieldPanel('to_address'),
|
||||
]),
|
||||
FieldPanel('subject'),
|
||||
], "Email"),
|
||||
]
|
||||
|
|
15
base/templates/base/form_page.html
Normal file
15
base/templates/base/form_page.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
{% extends "base.html" %}
|
||||
{% load wagtailcore_tags %}
|
||||
|
||||
{% block body_class %}template-formpage{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ page.title }}</h1>
|
||||
<div>{{ page.intro|richtext }}</div>
|
||||
|
||||
<form class="page-form" action="{% pageurl page %}" method="POST">
|
||||
{% csrf_token %}
|
||||
{{ form.as_div }}
|
||||
<button type="Submit">Submit</button>
|
||||
</form>
|
||||
{% endblock content %}
|
9
base/templates/base/form_page_landing.html
Normal file
9
base/templates/base/form_page_landing.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
{% extends "base.html" %}
|
||||
{% load wagtailcore_tags %}
|
||||
|
||||
{% block body_class %}template-formpage{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ page.title }}</h1>
|
||||
<div>{{ page.thank_you_text|richtext }}</div>
|
||||
{% endblock content %}
|
|
@ -42,4 +42,22 @@ header {
|
|||
|
||||
.skip-link:focus-visible {
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
.page-form label {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.page-form :is(textarea, input, select) {
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
min-height: 40px;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.page-form .helptext {
|
||||
font-style: italic;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue