Better bango registration form (bug 824799)

This commit is contained in:
Matt Basta 2013-01-09 19:43:40 -08:00
Родитель f669143779
Коммит 4aa2508c98
8 изменённых файлов: 465 добавлений и 67 удалений

Просмотреть файл

@ -68,12 +68,6 @@ form div[style]:first-child + p {
margin-top: 0;
}
.optional {
color: @note-gray;
font-size: 11px;
font-weight: normal;
}
textarea {
.border-box();
display: block;
@ -244,6 +238,12 @@ textarea {
cursor: help;
}
}
.optional {
color: @note-gray;
font-size: 11px;
font-weight: normal;
}
ul {
font-size: 13px;
&.note {

Просмотреть файл

@ -125,11 +125,14 @@
/* overlays */
.overlay {
.close {
header .close {
color: #888;
cursor: pointer;
float: right;
font-size: 1.5em;
&:hover {
cursor: pointer;
background-position: -25px 0;
background-color: @red;
color: #666;
}
}
h2 {
@ -143,10 +146,80 @@
}
form {
margin: 0;
}
a {
display: block;
margin-top: 10px;
.field {
clear: left;
padding: 1em 0;
&.no-border, &:last-child {
padding-bottom: 0;
}
+ .field {
border-top: 1px solid #bbb;
}
&.no-border + .field {
border-top: none;
}
label {
display: block;
float: left;
line-height: 2em;
padding-right: 2%;
position: relative;
text-align: right;
width: 30%;
&[data-optional] {
line-height: 1em;
&:after {
content: attr(data-optional);
display: block;
font-size: 0.8em;
font-weight: normal;
}
}
}
input, select, textarea {
width: 65%;
}
input,
select,
textarea,
.faux-input {
display: block;
margin: 0;
.error {
padding-left: 0;
}
+ small {
font-size: 0.8em;
}
}
.faux-input, .error {
padding-left: 32%;
}
.horiz-strip > * {
display: inline-block;
}
.inline-strip > * {
display: inline;
}
.error {
font-size: 0.9em;
padding-top: 3.5px; // This was a compromise with cvan.
}
}
}
.listing-footer {
clear: both;
@ -163,46 +236,57 @@
> div {
margin: 0.25em 0;
}
span, ul.errorlist {
display: inline-block;
vertical-align: top;
}
}
p label {
.bank-accounts-strip div {
width: 45px;
+ div {
width: 100px;
}
+ div + div {
width: 150px;
}
+ div + div + div {
width: 45px;
}
input,
+ div input {
width: auto;
}
&:last-child {
line-height: 40px;
vertical-align: top;
width: auto;
}
}
.un-groupie-bank-accounts {
background: #eee;
border-radius: 1em;
color: #666;
cursor: pointer;
display: inline-block;
text-align: right;
width: 30%;
}
font-size: 1.15em;
font-weight: bold;
height: 25px;
line-height: 25px;
text-align: center;
width: 25px;
// Wide controls
#id_address1,
#id_address2,
#id_bankAddress1,
#id_bankAddress2, {
width: 400px;
}
// Smallish controls
#id_addressState,
#id_bankAddressState, {
width: 120px;
}
// Skinny controls
#id_addressZipCode,
#id_bankAddressZipCode, {
width: 100px;
}
label[for=id_account_name]:before {
background: #666;
clear: both;
content: '';
display: block;
height: 1px;
margin: 1em 0 1.5em;
width: 600px;
&:hover {
background: #2b69a2;
color: #fff;
}
}
}

Просмотреть файл

@ -12,7 +12,7 @@
position: absolute;
padding: 1em;
pointer-events: none;
z-index: 2;
z-index: 2001;
&.error {
background: darken(@error-red, 15%);
}

Просмотреть файл

@ -7,7 +7,7 @@
top: 0;
left: 0;
display: none;
z-index: 9000;
z-index: 2000;
opacity: 0;
overflow: hidden;
color: #000;

Просмотреть файл

@ -12,6 +12,165 @@ exports.payment_setup = function() {
return overlay;
};
// We listen for events on z.body because overlays are outside of the page.
z.body.on('keyup', '.groupie', function() {
var $parent;
if (this.groupie_parent) {
$parent = this.groupie_parent;
} else {
$parent = $(this).closest('input[type=hidden] + *').parent();
this.groupie_parent = $parent;
}
var new_val = _.pluck($parent.find('.groupie'), 'value').join('');
$parent.children('input[type=hidden]').val(new_val);
console.log('Concatted groupie value', new_val);
});
z.body.on('click', '.un-groupie-bank-accounts', _pd(function() {
$('.bank-accounts-strip').hide();
// jQuery won't let you attr('type', ...).
document.getElementById('id_bankAccountNumber').type = 'text';
}));
z.body.on('keyup', '#id_bankAccountCode', _.debounce(_pd(function() {
var get_code_type = function(code) {
var filtered = code.replace(/\W/g, '');
var test = function(re) {return re.test(filtered);};
switch(true) {
case test(/^\d{20}$/):
return gettext('Spanish Banking Code');
case test(/^\d{14}$/):
return gettext('Irish Sort Code');
case test(/^\d{12}$/):
return gettext('Belgian Sort Code');
case test(/^\d{10}$/):
return gettext('Spanish/French/Italian/Dutch Banking Code');
case test(/^\d{9}$/):
return gettext('Dutch/US Sort Code');
case test(/^\d{8}$/):
return gettext('Canadian Transit Number/German Routing Code');
case test(/^[02]\d{6}$/):
return gettext('Korean Bank and Branch/Indonesian Bank Code');
case test(/^\d{7}$/):
return gettext('Greek HEBIC/Indonesian Bank Code');
case test(/^\d{6}$/):
return gettext('UK/Irish Sort Code or NZ Account Prefix or Australian BSB Code');
case test(/^\d{5}$/):
return gettext('Austrian/Swiss Bank Code');
case test(/^\d{4}$/):
return gettext('Danish/Swiss Bank Code');
case test(/^\d{3}$/):
return gettext('Swiss/Iraqi Bank Code');
case test(/^\d{1,2}$/):
return gettext('Iraqi Bank Code');
default:
return false;
}
};
var result = get_code_type($(this).val());
var $small = $(this).siblings('small');
if (result) {
$small.text(format(gettext('Detected: {0}'), result));
} else {
$small.text('');
}
}), 200));
// Handle bouncing between bank account fields gracefully.
z.body.on('keyup', '.bank-accounts-strip input', _.debounce(function(e) {
if (e.which < 48 || // Action keys
(e.which > 90 && e.which < 96) || // Left/right/select
e.which > 105) {
// The user pressed a key that we don't care about.
return;
}
var $this = $(this);
var value = $this.val();
if (!value) {
// We don't care about the first keypress.
return;
}
// The user tabbed out already. Fast-typers rejoice!
if (!$this.is(':focus')) {
console.log('Input already lost focus');
return;
}
var previous_value = this.previous_value || '';
this.previous_value = value;
var maxlength = $this.data('maxlength');
var difflength = value.length - maxlength;
if (difflength >= 0 && value.length != previous_value.length) {
console.log('At max length of segment');
var next = $this.parent().next().children('input');
if (!next.length) {
// We're at the end anyway.
// TODO: Show an error?
return;
}
next.focus();
if (difflength) {
// The user has typed past the end of the input.
console.log('Typed past length of segment');
$this.val(value.substring(0, maxlength));
next.val(value.substr(maxlength));
next.trigger('keyup');
}
}
}, 200));
// This generates the pre-filled bank account name.
z.body.on(
'keyup',
'.bank-accounts-strip input, #id_bankName, #id_bankAccountPayeeName',
_.debounce(function(e) {
var $account_name = $('#id_account_name');
var accnum = $('#id_bankAccountNumber').val();
var bankname = $('#id_bankName').val();
var name = $('#id_bankAccountPayeeName').val();
var acc_name = name;
if (accnum.length > 10) {
if (acc_name) {
acc_name += ' ';
}
acc_name += (
'(' +
accnum.substr(0, 2) +
'-' +
accnum.substr(2, 2) +
'XX-XXXXX' +
accnum.substr(accnum.length - 4, 2) +
'-' +
accnum.substr(accnum.length - 2) +
')'
);
}
if (bankname) {
if (acc_name) {
acc_name += ' ';
}
acc_name += bankname;
}
var account_name_value = $account_name.val();
var last_acc_name = $account_name.data('last');
// If the account name is empty or the value is the last one we generated.
if (!account_name_value || account_name_value == last_acc_name) {
// Overwrite the value because it's not user-supplied.
$account_name.val(acc_name);
}
$account_name.data('last', acc_name);
}, 1000) // We don't need this to run very often.
);
// Set up account modal.
var newBangoPaymentAccount = function(e) {
var $overlay = getOverlay('add-bango-account');
@ -33,7 +192,21 @@ exports.payment_setup = function() {
).error(function(error_data) {
// If there's an error, revert to the form and reset the buttons.
$waiting_overlay.empty().append($old_overlay);
$old_overlay.find('#bango-account-errors').html(error_data.responseText);
try {
var parsed_errors = JSON.parse(error_data.responseText);
for(var field_error in parsed_errors) {
var field = $('#id_' + field_error);
field.siblings('.error').remove();
$('<div>').addClass('error')
.insertAfter(field)
.text(parsed_errors[field_error].join('\n'));
}
} catch(err) {
// There was a JSON parse error, just stick the error
// message on the form.
$old_overlay.find('#bango-account-errors').html(error_data.responseText);
}
setupBangoForm($waiting_overlay);
});
$waiting_overlay = getOverlay('bango-waiting');

Просмотреть файл

@ -278,8 +278,10 @@ class BangoPaymentAccountForm(happyforms.Form):
bankAccountPayeeName = forms.CharField(
max_length=50, label=_lazy(u'Account Holder Name'))
companyName = forms.CharField(max_length=255, label=_lazy(u'Company Name'))
vendorName = forms.CharField(max_length=255, label=_lazy(u'Vendor Name'))
companyName = forms.CharField(
max_length=255, label=_lazy(u'Company Name'))
vendorName = forms.CharField(
max_length=255, label=_lazy(u'Vendor Name'))
financeEmailAddress = forms.EmailField(
required=False, label=_lazy(u'Financial Email'))
adminEmailAddress = forms.EmailField(
@ -295,31 +297,35 @@ class BangoPaymentAccountForm(happyforms.Form):
max_length=64, label=_lazy(u'State/Province/Region'))
addressZipCode = forms.CharField(
max_length=128, label=_lazy(u'Zip/Postal Code'))
addressPhone = forms.CharField(max_length=20, label=_lazy(u'Phone'))
addressPhone = forms.CharField(
max_length=20, label=_lazy(u'Phone'))
countryIso = forms.ChoiceField(
choices=BANGO_COUNTRIES, label=_lazy(u'Country'))
currencyIso = forms.ChoiceField(
choices=BANGO_OUTPAYMENT_CURRENCIES,
label=_lazy(u'Preferred Currency'))
label=_lazy(u'I prefer to be paid in'))
vatNumber = forms.CharField(
max_length=17, required=False, label=_lazy(u'VAT Number'))
bankAccountNumber = forms.CharField(
max_length=20, required=False, label=_lazy(u'Bank Account Number'))
max_length=20, label=_lazy(u'Bank Account Number'),
widget=forms.HiddenInput())
bankAccountCode = forms.CharField(
max_length=20, label=_lazy(u'Bank Account Code'))
bankName = forms.CharField(max_length=50, label=_lazy(u'Bank Name'))
bankAddress1 = forms.CharField(max_length=50, label=_lazy(u'Bank Address'))
bankName = forms.CharField(
max_length=50, label=_lazy(u'Bank Name'))
bankAddress1 = forms.CharField(
max_length=50, label=_lazy(u'Bank Address'))
bankAddress2 = forms.CharField(
max_length=50, required=False, label=_lazy(u'Bank Address 2'))
bankAddressCity = forms.CharField(max_length=50, required=False,
label=_lazy(u'Bank City/Municipality'))
bankAddressCity = forms.CharField(
max_length=50, required=False, label=_lazy(u'Bank City/Municipality'))
bankAddressState = forms.CharField(
max_length=50, required=False,
label=_lazy(u'Bank State/Province/Region'))
bankAddressZipCode = forms.CharField(max_length=50,
label=_lazy(u'Bank Zip/Postal Code'))
bankAddressZipCode = forms.CharField(
max_length=50, label=_lazy(u'Bank Zip/Postal Code'))
bankAddressIso = forms.ChoiceField(
choices=BANGO_COUNTRIES, label=_lazy(u'Bank Country'))

Просмотреть файл

@ -1,14 +1,147 @@
<script type="text/template" id="add-bango-account-template">
<section class="add-bango-account">
<h2>{{ _('Add Bango Account') }}</h2>
<a class="close">{{ _('close') }}</a>
<form action="{{ url('mkt.developers.bango.add_payment_account') }}" method="post">
<header>
<a class="close" title="{{ _('close') }}">&times;</a>
<h2>{{ _('Add Bango Account') }}</h2>
</header>
<form action="{{ url('mkt.developers.bango.add_payment_account') }}" method="post" class="island">
{{ csrf() }}
<div id="bango-account-errors"></div>
{{ bango_account_form.as_p() }}
<div>
<div class="field">
<label>{{ bango_account_form.bankAccountPayeeName.label }}</label>
{{ bango_account_form.bankAccountPayeeName }}
</div>
<div class="field no-border">
<label>{{ bango_account_form.bankAccountNumber.label }}</label>
<div class="faux-input horiz-strip bank-accounts-strip">
<div>
{#
We use our own custom maxlength because if the user pastes
into the form, we do not want to be a dingus.
#}
<input type="text" class="groupie" value="" data-maxlength="2">
<small>Bank (2)</small>
</div>
<div>
<input type="text" class="groupie" value="" data-maxlength="4">
<small>Branch (4)</small>
</div>
<div>
<input type="text" class="groupie" value="" data-maxlength="7">
<small>Account (7)</small>
</div>
<div>
<input type="text" class="groupie" value="" data-maxlength="2">
<small>Suffix (2)</small>
</div>
<div>
<a class="tooltip un-groupie-bank-accounts" title="{{ _('My account number is not in this format.') }}">!</a>
</div>
</div>
{{ bango_account_form.bankAccountNumber }}
</div>
<div class="field">
<label>{{ bango_account_form.bankAccountCode.label }}</label>
<div class="faux-input">
{{ bango_account_form.bankAccountCode }}
<small></small>
</div>
</div>
<div class="field">
<label>{{ bango_account_form.currencyIso.label }}</label>
{{ bango_account_form.currencyIso }}
</div>
<div class="field">
<label data-optional="{{ _('Optional') }}">{{ bango_account_form.vatNumber.label }}</label>
{{ bango_account_form.vatNumber }}
</div>
<div class="field no-border">
<label>{{ bango_account_form.address1.label }}</label>
{{ bango_account_form.address1 }}
</div>
<div class="field no-border">
<label>{{ bango_account_form.address2.label }}</label>
{{ bango_account_form.address2 }}
</div>
<div class="field no-border">
<label>{{ bango_account_form.addressCity.label }}</label>
{{ bango_account_form.addressCity }}
</div>
<div class="field no-border">
<label>{{ bango_account_form.addressState.label }}</label>
{{ bango_account_form.addressState }}
</div>
<div class="field no-border">
<label>{{ bango_account_form.addressZipCode.label }}</label>
{{ bango_account_form.addressZipCode }}
</div>
<div class="field">
<label>{{ bango_account_form.countryIso.label }}</label>
{{ bango_account_form.countryIso }}
</div>
<div class="field">
<label>{{ bango_account_form.addressPhone.label }}</label>
{{ bango_account_form.addressPhone }}
</div>
<div class="field">
<label>{{ bango_account_form.bankName.label }}</label>
{{ bango_account_form.bankName }}
</div>
<div class="field no-border">
<label>{{ bango_account_form.bankAddress1.label }}</label>
{{ bango_account_form.bankAddress1 }}
</div>
<div class="field no-border">
<label>{{ bango_account_form.bankAddress2.label }}</label>
{{ bango_account_form.bankAddress2 }}
</div>
<div class="field no-border">
<label>{{ bango_account_form.bankAddressCity.label }}</label>
{{ bango_account_form.bankAddressCity }}
</div>
<div class="field no-border">
<label>{{ bango_account_form.bankAddressState.label }}</label>
{{ bango_account_form.bankAddressState }}
</div>
<div class="field no-border">
<label>{{ bango_account_form.bankAddressZipCode.label }}</label>
{{ bango_account_form.bankAddressZipCode }}
</div>
<div class="field">
<label>{{ bango_account_form.bankAddressIso.label }}</label>
{{ bango_account_form.bankAddressIso }}
</div>
<div class="field no-border">
<label>{{ bango_account_form.companyName.label }}</label>
{{ bango_account_form.companyName }}
</div>
<div class="field">
<label>{{ bango_account_form.vendorName.label }}</label>
{{ bango_account_form.vendorName }}
</div>
<div class="field no-border">
<label>{{ bango_account_form.financeEmailAddress.label }}</label>
{{ bango_account_form.financeEmailAddress }}
</div>
<div class="field">
<label>{{ bango_account_form.adminEmailAddress.label }}</label>
{{ bango_account_form.adminEmailAddress }}
</div>
<div class="field">
<label>{{ bango_account_form.account_name.label }}</label>
{{ bango_account_form.account_name }}
</div>
</div>
<div class="listing-footer">
<button type="submit" class="continue prominent">
{{ _('Register Account') }}
<button type="submit">
{{ _('Register Payment Account') }}
</button>
</div>
</form>

Просмотреть файл

@ -1,3 +1,5 @@
import json
from django import http
from django.shortcuts import get_object_or_404, redirect
@ -139,7 +141,7 @@ def payments_accounts(request):
def payments_accounts_add(request):
form = forms_payments.BangoPaymentAccountForm(request.POST)
if not form.is_valid():
return http.HttpResponse(form.happy_errors, status=400)
return http.HttpResponse(json.dumps(form.errors), status=400)
try:
models.PaymentAccount.create_bango(