Skip to content

Commit 7e66527

Browse files
authored
Show Wikimedia username in ticket checkout page (#1351)
* Show Wikimedia username in ticket checkout page * Address Sourcery review * Correct the label of `wikimedia_username` in User Settings form
1 parent ed8b429 commit 7e66527

File tree

4 files changed

+77
-38
lines changed

4 files changed

+77
-38
lines changed

app/eventyay/base/forms/user.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,13 @@ class UserSettingsForm(forms.ModelForm):
5454
class Meta:
5555
model = User
5656
fields = ['fullname', 'wikimedia_username', 'locale', 'timezone', 'email']
57-
labels = {
58-
'wikimedia_username': 'Nick name',
59-
}
6057
widgets = {'locale': SingleLanguageWidget}
6158

6259
def __init__(self, *args, **kwargs):
6360
self.user = kwargs.pop('user')
6461
super().__init__(*args, **kwargs)
6562
self.fields['email'].required = True
66-
self.fields['wikimedia_username'].widget.attrs['readonly'] = True
63+
self.fields['wikimedia_username'].disabled = True
6764
if self.user.auth_backend != 'native':
6865
del self.fields['old_pw']
6966
del self.fields['new_pw']

app/eventyay/control/forms/orders.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@
2727
)
2828
from eventyay.base.models import (
2929
InvoiceAddress,
30-
ProductAddOn,
3130
Order,
3231
OrderFee,
3332
OrderPosition,
33+
ProductAddOn,
3434
TaxRule,
3535
)
3636
from eventyay.base.models.event import SubEvent

app/eventyay/presale/forms/checkout.py

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import logging
12
from itertools import chain
23

34
from django import forms
45
from django.core.exceptions import ValidationError
6+
from django.http import HttpRequest
57
from django.utils.encoding import force_str
68
from django.utils.translation import gettext_lazy as _
79
from phonenumber_field.formfields import PhoneNumberField
@@ -16,9 +18,12 @@
1618
guess_country,
1719
)
1820
from eventyay.base.i18n import get_babel_locale, language
21+
from eventyay.base.models import Event
1922
from eventyay.base.validators import EmailBanlistValidator
2023
from eventyay.presale.signals import contact_form_fields
2124

25+
logger = logging.getLogger(__name__)
26+
2227

2328
class ContactForm(forms.Form):
2429
required_css_class = 'required'
@@ -27,51 +32,78 @@ class ContactForm(forms.Form):
2732
validators=[EmailBanlistValidator()],
2833
widget=forms.EmailInput(attrs={'autocomplete': 'section-contact email'}),
2934
)
35+
# This field will be dropped depending on `include_wikimedia_username` event setting.
36+
wikimedia_username = forms.CharField(
37+
label=_('Wikimedia Username'),
38+
required=False,
39+
disabled=True,
40+
widget=forms.TextInput(attrs={'readonly': 'readonly'}),
41+
)
42+
phone = PhoneNumberField(
43+
label=_('Phone number'),
44+
required=False,
45+
help_text='',
46+
widget=WrappedPhoneNumberPrefixWidget(),
47+
)
3048

31-
def __init__(self, *args, **kwargs):
32-
self.event = kwargs.pop('event')
33-
self.request = kwargs.pop('request')
34-
self.all_optional = kwargs.pop('all_optional', False)
49+
def __init__(self, *args, event: Event, request: HttpRequest, all_optional=False, **kwargs):
50+
self.event = event
51+
self.request = request
52+
self.all_optional = all_optional
3553
super().__init__(*args, **kwargs)
3654

37-
if self.event.settings.order_email_asked_twice:
55+
if event.settings.order_email_asked_twice:
3856
self.fields['email_repeat'] = forms.EmailField(
3957
label=_('E-mail address (repeated)'),
4058
help_text=_('Please enter the same email address again to make sure you typed it correctly.'),
4159
)
4260

43-
if self.event.settings.order_phone_asked:
61+
if event.settings.order_phone_asked:
62+
self.fields['phone'].required = True
63+
self.fields['phone'].help_text = event.settings.checkout_phone_helptext
4464
with language(get_babel_locale()):
45-
default_country = guess_country(self.event)
65+
default_country = guess_country(event)
4666
default_prefix = None
67+
phone_initial = ''
4768
for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items():
4869
if str(default_country) in values:
4970
default_prefix = prefix
50-
try:
51-
initial = self.initial.pop('phone', None)
52-
initial = PhoneNumber().from_string(initial) if initial else '+{}.'.format(default_prefix)
53-
except NumberParseException:
54-
initial = None
55-
self.fields['phone'] = PhoneNumberField(
56-
label=_('Phone number'),
57-
required=self.event.settings.order_phone_required,
58-
help_text=self.event.settings.checkout_phone_helptext,
59-
# We now exploit an implementation detail in PhoneNumberPrefixWidget to allow us to pass just
60-
# a country code but no number as an initial value. It's a bit hacky, but should be stable for
61-
# the future.
62-
initial=initial,
63-
widget=WrappedPhoneNumberPrefixWidget(),
64-
)
71+
break
72+
if passed_initial := self.initial.get('phone'):
73+
try:
74+
phone_number = PhoneNumber().from_string(passed_initial)
75+
phone_initial = str(phone_number)
76+
except NumberParseException:
77+
pass
78+
elif default_prefix:
79+
phone_initial = f'+{default_prefix}.'
80+
self.fields['phone'].initial = phone_initial
81+
else:
82+
del self.fields['phone']
83+
84+
# Wikimedia username field visibility based on event setting
85+
if not event.settings.include_wikimedia_username:
86+
logger.debug('Dropping wikimedia_username field because `include_wikimedia_username` setting is False.')
87+
self.fields.pop('wikimedia_username', None)
88+
else:
89+
# Configure read-only Wikimedia username initial without redefining the field
90+
wm_initial = (
91+
self.initial.get('wikimedia_username')
92+
or getattr(getattr(request, 'user', None), 'wikimedia_username', None)
93+
or request.session.get('wikimedia_username')
94+
)
95+
if wm_initial:
96+
self.fields['wikimedia_username'].initial = wm_initial
6597

66-
if not self.request.session.get('iframe_session', False):
98+
if not request.session.get('iframe_session', False):
6799
# There is a browser quirk in Chrome that leads to incorrect initial scrolling in iframes if there
68100
# is an autofocus field. Who would have thought… See e.g. here:
69101
# https://floatboxjs.com/forum/topic.php?post=8440&usebb_sid=2e116486a9ec6b7070e045aea8cded5b#post8440
70102
self.fields['email'].widget.attrs['autofocus'] = 'autofocus'
71-
self.fields['email'].help_text = self.event.settings.checkout_email_helptext
103+
self.fields['email'].help_text = event.settings.checkout_email_helptext
72104
self.fields['email'].widget.attrs['placeholder'] = 'Valid Email address'
73105

74-
responses = contact_form_fields.send(self.event, request=self.request)
106+
responses = contact_form_fields.send(event, request=request)
75107
for r, response in responses:
76108
for key, value in response.items():
77109
# We need to be this explicit, since OrderedDict.update does not retain ordering

app/eventyay/presale/views/checkout.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
from urllib.parse import quote
23

34
from django.contrib import messages
@@ -18,9 +19,10 @@
1819
iframe_entry_view_wrapper,
1920
)
2021

22+
logger = logging.getLogger(__name__)
2123

22-
@method_decorator(allow_frame_if_namespaced, 'dispatch')
23-
@method_decorator(iframe_entry_view_wrapper, 'dispatch')
24+
25+
@method_decorator((allow_frame_if_namespaced, iframe_entry_view_wrapper), 'dispatch')
2426
class CheckoutView(View):
2527
def get_index_url(self, request):
2628
kwargs = {}
@@ -37,7 +39,9 @@ def dispatch(self, request, *args, **kwargs):
3739

3840
if not request.event.presale_is_running:
3941
messages.error(request, _('The presale for this event is over or has not yet started.'))
40-
return self.redirect(self.get_index_url(self.request))
42+
new_url = self.get_index_url(self.request)
43+
logger.info('Redirecting to %s as presale is not running.', new_url)
44+
return self.redirect(new_url)
4145

4246
cart_error = None
4347
try:
@@ -52,29 +56,35 @@ def dispatch(self, request, *args, **kwargs):
5256
continue
5357
if step.requires_valid_cart and cart_error:
5458
messages.error(request, str(cart_error))
55-
return self.redirect(
56-
previous_step.get_step_url(request) if previous_step else self.get_index_url(request)
57-
)
59+
new_url = previous_step.get_step_url(request) if previous_step else self.get_index_url(request)
60+
logger.info('Redirecting to %s as cart is invalid.', new_url)
61+
return self.redirect(new_url)
5862

5963
if 'step' not in kwargs:
60-
return self.redirect(step.get_step_url(request))
64+
new_url = step.get_step_url(request)
65+
logger.info('Redirecting to %s as no step is specified.', new_url)
66+
return self.redirect(new_url)
6167
is_selected = step.identifier == kwargs.get('step', '')
6268
if (
6369
'async_id' not in request.GET
6470
and not is_selected
6571
and not step.is_completed(request, warn=not is_selected)
6672
):
67-
return self.redirect(step.get_step_url(request))
73+
new_url = step.get_step_url(request)
74+
logger.info('Redirecting to %s as previous steps are not completed.', new_url)
75+
return self.redirect(new_url)
6876
if is_selected:
6977
if request.method.lower() in self.http_method_names:
7078
handler = getattr(step, request.method.lower(), self.http_method_not_allowed)
7179
else:
7280
handler = self.http_method_not_allowed
81+
logger.debug('Dispatching to step handler %s.', handler)
7382
return handler(request)
7483
else:
7584
previous_step = step
7685
step.c_is_before = True
7786
step.c_resolved_url = step.get_step_url(request)
87+
logger.warning('No matching step found in checkout flow.')
7888
raise Http404()
7989

8090
def redirect(self, url):

0 commit comments

Comments
 (0)