mirror of
https://github.com/pretix/pretix.git
synced 2026-04-26 23:52:35 +00:00
Question list: Drop pagination, allow to mix ordering with system fields
This commit is contained in:
@@ -244,8 +244,10 @@ class BaseQuestionsForm(forms.Form):
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
add_fields = {}
|
||||
|
||||
if item.admission and event.settings.attendee_names_asked:
|
||||
self.fields['attendee_name_parts'] = NamePartsFormField(
|
||||
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,
|
||||
@@ -254,7 +256,7 @@ class BaseQuestionsForm(forms.Form):
|
||||
initial=(cartpos.attendee_name_parts if cartpos else orderpos.attendee_name_parts),
|
||||
)
|
||||
if item.admission and event.settings.attendee_emails_asked:
|
||||
self.fields['attendee_email'] = forms.EmailField(
|
||||
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),
|
||||
@@ -265,14 +267,14 @@ class BaseQuestionsForm(forms.Form):
|
||||
)
|
||||
)
|
||||
if item.admission and event.settings.attendee_company_asked:
|
||||
self.fields['company'] = forms.CharField(
|
||||
add_fields['company'] = forms.CharField(
|
||||
required=event.settings.attendee_company_required and not self.all_optional,
|
||||
label=_('Company'),
|
||||
initial=(cartpos.company if cartpos else orderpos.company),
|
||||
)
|
||||
|
||||
if item.admission and event.settings.attendee_addresses_asked:
|
||||
self.fields['street'] = forms.CharField(
|
||||
add_fields['street'] = forms.CharField(
|
||||
required=event.settings.attendee_addresses_required and not self.all_optional,
|
||||
label=_('Address'),
|
||||
widget=forms.Textarea(attrs={
|
||||
@@ -282,7 +284,7 @@ class BaseQuestionsForm(forms.Form):
|
||||
}),
|
||||
initial=(cartpos.street if cartpos else orderpos.street),
|
||||
)
|
||||
self.fields['zipcode'] = forms.CharField(
|
||||
add_fields['zipcode'] = forms.CharField(
|
||||
required=event.settings.attendee_addresses_required and not self.all_optional,
|
||||
label=_('ZIP code'),
|
||||
initial=(cartpos.zipcode if cartpos else orderpos.zipcode),
|
||||
@@ -290,7 +292,7 @@ class BaseQuestionsForm(forms.Form):
|
||||
'autocomplete': 'postal-code',
|
||||
}),
|
||||
)
|
||||
self.fields['city'] = forms.CharField(
|
||||
add_fields['city'] = forms.CharField(
|
||||
required=event.settings.attendee_addresses_required and not self.all_optional,
|
||||
label=_('City'),
|
||||
initial=(cartpos.city if cartpos else orderpos.city),
|
||||
@@ -299,7 +301,7 @@ class BaseQuestionsForm(forms.Form):
|
||||
}),
|
||||
)
|
||||
country = (cartpos.country if cartpos else orderpos.country) or guess_country(event)
|
||||
self.fields['country'] = CountryField(
|
||||
add_fields['country'] = CountryField(
|
||||
countries=CachedCountries
|
||||
).formfield(
|
||||
required=event.settings.attendee_addresses_required and not self.all_optional,
|
||||
@@ -324,7 +326,7 @@ class BaseQuestionsForm(forms.Form):
|
||||
self.data = self.data.copy()
|
||||
del self.data[fprefix + 'state']
|
||||
|
||||
self.fields['state'] = forms.ChoiceField(
|
||||
add_fields['state'] = forms.ChoiceField(
|
||||
label=pgettext_lazy('address', 'State'),
|
||||
required=False,
|
||||
choices=c,
|
||||
@@ -332,7 +334,14 @@ class BaseQuestionsForm(forms.Form):
|
||||
'autocomplete': 'address-level1',
|
||||
}),
|
||||
)
|
||||
self.fields['state'].widget.is_required = True
|
||||
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
|
||||
@@ -485,7 +494,12 @@ class BaseQuestionsForm(forms.Form):
|
||||
field._required = q.required and not self.all_optional
|
||||
field.required = False
|
||||
|
||||
self.fields['question_%s' % q.id] = field
|
||||
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
|
||||
|
||||
@@ -56,6 +56,10 @@ DEFAULTS = {
|
||||
|
||||
)
|
||||
},
|
||||
'system_question_order': {
|
||||
'default': {},
|
||||
'type': dict,
|
||||
},
|
||||
'attendee_names_asked': {
|
||||
'default': 'True',
|
||||
'type': bool,
|
||||
|
||||
@@ -10,81 +10,89 @@
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
{% csrf_token %}
|
||||
{% if questions|length == 0 %}
|
||||
<div class="empty-collection">
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
You haven't created any questions yet.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
<a href="{% url "control:event.items.questions.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new question" %}</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<p>
|
||||
<a href="{% url "control:event.items.questions.add" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new question" %}
|
||||
</a>
|
||||
</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-quotas">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Question" %}</th>
|
||||
<th>{% trans "Type" %}</th>
|
||||
<th class="iconcol"></th>
|
||||
<th class="iconcol"></th>
|
||||
<th class="iconcol"></th>
|
||||
<th>{% trans "Products" %}</th>
|
||||
<th class="action-col-2"></th>
|
||||
<th class="action-col-2"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-dnd-url="{% url "control:event.items.questions.reorder" organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% for q in questions %}
|
||||
<tr data-dnd-id="{{q.id}}">
|
||||
<td><strong><a href="
|
||||
{% url "control:event.items.questions.show" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}">{{ q.question }}</a></strong>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<a href="{% url "control:event.items.questions.add" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new question" %}
|
||||
</a>
|
||||
</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-quotas">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Question" %}</th>
|
||||
<th>{% trans "Type" %}</th>
|
||||
<th class="iconcol"></th>
|
||||
<th class="iconcol"></th>
|
||||
<th class="iconcol"></th>
|
||||
<th>{% trans "Products" %}</th>
|
||||
<th class="action-col-2"></th>
|
||||
<th class="action-col-2"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-dnd-url="{% url "control:event.items.questions.reorder" organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% for q in questions %}
|
||||
<tr data-dnd-id="{{ q.id }}">
|
||||
<td>
|
||||
<strong>
|
||||
{% if q.pk %}
|
||||
<a href="{% url "control:event.items.questions.show" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}">
|
||||
{% endif %}
|
||||
{{ q.question }}
|
||||
{% if q.pk %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</strong>
|
||||
</td>
|
||||
<td>
|
||||
{% if q.pk %}
|
||||
{{ q.get_type_display }}
|
||||
</td>
|
||||
<td>
|
||||
{% if q.required %}
|
||||
<span class="fa fa-exclamation-circle text-muted" data-toggle="tooltip" title="{% trans "Required question" %}"></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if q.ask_during_checkin %}
|
||||
<span class="fa fa-check-square text-muted" data-toggle="tooltip" title="{% trans "Ask during check-in" %}"></span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% trans "System question" %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if q.required %}
|
||||
<span class="fa fa-exclamation-circle text-muted" data-toggle="tooltip" title="{% trans "Required question" %}"></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if q.pk and q.ask_during_checkin %}
|
||||
<span class="fa fa-check-square text-muted" data-toggle="tooltip" title="{% trans "Ask during check-in" %}"></span>
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
<td>
|
||||
{% if q.hidden %}
|
||||
<span class="fa fa-eye-slash text-muted" data-toggle="tooltip" title="{% trans "Hidden question" %}"></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
{% if q.pk and q.hidden %}
|
||||
<span class="fa fa-eye-slash text-muted" data-toggle="tooltip" title="{% trans "Hidden question" %}"></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if q.pk %}
|
||||
<ul>
|
||||
{% for item in q.items.all %}
|
||||
<li><a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=item.id %}">{{ item }}</a></li>
|
||||
<li>
|
||||
<a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=item.id %}">{{ item }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<a href="{% url "control:event.items.questions.up" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}" class="btn btn-default btn-sm {% if forloop.counter0 == 0 and is_paginated and not page_obj.has_previous %}disabled{% endif %}"><i class="fa fa-arrow-up"></i></a>
|
||||
<a href="{% url "control:event.items.questions.down" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}" class="btn btn-default btn-sm {% if forloop.revcounter0 == 0 and is_paginated and not page_obj.has_next %}disabled{% endif %}"><i class="fa fa-arrow-down"></i></a>
|
||||
</td>
|
||||
<td class="text-right flip">
|
||||
{% else %}
|
||||
<small>{% trans "All admission products" %}</small>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="dnd-container">
|
||||
</td>
|
||||
<td class="text-right flip">
|
||||
{% if q.pk %}
|
||||
<a href="{% url "control:event.items.questions.show" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}" class="btn btn-default btn-sm"><i class="fa fa-bar-chart"></i></a>
|
||||
<a href="{% url "control:event.items.questions.edit" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||
<a href="{% url "control:event.items.questions.delete" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% include "pretixcontrol/pagination.html" %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<a href="{% url "control:event.settings" organizer=request.event.organizer.slug event=request.event.slug %}#tab-0-2-open"
|
||||
class="btn btn-default btn-sm"><i class="fa fa-wrench"></i></a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -180,9 +180,6 @@ urlpatterns = [
|
||||
url(r'^questions/reorder$', item.reorder_questions, name='event.items.questions.reorder'),
|
||||
url(r'^questions/(?P<question>\d+)/delete$', item.QuestionDelete.as_view(),
|
||||
name='event.items.questions.delete'),
|
||||
url(r'^questions/(?P<question>\d+)/up$', item.question_move_up, name='event.items.questions.up'),
|
||||
url(r'^questions/(?P<question>\d+)/down$', item.question_move_down,
|
||||
name='event.items.questions.down'),
|
||||
url(r'^questions/(?P<question>\d+)/$', item.QuestionView.as_view(),
|
||||
name='event.items.questions.show'),
|
||||
url(r'^questions/(?P<question>\d+)/change$', item.QuestionUpdate.as_view(),
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
from collections import OrderedDict, namedtuple
|
||||
from json.decoder import JSONDecodeError
|
||||
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.files import File
|
||||
from django.db import transaction
|
||||
from django.db.models import Count, Exists, F, Max, OuterRef, Prefetch, Q
|
||||
from django.db.models import Count, Exists, F, OuterRef, Prefetch, Q
|
||||
from django.forms.models import inlineformset_factory
|
||||
from django.http import (
|
||||
Http404, HttpResponse, HttpResponseBadRequest, HttpResponseRedirect,
|
||||
@@ -279,7 +279,12 @@ def category_move_down(request, organizer, event, category):
|
||||
event=request.event.slug)
|
||||
|
||||
|
||||
class QuestionList(PaginationMixin, ListView):
|
||||
FakeQuestion = namedtuple(
|
||||
'FakeQuestion', 'id question position required'
|
||||
)
|
||||
|
||||
|
||||
class QuestionList(ListView):
|
||||
model = Question
|
||||
context_object_name = 'questions'
|
||||
template_name = 'pretixcontrol/items/questions.html'
|
||||
@@ -287,98 +292,125 @@ class QuestionList(PaginationMixin, ListView):
|
||||
def get_queryset(self):
|
||||
return self.request.event.questions.prefetch_related('items')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['questions'] = list(ctx['questions'])
|
||||
|
||||
if self.request.event.settings.attendee_names_asked:
|
||||
ctx['questions'].append(
|
||||
FakeQuestion(
|
||||
id='attendee_name_parts',
|
||||
question=_('Attendee name'),
|
||||
position=self.request.event.settings.system_question_order.get(
|
||||
'attendee_name_parts', 0
|
||||
),
|
||||
required=self.request.event.settings.attendee_names_required,
|
||||
)
|
||||
)
|
||||
|
||||
if self.request.event.settings.attendee_emails_asked:
|
||||
ctx['questions'].append(
|
||||
FakeQuestion(
|
||||
id='attendee_email',
|
||||
question=_('Attendee email'),
|
||||
position=self.request.event.settings.system_question_order.get(
|
||||
'attendee_email', 0
|
||||
),
|
||||
required=self.request.event.settings.attendee_emails_required,
|
||||
)
|
||||
)
|
||||
|
||||
if self.request.event.settings.attendee_emails_asked:
|
||||
ctx['questions'].append(
|
||||
FakeQuestion(
|
||||
id='company',
|
||||
question=_('Company'),
|
||||
position=self.request.event.settings.system_question_order.get(
|
||||
'company', 0
|
||||
),
|
||||
required=self.request.event.settings.attendee_company_required,
|
||||
)
|
||||
)
|
||||
|
||||
if self.request.event.settings.attendee_addresses_asked:
|
||||
ctx['questions'].append(
|
||||
FakeQuestion(
|
||||
id='street',
|
||||
question=_('Street'),
|
||||
position=self.request.event.settings.system_question_order.get(
|
||||
'street', 0
|
||||
),
|
||||
required=self.request.event.settings.attendee_addresses_required,
|
||||
)
|
||||
)
|
||||
ctx['questions'].append(
|
||||
FakeQuestion(
|
||||
id='zipcode',
|
||||
question=_('ZIP code'),
|
||||
position=self.request.event.settings.system_question_order.get(
|
||||
'zipcode', 0
|
||||
),
|
||||
required=self.request.event.settings.attendee_addresses_required,
|
||||
)
|
||||
)
|
||||
ctx['questions'].append(
|
||||
FakeQuestion(
|
||||
id='city',
|
||||
question=_('City'),
|
||||
position=self.request.event.settings.system_question_order.get(
|
||||
'city', 0
|
||||
),
|
||||
required=self.request.event.settings.attendee_addresses_required,
|
||||
)
|
||||
)
|
||||
ctx['questions'].append(
|
||||
FakeQuestion(
|
||||
id='country',
|
||||
question=_('Country'),
|
||||
position=self.request.event.settings.system_question_order.get(
|
||||
'country', 0
|
||||
),
|
||||
required=self.request.event.settings.attendee_addresses_required,
|
||||
)
|
||||
)
|
||||
|
||||
ctx['questions'].sort(key=lambda q: q.position)
|
||||
return ctx
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
@event_permission_required("can_change_items")
|
||||
def reorder_questions(request, organizer, event):
|
||||
try:
|
||||
ids = [int(id) for id in json.loads(request.body.decode('utf-8'))['ids']]
|
||||
ids = json.loads(request.body.decode('utf-8'))['ids']
|
||||
except (JSONDecodeError, KeyError, ValueError):
|
||||
return HttpResponseBadRequest("expected JSON: {ids:[]}")
|
||||
|
||||
input_questions = request.event.questions.filter(id__in=ids)
|
||||
input_questions = request.event.questions.filter(id__in=[i for i in ids if i.isdigit()])
|
||||
|
||||
if input_questions.count() != len(ids):
|
||||
if input_questions.count() != len([i for i in ids if i.isdigit()]):
|
||||
raise Http404(_("Some of the provided question ids are invalid."))
|
||||
|
||||
first = input_questions.first()
|
||||
last = input_questions.last()
|
||||
original_lowest_score = (first.position, first.id)
|
||||
original_highest_score = (last.position, last.id)
|
||||
if input_questions.count() != request.event.questions.count():
|
||||
raise Http404(_("Not all questions have been selected."))
|
||||
|
||||
if request.event.questions.filter(
|
||||
Q(Q(position__gt=original_lowest_score[0])
|
||||
| Q(Q(position=original_lowest_score[0]) & Q(pk__gt=original_lowest_score[1])))
|
||||
&
|
||||
Q(Q(position__lt=original_highest_score[0])
|
||||
| Q(Q(position=original_highest_score[0]) & Q(pk__lt=original_highest_score[1])))
|
||||
).exclude(id__in=ids).exists():
|
||||
return HttpResponseBadRequest("ids need to be from a consecutive range of questions")
|
||||
|
||||
highest_position_on_previous_page = request.event.questions.filter(
|
||||
Q(position__lt=original_lowest_score[0])
|
||||
| Q(Q(position=original_lowest_score[0]) & Q(pk__lt=original_lowest_score[1]))
|
||||
).aggregate(m=Max('position'))['m'] or 0
|
||||
|
||||
questions_on_later_pages = request.event.questions.filter(
|
||||
Q(position__gt=original_highest_score[0])
|
||||
| Q(Q(position=original_highest_score[0]) & Q(pk__gt=original_highest_score[1]))
|
||||
)
|
||||
|
||||
ordered_questions = sorted(input_questions, key=lambda k: ids.index(k.pk))
|
||||
|
||||
for i, q in enumerate(ordered_questions + list(questions_on_later_pages)):
|
||||
pos = highest_position_on_previous_page + 1 + i
|
||||
for q in input_questions:
|
||||
pos = ids.index(str(q.pk))
|
||||
if pos != q.position: # Save unneccessary UPDATE queries
|
||||
q.position = pos
|
||||
q.save(update_fields=['position'])
|
||||
|
||||
system_question_order = {}
|
||||
for s in ('attendee_name_parts', 'attendee_email', 'company', 'street', 'zipcode', 'city', 'country'):
|
||||
if s in ids:
|
||||
system_question_order[s] = ids.index(s)
|
||||
else:
|
||||
system_question_order[s] = -1
|
||||
request.event.settings.system_question_order = system_question_order
|
||||
|
||||
return HttpResponse()
|
||||
|
||||
|
||||
def question_move(request, question, up=True):
|
||||
"""
|
||||
This is a helper function to avoid duplicating code in question_move_up and
|
||||
question_move_down. It takes a question and a direction and then tries to bring
|
||||
all items for this question in a new order.
|
||||
"""
|
||||
try:
|
||||
question = request.event.questions.get(
|
||||
id=question
|
||||
)
|
||||
except Question.DoesNotExist:
|
||||
raise Http404(_("The selected question does not exist."))
|
||||
questions = list(request.event.questions.order_by("position"))
|
||||
|
||||
index = questions.index(question)
|
||||
if index != 0 and up:
|
||||
questions[index - 1], questions[index] = questions[index], questions[index - 1]
|
||||
elif index != len(questions) - 1 and not up:
|
||||
questions[index + 1], questions[index] = questions[index], questions[index + 1]
|
||||
|
||||
for i, qt in enumerate(questions):
|
||||
if qt.position != i:
|
||||
qt.position = i
|
||||
qt.save()
|
||||
messages.success(request, _('The order of questions has been updated.'))
|
||||
|
||||
|
||||
@event_permission_required("can_change_items")
|
||||
def question_move_up(request, organizer, event, question):
|
||||
question_move(request, question, up=True)
|
||||
return redirect('control:event.items.questions',
|
||||
organizer=request.event.organizer.slug,
|
||||
event=request.event.slug)
|
||||
|
||||
|
||||
@event_permission_required("can_change_items")
|
||||
def question_move_down(request, organizer, event, question):
|
||||
question_move(request, question, up=False)
|
||||
return redirect('control:event.items.questions',
|
||||
organizer=request.event.organizer.slug,
|
||||
event=request.event.slug)
|
||||
|
||||
|
||||
class QuestionDelete(EventPermissionRequiredMixin, DeleteView):
|
||||
model = Question
|
||||
template_name = 'pretixcontrol/items/question_delete.html'
|
||||
|
||||
@@ -3,21 +3,10 @@ $(function () {
|
||||
$("[data-dnd-url]").each(function(){
|
||||
var container = $(this),
|
||||
url = container.data("dnd-url"),
|
||||
up = container.find("a:has(.fa-arrow-up)"),
|
||||
handle = $('<span class="btn btn-default btn-sm dnd-sort-handle"><i class="fa fa-arrows"></i></span>');
|
||||
|
||||
function hideArrows(container){
|
||||
var up = container.find("a:has(.fa-arrow-up)"),
|
||||
firstUp = up.first(),
|
||||
down = container.find("a:has(.fa-arrow-down)"),
|
||||
lastDown = down.last();
|
||||
up.not(firstUp).css("display","none");
|
||||
down.not(lastDown).css("display","none");
|
||||
firstUp.css("display","inline-block");
|
||||
lastDown.css("display","inline-block");
|
||||
}
|
||||
up.after(handle);
|
||||
hideArrows(container);
|
||||
console.log(container, container.find(".dnd-container"));
|
||||
container.find(".dnd-container").append(handle);
|
||||
|
||||
Sortable.create(container.get(0), {
|
||||
handle: ".dnd-sort-handle",
|
||||
@@ -25,8 +14,6 @@ $(function () {
|
||||
var container = $(evt.to),
|
||||
ids = container.find("[data-dnd-id]").toArray().map(function (e) { return e.dataset.dndId; });
|
||||
|
||||
hideArrows(container);
|
||||
|
||||
$.ajax(
|
||||
{
|
||||
'type': 'POST',
|
||||
|
||||
@@ -171,35 +171,6 @@ class QuestionsTest(ItemFormTest):
|
||||
self.assertTrue(c.required)
|
||||
assert str(Question.objects.get(id=c.id).question) == 'How old are you?'
|
||||
|
||||
def test_sort(self):
|
||||
with scopes_disabled():
|
||||
q1 = Question.objects.create(event=self.event1, question="Vegetarian?", type="N", required=True, position=0)
|
||||
q2 = Question.objects.create(event=self.event1, question="Food allergies?", position=1)
|
||||
doc = self.get_doc('/control/event/%s/%s/questions/' % (self.orga1.slug, self.event1.slug))
|
||||
self.assertIn("Vegetarian?", doc.select("table > tbody > tr")[0].text)
|
||||
self.assertIn("Food allergies?", doc.select("table > tbody > tr")[1].text)
|
||||
|
||||
self.client.get('/control/event/%s/%s/questions/%s/down' % (self.orga1.slug, self.event1.slug, q1.id))
|
||||
doc = self.get_doc('/control/event/%s/%s/questions/' % (self.orga1.slug, self.event1.slug))
|
||||
self.assertIn("Vegetarian?", doc.select("table > tbody > tr")[1].text)
|
||||
self.assertIn("Food allergies?", doc.select("table > tbody > tr")[0].text)
|
||||
|
||||
self.client.get('/control/event/%s/%s/questions/%s/up' % (self.orga1.slug, self.event1.slug, q1.id))
|
||||
doc = self.get_doc('/control/event/%s/%s/questions/' % (self.orga1.slug, self.event1.slug))
|
||||
self.assertIn("Vegetarian?", doc.select("table > tbody > tr")[0].text)
|
||||
self.assertIn("Food allergies?", doc.select("table > tbody > tr")[1].text)
|
||||
|
||||
self.client.post(
|
||||
'/control/event/%s/%s/questions/reorder' % (self.orga1.slug, self.event1.slug),
|
||||
{
|
||||
"ids": [q2.id, q1.id]
|
||||
},
|
||||
content_type='application/json'
|
||||
)
|
||||
doc = self.get_doc('/control/event/%s/%s/questions/' % (self.orga1.slug, self.event1.slug))
|
||||
self.assertIn("Vegetarian?", doc.select("table > tbody > tr")[1].text)
|
||||
self.assertIn("Food allergies?", doc.select("table > tbody > tr")[0].text)
|
||||
|
||||
def test_delete(self):
|
||||
with scopes_disabled():
|
||||
c = Question.objects.create(event=self.event1, question="What is your shoe size?", type="N", required=True)
|
||||
|
||||
@@ -260,8 +260,6 @@ event_permission_urls = [
|
||||
# ("can_change_items", "questions/", 200),
|
||||
("can_change_items", "questions/2/", 404),
|
||||
("can_change_items", "questions/2/delete", 404),
|
||||
("can_change_items", "questions/2/up", 404),
|
||||
("can_change_items", "questions/2/down", 404),
|
||||
("can_change_items", "questions/reorder", 400),
|
||||
("can_change_items", "questions/add", 200),
|
||||
# ("can_change_items", "quotas/", 200),
|
||||
|
||||
Reference in New Issue
Block a user