diff --git a/quest/events.py b/quest/events.py
index 5352162..c6212f6 100644
--- a/quest/events.py
+++ b/quest/events.py
@@ -12,8 +12,8 @@ import random
import bleach
from django.utils.timezone import localtime
-from quest.models import Message, Quest, Post, DiceCall, DiceRoll
-from quest.forms import DiceCallForm
+from quest.models import *
+from quest.forms import DiceCallForm, PollForm
def message(socket, data):
"""
@@ -209,10 +209,53 @@ def dice_post(socket, data):
dc.save()
data = {}
- data['post_text'] = post_text
- data['post_type'] = 'dice'
- data['date'] = localtime(p.timestamp).strftime('%Y-%m-%d %H:%M')
data['post_id'] = p.id
+ data['post_type'] = 'dice'
+ data['post_text'] = post_text
+ data['date'] = localtime(p.timestamp).strftime('%Y-%m-%d %H:%M')
+ socket.send('new_post', data)
+
+
+def poll_post(socket, data):
+ """
+ Called when the QM makes a new dice post.
+ """
+ quest_id = data.get('quest_id')
+ page_num = data.get('page_num')
+ form = PollForm(data)
+ if not form.is_valid():
+ return # error message?
+ form = form.cleaned_data
+
+ p = Post(
+ quest=Quest.objects.get(id=quest_id),
+ page_num=page_num,
+ post_type='poll',
+ post_text="Poll"
+ )
+ p.save()
+ pl = Poll(
+ post=p,
+ multi_choice=form.pop('multi_choice'),
+ allow_writein=form.pop('allow_writein'),
+ open=True
+ )
+ pl.save()
+ options = []
+ for key, option in form.items():
+ o = PollOption(
+ poll=pl,
+ text=option
+ )
+ o.save()
+ options.append(o)
+
+ data = {}
+ data['post_type'] = 'poll'
+ data['post_id'] = p.id
+ data['post_text'] = "Poll"
+ data['date'] = localtime(p.timestamp).strftime('%Y-%m-%d %H:%M')
+ data['options'] = [o.text for o in options]
socket.send('new_post', data)
diff --git a/quest/forms.py b/quest/forms.py
index 463fef6..335f402 100644
--- a/quest/forms.py
+++ b/quest/forms.py
@@ -17,3 +17,22 @@ class DiceCallForm(forms.Form):
diceRollsTaken = forms.IntegerField(
min_value=1, max_value=99, required=False)
diceStrict = forms.BooleanField(required=False)
+
+
+class PollForm(forms.Form):
+ """
+ The form for the QM making new polls.
+ """
+ multi_choice = forms.BooleanField(required=False)
+ allow_writein = forms.BooleanField(required=False)
+
+ def __init__(self, *args, **kwargs):
+ super(PollForm, self).__init__(*args, **kwargs)
+ data = args[0] # it's not nice to assume
+ options = {k: v for k, v in data.items() if k.startswith('pollOption')}
+ if len(options) > 20:
+ return
+ for key, value in options.items():
+ if not value:
+ continue
+ self.fields[key] = forms.CharField(max_length=200)
diff --git a/quest/jinja2/quest/quest.html b/quest/jinja2/quest/quest.html
index 4983e3a..90d2df8 100644
--- a/quest/jinja2/quest/quest.html
+++ b/quest/jinja2/quest/quest.html
@@ -68,16 +68,16 @@
{% elif post.post_type == "poll" %}
{# if post.id == quest.open_post_id and post.id|is_write_in %}
diff --git a/quest/migrations/0010_auto_20180829_1308.py b/quest/migrations/0010_auto_20180829_1308.py
new file mode 100644
index 0000000..f9d0020
--- /dev/null
+++ b/quest/migrations/0010_auto_20180829_1308.py
@@ -0,0 +1,47 @@
+# Generated by Django 2.1 on 2018-08-29 17:08
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('quest', '0009_diceroll'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Poll',
+ fields=[
+ ('post', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='quest.Post')),
+ ('multi_choice', models.BooleanField()),
+ ('allow_writein', models.BooleanField()),
+ ('open', models.BooleanField()),
+ ],
+ ),
+ migrations.CreateModel(
+ name='PollOption',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('text', models.CharField(max_length=200)),
+ ('poll', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.Poll')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='PollVote',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('ip_address', models.GenericIPAddressField()),
+ ('option', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.PollOption')),
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ migrations.AlterField(
+ model_name='dicecall',
+ name='open',
+ field=models.BooleanField(),
+ ),
+ ]
diff --git a/quest/models.py b/quest/models.py
index 610cd16..bc0e15b 100644
--- a/quest/models.py
+++ b/quest/models.py
@@ -73,7 +73,7 @@ class DiceCall(models.Model):
MinValueValidator(1)
]
)
- open = models.BooleanField(default=False)
+ open = models.BooleanField()
class DiceRoll(models.Model):
@@ -91,6 +91,41 @@ class DiceRoll(models.Model):
total = models.IntegerField()
+class Poll(models.Model):
+ """
+ An object representing polls made by the QM.
+ """
+ post = models.OneToOneField(
+ Post,
+ on_delete=models.CASCADE,
+ primary_key=True,
+ )
+ multi_choice = models.BooleanField()
+ allow_writein = models.BooleanField()
+ open = models.BooleanField()
+
+
+class PollOption(models.Model):
+ """
+ Represents options (choices) attached to a given poll. These can be
+ added by the QM upon creation, or by users through write-ins.
+ """
+ poll = models.ForeignKey(Poll, on_delete=models.CASCADE)
+ text = models.CharField(max_length=200)
+
+
+class PollVote(models.Model):
+ """
+ Represents a user voting for an option.
+ """
+ option = models.ForeignKey(PollOption, on_delete=models.CASCADE)
+ user = models.ForeignKey(
+ settings.AUTH_USER_MODEL,
+ on_delete=models.CASCADE
+ )
+ ip_address = models.GenericIPAddressField()
+
+
class PageTitle(models.Model):
"""
Represents the title of a quest page.
diff --git a/quest/static/questQM.js b/quest/static/questQM.js
index 3f0d7fc..b2a4698 100644
--- a/quest/static/questQM.js
+++ b/quest/static/questQM.js
@@ -139,3 +139,15 @@ function open_post(post_id) {
}
}
}
+function insertPollOption() {
+ let opts = document.getElementById('pollOptions');
+ let num = opts.children.length+1;
+ let temp = document.createElement('template');
+ temp.innerHTML = '
';
+ opts.appendChild(temp.content);
+}
+function removePollOption() {
+ let opts = document.getElementById('pollOptions');
+ if (opts.children.length == 0) { return; }
+ opts.children[opts.children.length-1].outerHTML = '';
+}
diff --git a/quest/views.py b/quest/views.py
index 2e825c6..fb58656 100644
--- a/quest/views.py
+++ b/quest/views.py
@@ -5,7 +5,7 @@ Quest and quest accessory views.
from django.shortcuts import render
from django.http import HttpResponse
-from .models import Quest, DiceRoll
+from .models import Quest, DiceRoll, PollOption, PollVote
def index(request):
"""
@@ -23,5 +23,7 @@ def quest(request, quest_id, page_num=1):
messages = quest.message_set.all()
posts = quest.post_set.all()
dice_rolls = DiceRoll.objects.filter(dicecall__post__quest__id=quest_id)
+ poll_options = PollOption.objects.filter(poll__post__quest__id=quest_id)
+ poll_votes = PollVote.objects.filter(option__poll__post__quest__id=quest_id)
context = locals()
return render(request, 'quest/quest.html', context)