Skip to content

Commit 79bef2c

Browse files
authored
Merge branch 'development' into Issue18
2 parents 42ff963 + 4d4212b commit 79bef2c

File tree

9 files changed

+133
-35
lines changed

9 files changed

+133
-35
lines changed

src/pretalx/cfp/flow.py

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@
1919
from django.utils.translation import gettext
2020
from django.utils.translation import gettext_lazy as _
2121
from django.views.generic.base import TemplateResponseMixin
22+
23+
from django_context_decorator import context
24+
2225
from i18nfield.strings import LazyI18nString
2326
from i18nfield.utils import I18nJSONEncoder
2427

2528
from pretalx.cfp.signals import cfp_steps
2629
from pretalx.common.exceptions import SendMailException
2730
from pretalx.common.phrases import phrases
2831
from pretalx.common.utils import language
32+
from pretalx.common.views import is_form_bound
2933
from pretalx.person.forms import SpeakerProfileForm, UserForm
3034
from pretalx.person.models import User
3135
from pretalx.submission.forms import InfoForm, QuestionsForm
@@ -407,29 +411,7 @@ def _text(self):
407411
)
408412

409413
def is_applicable(self, request):
410-
self.request = request
411-
info_data = self.cfp_session.get("data", {}).get("info", {})
412-
track = info_data.get("track")
413-
if track:
414-
questions = self.event.questions.exclude(
415-
Q(target=QuestionTarget.SUBMISSION)
416-
& (
417-
(~Q(tracks__in=[info_data.get("track")]) & Q(tracks__isnull=False))
418-
| (
419-
~Q(submission_types__in=[info_data.get("submission_type")])
420-
& Q(submission_types__isnull=False)
421-
)
422-
)
423-
)
424-
else:
425-
questions = self.event.questions.exclude(
426-
Q(target=QuestionTarget.SUBMISSION)
427-
& (
428-
~Q(submission_types__in=[info_data.get("submission_type")])
429-
& Q(submission_types__isnull=False)
430-
)
431-
)
432-
return questions.exists()
414+
return False
433415

434416
def get_form_kwargs(self):
435417
result = super().get_form_kwargs()
@@ -537,6 +519,18 @@ def get_context_data(self, **kwargs):
537519
result["gravatar_parameter"] = User(email=email).gravatar_parameter
538520
return result
539521

522+
@context
523+
@cached_property
524+
def questions_form(self):
525+
bind = is_form_bound(self.request, "questions")
526+
return QuestionsForm(
527+
data=self.request.POST if bind else None,
528+
files=self.request.FILES if bind else None,
529+
speaker=self.request.user,
530+
event=self.request.event,
531+
target="speaker",
532+
)
533+
540534
def done(self, request, draft=False):
541535
form = self.get_form(from_storage=True)
542536
form.is_valid()

src/pretalx/cfp/templates/cfp/event/submission_profile.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ <h2>{{ title }}</h2>
2424

2525
{% bootstrap_field form.name layout='event' %}
2626
{% if form.biography %}{% bootstrap_field form.biography layout='event' %}{% endif %}
27+
{% if questions_form %}{% bootstrap_form questions_form layout='event' %}{% endif %}
2728
{% if form.availabilities %}
2829
{% compress js %}
2930
<script defer src="{% static "vendored/moment-with-locales.js" %}"></script>

src/pretalx/orga/forms/cfp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def __init__(self, *args, obj, **kwargs):
5353
self.fields[
5454
"mail_on_new_submission"
5555
].help_text += f' (<a href="mailto:{obj.email}">{obj.email}</a>)'
56-
self.length_fields = ["title", "abstract", "description", "biography"]
56+
self.length_fields = ["title", "abstract", "description", "biography", "avatar_source", "avatar_license"]
5757
self.request_require_fields = [
5858
"abstract",
5959
"description",

src/pretalx/orga/templates/orga/cfp/text.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,14 +169,14 @@
169169
<tr>
170170
<th>{% translate "Profile picture source" %}</th>
171171
<td class="hide-label">{% bootstrap_field sform.cfp_ask_avatar_source layout='event-inline' %}</td>
172-
<td></td>
173-
<td></td>
172+
<td>{% bootstrap_field sform.cfp_avatar_source_min_length use_label=False layout='inline' %}</td>
173+
<td>{% bootstrap_field sform.cfp_avatar_source_max_length use_label=False layout='inline' %}</td>
174174
</tr>
175175
<tr>
176176
<th>{% translate "Profile picture license" %}</th>
177177
<td class="hide-label">{% bootstrap_field sform.cfp_ask_avatar_license layout='event-inline' %}</td>
178-
<td></td>
179-
<td></td>
178+
<td>{% bootstrap_field sform.cfp_avatar_license_min_length use_label=False layout='inline' %}</td>
179+
<td>{% bootstrap_field sform.cfp_avatar_license_max_length use_label=False layout='inline' %}</td>
180180
</tr>
181181
<tr>
182182
<th>{% translate "Biography" %}</th>

src/pretalx/person/forms.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ def __init__(self, *args, name=None, **kwargs):
198198
self.fields[field] = field_class(
199199
initial=initial.get(field), disabled=read_only
200200
)
201+
if self.Meta.widgets.get(field):
202+
self.fields[field].widget = self.Meta.widgets.get(field)()
201203
self._update_cfp_texts(field)
202204

203205
if not self.event.cfp.request_avatar:
@@ -276,6 +278,8 @@ class Meta:
276278
}
277279
widgets = {
278280
"biography": MarkdownWidget,
281+
"avatar_source": MarkdownWidget,
282+
"avatar_license": MarkdownWidget,
279283
}
280284
request_require = {"biography", "availabilities"}
281285

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 4.2.11 on 2024-03-16 15:15
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("person", "0030_user_avatar_source_alter_user_avatar_license"),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name="user",
15+
name="avatar_license",
16+
field=models.TextField(null=True),
17+
),
18+
]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 4.2.11 on 2024-03-16 22:03
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("person", "0031_alter_user_avatar_license"),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name="user",
15+
name="avatar_source",
16+
field=models.TextField(null=True),
17+
),
18+
]

src/pretalx/person/models/user.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,17 @@ class User(PermissionsMixin, GenerateCode, FileCleanupMixin, AbstractBaseUser):
128128
"If you have registered with an email address that has a gravatar account, we can retrieve your profile picture from there."
129129
),
130130
)
131-
avatar_source = models.CharField(
131+
avatar_source = models.TextField(
132132
null=True,
133133
blank=True,
134-
max_length=999,
135134
verbose_name=_("Profile Picture Source"),
136135
help_text=_(
137136
"Please enter the name of the author or source of image and a link if applicable."
138137
),
139138
)
140-
avatar_license = models.CharField(
139+
avatar_license = models.TextField(
141140
null=True,
142141
blank=True,
143-
max_length=999,
144142
verbose_name=_("Profile Picture License"),
145143
help_text=_(
146144
"Please enter the name of the license of the photo and link to it if applicable."

src/pretalx/submission/forms/submission.py

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
from django import forms
22
from django.db.models import Count, Exists, OuterRef, Q
3+
from django.utils.functional import cached_property
34
from django.utils.timezone import now
45
from django.utils.translation import gettext_lazy as _
56
from django_scopes.forms import SafeModelChoiceField
67

78
from pretalx.cfp.forms.cfp import CfPFormMixin
89
from pretalx.common.forms.fields import ImageField
910
from pretalx.common.forms.widgets import MarkdownWidget
10-
from pretalx.common.mixins.forms import PublicContent, RequestRequire
11+
from pretalx.common.mixins.forms import PublicContent, RequestRequire, QuestionFieldsMixin
1112
from pretalx.common.mixins.views import Filterable
1213
from pretalx.submission.forms.track_select_widget import TrackSelectWidget
13-
from pretalx.submission.models import Answer, Question, Submission, SubmissionStates
14+
from pretalx.submission.models import Answer, Question, Submission, SubmissionStates, QuestionTarget, QuestionVariant
1415

1516

16-
class InfoForm(CfPFormMixin, RequestRequire, PublicContent, forms.ModelForm):
17+
class InfoForm(CfPFormMixin, RequestRequire, PublicContent, QuestionFieldsMixin, forms.ModelForm):
1718
additional_speaker = forms.EmailField(
1819
label=_("Additional Speaker"),
1920
help_text=_(
@@ -30,6 +31,13 @@ class InfoForm(CfPFormMixin, RequestRequire, PublicContent, forms.ModelForm):
3031

3132
def __init__(self, event, **kwargs):
3233
self.event = event
34+
self.submission = kwargs.pop("submission", None)
35+
self.track = kwargs.pop("track", None) or getattr(
36+
self.submission, "track", None
37+
)
38+
self.submission_type = kwargs.pop("submission_type", None) or getattr(
39+
self.submission, "submission_type", None
40+
)
3341
self.readonly = kwargs.pop("readonly", False)
3442
self.access_code = kwargs.pop("access_code", None)
3543
self.default_values = {}
@@ -60,6 +68,55 @@ def __init__(self, event, **kwargs):
6068
for f in self.fields.values():
6169
f.disabled = True
6270

71+
self.target_type = kwargs.pop("target", QuestionTarget.SUBMISSION)
72+
self.for_reviewers = kwargs.pop("for_reviewers", False)
73+
if self.target_type == QuestionTarget.SUBMISSION:
74+
target_object = self.submission
75+
elif self.target_type == QuestionTarget.SPEAKER:
76+
target_object = self.speaker
77+
78+
self.queryset = Question.all_objects.filter(event=self.event, active=True)
79+
if self.target_type:
80+
self.queryset = self.queryset.filter(target=self.target_type)
81+
else:
82+
self.queryset = self.queryset.exclude(target=QuestionTarget.REVIEWER)
83+
if self.track:
84+
self.queryset = self.queryset.filter(
85+
Q(tracks__in=[self.track]) | Q(tracks__isnull=True)
86+
)
87+
if self.submission_type:
88+
self.queryset = self.queryset.filter(
89+
Q(submission_types__in=[self.submission_type])
90+
| Q(submission_types__isnull=True)
91+
)
92+
93+
for question in self.queryset.prefetch_related("options"):
94+
initial_object = None
95+
initial = question.default_answer
96+
if target_object:
97+
answers = [
98+
a
99+
for a in target_object.answers.all()
100+
if a.question_id == question.id
101+
]
102+
if answers:
103+
initial_object = answers[0]
104+
initial = (
105+
answers[0].answer_file
106+
if question.variant == QuestionVariant.FILE
107+
else answers[0].answer
108+
)
109+
110+
field = self.get_field(
111+
question=question,
112+
initial=initial,
113+
initial_object=initial_object,
114+
readonly=self.readonly,
115+
)
116+
field.question = question
117+
field.answer = initial_object
118+
self.fields[f"question_{question.pk}"] = field
119+
63120
def _set_track(self, instance=None):
64121
if "track" in self.fields:
65122
if (
@@ -160,6 +217,14 @@ def _set_slot_count(self, instance=None):
160217
)
161218
)
162219

220+
@cached_property
221+
def submission_fields(self):
222+
return [
223+
forms.BoundField(self, field, name)
224+
for name, field in self.fields.items()
225+
if hasattr(field, "question") and field.question.target == QuestionTarget.SUBMISSION
226+
]
227+
163228
def save(self, *args, **kwargs):
164229
for key, value in self.default_values.items():
165230
setattr(self.instance, key, value)

0 commit comments

Comments
 (0)