diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 4098b19..be6c425 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -14,11 +14,10 @@ jobs: matrix: python-version: [ 3.9, "3.10", "3.11", "3.12"] # latest release minus two requirements-file: [ - dj32_cms310.txt, - dj32_cms311.txt, dj42_cms311.txt, dj42_cms41.txt, dj50_cms41.txt, + dj51_cms41.txt, ] os: [ ubuntu-20.04, @@ -26,6 +25,8 @@ jobs: exclude: - python-version: 3.9 requirements-file: dj50_cms41.txt + - python-version: 3.9 + requirements-file: dj51_cms41.txt steps: - uses: actions/checkout@v3 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a5e929f..df4b604 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog ========= +0.3.0 (2025-01-07) +================== + +* feat: Success message and redirect action by @fsbraun +* fix: forms did not redirect to same page if sent from alias by @fsbraun + 0.2.0 (2025-01-06) ================== diff --git a/README.rst b/README.rst index 6de6f43..3c2c5a6 100644 --- a/README.rst +++ b/README.rst @@ -86,7 +86,21 @@ A Form plugin must not be used within another Form plugin. Actions ------- -Upon submission of a valid form actions can be performed. A project can register as many actions as it likes:: +Upon submission of a valid form actions can be performed. + +Four actions come with djangocms-form-builder comes with four actions built-in + +* **Save form submission** - Saves each form submission to the database. See the + results in the admin interface. +* **Send email** - Sends an email to the site admins with the form data. +* **Success message** - Specify a message to be shown to the user upon + successful form submission. +* **Redirect after submission** - Specify a link to a page where the user is + redirected after successful form submission. + +Actions can be configured in the form plugin. + +A project can register as many actions as it likes:: from djangocms_form_builder import actions diff --git a/djangocms_form_builder/__init__.py b/djangocms_form_builder/__init__.py index f892d48..09aa6ee 100644 --- a/djangocms_form_builder/__init__.py +++ b/djangocms_form_builder/__init__.py @@ -3,10 +3,10 @@ try: from django.utils.translation import gettext_lazy as _ except ModuleNotFoundError: - _ = lambda x: x + _ = lambda x: x # noqa: E731 -__version__ = "0.2.0" +__version__ = "0.3.0" _form_registry = {} diff --git a/djangocms_form_builder/actions.py b/djangocms_form_builder/actions.py index 4058a44..861c753 100644 --- a/djangocms_form_builder/actions.py +++ b/djangocms_form_builder/actions.py @@ -1,6 +1,7 @@ import hashlib from django import forms +from django.apps import apps from django.core.exceptions import ImproperlyConfigured from django.core.mail import mail_admins, send_mail from django.core.validators import EmailValidator @@ -8,6 +9,7 @@ from django.template.loader import render_to_string from django.utils.html import strip_tags from django.utils.translation import gettext_lazy as _ +from djangocms_text_ckeditor.fields import HTMLFormField from entangled.forms import EntangledModelFormMixin from . import models @@ -219,3 +221,51 @@ def execute(self, form, request): fail_silently=True, html_message=html_message, ) + + +@register +class SuccessMessageAction(FormAction): + verbose_name = _("Success message") + + class Meta: + entangled_fields = { + "action_parameters": [ + "submitmessage_message", + ] + } + + submitmessage_message = HTMLFormField( + label=_("Message"), + required=True, + initial=_("

Thank you for your submission.

"), + ) + + def execute(self, form, request): + message = self.get_parameter(form, "submitmessage_message") + form.get_success_context = lambda *args, **kwargs: {"message": message} + form.Meta.options["render_success"] = "djangocms_form_builder/actions/submit_message.html" + form.Meta.options["redirect"] = None + + +if apps.is_installed("djangocms_link"): + from djangocms_link.fields import LinkFormField + from djangocms_link.helpers import get_link + + @register + class RedirectAction(FormAction): + verbose_name = _("Redirect after submission") + + class Meta: + entangled_fields = { + "action_parameters": [ + "redirect_link", + ] + } + + redirect_link = LinkFormField( + label=_("Link"), + required=True, + ) + + def execute(self, form, request): + form.Meta.options["redirect"] = get_link(self.get_parameter(form, "redirect_link")) diff --git a/djangocms_form_builder/cms_plugins/ajax_plugins.py b/djangocms_form_builder/cms_plugins/ajax_plugins.py index cf7c382..1935875 100644 --- a/djangocms_form_builder/cms_plugins/ajax_plugins.py +++ b/djangocms_form_builder/cms_plugins/ajax_plugins.py @@ -19,6 +19,8 @@ from ..forms import SimpleFrontendForm from ..helpers import get_option, insert_fields, mark_safe_lazy +SAME_PAGE_REDIRECT = "result" + class CMSAjaxBase(CMSPluginBase): def ajax_post(self, request, instance, parameter): @@ -82,6 +84,7 @@ def form_valid(self, form): if hasattr(form, get_success_context): get_success_context = getattr(form, get_success_context) context.update(get_success_context(self.request, self.instance, form)) + print(context) errors, result, redir, content = ( [], context.get("result", "success"), @@ -351,7 +354,7 @@ def traverse(instance): fields = {} traverse(self.instance) - # Add recaptcha field in necessary + # Add recaptcha field if necessary if recaptcha.installed and self.instance.captcha_widget: fields[recaptcha.field_name] = recaptcha.get_recaptcha_field(self.instance) @@ -364,7 +367,7 @@ def traverse(instance): ] = f'{self.instance.form_spacing}' meta_options[ "redirect" - ] = self.instance.placeholder.page # Default behavior: redirect to same page + ] = SAME_PAGE_REDIRECT # Default behavior: redirect to same page meta_options["login_required"] = self.instance.form_login_required meta_options["unique"] = self.instance.form_unique form_actions = self.instance.form_actions or "[]" diff --git a/djangocms_form_builder/models.py b/djangocms_form_builder/models.py index 76d07b5..72eb693 100644 --- a/djangocms_form_builder/models.py +++ b/djangocms_form_builder/models.py @@ -255,13 +255,13 @@ def format_value(self, value): return "" value = str(value) if "." in value: - l, r = value.rsplit(".", 1) + left, right = value.rsplit(".", 1) else: - l, r = value, "" + left, right = value, "" if self.decimal_places == 0: - return l - r = (r + self.decimal_places * "0")[: self.decimal_places] - return super().format_value(".".join((l, r))) + return left + right = (right + self.decimal_places * "0")[: self.decimal_places] + return super().format_value(".".join((left, right))) class StrDecimalField(forms.DecimalField): def clean(self, value): diff --git a/djangocms_form_builder/static/djangocms_form_builder/css/actions_form.css b/djangocms_form_builder/static/djangocms_form_builder/css/actions_form.css index 2eab46e..4bea84c 100644 --- a/djangocms_form_builder/static/djangocms_form_builder/css/actions_form.css +++ b/djangocms_form_builder/static/djangocms_form_builder/css/actions_form.css @@ -1,3 +1,3 @@ -fieldset.action-hide { +fieldset.action-hide, fieldset.empty { display: none; } diff --git a/djangocms_form_builder/static/djangocms_form_builder/js/actions_form.js b/djangocms_form_builder/static/djangocms_form_builder/js/actions_form.js index 261aa14..283470f 100644 --- a/djangocms_form_builder/static/djangocms_form_builder/js/actions_form.js +++ b/djangocms_form_builder/static/djangocms_form_builder/js/actions_form.js @@ -1,7 +1,12 @@ $(function () { + 'use strict'; $('fieldset.action-auto-hide input[type="checkbox"][name="form_actions"]').each(function (index, element) { + const target = $('.' + $(element).attr("value")); if (element.checked) { - $("."+$(element).attr("value")).removeClass("action-hide"); + target.removeClass("action-hide"); + } + if (!target.find('.form-row:not(.hidden)').length) { + target.addClass("empty"); } $(element).on("change", function (event) { var element = event.target; diff --git a/djangocms_form_builder/templates/djangocms_form_builder/actions/submit_message.html b/djangocms_form_builder/templates/djangocms_form_builder/actions/submit_message.html new file mode 100644 index 0000000..49be4d2 --- /dev/null +++ b/djangocms_form_builder/templates/djangocms_form_builder/actions/submit_message.html @@ -0,0 +1 @@ +{{ message|safe }} diff --git a/djangocms_form_builder/templates/djangocms_form_builder/ajax_form.html b/djangocms_form_builder/templates/djangocms_form_builder/ajax_form.html index a542e43..a8a0541 100644 --- a/djangocms_form_builder/templates/djangocms_form_builder/ajax_form.html +++ b/djangocms_form_builder/templates/djangocms_form_builder/ajax_form.html @@ -98,8 +98,9 @@ if ('redirect' in data) { if (data.redirect !== '' && data.redirect !== 'result') { window.location.href = data.redirect; - } else + } else if (data.redirect !== '') { window.location.reload(); + } } } diff --git a/pyproject.toml b/pyproject.toml index 804703f..e24ff66 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,13 +16,13 @@ classifiers = [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Django", - "Framework :: Django :: 2.2", - "Framework :: Django :: 3.2", + "Framework :: Django :: 4.2", + "Framework :: Django :: 5.0", + "Framework :: Django :: 5.1", "Framework :: Django CMS", + "Framework :: Django CMS :: 3.9", "Framework :: Django CMS :: 3.10", "Framework :: Django CMS :: 3.11", - "Framework :: Django CMS :: 3.8", - "Framework :: Django CMS :: 3.9", "Framework :: Django CMS :: 4.0", "Framework :: Django CMS :: 4.1", "Intended Audience :: Developers", diff --git a/tests/requirements/dj42_cms41.txt b/tests/requirements/dj42_cms41.txt index adcd0a0..ad0a60e 100644 --- a/tests/requirements/dj42_cms41.txt +++ b/tests/requirements/dj42_cms41.txt @@ -2,5 +2,5 @@ Django>=4.2,<4.3 django-cms>=4.1,<4.2 -djangocms-text-ckeditor +djangocms-text djangocms-versioning diff --git a/tests/requirements/dj50_cms41.txt b/tests/requirements/dj50_cms41.txt index 6fb158a..9316b91 100644 --- a/tests/requirements/dj50_cms41.txt +++ b/tests/requirements/dj50_cms41.txt @@ -2,5 +2,5 @@ Django>=5.0,<5.1 django-cms>=4.1,<4.2 -djangocms-text-ckeditor +djangocms-text djangocms-versioning diff --git a/tests/requirements/dj51_cms41.txt b/tests/requirements/dj51_cms41.txt new file mode 100644 index 0000000..116a914 --- /dev/null +++ b/tests/requirements/dj51_cms41.txt @@ -0,0 +1,6 @@ +-r base.txt + +Django>=5.1,<5.2 +django-cms>=4.1,<4.2 +djangocms-text +djangocms-versioning