diff --git a/.gitignore b/.gitignore index 12dadd7c..037bf0da 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,6 @@ README_PARTS.rst /src/django_fobi.egg-info /src/fobi/contrib/plugins/form_elements/fields/hidden_model_object/ /src/fobi/contrib/plugins/form_importers/mailchimp_importer/bucket.py -/src/fobi/contrib/apps/wagtail_integration/ /scripts/install_django_1_7_wagtail.sh /scripts/reinstall_django_1_7_wagtail.sh diff --git a/src/fobi/contrib/apps/wagtail_integration/__init__.py b/src/fobi/contrib/apps/wagtail_integration/__init__.py new file mode 100644 index 00000000..bf3c7d39 --- /dev/null +++ b/src/fobi/contrib/apps/wagtail_integration/__init__.py @@ -0,0 +1,7 @@ +__title__ = 'fobi.contrib.apps.wagtail_integration' +__author__ = 'Andy Babic ' +__copyright__ = '2014-2016 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ('default_app_config',) + +default_app_config = 'fobi.contrib.apps.wagtail_integration.apps.Config' diff --git a/src/fobi/contrib/apps/wagtail_integration/apps.py b/src/fobi/contrib/apps/wagtail_integration/apps.py new file mode 100644 index 00000000..3f211105 --- /dev/null +++ b/src/fobi/contrib/apps/wagtail_integration/apps.py @@ -0,0 +1,17 @@ +__title__ = 'fobi.contrib.apps.wagtail_integration.apps' +__author__ = 'Andy Babic ' +__copyright__ = '2014-2016 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ('Config',) + +try: + from django.apps import AppConfig + + class Config(AppConfig): + """Config.""" + + name = 'fobi.contrib.apps.wagtail_integration' + label = 'fobi_contrib_apps_wagtail_integration' + +except ImportError: + pass diff --git a/src/fobi/contrib/apps/wagtail_integration/conf.py b/src/fobi/contrib/apps/wagtail_integration/conf.py new file mode 100644 index 00000000..22045d8b --- /dev/null +++ b/src/fobi/contrib/apps/wagtail_integration/conf.py @@ -0,0 +1,33 @@ +from django.conf import settings + +from . import defaults + +__title__ = 'fobi.contrib.apps.wagtail_integration.conf' +__author__ = 'Andy Babic ' +__copyright__ = '2014-2016 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ('get_setting',) + + +def get_setting(setting, override=None): + """Get setting. + + Get a setting from ``fobi.contrib.apps.wagtail_integration`` conf module, + falling back to the default. + + If override is not None, it will be used instead of the setting. + + :param setting: String with setting name + :param override: Value to use when no setting is available. Defaults + to None. + :return: Setting value. + """ + if override is not None: + return override + if hasattr(settings, 'FOBI_WAGTAIL_INTEGRATION_{0}'.format(setting)): + return getattr( + settings, + 'FOBI_WAGTAIL_INTEGRATION_{0}'.format(setting) + ) + else: + return getattr(defaults, setting) diff --git a/src/fobi/contrib/apps/wagtail_integration/defaults.py b/src/fobi/contrib/apps/wagtail_integration/defaults.py new file mode 100644 index 00000000..fc278a2f --- /dev/null +++ b/src/fobi/contrib/apps/wagtail_integration/defaults.py @@ -0,0 +1,15 @@ +__title__ = 'fobi.contrib.apps.wagtail_integration.defaults' +__author__ = 'Andy Babic ' +__copyright__ = '2014-2016 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ( + 'WIDGET_FORM_SENT_GET_PARAM', + 'FORM_TEMPLATE_CHOICES', + 'SUCCESS_PAGE_TEMPLATE_CHOICES', +) + +WIDGET_FORM_SENT_GET_PARAM = 'sent' + +FORM_TEMPLATE_CHOICES = () + +SUCCESS_PAGE_TEMPLATE_CHOICES = () diff --git a/src/fobi/contrib/apps/wagtail_integration/helpers.py b/src/fobi/contrib/apps/wagtail_integration/helpers.py new file mode 100644 index 00000000..c5509df8 --- /dev/null +++ b/src/fobi/contrib/apps/wagtail_integration/helpers.py @@ -0,0 +1,38 @@ +from fobi.integration.helpers import get_template_choices + +from .settings import FORM_TEMPLATE_CHOICES, SUCCESS_PAGE_TEMPLATE_CHOICES + +__title__ = 'fobi.contrib.apps.wagtail_integration.helpers' +__author__ = 'Andy Babic ' +__copyright__ = '2014-2016 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ( + 'get_form_template_choices', + 'get_success_page_template_choices', +) + + +def get_form_template_choices(): + """Gets the form template choices. + + It's possible to provide theme templates per theme or just per project. + + :return list: + """ + return get_template_choices( + 'wagtail_integration', + FORM_TEMPLATE_CHOICES, + 'form_template_choices' + ) + + +def get_success_page_template_choices(): + """Get success page template choices. + + :return list: + """ + return get_template_choices( + 'wagtail_integration', + SUCCESS_PAGE_TEMPLATE_CHOICES, + 'success_page_template_choices' + ) diff --git a/src/fobi/contrib/apps/wagtail_integration/models.py b/src/fobi/contrib/apps/wagtail_integration/models.py new file mode 100644 index 00000000..b4ecc2d4 --- /dev/null +++ b/src/fobi/contrib/apps/wagtail_integration/models.py @@ -0,0 +1,192 @@ +from __future__ import absolute_import, unicode_literals + +import os + +from django.db import models +from django.utils.translation import ugettext_lazy as _ + +from fobi.integration.processors import IntegrationProcessor + +from wagtail.wagtailadmin.edit_handlers import FieldPanel, MultiFieldPanel +from wagtail.wagtailcore.models import Page + + +from .helpers import ( + get_form_template_choices, get_success_page_template_choices +) +from .settings import WIDGET_FORM_SENT_GET_PARAM + +__title__ = 'fobi.contrib.apps.wagtail_integration.models' +__author__ = 'Andy Babic ' +__copyright__ = '2014-2016 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ('AbstractFobiFormPage',) + + +class FobiFormProcessor(IntegrationProcessor): + """Form processor.""" + + can_redirect = True + form_sent_get_param = WIDGET_FORM_SENT_GET_PARAM + + def get_context_data(self, request, instance, **kwargs): + context = instance.get_context(request) + super(FobiFormProcessor, self).get_context_data(self, request, + instance, **context) + + def get_form_template_name(self, request, instance): + return instance.get_form_template(request) + + def get_success_page_template_name(self, request, instance): + return instance.get_success_template(request) + + def show_thanks_page(self, request, instance, **kwargs): + """Renders the result of _show_thanks_page() without having to pass + through process() (Needed to support Wagtail's preview functionality) + :param django.http.HttpRequest request: + :return django.http.HttpResponse | None: + """ + return self._show_thanks_page(request, instance, **kwargs) + + def process(self, request, instance, **kwargs): + """This is where most of the form handling happens. + :param django.http.HttpRequest request: + :return django.http.HttpResponse | NULL: + """ + return self._process(request, instance, **kwargs) + + +class AbstractFobiFormPage(Page): + """A Fobi Form Page. Pages implementing a Fobi form should inherit from it. + :property fobi.models.FormEntry form_entry: Form entry to be rendered. + """ + @classmethod + def __init__(cls, name, bases, dct): + super(AbstractFobiFormPage, cls).__init__(name, bases, dct) + if 'form_template' not in dct: + cls.form_template = cls.template + if 'success_page_template' not in dct: + name, ext = os.path.splitext(cls.template) + cls.success_template = name + '_success' + ext + + form_entry = models.ForeignKey('fobi.FormEntry', verbose_name=_("Form")) + + hide_form_title = models.BooleanField( + _("Hide form title"), default=False, + help_text=_("If checked, no form title is shown.") + ) + + form_title = models.CharField( + _("Form title"), max_length=255, null=True, blank=True, + help_text=_("Overrides the default form title.") + ) + + form_submit_button_text = models.CharField( + _("Submit button text"), max_length=255, null=True, blank=True, + help_text=_("Overrides the default form submit button text.") + ) + + form_template_name = models.CharField( + _("Form template name"), max_length=255, null=True, blank=True, + choices=get_form_template_choices(), + help_text=_( + "Choose an alternative template to render the form with. Leave " + "blank to use the default for this page type (e.g. " + "fobi_form_page.html)." + ) + ) + + hide_success_page_title = models.BooleanField( + _("Hide success page title"), default=False, + help_text=_("If checked, no success page title is shown.") + ) + + success_page_title = models.CharField( + _("Success page title"), max_length=255, null=True, blank=True, + help_text=_("Overrides the default success page title.") + ) + + success_page_text = models.TextField( + _("Success page text"), null=True, blank=True, + help_text=_("Overrides the default success page text.") + ) + + success_page_template_name = models.CharField( + _("Success page template name"), max_length=255, null=True, blank=True, + choices=get_success_page_template_choices(), + help_text=_( + "Choose an alternative template to render the success page with. " + "Leave blank to use the default for this page type (e.g. " + "fobi_form_page_success.html)." + ) + ) + + class Meta: + """Meta class.""" + verbose_name = _('Fobi form page') + verbose_name_plural = _('Fobi form pages') + abstract = True + + form_page_panels = [ + FieldPanel('hide_form_title'), + FieldPanel('form_title'), + FieldPanel('form_entry'), + FieldPanel('form_submit_button_text'), + ] + + if get_form_template_choices(): + form_page_panels.append(FieldPanel('form_template_name')) + + success_page_panels = [ + FieldPanel('hide_success_page_title'), + FieldPanel('success_page_title'), + FieldPanel('success_page_text'), + ] + + if get_success_page_template_choices(): + success_page_panels.append(FieldPanel('success_page_template_name')) + + content_panels = Page.content_panels + ( + MultiFieldPanel(form_page_panels, heading=_('Form page')), + MultiFieldPanel(success_page_panels, heading=_('Success page')), + ) + + preview_modes = [ + ('form', _('Form page')), + ('success', _('Success page')), + ] + + def get_form_template(self, request): + """Return an alternative template name from the object's + ``form_template_name`` field, or the ``form_template`` attr defined on + the page type model. + :param django.http.HttpRequest request: + """ + return self.form_template_name or self.form_template + + def get_success_template(self, request): + """Return an alternative template name from the object's + ``success_page_template_name`` field, or the ``success_template`` attr + defined on the page type model. + :param django.http.HttpRequest request: + """ + return self.success_page_template_name or self.success_template + + def serve(self, request, *args, **kwargs): + """Serve the page using the ``FobiFormProcessor``.""" + fobi_form_processor = FobiFormProcessor() + response = fobi_form_processor.process(request, instance=self) + + if response: + return response + + return fobi_form_processor.rendered_output + + def serve_preview(self, request, mode): + """Serves the page in Wagtail's 'preview' mode.""" + if mode == 'success': + fobi_form_processor = FobiFormProcessor() + return fobi_form_processor.show_thanks_page(request, self) + else: + return super(AbstractFobiFormPage, self).serve_preview(request, + mode) diff --git a/src/fobi/contrib/apps/wagtail_integration/settings.py b/src/fobi/contrib/apps/wagtail_integration/settings.py new file mode 100644 index 00000000..04452884 --- /dev/null +++ b/src/fobi/contrib/apps/wagtail_integration/settings.py @@ -0,0 +1,25 @@ +""" +- `WIDGET_FORM_SENT_GET_PARAM` (str): Name of the GET param indicating that + form has been successfully sent. +""" +from .conf import get_setting + +__title__ = 'fobi.contrib.apps.wagtail_integration.settings' +__author__ = 'Andy Babic ' +__copyright__ = '2014-2016 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ( + 'WIDGET_FORM_SENT_GET_PARAM', + 'FORM_TEMPLATE_CHOICES', + 'SUCCESS_PAGE_TEMPLATE_CHOICES', +) + +# ************************************************************** +# ************************************************************** +# *************************** Core ***************************** +# ************************************************************** +# ************************************************************** + +WIDGET_FORM_SENT_GET_PARAM = get_setting('WIDGET_FORM_SENT_GET_PARAM') +FORM_TEMPLATE_CHOICES = get_setting('FORM_TEMPLATE_CHOICES') +SUCCESS_PAGE_TEMPLATE_CHOICES = get_setting('SUCCESS_PAGE_TEMPLATE_CHOICES') diff --git a/src/fobi/contrib/apps/wagtail_integration/templates/fobi_form_page.html.example b/src/fobi/contrib/apps/wagtail_integration/templates/fobi_form_page.html.example new file mode 100644 index 00000000..2d2b5b02 --- /dev/null +++ b/src/fobi/contrib/apps/wagtail_integration/templates/fobi_form_page.html.example @@ -0,0 +1,23 @@ +{% extends "pages/page.html" %} + +{% load static %} + +{% block extra_css %} + {{ block.super }} + {% for css_file in fobi_theme.get_media_css %} + + {% endfor %} +{% endblock extra_css %} + +{% block main %} + {{ block.super }} + {% if not fobi_hide_form_title and fobi_form_title %}

{{ fobi_form_title }}

{% endif %} + {% include fobi_theme.form_snippet_template_name %} +{% endblock main %} + +{% block extra_js %} + {{ block.super }} + {% for js_file in fobi_theme.get_media_js %} + + {% endfor %} +{% endblock extra_js %} diff --git a/src/fobi/contrib/apps/wagtail_integration/templates/fobi_form_page_success.html.example b/src/fobi/contrib/apps/wagtail_integration/templates/fobi_form_page_success.html.example new file mode 100644 index 00000000..035ee13d --- /dev/null +++ b/src/fobi/contrib/apps/wagtail_integration/templates/fobi_form_page_success.html.example @@ -0,0 +1,6 @@ +{% extends "pages/page.html" %} + +{% block main %} +

{{ fobi_success_page_title }}

+

{{ fobi_success_page_text }}

+{% endblock main %}