Add special input widgets for markdown fields (#1577)

* Add markdown text input widgets

* Update src/pretix/static/pretixcontrol/scss/_forms.scss

* Improvements

---------

Co-authored-by: Raphael Michel <michel@rami.io>
This commit is contained in:
Martin Gross
2024-04-23 14:40:30 +02:00
committed by GitHub
parent 64d6a34039
commit 5c833cd493
14 changed files with 155 additions and 77 deletions

View File

@@ -39,6 +39,7 @@ from django import forms
from django.core.validators import URLValidator
from django.forms.models import ModelFormMetaclass
from django.utils.crypto import get_random_string
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from formtools.wizard.views import SessionWizardView
from hierarkey.forms import HierarkeyForm
@@ -85,6 +86,43 @@ class I18nInlineFormSet(i18nfield.forms.I18nInlineFormSet):
super().__init__(*args, **kwargs)
class MarkdownTextarea(forms.Textarea):
def _render(self, template_name, context, renderer=None):
return mark_safe(
'<div class="i18n-form-group">%s<div class="i18n-field-markdown-note">%s</div></div>' % (
super()._render(template_name, context, renderer=None),
_("You can use {markup_name} in this field.").format(
markup_name='<a href="https://docs.pretix.eu/en/latest/user/markdown.html" target="_blank">Markdown</a>'
)
)
)
class I18nMarkdownTextarea(i18nfield.forms.I18nTextarea):
def format_output(self, rendered_widgets) -> str:
rendered_widgets = rendered_widgets + [
'<div class="i18n-field-markdown-note">%s</div>' % (
_("You can use {markup_name} in this field.").format(
markup_name='<a href="https://docs.pretix.eu/en/latest/user/markdown.html" target="_blank">Markdown</a>'
)
)
]
return super().format_output(rendered_widgets)
class I18nMarkdownTextInput(i18nfield.forms.I18nTextInput):
def format_output(self, rendered_widgets) -> str:
rendered_widgets = rendered_widgets + [
'<div class="i18n-field-markdown-note">%s</div>' % (
_("You can use {markup_name} in this field.").format(
markup_name='<a href="https://docs.pretix.eu/en/latest/user/markdown.html" target="_blank">Markdown</a>'
)
)
]
return super().format_output(rendered_widgets)
SECRET_REDACTED = '*****'

View File

@@ -1461,7 +1461,7 @@ class SubEvent(EventMixin, LoggedModel):
)
frontpage_text = I18nTextField(
null=True, blank=True,
verbose_name=_("Frontpage text")
verbose_name=_("Frontpage text"),
)
seating_plan = models.ForeignKey('SeatingPlan', on_delete=models.PROTECT, null=True, blank=True,
related_name='subevents', verbose_name=_('Seating plan'))

View File

@@ -57,7 +57,7 @@ from i18nfield.forms import I18nFormField, I18nTextarea, I18nTextInput
from i18nfield.strings import LazyI18nString
from pretix.base.channels import get_all_sales_channels
from pretix.base.forms import PlaceholderValidator
from pretix.base.forms import I18nMarkdownTextarea, PlaceholderValidator
from pretix.base.models import (
CartPosition, Event, GiftCard, InvoiceAddress, Order, OrderPayment,
OrderRefund, Quota, TaxRule,
@@ -1185,14 +1185,14 @@ class ManualPayment(BasePaymentProvider):
label=_('Payment process description during checkout'),
help_text=_('This text will be shown during checkout when the user selects this payment method. '
'It should give a short explanation on this payment method.'),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
)),
('email_instructions', I18nFormField(
label=_('Payment process description in order confirmation emails'),
help_text=_('This text will be included for the {payment_info} placeholder in order confirmation '
'mails. It should instruct the user on how to proceed with the payment. You can use '
'the placeholders {order}, {amount}, {currency} and {amount_with_currency}.'),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
validators=[PlaceholderValidator(['{order}', '{amount}', '{currency}', '{amount_with_currency}'])],
)),
('pending_description', I18nFormField(
@@ -1200,7 +1200,7 @@ class ManualPayment(BasePaymentProvider):
help_text=_('This text will be shown on the order confirmation page for pending orders. '
'It should instruct the user on how to proceed with the payment. You can use '
'the placeholders {order}, {amount}, {currency} and {amount_with_currency}.'),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
validators=[PlaceholderValidator(['{order}', '{amount}', '{currency}', '{amount_with_currency}'])],
)),
('invoice_immediately',
@@ -1325,7 +1325,7 @@ class GiftCardPayment(BasePaymentProvider):
(
"public_description",
I18nFormField(
label=_("Payment method description"), widget=I18nTextarea, required=False
label=_("Payment method description"), widget=I18nMarkdownTextarea, required=False
),
),
]

View File

@@ -64,7 +64,7 @@ from pretix.api.serializers.fields import (
ListMultipleChoiceField, UploadedFileField,
)
from pretix.api.serializers.i18n import I18nField, I18nURLField
from pretix.base.forms import I18nURLFormField
from pretix.base.forms import I18nMarkdownTextarea, I18nURLFormField
from pretix.base.models.tax import VAT_ID_COUNTRIES, TaxRule
from pretix.base.reldate import (
RelativeDateField, RelativeDateTimeField, RelativeDateWrapper,
@@ -602,7 +602,7 @@ DEFAULTS = {
'serializer_class': I18nField,
'form_kwargs': dict(
label=_("Invoice address explanation"),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
widget_kwargs={'attrs': {'rows': '2'}},
help_text=_("This text will be shown above the invoice address form during checkout.")
)
@@ -801,7 +801,7 @@ DEFAULTS = {
'serializer_class': I18nField,
'form_kwargs': dict(
label=_("End of presale text"),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
widget_kwargs={'attrs': {'rows': '2'}},
help_text=_("This text will be shown above the ticket shop once the designated sales timeframe for this event "
"is over. You can use it to describe other options to get a ticket, such as a box office.")
@@ -813,7 +813,7 @@ DEFAULTS = {
'form_class': I18nFormField,
'serializer_class': I18nField,
'form_kwargs': dict(
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
widget_kwargs={'attrs': {
'rows': 3,
}},
@@ -1459,7 +1459,7 @@ DEFAULTS = {
'serializer_class': I18nField,
'form_kwargs': dict(
label=_("Phone number explanation"),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
widget_kwargs={'attrs': {'rows': '2'}},
help_text=_("If you ask for a phone number, explain why you do so and what you will use the phone number for.")
)
@@ -1876,7 +1876,7 @@ DEFAULTS = {
'form_class': I18nFormField,
'form_kwargs': dict(
label=_("Voluntary lower refund explanation"),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
widget_kwargs={'attrs': {'rows': '2'}},
help_text=_("This text will be shown in between the explanation of how the refunds work and the slider "
"which your customers can use to choose the amount they would like to receive. You can use it "
@@ -1958,7 +1958,7 @@ DEFAULTS = {
'form_class': I18nFormField,
'form_kwargs': dict(
label=_("Terms of cancellation"),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
widget_kwargs={'attrs': {'rows': '2'}},
help_text=_("This text will be shown when cancellation is allowed for a paid order. Leave empty if you "
"want pretix to automatically generate the terms of cancellation based on your settings.")
@@ -1971,7 +1971,7 @@ DEFAULTS = {
'form_class': I18nFormField,
'form_kwargs': dict(
label=_("Terms of cancellation"),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
widget_kwargs={'attrs': {'rows': '2'}},
help_text=_("This text will be shown when cancellation is allowed for an unpaid or free order. Leave empty "
"if you want pretix to automatically generate the terms of cancellation based on your settings.")
@@ -2060,7 +2060,7 @@ DEFAULTS = {
'form_class': I18nFormField,
'form_kwargs': dict(
label=_("Event description"),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
help_text=_(
"You can use this to share information with your attendees, such as travel information or the link to a digital event. "
"If you keep it empty, we will put a link to the event shop, the admission time, and your organizer name in there. "
@@ -2991,7 +2991,7 @@ Your {organizer} team""")) # noqa: W291
'form_class': I18nFormField,
'form_kwargs': dict(
label=_("Frontpage text"),
widget=I18nTextarea
widget=I18nMarkdownTextarea,
)
},
'event_info_text': {
@@ -3013,7 +3013,7 @@ Your {organizer} team""")) # noqa: W291
'form_class': I18nFormField,
'form_kwargs': dict(
label=_("Banner text (top)"),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
widget_kwargs={'attrs': {'rows': '2'}},
help_text=_("This text will be shown above every page of your shop. Please only use this for "
"very important messages.")
@@ -3026,7 +3026,7 @@ Your {organizer} team""")) # noqa: W291
'form_class': I18nFormField,
'form_kwargs': dict(
label=_("Banner text (bottom)"),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
widget_kwargs={'attrs': {'rows': '2'}},
help_text=_("This text will be shown below every page of your shop. Please only use this for "
"very important messages.")
@@ -3039,7 +3039,7 @@ Your {organizer} team""")) # noqa: W291
'form_class': I18nFormField,
'form_kwargs': dict(
label=_("Voucher explanation"),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
widget_kwargs={'attrs': {'rows': '2'}},
help_text=_("This text will be shown next to the input for a voucher code. You can use it e.g. to explain "
"how to obtain a voucher code.")
@@ -3052,7 +3052,7 @@ Your {organizer} team""")) # noqa: W291
'form_class': I18nFormField,
'form_kwargs': dict(
label=_("Attendee data explanation"),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
widget_kwargs={'attrs': {'rows': '2'}},
help_text=_("This text will be shown above the questions asked for every personalized product. You can use it e.g. to explain "
"why you need information from them.")
@@ -3068,7 +3068,7 @@ Your {organizer} team""")) # noqa: W291
help_text=_("This message will be shown after an order has been created successfully. It will be shown in additional "
"to the default text."),
widget_kwargs={'attrs': {'rows': '2'}},
widget=I18nTextarea
widget=I18nMarkdownTextarea,
)
},
'checkout_phone_helptext': {
@@ -3079,7 +3079,7 @@ Your {organizer} team""")) # noqa: W291
'form_kwargs': dict(
label=_("Help text of the phone number field"),
widget_kwargs={'attrs': {'rows': '2'}},
widget=I18nTextarea
widget=I18nMarkdownTextarea,
)
},
'checkout_email_helptext': {
@@ -3093,7 +3093,7 @@ Your {organizer} team""")) # noqa: W291
'form_kwargs': dict(
label=_("Help text of the email field"),
widget_kwargs={'attrs': {'rows': '2'}},
widget=I18nTextarea
widget=I18nMarkdownTextarea,
)
},
'order_import_settings': {
@@ -3223,7 +3223,7 @@ Your {organizer} team""")) # noqa: W291
'form_class': I18nFormField,
'form_kwargs': dict(
label=_('Homepage text'),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
help_text=_('This will be displayed on the organizer homepage.')
)
},
@@ -3280,7 +3280,7 @@ Your {organizer} team""")) # noqa: W291
'form_class': I18nFormField,
'form_kwargs': dict(
label=_("Dialog text"),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
widget_kwargs={'attrs': {'rows': '3', 'data-display-dependency': '#id_settings-cookie_consent'}},
)
},
@@ -3295,7 +3295,7 @@ Your {organizer} team""")) # noqa: W291
'form_class': I18nFormField,
'form_kwargs': dict(
label=_("Secondary dialog text"),
widget=I18nTextarea,
widget=I18nMarkdownTextarea,
widget_kwargs={'attrs': {'rows': '3', 'data-display-dependency': '#id_settings-cookie_consent'}},
)
},