mirror of
https://github.com/pretix/pretix.git
synced 2026-10-01 19:14:43 +00:00
wip2
This commit is contained in:
@@ -553,9 +553,9 @@ class DatafieldSerializer(I18nAwareModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Question
|
||||
fields = ('id', 'question', 'type', 'required', 'items', 'options', 'position',
|
||||
'ask_during_checkin', 'show_during_checkin', 'identifier',
|
||||
'hidden', 'print_on_invoice', 'help_text', 'valid_number_min',
|
||||
fields = ('id', 'question', 'type', 'options',
|
||||
'show_during_checkin', 'identifier',
|
||||
'hidden', 'print_on_invoice', 'valid_number_min',
|
||||
'valid_number_max', 'valid_date_min', 'valid_date_max', 'valid_datetime_min', 'valid_datetime_max',
|
||||
'valid_string_length_max', 'valid_string_length_min', 'valid_file_portrait', 'internal_name',)
|
||||
|
||||
@@ -682,6 +682,7 @@ class QuestionnaireSerializer(I18nAwareModelSerializer):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.fields['children'] = InlineQuestionnaireChildSerializer(many=True, required=True, context=kwargs['context'], partial=False)
|
||||
self.fields['limit_sales_channels'].child_relation.queryset = kwargs['context']['event'].organizer.sales_channels.all()
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def validate(self, data):
|
||||
|
||||
@@ -463,7 +463,7 @@ with scopes_disabled():
|
||||
class QuestionFilter(FilterSet):
|
||||
class Meta:
|
||||
model = Question
|
||||
fields = ['ask_during_checkin', 'required', 'identifier']
|
||||
fields = ['identifier']
|
||||
|
||||
|
||||
class DatafieldViewSet(ConditionalListView, viewsets.ModelViewSet):
|
||||
@@ -471,8 +471,8 @@ class DatafieldViewSet(ConditionalListView, viewsets.ModelViewSet):
|
||||
queryset = Question.objects.none()
|
||||
filter_backends = (DjangoFilterBackend, TotalOrderingFilter)
|
||||
filterset_class = QuestionFilter
|
||||
ordering_fields = ('id', 'position')
|
||||
ordering = ('position', 'id')
|
||||
ordering_fields = ('id')
|
||||
ordering = ('id')
|
||||
permission = None
|
||||
write_permission = 'event.items:write'
|
||||
|
||||
@@ -568,11 +568,18 @@ class QuestionOptionViewSet(viewsets.ModelViewSet):
|
||||
super().perform_destroy(instance)
|
||||
|
||||
|
||||
with scopes_disabled():
|
||||
class QuestionnaireFilter(FilterSet):
|
||||
class Meta:
|
||||
model = Questionnaire
|
||||
fields = ['type']
|
||||
|
||||
|
||||
class QuestionnaireViewSet(ConditionalListView, viewsets.ModelViewSet):
|
||||
serializer_class = QuestionnaireSerializer
|
||||
queryset = Questionnaire.objects.none()
|
||||
#filter_backends = (DjangoFilterBackend, TotalOrderingFilter)
|
||||
#filterset_class = QuestionFilter
|
||||
filter_backends = (DjangoFilterBackend, TotalOrderingFilter)
|
||||
filterset_class = QuestionnaireFilter
|
||||
ordering_fields = ('id', 'position')
|
||||
ordering = ('position', 'id')
|
||||
permission = None
|
||||
|
||||
@@ -50,7 +50,7 @@ from django.core.exceptions import ValidationError
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import ProgrammingError
|
||||
from django.db.models import Prefetch, QuerySet
|
||||
from django.db.models import Prefetch, Q, QuerySet
|
||||
from django.forms import Select, widgets
|
||||
from django.forms.widgets import FILE_INPUT_CONTRADICTION
|
||||
from django.utils.formats import date_format
|
||||
@@ -943,8 +943,7 @@ class OrderLevelQuestionsForm(BaseQuestionsForm):
|
||||
"""
|
||||
Takes two additional keyword arguments:
|
||||
|
||||
:param checkoutsession: The checkout session the form should be for
|
||||
:param order: The order the form should be for
|
||||
:param container: The checkout session or order the form should be for
|
||||
:param event: The event this belongs to
|
||||
"""
|
||||
request = kwargs.pop('request', None)
|
||||
@@ -954,6 +953,7 @@ class OrderLevelQuestionsForm(BaseQuestionsForm):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
questionnaires = Questionnaire.objects.filter(
|
||||
Q(all_sales_channels=True) | Q(limit_sales_channels__identifier=container.sales_channel.identifier),
|
||||
event=event, type=Questionnaire.QuestionnaireType.ORDER_SALE,
|
||||
).order_by('position').prefetch_related(
|
||||
Prefetch('children', QuestionnaireChild.objects.prefetch_related(
|
||||
|
||||
@@ -1671,37 +1671,37 @@ class Question(LoggedModel):
|
||||
),
|
||||
],
|
||||
)
|
||||
help_text = I18nTextField(
|
||||
# TODO(questionnaires) : to be removed
|
||||
verbose_name=_("Help text"),
|
||||
help_text=_("If the question needs to be explained or clarified, do it here!"),
|
||||
null=True, blank=True,
|
||||
)
|
||||
#help_text = I18nTextField(
|
||||
# # TODO(questionnaires) : to be removed
|
||||
# verbose_name=_("Help text"),
|
||||
# help_text=_("If the question needs to be explained or clarified, do it here!"),
|
||||
# null=True, blank=True,
|
||||
#)
|
||||
type = models.CharField(
|
||||
max_length=5,
|
||||
choices=FieldType.choices,
|
||||
verbose_name=_("Question type")
|
||||
)
|
||||
required = models.BooleanField( # TODO(questionnaires) : to be removed, -> QuestionnaireChild
|
||||
default=False,
|
||||
verbose_name=_("Required question")
|
||||
)
|
||||
items = models.ManyToManyField( # TODO(questionnaires) : to be removed, -> Questionnaire
|
||||
Item,
|
||||
related_name='questions',
|
||||
verbose_name=_("Products"),
|
||||
blank=True,
|
||||
help_text=_('This question will be asked to buyers of the selected products')
|
||||
)
|
||||
position = models.PositiveIntegerField( # TODO(questionnaires) : to be removed, -> Questionnaire + QuestionnaireChild
|
||||
default=0,
|
||||
verbose_name=_("Position")
|
||||
)
|
||||
ask_during_checkin = models.BooleanField( # TODO(questionnaires) : to be removed
|
||||
verbose_name=_('Ask during check-in instead of in the ticket buying process'),
|
||||
help_text=_('Not supported by all check-in apps for all question types.'),
|
||||
default=False
|
||||
)
|
||||
#required = models.BooleanField( # TODO(questionnaires) : to be removed, -> QuestionnaireChild
|
||||
# default=False,
|
||||
# verbose_name=_("Required question")
|
||||
#)
|
||||
#items = models.ManyToManyField( # TODO(questionnaires) : to be removed, -> Questionnaire
|
||||
# Item,
|
||||
# related_name='questions',
|
||||
# verbose_name=_("Products"),
|
||||
# blank=True,
|
||||
# help_text=_('This question will be asked to buyers of the selected products')
|
||||
#)
|
||||
#position = models.PositiveIntegerField( # TODO(questionnaires) : to be removed, -> Questionnaire + QuestionnaireChild
|
||||
# default=0,
|
||||
# verbose_name=_("Position")
|
||||
#)
|
||||
#ask_during_checkin = models.BooleanField( # TODO(questionnaires) : to be removed
|
||||
# verbose_name=_('Ask during check-in instead of in the ticket buying process'),
|
||||
# help_text=_('Not supported by all check-in apps for all question types.'),
|
||||
# default=False
|
||||
#)
|
||||
show_during_checkin = models.BooleanField(
|
||||
verbose_name=_('Show answer during check-in'),
|
||||
help_text=_('Not supported by all check-in apps for all question types.'),
|
||||
|
||||
@@ -37,7 +37,7 @@ from pretix.base.forms.questions import (
|
||||
)
|
||||
from pretix.base.models import (
|
||||
CartPosition, InvoiceAddress, OrderPosition, Question, QuestionAnswer,
|
||||
QuestionnaireChild, QuestionOption,
|
||||
Questionnaire, QuestionnaireChild, QuestionOption,
|
||||
)
|
||||
from pretix.base.models.customers import AttendeeProfile
|
||||
from pretix.base.models.orders import CheckoutSession, Order
|
||||
@@ -350,7 +350,7 @@ class OrderQuestionsViewMixin(BaseQuestionsViewMixin):
|
||||
def positions(self):
|
||||
qqs = self.request.event.questionnaires.all()
|
||||
if self.only_user_visible:
|
||||
qqs = qqs.filter(type='PS')
|
||||
qqs = qqs.filter(type=Questionnaire.QuestionnaireType.ORDER_POSITION_SALE)
|
||||
else:
|
||||
qqs = qqs.filter(type__startswith='P')
|
||||
qqs = qqs.filter(
|
||||
|
||||
@@ -157,7 +157,6 @@ class QuestionForm(I18nModelForm):
|
||||
del self.fields['show_during_checkin']
|
||||
del self.fields['print_on_invoice']
|
||||
self.fields['identifier'].required = False
|
||||
self.fields['help_text'].widget.attrs['rows'] = 3
|
||||
|
||||
def clean_show_during_checkin(self):
|
||||
val = self.cleaned_data.get('show_during_checkin')
|
||||
@@ -191,9 +190,7 @@ class QuestionForm(I18nModelForm):
|
||||
localized_fields = '__all__'
|
||||
fields = [
|
||||
'question',
|
||||
'help_text',
|
||||
'type',
|
||||
'required',
|
||||
'show_during_checkin',
|
||||
'hidden',
|
||||
'identifier',
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
{% url "control:event.items.questions.edit" organizer=request.event.organizer.slug event=request.event.slug question=0 as datafield_edit_url %}
|
||||
{{ datafield_edit_url|json_script:"datafield_edit_url" }}
|
||||
|
||||
{% url "control:event.items.questions.show" organizer=request.event.organizer.slug event=request.event.slug question=0 as datafield_view_url %}
|
||||
{{ datafield_view_url|json_script:"datafield_view_url" }}
|
||||
|
||||
{% url "control:event.items.questions.add" organizer=request.event.organizer.slug event=request.event.slug as datafield_create_url %}
|
||||
{{ datafield_create_url|json_script:"datafield_create_url" }}
|
||||
|
||||
|
||||
@@ -555,7 +555,7 @@ class QuestionView(EventPermissionRequiredMixin, ChartContainingView, DetailView
|
||||
question=self.object, orderposition__isnull=False,
|
||||
)
|
||||
qs = qs.filter(orderposition__in=opqs)
|
||||
op_cnt = opqs.filter(item__in=self.object.items.all()).count()
|
||||
op_cnt = 0 # TODO opqs.filter(item__in=self.object.items.all()).count()
|
||||
|
||||
if self.object.type == Question.TYPE_FILE:
|
||||
qs = [
|
||||
@@ -600,7 +600,7 @@ class QuestionView(EventPermissionRequiredMixin, ChartContainingView, DetailView
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data()
|
||||
ctx['items'] = self.object.items.exists()
|
||||
#ctx['items'] = self.object.items.exists()
|
||||
ctx['has_subevents'] = self.request.event.has_subevents
|
||||
stats = self.get_answer_statistics()
|
||||
ctx['stats'], ctx['total'] = stats
|
||||
|
||||
@@ -87,6 +87,8 @@ dialog::backdrop {
|
||||
100% { transform: skewX(0deg); }
|
||||
}
|
||||
|
||||
.modal-card.no-padding, .modal-card.no-padding .modal-card-content { padding: 0; }
|
||||
.modal-card.no-scroll { overflow: hidden; }
|
||||
|
||||
|
||||
/* Legacy dialogs (still used for #ajaxerr and #popupmodal) */
|
||||
|
||||
@@ -1139,10 +1139,12 @@ function notify_parent_frame() {
|
||||
}, location.origin)
|
||||
} catch {}
|
||||
$(function () {
|
||||
window.parent.postMessage({
|
||||
type: 'pretix:dialog-loaded',
|
||||
contentHeight: $('body').height(),
|
||||
}, location.origin)
|
||||
setTimeout(() => {
|
||||
window.parent.postMessage({
|
||||
type: 'pretix:dialog-loaded',
|
||||
contentHeight: $('#page-wrapper > .container-fluid').outerHeight() + 20,
|
||||
}, location.origin)
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
notify_parent_frame()
|
||||
|
||||
@@ -4,7 +4,10 @@ import {gettext} from "./gettextstub";
|
||||
import NativeDialog from "./NativeDialog.vue";
|
||||
import {computed, onMounted, onUnmounted, ref, watch} from "vue";
|
||||
|
||||
const props = defineProps(['defaultUrl'])
|
||||
const props = defineProps({
|
||||
'defaultUrl': {type: String, default: null},
|
||||
'maxWidth': {type: String, default: '43em'},
|
||||
})
|
||||
const emit = defineEmits(['confirm'])
|
||||
const dlgDjangoDialog = ref()
|
||||
const url = ref(props.defaultUrl)
|
||||
@@ -40,20 +43,20 @@ defineExpose({
|
||||
frameHeight.value = 400
|
||||
url.value = newUrl
|
||||
dlgDjangoDialog.value.show()
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NativeDialog ref="dlgDjangoDialog" class="modal-card" no-padding="true" no-scroll="true">
|
||||
<NativeDialog ref="dlgDjangoDialog" class="modal-card" :no-padding="true" :no-scroll="true" :max-width="maxWidth">
|
||||
<div :style="{'height': frameHeight + 'px'}">
|
||||
<i class="fa fa-cog big-rotating-icon" v-if="frameLoading"></i>
|
||||
<iframe :src="url" v-if="dlgDjangoDialog.visible" :height="frameHeight" :style="{'visibility': frameLoading ? 'hidden' : 'visible'}"></iframe>
|
||||
<div class="frame-load-indicator" v-if="frameLoading"><i class="fa fa-cog big-rotating-icon"></i></div>
|
||||
<iframe :src="url" v-if="dlgDjangoDialog.visible" :height="frameHeight" :style="{'opacity': frameLoading ? '0' : '1'}"></iframe>
|
||||
</div>
|
||||
</NativeDialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
div { text-align: center; }
|
||||
iframe { width: 100%; border: 0; }
|
||||
.frame-load-indicator { text-align: center; }
|
||||
iframe { width: 100%; border: 0; }
|
||||
</style>
|
||||
|
||||
@@ -8,6 +8,7 @@ import {onMounted, onUnmounted, ref} from 'vue';
|
||||
import { SlickList, SlickItem } from 'vue-slicksort';
|
||||
import { ProgressBar } from "./ProgressBar";
|
||||
|
||||
const sales_channels_list = await api.getSalesChannels();
|
||||
const items_list = await api.getItems();
|
||||
const categories_list = await api.getCategories();
|
||||
const categories = Object.fromEntries(categories_list.map(cat => [cat.id, cat]));
|
||||
@@ -34,6 +35,7 @@ async function refreshQuestionnaireList () {
|
||||
async function refreshDatafieldList () {
|
||||
order_datafields.value = await api.getDatafields('O')
|
||||
position_datafields.value = (await api.getDatafields('P')).concat(Object.values(SYSTEM_DATAFIELDS))
|
||||
console.log('datafield list refreshed')
|
||||
}
|
||||
await Promise.all([refreshQuestionnaireList(), refreshDatafieldList()])
|
||||
|
||||
@@ -46,14 +48,12 @@ function saveQuestionnaire(questionnaire) {
|
||||
result = api.createQuestionnaire(questionnaire)
|
||||
}
|
||||
result = result.then(d => {
|
||||
console.log(questionnaire, 'ok')
|
||||
questionnaire.id = d.id
|
||||
questionnaire.children = d.children
|
||||
questionnaire._err_mes = null
|
||||
questionnaire._loading = false
|
||||
return d;
|
||||
}, err => {
|
||||
console.log(questionnaire, 'err:', err)
|
||||
questionnaire._err_mes = err
|
||||
questionnaire._loading = false
|
||||
return err;
|
||||
@@ -180,8 +180,8 @@ const preview_mode = ref(false)
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.questionnaires-list > .editor-action-row { border-top: 1px solid rgb(175 175 175 / 0.3); }
|
||||
.editor-action-row { padding-top: 10px; width: calc(100% + 190px); padding-right: 170px }
|
||||
.questionnaires-list > .editor-action-row { border-top: 1px solid rgb(175 175 175 / 0.3); padding-top: 25px; padding-bottom: 10px }
|
||||
</style>
|
||||
<template>
|
||||
<div class="questionnaires-editor" v-if="!preview_mode">
|
||||
@@ -194,6 +194,7 @@ const preview_mode = ref(false)
|
||||
<QuestionnaireElement
|
||||
:questionnaire="questionnaire"
|
||||
:datafields="order_datafields"
|
||||
:sales_channels="sales_channels_list"
|
||||
:grouped_items="null"
|
||||
:selected_product="null"
|
||||
:preview_mode="false"
|
||||
@@ -241,6 +242,7 @@ const preview_mode = ref(false)
|
||||
<QuestionnaireElement v-for="(questionnaire, index) in position_questionnaires.filter(q => q.items.indexOf(selected_product as any) !== -1)"
|
||||
:questionnaire="questionnaire"
|
||||
:datafields="position_datafields"
|
||||
:sales_channels="sales_channels_list"
|
||||
:grouped_items="grouped_items"
|
||||
:selected_product="selected_product"
|
||||
:preview_mode="true"
|
||||
@@ -255,6 +257,7 @@ const preview_mode = ref(false)
|
||||
<QuestionnaireElement
|
||||
:questionnaire="questionnaire"
|
||||
:datafields="position_datafields"
|
||||
:sales_channels="sales_channels_list"
|
||||
:grouped_items="grouped_items"
|
||||
:selected_product="selected_product"
|
||||
:preview_mode="false"
|
||||
|
||||
@@ -8,9 +8,10 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
title: '',
|
||||
noPadding: false,
|
||||
noScroll: true,
|
||||
title: {type: String, default: ''},
|
||||
noPadding: {type: Boolean, default: false},
|
||||
noScroll: {type: Boolean, default: true},
|
||||
maxWidth: {type: String, default: '43em'},
|
||||
});
|
||||
|
||||
const visible = ref(false);
|
||||
@@ -34,6 +35,7 @@ const id = useId();
|
||||
@close="visible = false"
|
||||
closedby="any"
|
||||
:aria-labelledby="`${id}-title`"
|
||||
:style="{maxWidth: props.maxWidth}"
|
||||
>
|
||||
<form
|
||||
v-if="visible"
|
||||
|
||||
@@ -4,7 +4,7 @@ import NativeDialog from './NativeDialog.vue';
|
||||
import I18nTextField from './I18nTextField.vue';
|
||||
import {useId, ref, computed} from 'vue'
|
||||
import { DragHandle } from 'vue-slicksort';
|
||||
import {getDatafieldCreateUrl, getDatafieldEditUrl} from "./api";
|
||||
import {getDatafieldCreateUrl, getDatafieldEditUrl, getDatafieldViewUrl} from "./api";
|
||||
import I18nTextArea from "./I18nTextArea.vue";
|
||||
import DjangoDialog from "./DjangoDialog.vue";
|
||||
|
||||
@@ -16,11 +16,11 @@ const question = ref(props.question);
|
||||
|
||||
const dlgEditDatafield = ref()
|
||||
|
||||
const df = typeof question.value.question === 'number' ?
|
||||
const df = computed(() => typeof question.value.question === 'number' ?
|
||||
props.datafields.find(el => el.id === question.value.question) :
|
||||
typeof question.value.question === 'string' ?
|
||||
SYSTEM_DATAFIELDS[question.value.question] :
|
||||
null;
|
||||
null);
|
||||
|
||||
const dependency_values_options = computed(() => props.datafields.find(el => el.id === question.value.dependency_question)?.options);
|
||||
const dependency_values_resolved = computed(() => question.value.dependency_values.map(ident => i18n_any(dependency_values_options.value.find(opt => opt.identifier === ident)?.answer) ?? ident));
|
||||
@@ -109,7 +109,10 @@ const editor = ref();
|
||||
<p class="form-control-static">
|
||||
<template v-if="typeof question.question === 'number'">
|
||||
{{ df.internal_name }}
|
||||
<a href="javascript:" @click="dlgEditDatafield.open(getDatafieldEditUrl(df.id))">Manage data field details</a>
|
||||
<div>
|
||||
<a class="btn btn-sm btn-default" href="javascript:" @click="dlgEditDatafield.open(getDatafieldEditUrl(df.id))"><span class="fa fa-wrench"></span> Manage data field details</a>
|
||||
<a class="btn btn-sm btn-default" :href="getDatafieldViewUrl(df.id)" target="_blank"><span class="fa fa-external-link"></span> View answers</a>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ question.question }}
|
||||
@@ -161,6 +164,6 @@ const editor = ref();
|
||||
<button @click="emit('removeSelf')" class="btn btn-default">Remove from questionnaire</button>
|
||||
</NativeDialog>
|
||||
|
||||
<DjangoDialog ref="dlgEditDatafield" @confirm="emit('invalidate:datafields')"></DjangoDialog>
|
||||
<DjangoDialog ref="dlgEditDatafield" @confirm="emit('invalidate:datafields')" max-width="60em"></DjangoDialog>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import {useId, ref, computed, onMounted} from 'vue'
|
||||
import {useId, ref, computed, onMounted, watch} from 'vue'
|
||||
import QuestionElement from "./QuestionElement.vue";
|
||||
import {
|
||||
i18n_any,
|
||||
@@ -25,12 +25,15 @@ const newTextblockTitle = ref()
|
||||
const newTextblockText = ref()
|
||||
|
||||
const id = useId();
|
||||
const props = defineProps(['questionnaire', 'datafields', 'selected_product', 'grouped_items', 'preview_mode', 'err_mes'])
|
||||
const props = defineProps(['questionnaire', 'datafields', 'sales_channels', 'selected_product', 'grouped_items', 'preview_mode', 'err_mes'])
|
||||
const emit = defineEmits(['update', 'invalidate:datafields'])
|
||||
|
||||
for (let qc of props.questionnaire.children) {
|
||||
if (!qc._cid) qc._cid = useId();
|
||||
}
|
||||
let nextId = 1;
|
||||
watch(() => props.questionnaire.children, () => {
|
||||
for (let qc of props.questionnaire.children) {
|
||||
if (!qc._cid) qc._cid = id + (++nextId);
|
||||
}
|
||||
})
|
||||
|
||||
function setVisibleOnItem (checked, itemId) {
|
||||
const i = props.questionnaire.items.indexOf(itemId)
|
||||
@@ -76,12 +79,19 @@ function addTextblock () {
|
||||
}
|
||||
|
||||
function newDatafield (container_type) {
|
||||
dlgNewDatafield.value.dialog.show()
|
||||
dlgNewDatafield.value.open(getDatafieldCreateUrl(props.questionnaire.type[0]))
|
||||
}
|
||||
|
||||
async function onNewDatafieldCreated (data) {
|
||||
await emit('invalidate:datafields')
|
||||
dlgAddExisting.value.show()
|
||||
watch(
|
||||
() => props.datafields,
|
||||
(newValue, oldValue) => {
|
||||
console.log('datafields changed watcher called')
|
||||
addExistingDatafield(newValue.find(f => f.id === data.object))
|
||||
},
|
||||
{ once: true }
|
||||
)
|
||||
emit('invalidate:datafields')
|
||||
}
|
||||
|
||||
const isHidden = computed(() => props.selected_product && props.questionnaire.items.indexOf(props.selected_product) === -1)
|
||||
@@ -97,7 +107,7 @@ const isEditable = computed(() => props.selected_product && props.questionnaire.
|
||||
<summary class="questionnaire-panel-heading">
|
||||
<div class=" editor-row">
|
||||
<div class="editor-preview-area">
|
||||
<input type="checkbox" @change="setVisibleOnItem(this.checked, selected_product); emit('update')" v-if="selected_product && !preview_mode" :checked="!isHidden">
|
||||
<input type="checkbox" @change="e => {setVisibleOnItem(e.target.checked, selected_product); emit('update')}" v-if="selected_product && !preview_mode" :checked="!isHidden">
|
||||
{{ props.questionnaire.internal_name }}
|
||||
<span class="fa fa-warning" v-if="questionnaire._err_mes"></span>
|
||||
<span class="fa fa-cog fa-spin" v-if="questionnaire._loading"></span>
|
||||
@@ -170,6 +180,14 @@ const isEditable = computed(() => props.selected_product && props.questionnaire.
|
||||
<input type="checkbox" v-model="questionnaire.all_sales_channels"> {{ gettext('All sales channels') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox" v-for="channel in sales_channels">
|
||||
<label>
|
||||
<input type="checkbox" :checked="questionnaire.all_sales_channels || questionnaire.limit_sales_channels.indexOf(channel.identifier) !== -1"
|
||||
@change="e => e.target.checked ? questionnaire.limit_sales_channels.push(channel.identifier) : questionnaire.limit_sales_channels.splice(questionnaire.limit_sales_channels.indexOf(channel.identifier), 1)"
|
||||
:disabled="questionnaire.all_sales_channels">
|
||||
{{ i18n_any(channel.label) }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" v-if="grouped_items">
|
||||
@@ -181,7 +199,7 @@ const isEditable = computed(() => props.selected_product && props.questionnaire.
|
||||
<div class="category-header">{{ category.internal_name || i18n_any(category.name) }}</div>
|
||||
<div class="checkbox" v-for="item in items">
|
||||
<label :for="id + '_' + item.id">
|
||||
<input :id="id + '_' + item.id" type="checkbox" :checked="questionnaire.items.indexOf(item.id) !== -1" @change="setVisibleOnItem(this.checked, item.id)"> {{ item.internal_name || i18n_any(item.name) }}
|
||||
<input :id="id + '_' + item.id" type="checkbox" :checked="questionnaire.items.indexOf(item.id) !== -1" @change="e => setVisibleOnItem(e.target.checked, item.id)"> {{ item.internal_name || i18n_any(item.name) }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -226,6 +244,6 @@ const isEditable = computed(() => props.selected_product && props.questionnaire.
|
||||
|
||||
</NativeDialog>
|
||||
|
||||
<DjangoDialog ref="dlgNewDatafield" :default-url="getDatafieldCreateUrl(questionnaire.type[0])" @confirm="onNewDatafieldCreated"></DjangoDialog>
|
||||
<DjangoDialog ref="dlgNewDatafield" @confirm="onNewDatafieldCreated" max-width="60em"></DjangoDialog>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
@@ -71,10 +71,17 @@ export async function getCategories() {
|
||||
return await api_get_all<Category>(`organizers/${organizer_slug}/events/${event_slug}/categories/`);
|
||||
}
|
||||
|
||||
export async function getSalesChannels() {
|
||||
return await api_get_all<Category>(`organizers/${organizer_slug}/saleschannels/`);
|
||||
}
|
||||
|
||||
export function getEventLocales() {
|
||||
return fromJsonScript('event_locales');
|
||||
}
|
||||
|
||||
export function getDatafieldViewUrl(datafield_id) {
|
||||
return fromJsonScript('datafield_view_url').replace('/0/', `/${datafield_id}/`);
|
||||
}
|
||||
export function getDatafieldEditUrl(datafield_id) {
|
||||
return fromJsonScript('datafield_edit_url').replace('/0/', `/${datafield_id}/`) + '?notify_parent=true&';
|
||||
}
|
||||
|
||||
@@ -900,6 +900,7 @@ tbody th {
|
||||
|
||||
html.in-iframe body { background: white }
|
||||
.in-iframe #wrapper > nav.navbar, .in-iframe #page-wrapper > div > footer { display: none; }
|
||||
.in-iframe #page-wrapper { padding: 0 15px; min-height: 568px; border-left: 0; margin: 0; }
|
||||
|
||||
@import "../../pretixbase/scss/_rtl.scss";
|
||||
@import "../../bootstrap/scss/_rtl.scss";
|
||||
|
||||
Reference in New Issue
Block a user