diff --git a/pinaxcon/proposals/forms.py b/pinaxcon/proposals/forms.py
index b8d52ad..b2a3337 100644
--- a/pinaxcon/proposals/forms.py
+++ b/pinaxcon/proposals/forms.py
@@ -1,9 +1,34 @@
from django import forms
+from symposion.proposals.forms import ProposalMixIn
-from .models import TalkProposal
+from .models import ConferenceSpeaker, TalkProposal
-class ProposalForm(forms.ModelForm):
+class ConferenceSpeakerForm(forms.ModelForm):
+
+ class Meta:
+ model = ConferenceSpeaker
+ exclude = [
+ 'user',
+ 'biography_html',
+ 'experience_html',
+ 'invite_email',
+ 'invite_token',
+ 'annotation',
+ ]
+
+ def __init__(self, *a, **k):
+ super(ConferenceSpeakerForm, self).__init__(*a, **k)
+ self.fields['code_of_conduct'].required = True
+
+
+
+class ProposalForm(forms.ModelForm, ProposalMixIn):
+
+ def __init__(self, *a, **k):
+ super(ProposalForm, self).__init__(*a, **k)
+ self.description_required()
+ self.abstract_required()
def clean_description(self):
value = self.cleaned_data["description"]
@@ -20,9 +45,12 @@ class TalkProposalForm(ProposalForm):
model = TalkProposal
fields = [
"title",
- "audience_level",
"description",
"abstract",
+ "new_presentation",
+ "extended_presentation",
"additional_notes",
+ "extra_av",
+ "slides_release",
"recording_release",
]
diff --git a/pinaxcon/proposals/migrations/0002_conferencespeaker.py b/pinaxcon/proposals/migrations/0002_conferencespeaker.py
new file mode 100644
index 0000000..52f1657
--- /dev/null
+++ b/pinaxcon/proposals/migrations/0002_conferencespeaker.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-08-13 18:45
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('symposion_speakers', '0007_auto_20170810_1651'),
+ ('proposals', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='ConferenceSpeaker',
+ fields=[
+ ('speakerbase_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='symposion_speakers.SpeakerBase')),
+ ('twitter_username', models.CharField(blank=True, help_text='Your Twitter account', max_length=15)),
+ ('first_time', models.BooleanField(help_text='')),
+ ('experience', models.TextField(blank=True, help_text="List any past speaking experience you have. Edit using Markdown.", verbose_name='Past speaking experience')),
+ ('experience_html', models.TextField(blank=True)),
+ ('travel_assistance', models.BooleanField(help_text='Check this field if you require travel assistance to get to North Bay Python in Petaluma, California.')),
+ ('lodging_assistance', models.BooleanField(help_text='Check this field if you require lodging assistance in Petaluma, California during North Bay Python.')),
+ ('home_city', models.CharField(blank=True, help_text='Which city (and state, and country) will you be traveling from to get to North Bay Python?', max_length=127)),
+ ('minority_group', models.CharField(blank=True, help_text='If you are a member of one or more groups that are underrepresented in the tech industry, you may list these here. Your response is optional.', max_length=256, verbose_name='Diversity statement')),
+ ('code_of_conduct', models.BooleanField(help_text="I have read and, in the event that my proposal is accepted, agree that I will comply with the Code of Conduct.")),
+ ],
+ bases=('symposion_speakers.speakerbase',),
+ ),
+ ]
diff --git a/pinaxcon/proposals/migrations/0003_auto_20170813_1945.py b/pinaxcon/proposals/migrations/0003_auto_20170813_1945.py
new file mode 100644
index 0000000..0642b22
--- /dev/null
+++ b/pinaxcon/proposals/migrations/0003_auto_20170813_1945.py
@@ -0,0 +1,69 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-08-13 19:45
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('proposals', '0002_conferencespeaker'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='talkproposal',
+ name='audience_level',
+ ),
+ migrations.AddField(
+ model_name='talkproposal',
+ name='extended_presentation',
+ field=models.BooleanField(default=False, help_text='Most talks at North Bay Python go for 30 minutes. We have some openings for 45-minute talks. If you check this field, please explain in your additional notes how you would use the extra 15 minutes.', verbose_name='Optionally consider this proposal for a 45-minute slot'),
+ ),
+ migrations.AddField(
+ model_name='talkproposal',
+ name='extra_av',
+ field=models.TextField(blank=True, help_text='We will provide you with a projector with HDMI connection, an audio connection, and one microphone per speaker. If you need anything more than this to present this talk, please list them here.', verbose_name='Extra tech and A/V requirements'),
+ ),
+ migrations.AddField(
+ model_name='talkproposal',
+ name='new_presentation',
+ field=models.BooleanField(default=False, help_text='Check this box if North Bay Python will be the first time this talk is presented at a technical conference.', verbose_name='This is a new presentation'),
+ ),
+ migrations.AddField(
+ model_name='talkproposal',
+ name='slides_release',
+ field=models.BooleanField(default=True, help_text='I authorize North Bay Python to release a copy of my slides and related materials under the Creative Commons Attribution-ShareAlike 3.0 United States licence, and certify that I have the authority to do so.'),
+ ),
+ migrations.AlterField(
+ model_name='conferencespeaker',
+ name='experience',
+ field=models.TextField(blank=True, help_text="List any past speaking experience you have. This can include user groups, meetups, or presentations at work or school. Edit using Markdown.", verbose_name='Past speaking experience'),
+ ),
+ migrations.AlterField(
+ model_name='conferencespeaker',
+ name='first_time',
+ field=models.BooleanField(help_text='Check this field if this is your first time speaking at a technical conference.', verbose_name='First-time speaker?'),
+ ),
+ migrations.AlterField(
+ model_name='conferencespeaker',
+ name='lodging_assistance',
+ field=models.BooleanField(help_text='Check this field if you require lodging assistance in Petaluma, California during North Bay Python.', verbose_name='Lodging assistance required?'),
+ ),
+ migrations.AlterField(
+ model_name='conferencespeaker',
+ name='minority_group',
+ field=models.CharField(blank=True, help_text='If you are a member of one or more groups that are under-represented in the tech industry, you may list these here. Your response is optional.', max_length=256, verbose_name='Diversity statement'),
+ ),
+ migrations.AlterField(
+ model_name='conferencespeaker',
+ name='travel_assistance',
+ field=models.BooleanField(help_text='Check this field if you require travel assistance to get to North Bay Python in Petaluma, California.', verbose_name='Travel assistance required?'),
+ ),
+ migrations.AlterField(
+ model_name='talkproposal',
+ name='recording_release',
+ field=models.BooleanField(default=True, help_text='I authorize North Bay Python to release a recording of my talk under the Creative Commons Attribution-ShareAlike 3.0 United States licence.'),
+ ),
+ ]
diff --git a/pinaxcon/proposals/models.py b/pinaxcon/proposals/models.py
index 2da49d8..d0f81af 100644
--- a/pinaxcon/proposals/models.py
+++ b/pinaxcon/proposals/models.py
@@ -1,25 +1,121 @@
from django.db import models
+from django.utils.translation import ugettext_lazy as _
+from symposion.markdown_parser import parse
from symposion.proposals.models import ProposalBase
+from symposion.speakers.models import SpeakerBase
+
+
+
+class ConferenceSpeaker(SpeakerBase):
+
+ def clean_twitter_username(self):
+ value = self.twitter_username
+ if value.startswith("@"):
+ value = value[1:]
+ return value
+
+ def save(self, *args, **kwargs):
+ self.experience_html = parse(self.experience)
+ self.twitter_username = self.clean_twitter_username()
+ return super(ConferenceSpeaker, self).save(*args, **kwargs)
+
+ twitter_username = models.CharField(
+ max_length=15,
+ blank=True,
+ help_text=_(u"Your Twitter account")
+ )
+
+ first_time = models.BooleanField(
+ blank=True,
+ verbose_name=_("First-time speaker?"),
+ help_text=_("Check this field if this is your first time speaking "
+ "at a technical conference."),
+ )
+
+ experience = models.TextField(blank=True, help_text=_
+ ("List any past speaking experience you have. This can include "
+ "user groups, meetups, or presentations at work or school. Edit "
+ "using "
+ "Markdown."),
+ verbose_name=_("Past speaking experience"),
+ )
+ experience_html = models.TextField(blank=True)
+
+ travel_assistance = models.BooleanField(
+ blank=True,
+ verbose_name=_("Travel assistance required?"),
+ help_text=_("Check this field if you require travel assistance to get "
+ "to North Bay Python in Petaluma, California."),
+ )
+
+ lodging_assistance = models.BooleanField(
+ blank=True,
+ verbose_name=_("Lodging assistance required?"),
+ help_text=_("Check this field if you require lodging assistance in "
+ "Petaluma, California during North Bay Python."),
+ )
+
+ home_city = models.CharField(
+ blank=True,
+ max_length=127,
+ help_text=_("Which city (and state, and country) will you be "
+ "traveling from to get to North Bay Python?"),
+ )
+
+ minority_group = models.CharField(blank=True, max_length=256,
+ verbose_name=_("Diversity statement"),
+ help_text=_("If you are a member of one or more groups that are "
+ "under-represented in the tech industry, you may list "
+ "these here. Your response is optional."),
+ )
+
+ code_of_conduct = models.BooleanField(
+ help_text=_("I have read and, in the event that my proposal is "
+ "accepted, agree that I will comply with the "
+ "Code of Conduct."),
+ )
class Proposal(ProposalBase):
- AUDIENCE_LEVEL_NOVICE = 1
- AUDIENCE_LEVEL_EXPERIENCED = 2
- AUDIENCE_LEVEL_INTERMEDIATE = 3
-
- AUDIENCE_LEVELS = [
- (AUDIENCE_LEVEL_NOVICE, "Novice"),
- (AUDIENCE_LEVEL_INTERMEDIATE, "Intermediate"),
- (AUDIENCE_LEVEL_EXPERIENCED, "Experienced"),
- ]
-
- audience_level = models.IntegerField(choices=AUDIENCE_LEVELS)
-
+ extended_presentation = models.BooleanField(
+ default=False,
+ verbose_name=_("Optionally consider this proposal for a 45-minute "
+ "slot"),
+ help_text=_("Most talks at North Bay Python go for 30 minutes. We "
+ "have some openings for 45-minute talks. If you check this "
+ "field, please explain in your additional notes how you "
+ "would use the extra 15 minutes."),
+ )
+ extra_av = models.TextField(
+ blank=True,
+ verbose_name=_("Extra tech and A/V requirements"),
+ help_text=_("We will provide you with a projector with HDMI "
+ "connection, an audio connection, and one microphone per "
+ "speaker. If you need anything more than this to present "
+ "this talk, please list them here."),
+ )
+ new_presentation = models.BooleanField(
+ default=False,
+ verbose_name=_("This is a new presentation"),
+ help_text=_("Check this box if North Bay Python will be the first "
+ "time this talk is presented at a technical conference."),
+ )
+ slides_release = models.BooleanField(
+ default=True,
+ help_text=_("I authorize North Bay Python to release a copy of my "
+ "slides and related materials under the Creative Commons "
+ "Attribution-ShareAlike 3.0 United States licence, and "
+ "certify that I have the authority to do so."),
+ )
recording_release = models.BooleanField(
default=True,
- help_text="By submitting your proposal, you agree to give permission to the conference organizers to record, edit, and release audio and/or video of your presentation. If you do not agree to this, please uncheck this box."
+ help_text=_("I authorize North Bay Python to release a recording of "
+ "my talk under the Creative Commons "
+ "Attribution-ShareAlike 3.0 United States licence."),
+
)
class Meta:
diff --git a/pinaxcon/settings.py b/pinaxcon/settings.py
index d1e0f0f..f403c4b 100644
--- a/pinaxcon/settings.py
+++ b/pinaxcon/settings.py
@@ -256,6 +256,9 @@ PINAX_STRIPE_PUBLIC_KEY = os.environ.get("STRIPE_PUBLIC_KEY", "your test public
PINAX_STRIPE_SECRET_KEY = os.environ.get("STRIPE_SECRET_KEY", "your test secret key")
PINAX_STRIPE_SEND_EMAIL_RECEIPTS = False
+SYMPOSION_SPEAKER_MODEL = "pinaxcon.proposals.models.ConferenceSpeaker"
+SYMPOSION_SPEAKER_FORM = "pinaxcon.proposals.forms.ConferenceSpeakerForm"
+
# Registrasion Attendee profile model
ATTENDEE_PROFILE_MODEL = "pinaxcon.registrasion.models.AttendeeProfile"
# Registrasion attendee profile form -- must act on ATTENDEE_PROFILE_FORM
diff --git a/requirements/base.txt b/requirements/base.txt
index 2fb7510..b182309 100644
--- a/requirements/base.txt
+++ b/requirements/base.txt
@@ -13,6 +13,7 @@ django-sitetree==1.8.0
django-countries==4.6.1
easy-thumbnails==2.4.1
django-timezone-field==2.0
+django-mode-utils==3.0.0
# For testing
@@ -21,6 +22,6 @@ coverage==4.0.3
# Registrasion
https://github.com/chrisjrn/registrasion/tarball/master#egg=registrasion
-https://github.com/pinax/symposion/tarball/ad81810#egg=symposion
+https://github.com/chrisjrn/symposion/tarball/northbaypython#egg=symposion
https://github.com/chrisjrn/registrasion-stripe/tarball/master#egg=registrasion-stripe
https://github.com/chrisjrn/symposion-bootstrap-templates/tarball/master#egg=symposion-bootstrap-templates