Porównaj commity

...

11 Commity
0.4.0 ... main

Autor SHA1 Wiadomość Data
mtyton f8f3d35935 Merge pull request 'Renamed project to wagtail_store' (#23) from feature/project_rename into main
Reviewed-on: #23
2023-11-27 21:45:19 +00:00
mtyton 6bc385e47d Renamed project to wagtail_store 2023-11-27 22:34:44 +01:00
mtyton 345dbe3f46 Merge pull request 'Fixed tests' (#22) from feature/form_improvements into main
ci/woodpecker/push/build Pipeline was successful Szczegóły
ci/woodpecker/tag/build Pipeline was successful Szczegóły
Reviewed-on: #22
2023-11-12 09:30:30 +00:00
mtyton a5e243c55c Fixed tests
ci/woodpecker/push/build Pipeline was successful Szczegóły
ci/woodpecker/pr/build Pipeline was successful Szczegóły
2023-11-12 10:29:59 +01:00
mtyton 1ab8537c64 Merge pull request 'form anty-spam, hiden field rendering, added help_text showing' (#21) from feature/form_improvements into main
ci/woodpecker/push/build Pipeline was successful Szczegóły
Reviewed-on: #21
2023-11-12 09:08:56 +00:00
mtyton d365a1ee98 form anty-spam, hiden field rendering, added help_text showing
ci/woodpecker/push/build Pipeline was successful Szczegóły
ci/woodpecker/pr/build Pipeline failed Szczegóły
2023-11-12 09:51:09 +01:00
mtyton 19078bd03f Added submission_id to email context
ci/woodpecker/push/build Pipeline was successful Szczegóły
ci/woodpecker/tag/build Pipeline was successful Szczegóły
2023-11-05 20:03:03 +01:00
mtyton dd0998b96b Merge pull request 'Fixed menu translation' (#20) from fix/menu_translation into main
ci/woodpecker/push/build Pipeline was successful Szczegóły
ci/woodpecker/tag/build Pipeline was successful Szczegóły
Reviewed-on: #20
2023-11-03 22:05:42 +01:00
mtyton b07561d34c Fixed form styling
ci/woodpecker/push/build Pipeline was successful Szczegóły
ci/woodpecker/pr/build Pipeline was successful Szczegóły
2023-11-01 21:50:51 +01:00
mtyton 80ddd65ea6 Fixed menu translation
ci/woodpecker/push/build Pipeline was successful Szczegóły
ci/woodpecker/pr/build Pipeline was successful Szczegóły
2023-10-31 23:37:23 +01:00
mtyton c762438439 Added database depndency for beat
ci/woodpecker/push/build Pipeline was successful Szczegóły
2023-10-22 21:14:41 +02:00
207 zmienionych plików z 266 dodań i 99 usunięć

6
.gitignore vendored
Wyświetl plik

@ -139,8 +139,8 @@ GitHub.sublime-settings
#postgres pass files
*.my_pgpass
*.sql
artel/static/
wagtail_store/static/
# media
artel/media/*
artel/store/data/*
wagtail_store/media/*
wagtail_store/store/data/*

Wyświetl plik

@ -1,31 +0,0 @@
{% load static %}
{% load menu_tags %}
{% load wagtailcore_tags %}
{% load i18n %}
<div class="d-flex flex-column flex-shrink-0 p-3 mr-5">
<img src="{{logo}}" class="img-fluid rounded mx-auto d-block mt-3" style="width: 10rem; height: 10 rem;" alt="Portal Logo"/>
<hr>
<ul class="nav navbar-nav">
{% for item in menu_items %}
<li class="{{ item.active_class }}">
<a href="{{ item.href }}">{{ item.text }}</a>
{% if item.has_children_in_menu %}
<button class="btn btn-toggle" data-bs-target="#ddtoggle_{{ item.link_page.pk }}" data-bs-toggle="collapse"
aria-expanded={% if item.active_class %}"true" {% else %} "false" {% endif %}
aria-controls="#ddtoggle_{{ item.link_page.pk }}">
<img src = "{% static 'images/icons/caret-down.svg' %}" alt="&or;"/> </button>
{% sub_menu item template="menu/custom_submenu.html" %}
{% endif %}
</li>
{% endfor %}
</ul>
</div>
<div class="d-flex flex-column flex-shrink-0 p-3 mr-5">
<hr>
{% if shop_enabled %}
<a href={% url 'cart' %} alt="Koszyk" >{% trans "Cart" %}</a>
{% endif %}
</div>

Wyświetl plik

@ -1,7 +0,0 @@
{% load menu_tags %}
<ul class={% if item.active_class %} "sub-menu collapse show fw-normal pb-1 small" {% else %} "sub-menu collapse fw-normal pb-1 small" {% endif %}
id="ddtoggle_{{ item.link_page.pk }}">
{% for sub_item in menu_items %}
<li><a href="{{ sub_item.href }}" class="{{ sub_item.active_class }}">{{ sub_item.text }}</a></li>
{% endfor %}
</ul>

Wyświetl plik

@ -1,32 +0,0 @@
{% extends "base.html" %}
{% load wagtailcore_tags wagtailimages_tags %}
{% load i18n %}
{% block content %}
<h1>{{ page.title }}</h1>
<p class="meta">{{ page.date }}</p>
{% if form %}
<div>{{ page.intro|richtext }}</div>
<form enctype="multipart/form-data" action="{% pageurl page %}" method="POST">
{% csrf_token %}
{% for field in form %}
<div class="form-group mt-3">
<label for="{{field.id}}" class="form-label">
{% trans field.label %}
</label>
{{field}}
<small id="emailHelp" class="form-text text-muted">
{% trans field.help_text %}
</small>
</div>
{% endfor %}
<div class="text-end mt-3">
<input class="btn btn-lg btn-success" type="submit" value='{% trans "Submit" %}'>
</div>
</form>
{% else %}
<div>You can fill in the from only one time.</div>
{% endif %}
{% endblock %}

Wyświetl plik

@ -25,6 +25,9 @@ services:
ports:
- "5672:5672" # We forward this port because it's useful for debugging
- "15672:15672" # Here, we can access RabbitMQ management plugin
networks:
- nginx_network
comfy:
build:
@ -77,6 +80,9 @@ services:
depends_on:
- comfy
- rabbit
- db
networks:
- nginx_network
worker:
build:
@ -94,7 +100,10 @@ services:
depends_on:
- comfy
- rabbit
- db
- beat
networks:
- nginx_network
networks:
nginx_network:

Wyświetl plik

@ -20,9 +20,9 @@ services:
environment:
- RABBITMQ_DEFAULT_USER
- RABBITMQ_DEFAULT_PASS
ports:
- "5672:5672" # We forward this port because it's useful for debugging
- "15672:15672" # Here, we can access RabbitMQ management plugin
# ports:
# - "5672:5672" # We forward this port because it's useful for debugging
# - "15672:15672" # Here, we can access RabbitMQ management plugin
smtp-server:
image: mailhog/mailhog

Wyświetl plik

@ -1,4 +1,9 @@
from django import forms
from dynamic_forms.widgets import (
CheckboxSelectMultiple,
CheckboxInput,
RadioSelect
)
class MultipleFileInput(forms.ClearableFileInput):
@ -19,6 +24,23 @@ class MultipleFileField(forms.FileField):
return result
class HoneypotField(forms.BooleanField):
default_widget = forms.HiddenInput(
{'style': 'display:none !important;', 'tabindex': '-1', 'autocomplete': 'off'}
)
def __init__(self, *args, **kwargs):
kwargs.setdefault('widget', HoneypotField.default_widget)
kwargs['required'] = False
super().__init__(*args, **kwargs)
def clean(self, value):
if cleaned_value := super().clean(value):
raise forms.ValidationError('')
else:
return cleaned_value
class DynamicForm(forms.Form):
FIELD_TYPE_MAPPING = {
@ -27,11 +49,11 @@ class DynamicForm(forms.Form):
"email": forms.EmailField(max_length=255, widget=forms.EmailInput(attrs={"class": "form-control"})),
"number": forms.IntegerField(widget=forms.NumberInput(attrs={"class": "form-control"})),
"url": forms.URLField(max_length=255, widget=forms.URLInput(attrs={"class": "form-control"})),
"checkbox": forms.BooleanField(required=False, widget=forms.CheckboxInput(attrs={"class": "form-control"})),
"checkboxes": forms.MultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple(attrs={"class": "form-control"})),
"checkbox": forms.BooleanField(required=False, widget=CheckboxInput(attrs={"class": "form-check"})),
"checkboxes": forms.MultipleChoiceField(required=False, widget=CheckboxSelectMultiple(attrs={"class": "form-check"})),
"dropdown": forms.ChoiceField(widget=forms.Select(attrs={"class": "form-control"})),
"multiselect": forms.MultipleChoiceField(widget=forms.SelectMultiple(attrs={"class": "form-control"})),
"radio": forms.ChoiceField(widget=forms.RadioSelect(attrs={"class": "form-control"})),
"radio": forms.ChoiceField(widget=RadioSelect(attrs={"class": "form-control"})),
"date": forms.DateField(widget=forms.DateInput(attrs={"class": "form-control"})),
"datetime": forms.DateTimeField(widget=forms.DateTimeInput(attrs={"class": "form-control"})),
"hidden": forms.CharField(widget=forms.HiddenInput()),
@ -49,6 +71,7 @@ class DynamicForm(forms.Form):
if hasattr(f, "choices"):
f.choices = [(v, v) for v in field.choices.split(",")]
f.required = field.required
f.help_text = field.help_text or ""
self.fields[field.clean_name] = f
if file_uploads:
self.fields["attachments"] = MultipleFileField(
@ -56,3 +79,21 @@ class DynamicForm(forms.Form):
attrs={"class": "form-control"}
)
)
# add honeypot field
self.fields["secret_honey"] = HoneypotField()
def clean(self):
cleaned_data = super().clean()
new_cleaned_data = {}
for key, value in cleaned_data.items():
if isinstance(value, list):
if isinstance(self.fields[key], MultipleFileField):
continue
cleaned_data[key] = ",".join(value)
if key=="secret_honey":
continue
new_cleaned_data[key] = value
return new_cleaned_data

Wyświetl plik

@ -59,7 +59,12 @@ class Form(FormMixin, Page):
class EmailFormSubmission(AbstractFormSubmission):
# TODO - make this optional, allow to set pattern in admin
def get_submission_id(self, form_slug):
case_number_daily = EmailFormSubmission.objects.filter(submit_time__date=datetime.date.today()).count()
return f"{form_slug}-{datetime.date.today()}-{case_number_daily}"
def send_mail(self, data):
# modify this, get proper template
to_addresses = data.pop("to_address").split(",")
@ -69,7 +74,8 @@ class EmailFormSubmission(AbstractFormSubmission):
)
for file in data.pop("attachments", [])
]
subject = data.get("subject")
subject = data.pop("subject")
form_slug = data.pop("form_slug")
from_address = data.pop("from_address", settings.DEFAULT_FROM_EMAIL)
for address in to_addresses:
OutgoingEmail.objects.send(
@ -77,7 +83,7 @@ class EmailFormSubmission(AbstractFormSubmission):
template_name="form_mail",
recipient=address,
sender=from_address,
context=data,
context={"form_data": data, "submission_id": self.get_submission_id(form_slug)},
attachments=attachments
)
@ -112,7 +118,8 @@ class CustomEmailForm(Form):
"from_address": self.from_address,
"to_address": self.to_address,
"subject": self.subject,
"attachments": attachments
"attachments": attachments,
"form_slug": self.slug
})
submission.send_mail(data=mail_data)
return submission

Wyświetl plik

@ -0,0 +1,40 @@
{% extends "base.html" %}
{% load wagtailcore_tags wagtailimages_tags %}
{% load i18n %}
{% block content %}
<h1>{{ page.title }}</h1>
<p class="meta">{{ page.date }}</p>
{% if form %}
{{form.errors}}
<div>{{ page.intro|richtext }}</div>
<form enctype="multipart/form-data" action="{% pageurl page %}" method="POST">
{% csrf_token %}
{% for field in form %}
{% if field.is_hidden %}
<!--Empty space for reason, we don't want to show anything on empty fields-->
{{field}}
{% else %}
<div class="form-group mt-3">
<label for="{{field.id}}" class="form-label">
{% trans field.label %}
</label>
{{field}}
<small id="emailHelp" class="form-text text-muted">
{% trans field.help_text %}
</small>
{% if field.error %}
{{error}}
{% endif %}
</div>
{% endif %}
{% endfor %}
<div class="text-end mt-3">
<input class="btn btn-lg btn-success" type="submit" value='{% trans "Submit" %}'>
</div>
</form>
{% else %}
<div>You can fill in the from only one time.</div>
{% endif %}
{% endblock %}

Wyświetl plik

@ -0,0 +1,7 @@
<div class="form-check">
<input class="form-check-input" type="checkbox" id="{{ widget.attrs.id }}"
name="{{ widget.name }}">
<label class="form-check-label" for="{{ widget.attrs.id }}">
{{ widget.name }}
</label>
</div>

Wyświetl plik

@ -0,0 +1,14 @@
{% for group, options, index in widget.optgroups %}
{% if group %}
<label>{{ group }}</label>
{% endif %}
{% for option in options %}
<div class="form-check">
<input class="form-check-input" type="checkbox" value="{{ option.value }}" id="{{ option.attrs.id }}"
name="{{ option.name }}">
<label class="form-check-label" for="{{ option.attrs.id }}">
{{ option.value }}
</label>
</div>
{% endfor %}
{% endfor %}

Wyświetl plik

@ -0,0 +1,15 @@
{% for group, options, index in widget.optgroups %}
{% if group %}
<label>{{ group }}</label>
{% endif %}
{% for option in options %}
<div class="form-check">
<input class="form-check-input" type="radio"
value="{{ option.value }}" id="{{ option.attrs.id }}"
name="{{ option.name }}">
<label class="form-check-label" for="{{ option.attrs.id }}">
{{ option.value }}
</label>
</div>
{% endfor %}
{% endfor %}

Wyświetl plik

@ -104,7 +104,7 @@ class CustomEmailFormTestCase(WagtailPageTests):
def test_generate_html_form_from_model(self):
html_form = self.form.get_form()
self.assertIsInstance(html_form, DynamicForm)
self.assertEqual(len(html_form.fields), 13)
self.assertEqual(len(html_form.fields), 14)
self.assertEqual(html_form.fields["name"].label, "Name")
self.assertEqual(html_form.fields["name"].required, True)
self.assertEqual(html_form.fields["name"].widget.attrs["class"], "form-control")
@ -275,3 +275,30 @@ class CustomEmailFormTestCase(WagtailPageTests):
self.assertEqual(form.errors["name"], ['This field is required.'])
self.assertEqual(form.errors["url"], ['This field is required.'])
self.assertEqual(form.errors["attachments"], ['This field is required.'])
def test_no_hidden_field_in_clean_data_success(self):
form_data = {
# generate data for this class self.form.get_form()
"name": "Test",
"message": "Test message",
"email": "test@test.com",
"number": 1,
"url": "http://example.com",
"checkbox": True,
"checkboxes": ["a", "b"],
"dropdown": "a",
"multiselect": ["a", "b"],
"radio": "a",
"date": "2020-01-01",
"datetime": "2020-01-01 00:00:00",
"hidden": "hidden",
}
form = self.form.get_form(form_data)
self.assertTrue(form.is_valid())
cleaned_data = form.cleaned_data
self.assertIn("hidden", cleaned_data)
self.assertNotIn("secret_honey", cleaned_data)
self.assertIn("hidden", form.fields)
self.assertIn("secret_honey", form.fields)

Wyświetl plik

@ -0,0 +1,13 @@
from django import forms
class CheckboxInput(forms.CheckboxInput):
template_name = "widgets/checkbox.html"
class CheckboxSelectMultiple(forms.CheckboxSelectMultiple):
template_name = "widgets/checkbox_multiple.html"
class RadioSelect(forms.RadioSelect):
template_name = "widgets/radio_multiple.html"

Wyświetl plik

@ -3,7 +3,7 @@ import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "artel.settings.dev")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wagtail_store.settings.dev")
from django.core.management import execute_from_command_line

Some files were not shown because too many files have changed in this diff Show More