mirror of
https://github.com/pretix/pretix.git
synced 2026-08-16 11:46:27 +00:00
Display answers in confirm step, fix file upload/download
This commit is contained in:
@@ -157,16 +157,12 @@ class TimePickerWidget(forms.TimeInput):
|
||||
|
||||
class UploadedFileWidget(forms.ClearableFileInput):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.position = kwargs.pop('position')
|
||||
self.event = kwargs.pop('event')
|
||||
self.answer = kwargs.pop('answer')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
class FakeFile:
|
||||
def __init__(self, file, container, event, answer):
|
||||
def __init__(self, file, answer):
|
||||
self.file = file
|
||||
self.container = container
|
||||
self.event = event
|
||||
self.answer = answer
|
||||
|
||||
def __str__(self):
|
||||
@@ -174,25 +170,7 @@ class UploadedFileWidget(forms.ClearableFileInput):
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
from pretix.base.models import Order, OrderPosition
|
||||
from pretix.multidomain.urlreverse import eventreverse
|
||||
|
||||
order = None
|
||||
if isinstance(self.container, OrderPosition):
|
||||
order = self.container.order
|
||||
elif isinstance(self.container, Order):
|
||||
order = self.container
|
||||
|
||||
if order:
|
||||
return eventreverse(self.event, 'presale:event.order.download.answer', kwargs={
|
||||
'order': order.code,
|
||||
'secret': order.secret,
|
||||
'answer': self.answer.pk,
|
||||
})
|
||||
else:
|
||||
return eventreverse(self.event, 'presale:event.cart.download.answer', kwargs={
|
||||
'answer': self.answer.pk,
|
||||
})
|
||||
return self.answer.frontend_file_url
|
||||
|
||||
def get_context(self, name, value, attrs):
|
||||
# Browsers can't recognize that the server already has a file uploaded
|
||||
@@ -205,7 +183,7 @@ class UploadedFileWidget(forms.ClearableFileInput):
|
||||
|
||||
def format_value(self, value):
|
||||
if self.is_initial(value):
|
||||
return self.FakeFile(value, self.position, self.event, self.answer)
|
||||
return self.FakeFile(value, self.answer)
|
||||
|
||||
|
||||
class SplitDateTimePickerWidget(forms.SplitDateTimeWidget):
|
||||
|
||||
@@ -1608,7 +1608,7 @@ class Question(LoggedModel):
|
||||
"""
|
||||
class ContainerType(models.TextChoices):
|
||||
ORDER = "O", _("Order")
|
||||
ORDERPOSITION = "P", _("Order position")
|
||||
ORDERPOSITION = "P", _("Order position")
|
||||
TYPE_NUMBER = "N"
|
||||
TYPE_STRING = "S"
|
||||
TYPE_TEXT = "T"
|
||||
|
||||
@@ -1304,10 +1304,9 @@ class Order(LockModel, LoggedModel):
|
||||
|
||||
def answerfile_name(instance, filename: str) -> str:
|
||||
secret = get_random_string(length=32, allowed_chars=string.ascii_letters + string.digits)
|
||||
event = (instance.cartposition if instance.cartposition else instance.orderposition.order).event
|
||||
return 'cachedfiles/answers/{org}/{ev}/{secret}.{filename}'.format(
|
||||
org=event.organizer.slug,
|
||||
ev=event.slug,
|
||||
org=instance.event.organizer.slug,
|
||||
ev=instance.event.slug,
|
||||
secret=secret,
|
||||
filename=escape_uri_path(filename),
|
||||
)
|
||||
@@ -1369,11 +1368,11 @@ class QuestionAnswer(models.Model):
|
||||
@property
|
||||
def backend_file_url(self):
|
||||
if self.file:
|
||||
if self.orderposition:
|
||||
if self.associated_order:
|
||||
return reverse('control:event.order.download.answer', kwargs={
|
||||
'code': self.orderposition.order.code,
|
||||
'event': self.orderposition.order.event.slug,
|
||||
'organizer': self.orderposition.order.event.organizer.slug,
|
||||
'code': self.associated_order.code,
|
||||
'event': self.associated_order.event.slug,
|
||||
'organizer': self.associated_order.event.organizer.slug,
|
||||
'answer': self.pk,
|
||||
})
|
||||
return ""
|
||||
@@ -1383,14 +1382,14 @@ class QuestionAnswer(models.Model):
|
||||
from pretix.multidomain.urlreverse import eventreverse
|
||||
|
||||
if self.file:
|
||||
if self.orderposition:
|
||||
url = eventreverse(self.orderposition.order.event, 'presale:event.order.download.answer', kwargs={
|
||||
'order': self.orderposition.order.code,
|
||||
'secret': self.orderposition.order.secret,
|
||||
if self.associated_order:
|
||||
url = eventreverse(self.associated_order.event, 'presale:event.order.download.answer', kwargs={
|
||||
'order': self.associated_order.code,
|
||||
'secret': self.associated_order.secret,
|
||||
'answer': self.pk,
|
||||
})
|
||||
else:
|
||||
url = eventreverse(self.cartposition.event, 'presale:event.cart.download.answer', kwargs={
|
||||
url = eventreverse(self.event, 'presale:event.cart.download.answer', kwargs={
|
||||
'answer': self.pk,
|
||||
})
|
||||
|
||||
@@ -1405,6 +1404,24 @@ class QuestionAnswer(models.Model):
|
||||
def file_name(self):
|
||||
return self.file.name.split('.', 1)[-1]
|
||||
|
||||
@property
|
||||
def associated_order(self):
|
||||
if self.orderposition:
|
||||
return self.orderposition.order
|
||||
elif self.order:
|
||||
return self.order
|
||||
|
||||
@property
|
||||
def event(self):
|
||||
if self.orderposition:
|
||||
return self.orderposition.order.event
|
||||
elif self.cartposition:
|
||||
return self.cartposition.event
|
||||
elif self.order:
|
||||
return self.order.event
|
||||
elif self.checkoutsession:
|
||||
return self.checkoutsession.event
|
||||
|
||||
def __str__(self):
|
||||
return self.to_string(use_cached=True)
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{% load safelink %}
|
||||
{% load i18n %}
|
||||
{% load rich_text %}
|
||||
{% if answer %}
|
||||
{% if answer.file %}
|
||||
<span class="fa fa-file"></span>
|
||||
<a href="{{ answer.backend_file_url }}?token={% answer_token request answer %}">
|
||||
{{ answer.file_name }}
|
||||
</a>
|
||||
<span class="label label-danger" data-toggle="tooltip"
|
||||
title="{% trans "This file has been uploaded by a user and could contain viruses or other malicious content." %}">
|
||||
{% trans "UNSAFE" %}
|
||||
</span>
|
||||
{% if answer.is_image %}
|
||||
<br>
|
||||
<a href="{{ answer.backend_file_url }}?token={% answer_token request answer %}" data-lightbox="order"
|
||||
class="answer-thumb">
|
||||
<img src="{{ answer.backend_file_url }}?token={% answer_token request answer %}">
|
||||
</a>
|
||||
{% endif %}
|
||||
{% elif question.type == "M" %}
|
||||
{{ answer.to_string_i18n|rich_text_snippet }}
|
||||
{% else %}
|
||||
{{ answer.to_string_i18n|linebreaksbr }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<em>{% trans "not answered" %}</em>
|
||||
{% endif %}
|
||||
@@ -433,7 +433,7 @@
|
||||
{% endif %}
|
||||
{% for ans in order.answers.all %}
|
||||
<dt>{{ ans.question.internal_name|default:ans.question.question }}</dt>
|
||||
<dd>{{ ans.answer }}</dd>
|
||||
<dd>{% include "pretixcontrol/order/fragment_question_answer.html" with request=request question=ans.question answer=ans %}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
</div>
|
||||
@@ -672,31 +672,7 @@
|
||||
{% endif %}
|
||||
</dt>
|
||||
<dd>
|
||||
{% if q.answer %}
|
||||
{% if q.answer.file %}
|
||||
<span class="fa fa-file"></span>
|
||||
<a href="{{ q.answer.backend_file_url }}?token={% answer_token request q.answer %}">
|
||||
{{ q.answer.file_name }}
|
||||
</a>
|
||||
<span class="label label-danger" data-toggle="tooltip"
|
||||
title="{% trans "This file has been uploaded by a user and could contain viruses or other malicious content." %}">
|
||||
{% trans "UNSAFE" %}
|
||||
</span>
|
||||
{% if q.answer.is_image %}
|
||||
<br>
|
||||
<a href="{{ q.answer.backend_file_url }}?token={% answer_token request q.answer %}" data-lightbox="order"
|
||||
class="answer-thumb">
|
||||
<img src="{{ q.answer.backend_file_url }}?token={% answer_token request q.answer %}">
|
||||
</a>
|
||||
{% endif %}
|
||||
{% elif q.type == "M" %}
|
||||
{{ q.answer.to_string_i18n|rich_text_snippet }}
|
||||
{% else %}
|
||||
{{ q.answer.to_string_i18n|linebreaksbr }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<em>{% trans "not answered" %}</em>
|
||||
{% endif %}
|
||||
{% include "pretixcontrol/order/fragment_question_answer.html" with request=request question=q answer=q.answer %}
|
||||
</dd>
|
||||
{% endfor %}
|
||||
{% for q in line.additional_fields %}
|
||||
|
||||
@@ -2591,7 +2591,11 @@ class AnswerDownload(EventPermissionRequiredMixin, OrderViewMixin, ListView):
|
||||
answid = kwargs.get('answer')
|
||||
token = request.GET.get('token', '')
|
||||
|
||||
answer = get_object_or_404(QuestionAnswer, orderposition__order=self.order, id=answid)
|
||||
answer = get_object_or_404(
|
||||
QuestionAnswer,
|
||||
Q(orderposition__order=self.order) | Q(order=self.order),
|
||||
id=answid
|
||||
)
|
||||
if not answer.file:
|
||||
raise Http404()
|
||||
if not check_token(request, answer, token):
|
||||
@@ -2601,7 +2605,7 @@ class AnswerDownload(EventPermissionRequiredMixin, OrderViewMixin, ListView):
|
||||
resp = FileResponse(answer.file, content_type=ftype or 'application/binary')
|
||||
resp['Content-Disposition'] = 'attachment; filename="{}-{}-{}-{}"'.format(
|
||||
self.request.event.slug.upper(), self.order.code,
|
||||
answer.orderposition.positionid,
|
||||
answer.orderposition.positionid if answer.orderposition else '',
|
||||
os.path.basename(answer.file.name).split('.', 1)[1]
|
||||
)
|
||||
return resp
|
||||
|
||||
@@ -1564,6 +1564,7 @@ class ConfirmStep(CartMixin, AsyncAction, TemplateFlowStep):
|
||||
ctx['addr'] = self.invoice_address
|
||||
ctx['confirm_messages'] = self.confirm_messages
|
||||
ctx['cart_session'] = self.cart_session
|
||||
ctx['checkout_session'] = self.checkout_session
|
||||
ctx['invoice_address_asked'] = self.address_asked
|
||||
ctx['customer'] = self.cart_customer
|
||||
|
||||
|
||||
@@ -162,6 +162,26 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% if checkout_session.answers.all %}
|
||||
<div class="panel panel-default panel-contact">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
{% trans "Additional order information" %}
|
||||
<a href="{% eventurl request.event "presale:event.checkout" step="questions" cart_namespace=cart_namespace|default_if_none:"" %}" aria-label="{% trans "Modify contact information" %}" class="h6">
|
||||
<span class="fa fa-edit" aria-hidden="true"></span>{% trans "Modify" %}
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<dl class="dl-horizontal">
|
||||
{% for ans in checkout_session.answers.all %}
|
||||
<dt>{{ ans.question.question }}</dt>
|
||||
<dd>{% include "pretixpresale/event/fragment_question_answer.html" with request=request question=ans.question answer=ans %}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if confirm_messages %}
|
||||
|
||||
@@ -206,27 +206,7 @@
|
||||
{% for q in line.questions %}
|
||||
<dt>{{ q.question }}</dt>
|
||||
<dd>
|
||||
{% if q.answer %}
|
||||
{% if q.answer.file %}
|
||||
<span class="fa fa-file" aria-hidden="true"></span>
|
||||
<a href="{{ q.answer.frontend_file_url }}?token={% answer_token request q.answer %}">
|
||||
{{ q.answer.file_name }}
|
||||
</a>
|
||||
{% if q.answer.is_image %}
|
||||
<br>
|
||||
<a href="{{ q.answer.frontend_file_url }}?token={% answer_token request q.answer %}" data-lightbox="order"
|
||||
class="answer-thumb">
|
||||
<img src="{{ q.answer.frontend_file_url }}?token={% answer_token request q.answer %}" alt="{% trans "The image you previously uploaded" %}">
|
||||
</a>
|
||||
{% endif %}
|
||||
{% elif q.type == "M" %}
|
||||
{{ q.answer|rich_text_snippet }}
|
||||
{% else %}
|
||||
{{ q.answer|linebreaksbr }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<em class="text-muted">{% trans "not answered" %}</em>
|
||||
{% endif %}
|
||||
{% include "pretixpresale/event/fragment_question_answer.html" with request=request question=q answer=q.answer %}
|
||||
</dd>
|
||||
{% endfor %}
|
||||
{% for q in line.additional_answers %}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
{% load safelink %}
|
||||
{% load i18n %}
|
||||
{% load rich_text %}
|
||||
{% if answer %}
|
||||
{% if answer.file %}
|
||||
<span class="fa fa-file" aria-hidden="true"></span>
|
||||
<a href="{{ answer.frontend_file_url }}?token={% answer_token request answer %}">
|
||||
{{ answer.file_name }}
|
||||
</a>
|
||||
{% if answer.is_image %}
|
||||
<br>
|
||||
<a href="{{ answer.frontend_file_url }}?token={% answer_token request answer %}" data-lightbox="order"
|
||||
class="answer-thumb">
|
||||
<img src="{{ answer.frontend_file_url }}?token={% answer_token request answer %}" alt="{% trans "The image you previously uploaded" %}">
|
||||
</a>
|
||||
{% endif %}
|
||||
{% elif question.type == "M" %}
|
||||
{{ answer|rich_text_snippet }}
|
||||
{% else %}
|
||||
{{ answer|linebreaksbr }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<em class="text-muted">{% trans "not answered" %}</em>
|
||||
{% endif %}
|
||||
@@ -388,6 +388,7 @@ def get_or_create_cart_id(request, create=True):
|
||||
if 'carts' in request.session:
|
||||
request.session['carts'][current_id] = {}
|
||||
else:
|
||||
# We found a valid, existing cart.
|
||||
return current_id
|
||||
|
||||
cart_data = {}
|
||||
@@ -398,6 +399,7 @@ def get_or_create_cart_id(request, create=True):
|
||||
cart_data['widget_data'] = cached_widget_data
|
||||
else:
|
||||
if not create:
|
||||
# There is no existing cart for this request and we're not supposed to create a new one.
|
||||
return None
|
||||
new_id = generate_cart_id(request, prefix=prefix)
|
||||
|
||||
@@ -846,9 +848,10 @@ class RedeemView(NoSearchIndexViewMixin, EventViewMixin, CartMixin, TemplateView
|
||||
class AnswerDownload(EventViewMixin, View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
answid = kwargs.get('answer')
|
||||
cart_id = get_or_create_cart_id(self.request)
|
||||
answer = get_object_or_404(
|
||||
QuestionAnswer,
|
||||
cartposition__cart_id=get_or_create_cart_id(self.request),
|
||||
Q(cartposition__cart_id=cart_id) | Q(checkoutsession__cart_id=cart_id),
|
||||
id=answid
|
||||
)
|
||||
if not answer.file:
|
||||
|
||||
Reference in New Issue
Block a user