Exemple #1
0
    def __init__(self, *args, **kwargs):
        self.event = kwargs.pop('event')
        self.request = kwargs.pop('request')
        self.all_optional = kwargs.pop('all_optional', False)
        super().__init__(*args, **kwargs)

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

        if self.event.settings.order_phone_asked:
            with language(get_babel_locale()):
                default_country = guess_country(self.event)
                default_prefix = None
                for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items():
                    if str(default_country) in values:
                        default_prefix = prefix
                try:
                    initial = self.initial.pop('phone', None)
                    initial = PhoneNumber().from_string(
                        initial) if initial else "+{}.".format(default_prefix)
                except NumberParseException:
                    initial = None
                self.fields['phone'] = PhoneNumberField(
                    label=_('Phone number'),
                    required=self.event.settings.order_phone_required,
                    help_text=self.event.settings.checkout_phone_helptext,
                    # We now exploit an implementation detail in PhoneNumberPrefixWidget to allow us to pass just
                    # a country code but no number as an initial value. It's a bit hacky, but should be stable for
                    # the future.
                    initial=initial,
                    widget=WrappedPhoneNumberPrefixWidget())

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

        responses = contact_form_fields.send(self.event, request=self.request)
        for r, response in responses:
            for key, value in response.items():
                # We need to be this explicit, since OrderedDict.update does not retain ordering
                self.fields[key] = value
        if self.all_optional:
            for k, v in self.fields.items():
                v.required = False
                v.widget.is_required = False
Exemple #2
0
 def __init__(self, initial=None):
     choices = [("", "---------")]
     language = get_babel_locale()  # changed from default implementation that used the django locale
     locale = Locale(translation.to_locale(language))
     for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items():
         prefix = "+%d" % prefix
         if initial and initial in values:
             self.initial = prefix
         for country_code in values:
             country_name = locale.territories.get(country_code)
             if country_name:
                 choices.append((prefix, "{} {}".format(country_name, prefix)))
     super().__init__(choices=sorted(choices, key=lambda item: item[1]), attrs={'aria-label': pgettext_lazy('phonenumber', 'International area code')})
Exemple #3
0
    def __init__(self, *args, **kwargs):
        self.event = kwargs.pop('event')
        super().__init__(*args, **kwargs)

        event = self.event

        if event.settings.waiting_list_names_asked:
            self.fields['name_parts'] = NamePartsFormField(
                max_length=255,
                required=event.settings.waiting_list_names_required,
                scheme=event.settings.name_scheme,
                titles=event.settings.name_scheme_titles,
                label=_('Name'),
            )
        else:
            del self.fields['name_parts']

        if event.settings.waiting_list_phones_asked:
            with language(get_babel_locale()):
                default_country = guess_country(self.event)
                for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items():
                    if str(default_country
                           ) in values and not self.initial.get('phone'):
                        # We now exploit an implementation detail in PhoneNumberPrefixWidget to allow us to pass just
                        # a country code but no number as an initial value. It's a bit hacky, but should be stable for
                        # the future.
                        self.initial['phone'] = "+{}.".format(prefix)

                self.fields['phone'] = PhoneNumberField(
                    label=_("Phone number"),
                    required=event.settings.waiting_list_phones_required,
                    help_text=event.settings.
                    waiting_list_phones_explanation_text,
                    widget=WrappedPhoneNumberPrefixWidget())
        else:
            del self.fields['phone']
Exemple #4
0
    def __init__(self, *args, **kwargs):
        """
        Takes two additional keyword arguments:

        :param cartpos: The cart position the form should be for
        :param event: The event this belongs to
        """
        cartpos = self.cartpos = kwargs.pop('cartpos', None)
        orderpos = self.orderpos = kwargs.pop('orderpos', None)
        pos = cartpos or orderpos
        item = pos.item
        questions = pos.item.questions_to_ask
        event = kwargs.pop('event')
        self.all_optional = kwargs.pop('all_optional', False)

        super().__init__(*args, **kwargs)

        add_fields = {}

        if item.admission and event.settings.attendee_names_asked:
            add_fields['attendee_name_parts'] = NamePartsFormField(
                max_length=255,
                required=event.settings.attendee_names_required
                and not self.all_optional,
                scheme=event.settings.name_scheme,
                titles=event.settings.name_scheme_titles,
                label=_('Attendee name'),
                initial=(cartpos.attendee_name_parts
                         if cartpos else orderpos.attendee_name_parts),
            )
        if item.admission and event.settings.attendee_emails_asked:
            add_fields['attendee_email'] = forms.EmailField(
                required=event.settings.attendee_emails_required
                and not self.all_optional,
                label=_('Attendee email'),
                initial=(cartpos.attendee_email
                         if cartpos else orderpos.attendee_email),
                widget=forms.EmailInput(attrs={'autocomplete': 'email'}))
        if item.admission and event.settings.attendee_company_asked:
            add_fields['company'] = forms.CharField(
                required=event.settings.attendee_company_required
                and not self.all_optional,
                label=_('Company'),
                max_length=255,
                initial=(cartpos.company if cartpos else orderpos.company),
            )

        if item.admission and event.settings.attendee_addresses_asked:
            add_fields['street'] = forms.CharField(
                required=event.settings.attendee_addresses_required
                and not self.all_optional,
                label=_('Address'),
                widget=forms.Textarea(
                    attrs={
                        'rows': 2,
                        'placeholder': _('Street and Number'),
                        'autocomplete': 'street-address'
                    }),
                initial=(cartpos.street if cartpos else orderpos.street),
            )
            add_fields['zipcode'] = forms.CharField(
                required=event.settings.attendee_addresses_required
                and not self.all_optional,
                max_length=30,
                label=_('ZIP code'),
                initial=(cartpos.zipcode if cartpos else orderpos.zipcode),
                widget=forms.TextInput(attrs={
                    'autocomplete': 'postal-code',
                }),
            )
            add_fields['city'] = forms.CharField(
                required=event.settings.attendee_addresses_required
                and not self.all_optional,
                label=_('City'),
                max_length=255,
                initial=(cartpos.city if cartpos else orderpos.city),
                widget=forms.TextInput(attrs={
                    'autocomplete': 'address-level2',
                }),
            )
            country = (cartpos.country if cartpos else
                       orderpos.country) or guess_country(event)
            add_fields['country'] = CountryField(
                countries=CachedCountries).formfield(
                    required=event.settings.attendee_addresses_required
                    and not self.all_optional,
                    label=_('Country'),
                    initial=country,
                    widget=forms.Select(attrs={
                        'autocomplete': 'country',
                    }),
                )
            c = [('', pgettext_lazy('address', 'Select state'))]
            fprefix = str(
                self.prefix
            ) + '-' if self.prefix is not None and self.prefix != '-' else ''
            cc = None
            if fprefix + 'country' in self.data:
                cc = str(self.data[fprefix + 'country'])
            elif country:
                cc = str(country)
            if cc and cc in COUNTRIES_WITH_STATE_IN_ADDRESS:
                types, form = COUNTRIES_WITH_STATE_IN_ADDRESS[cc]
                statelist = [
                    s for s in pycountry.subdivisions.get(country_code=cc)
                    if s.type in types
                ]
                c += sorted([(s.code[3:], s.name) for s in statelist],
                            key=lambda s: s[1])
            elif fprefix + 'state' in self.data:
                self.data = self.data.copy()
                del self.data[fprefix + 'state']

            add_fields['state'] = forms.ChoiceField(
                label=pgettext_lazy('address', 'State'),
                required=False,
                choices=c,
                widget=forms.Select(attrs={
                    'autocomplete': 'address-level1',
                }),
            )
            add_fields['state'].widget.is_required = True

        field_positions = list([(n,
                                 event.settings.system_question_order.get(
                                     n if n != 'state' else 'country', 0))
                                for n in add_fields.keys()])

        for q in questions:
            # Do we already have an answer? Provide it as the initial value
            answers = [a for a in pos.answerlist if a.question_id == q.id]
            if answers:
                initial = answers[0]
            else:
                initial = None
            tz = pytz.timezone(event.settings.timezone)
            help_text = rich_text(q.help_text)
            label = escape(q.question)  # django-bootstrap3 calls mark_safe
            required = q.required and not self.all_optional
            if q.type == Question.TYPE_BOOLEAN:
                if q.required:
                    # For some reason, django-bootstrap3 does not set the required attribute
                    # itself.
                    widget = forms.CheckboxInput(
                        attrs={'required': 'required'})
                else:
                    widget = forms.CheckboxInput()

                if initial:
                    initialbool = (initial.answer == "True")
                else:
                    initialbool = False

                field = forms.BooleanField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=initialbool,
                    widget=widget,
                )
            elif q.type == Question.TYPE_NUMBER:
                field = forms.DecimalField(
                    label=label,
                    required=required,
                    min_value=q.valid_number_min or Decimal('0.00'),
                    max_value=q.valid_number_max,
                    help_text=q.help_text,
                    initial=initial.answer if initial else None,
                )
            elif q.type == Question.TYPE_STRING:
                field = forms.CharField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=initial.answer if initial else None,
                )
            elif q.type == Question.TYPE_TEXT:
                field = forms.CharField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    widget=forms.Textarea,
                    initial=initial.answer if initial else None,
                )
            elif q.type == Question.TYPE_COUNTRYCODE:
                field = CountryField(
                    countries=CachedCountries,
                    blank=True,
                    null=True,
                    blank_label=' ',
                ).formfield(
                    label=label,
                    required=required,
                    help_text=help_text,
                    widget=forms.Select,
                    empty_label=' ',
                    initial=initial.answer if initial else
                    (guess_country(event) if required else None),
                )
            elif q.type == Question.TYPE_CHOICE:
                field = forms.ModelChoiceField(
                    queryset=q.options,
                    label=label,
                    required=required,
                    help_text=help_text,
                    widget=forms.Select,
                    to_field_name='identifier',
                    empty_label='',
                    initial=initial.options.first() if initial else None,
                )
            elif q.type == Question.TYPE_CHOICE_MULTIPLE:
                field = forms.ModelMultipleChoiceField(
                    queryset=q.options,
                    label=label,
                    required=required,
                    help_text=help_text,
                    to_field_name='identifier',
                    widget=QuestionCheckboxSelectMultiple,
                    initial=initial.options.all() if initial else None,
                )
            elif q.type == Question.TYPE_FILE:
                field = ExtFileField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=initial.file if initial else None,
                    widget=UploadedFileWidget(position=pos,
                                              event=event,
                                              answer=initial),
                    ext_whitelist=(".png", ".jpg", ".gif", ".jpeg", ".pdf",
                                   ".txt", ".docx", ".gif", ".svg", ".pptx",
                                   ".ppt", ".doc", ".xlsx", ".xls", ".jfif",
                                   ".heic", ".heif", ".pages", ".bmp", ".tif",
                                   ".tiff"),
                    max_size=10 * 1024 * 1024,
                )
            elif q.type == Question.TYPE_DATE:
                attrs = {}
                if q.valid_date_min:
                    attrs['data-min'] = q.valid_date_min.isoformat()
                if q.valid_date_max:
                    attrs['data-max'] = q.valid_date_max.isoformat()
                field = forms.DateField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=dateutil.parser.parse(initial.answer).date()
                    if initial and initial.answer else None,
                    widget=DatePickerWidget(attrs),
                )
                if q.valid_date_min:
                    field.validators.append(MinDateValidator(q.valid_date_min))
                if q.valid_date_max:
                    field.validators.append(MaxDateValidator(q.valid_date_max))
            elif q.type == Question.TYPE_TIME:
                field = forms.TimeField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=dateutil.parser.parse(initial.answer).time()
                    if initial and initial.answer else None,
                    widget=TimePickerWidget(
                        time_format=get_format_without_seconds(
                            'TIME_INPUT_FORMATS')),
                )
            elif q.type == Question.TYPE_DATETIME:
                field = SplitDateTimeField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=dateutil.parser.parse(
                        initial.answer).astimezone(tz)
                    if initial and initial.answer else None,
                    widget=SplitDateTimePickerWidget(
                        time_format=get_format_without_seconds(
                            'TIME_INPUT_FORMATS'),
                        min_date=q.valid_datetime_min,
                        max_date=q.valid_datetime_max),
                )
                if q.valid_datetime_min:
                    field.validators.append(
                        MinDateTimeValidator(q.valid_datetime_min))
                if q.valid_datetime_max:
                    field.validators.append(
                        MaxDateTimeValidator(q.valid_datetime_max))
            elif q.type == Question.TYPE_PHONENUMBER:
                with language(get_babel_locale()):
                    default_country = guess_country(event)
                    default_prefix = None
                    for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items():
                        if str(default_country) in values:
                            default_prefix = prefix
                    try:
                        initial = PhoneNumber().from_string(
                            initial.answer) if initial else "+{}.".format(
                                default_prefix)
                    except NumberParseException:
                        initial = None
                    field = PhoneNumberField(
                        label=label,
                        required=required,
                        help_text=help_text,
                        # We now exploit an implementation detail in PhoneNumberPrefixWidget to allow us to pass just
                        # a country code but no number as an initial value. It's a bit hacky, but should be stable for
                        # the future.
                        initial=initial,
                        widget=WrappedPhoneNumberPrefixWidget())
            field.question = q
            if answers:
                # Cache the answer object for later use
                field.answer = answers[0]

            if q.dependency_question_id:
                field.widget.attrs[
                    'data-question-dependency'] = q.dependency_question_id
                field.widget.attrs[
                    'data-question-dependency-values'] = escapejson_attr(
                        json.dumps(q.dependency_values))
                if q.type != 'M':
                    field.widget.attrs[
                        'required'] = q.required and not self.all_optional
                    field._required = q.required and not self.all_optional
                field.required = False

            add_fields['question_%s' % q.id] = field
            field_positions.append(('question_%s' % q.id, q.position))

        field_positions.sort(key=lambda e: e[1])
        for fname, p in field_positions:
            self.fields[fname] = add_fields[fname]

        responses = question_form_fields.send(sender=event, position=pos)
        data = pos.meta_info_data
        for r, response in sorted(responses, key=lambda r: str(r[0])):
            for key, value in response.items():
                # We need to be this explicit, since OrderedDict.update does not retain ordering
                self.fields[key] = value
                value.initial = data.get('question_form_data', {}).get(key)

        for k, v in self.fields.items():
            if v.widget.attrs.get(
                    'autocomplete') or k == 'attendee_name_parts':
                v.widget.attrs['autocomplete'] = 'section-{} '.format(
                    self.prefix) + v.widget.attrs.get('autocomplete', '')
Exemple #5
0
def guess_phone_prefix(event):
    with language(get_babel_locale()):
        country = str(guess_country(event))
        return get_phone_prefix(country)
Exemple #6
0
 def __init__(self, *args, **kwargs):
     with language(get_babel_locale()):
         super().__init__(*args, **kwargs)
Exemple #7
0
    def __init__(self, *args, **kwargs):
        self.event = kwargs.pop('event')
        self.channel = kwargs.pop('channel')
        super().__init__(*args, **kwargs)

        choices = [('', '')]
        items, display_add_to_cart = get_grouped_items(self.event,
                                                       self.instance.subevent,
                                                       require_seat=None)
        for i in items:
            if not i.allow_waitinglist:
                continue

            if i.has_variations:
                for v in i.available_variations:
                    if v.cached_availability[0] == Quota.AVAILABILITY_OK:
                        continue
                    choices.append((f'{i.pk}-{v.pk}', f'{i.name} – {v.value}'))

            else:
                if i.cached_availability[0] == Quota.AVAILABILITY_OK:
                    continue
                choices.append((f'{i.pk}', f'{i.name}'))

        self.fields['itemvar'] = forms.ChoiceField(
            label=_('Product'),
            choices=choices,
        )

        event = self.event

        if event.settings.waiting_list_names_asked:
            self.fields['name_parts'] = NamePartsFormField(
                max_length=255,
                required=event.settings.waiting_list_names_required,
                scheme=event.settings.name_scheme,
                titles=event.settings.name_scheme_titles,
                label=_('Name'),
            )
        else:
            del self.fields['name_parts']

        if event.settings.waiting_list_phones_asked:
            with language(get_babel_locale()):
                default_country = guess_country(self.event)
                for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items():
                    if str(default_country
                           ) in values and not self.initial.get('phone'):
                        # We now exploit an implementation detail in PhoneNumberPrefixWidget to allow us to pass just
                        # a country code but no number as an initial value. It's a bit hacky, but should be stable for
                        # the future.
                        self.initial['phone'] = "+{}.".format(prefix)

                self.fields['phone'] = PhoneNumberField(
                    label=_("Phone number"),
                    required=event.settings.waiting_list_phones_required,
                    help_text=event.settings.
                    waiting_list_phones_explanation_text,
                    widget=WrappedPhoneNumberPrefixWidget())
        else:
            del self.fields['phone']