Skip to content

Commit

Permalink
Moved post processing to integration class
Browse files Browse the repository at this point in the history
  • Loading branch information
JakeUrban committed Dec 4, 2019
1 parent 9ea389c commit c1ad6ea
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 41 deletions.
63 changes: 38 additions & 25 deletions docs/integrations/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ You should be familiar with `Django Forms`_ and how they validate their inputs.
::

from django import forms
from polaris.integrations import TransactionForm
from polaris.models import Transaction
from polaris.integrations import TransactionForm, DepositIntegration
from myapp.models import FormSubmissions

class MyDepositForm(TransactionForm):
Expand All @@ -67,42 +68,39 @@ You should be familiar with `Django Forms`_ and how they validate their inputs.
raise ValidationError("Please enter your name.")
return data

def after_validation(self):

class MyDepositIntegration(DepositIntegration):
def after_form_validation(self, form: forms.Form, transaction: Transaction):
"""Saves the data collected as a FormSubmission database object"""
data = self.cleaned_data
data = form.cleaned_data
FormSubmission.objects.create(
name=" ".join(data["first_name"], data["last_name"])
amount=data["amount"]
asset=data["asset"]
asset=data["asset"],
transaction=transaction
)

``TransactionForm`` already collects the deposit amount and asset type and
validates that the amount is within the asset's accepted deposit range. In
this example, we've also added some contact information to the form fields
and validation that ensures they're not empty.

Polaris uses default CSS provided by Bulma_ for styling forms. To keep the
UX consistent, make sure to pass in a modified `widget` parameter to all
form fields displaying text like so:

::

widget=forms.widgets.TextInput(attrs={"class": "input"})

The `attrs` parameter adds a HTML attribute to the `<input>` tag that Bulma
uses to add better styling. You may also add more Bulma-supported attributes
to Polaris forms.
The ``TransactionForm`` superclass collects the deposit amount and asset type
and validates that the amount is within the asset's accepted deposit range.
In this example, we've also added contact information fields to the form
and validate that they're not empty after submission.

Polaris will also call the form's ``after_validation()`` function,
which in this case saves the form data collected to the database.
Processing Form Submissions
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Once the form is validated, Polaris will call :func:`after_form_validation` on
the integration subclass, which in this case saves the form data collected to
the database.

Specifically, Polaris will facilitate that functionality like so:
::

form = registered_deposit_integration.form(request.POST)
from polaris.integrations import registered_deposit_integration as rdi

form = rdi.form(request.POST)
if form.is_valid():
if hasattr(form, "after_validation") and callable(form.after_validation):
form.after_validation()
afv = getattr(rdi, "after_form_validation", None)
if callable(afv):
afv(form, transaction)

If form is not valid, Polaris will return a rendered form with the errors
raised during validation:
Expand All @@ -114,3 +112,18 @@ raised during validation:
Polaris does not yet allow you customize the template used to render the form,
although that functionality is on the road map. For now, you can be assured
that your ``ValidationError`` will be displayed.

Form CSS
^^^^^^^^
Polaris uses default CSS provided by Bulma_ for styling forms. To keep the
UX consistent, make sure to pass in a modified `widget` parameter to all
form fields displaying text like so:

::

widget=forms.widgets.TextInput(attrs={"class": "input"})

The `attrs` parameter adds a HTML attribute to the `<input>` tag that Bulma
uses to add better styling. You may also add more Bulma-supported attributes
to Polaris forms.

73 changes: 73 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
sys.path.insert(0, os.path.abspath('../../polaris'))

# Specify settings module
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'polaris.settings')

# Setup Django
import django
django.setup()


# -- Project information -----------------------------------------------------

project = 'django-polaris'
copyright = '2019, Jake Urban'
author = 'Jake Urban'

# The short X.Y version
version = 'v0.9.7'

# The full version, including alpha/beta/rc tags
release = 'v0.9.7'


# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx_autodoc_typehints',
'sphinx_rtd_theme'
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []

# The master toctree document.
master_doc = 'contents'

# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']


# -- Extension configuration -------------------------------------------------
16 changes: 8 additions & 8 deletions polaris/polaris/deposit/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"""
import base64
import binascii
import json
from urllib.parse import urlencode

from polaris import settings
Expand All @@ -32,7 +31,7 @@
from polaris.transaction.serializers import TransactionSerializer
from polaris.deposit.utils import create_stellar_deposit

from polaris.integrations import registered_deposit_integration
from polaris.integrations import registered_deposit_integration as rdi


def _construct_interactive_url(request, asset_code, account, transaction_id):
Expand Down Expand Up @@ -170,25 +169,26 @@ def interactive_deposit(request: Request) -> Response:

# GET: The server needs to display the form for the user to input the deposit information.
if request.method == "GET":
form = registered_deposit_integration.form()
form = rdi.form()
return Response({"form": form}, template_name="deposit/form.html")

form = registered_deposit_integration.form(request.POST)
form = rdi.form(request.POST)
asset = Asset.objects.get(code=asset_code)
form.asset = asset
# If the form is valid, we create a transaction pending external action
# and render the success page.
if form.is_valid():
# Perform any defined post-validation logic defined by Polaris users
if hasattr(form, "after_validation") and callable(form.after_validation):
form.after_validation()

transaction.amount_in = form.cleaned_data["amount"]
transaction.amount_fee = calc_fee(
asset, settings.OPERATION_DEPOSIT, transaction.amount_in
)
transaction.save()

# Perform any defined post-validation logic defined by Polaris users
afv = getattr(rdi, "after_form_validation", None)
if callable(afv):
afv(form, transaction)

return redirect(f"{reverse('more_info')}?{urlencode({'id': transaction_id})}")
else:
return Response({"form": form}, template_name="deposit/form.html")
Expand Down
16 changes: 8 additions & 8 deletions polaris/polaris/withdraw/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
validate_sep10_token,
)
from polaris.models import Asset, Transaction
from polaris.transaction.serializers import TransactionSerializer
from polaris.integrations import registered_withdrawal_integration
from polaris.integrations import registered_withdrawal_integration as rwi


def _construct_interactive_url(request: Request,
Expand Down Expand Up @@ -80,27 +79,28 @@ def interactive_withdraw(request: Request) -> Response:

# GET: The server needs to display the form for the user to input withdrawal information.
if request.method == "GET":
form = registered_withdrawal_integration.form()
form = rwi.form()
resp_data = {"form": form, "account": request.GET.get("account")}
return Response(resp_data, template_name="withdraw/form.html")

form = registered_withdrawal_integration.form(request.POST)
form = rwi.form(request.POST)
asset = Asset.objects.get(code=asset_code)
form.asset = asset

# If the form is valid, we create a transaction pending user action
# and render the success page.
if form.is_valid():
# Perform any defined post-validation logic defined by Polaris users
if hasattr(form, "after_validation") and callable(form.after_validation):
form.after_validation()

transaction.amount_in = form.cleaned_data["amount"]
transaction.amount_fee = calc_fee(
asset, settings.OPERATION_WITHDRAWAL, transaction.amount_in
)
transaction.save()

# Perform any defined post-validation logic defined by Polaris users
afv = getattr(rwi, "after_form_validation", None)
if callable(afv):
afv(form, transaction)

return redirect(f"{reverse('more_info')}?{urlencode({'id': transaction_id})}")
else:
resp_data = {"form": form, "account": request.POST.get("account")}
Expand Down

0 comments on commit c1ad6ea

Please sign in to comment.