added poll posting

This commit is contained in:
iou1name 2018-08-29 14:01:31 -04:00
parent 8513cdd86e
commit 1a21c882a2
7 changed files with 172 additions and 14 deletions

View File

@ -12,8 +12,8 @@ import random
import bleach import bleach
from django.utils.timezone import localtime from django.utils.timezone import localtime
from quest.models import Message, Quest, Post, DiceCall, DiceRoll from quest.models import *
from quest.forms import DiceCallForm from quest.forms import DiceCallForm, PollForm
def message(socket, data): def message(socket, data):
""" """
@ -209,10 +209,53 @@ def dice_post(socket, data):
dc.save() dc.save()
data = {} 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_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) socket.send('new_post', data)

View File

@ -17,3 +17,22 @@ class DiceCallForm(forms.Form):
diceRollsTaken = forms.IntegerField( diceRollsTaken = forms.IntegerField(
min_value=1, max_value=99, required=False) min_value=1, max_value=99, required=False)
diceStrict = forms.BooleanField(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)

View File

@ -68,16 +68,16 @@
{% elif post.post_type == "poll" %} {% elif post.post_type == "poll" %}
<h3>{{ post.post_text }} - {% if post.poll.open %}Open{% else %}Closed{% endif %}</h3> <h3>{{ post.post_text }} - {% if post.poll.open %}Open{% else %}Closed{% endif %}</h3>
<table class="poll" id="poll-{{ post.id }}"> <table class="poll" id="poll-{{ post.id }}">
{# for option in options.get(post.id, []) %} {% for option in poll_options.filter(poll=post.poll) %}
<tr id="optionRow-{{ option[0] }}"> <tr id="optionRow-{{ post.id }}">
<td class="pollCheckBox"> <td class="pollCheckBox">
<input type="checkbox" {% if ip_address in poll_votes.get(option[0], []) %}checked="true"{% endif %} id="pollInput-{{ option[0] }}" onchange="pollVote({{ post.id }}, {{ option[0] }})"{% if post.id != quest.open_post_id %} disabled{% endif %}/> <input type="checkbox" {# if ip_address in poll_votes.get(option[0], []) %}checked="true"{% endif #} id="pollInput-{{ option.id }}" onchange="pollVote({{ post.id }}, {{ option.id }})"{% if not post.poll.open %} disabled{% endif %}/>
<label for="pollInput-{{ option[0] }}"></label> <label for="pollInput-{{ option.id }}"></label>
</td> </td>
<td class="option_text">{{ option[2] }}</td> <td class="option_text">{{ option.text }}</td>
<td class="optionVotes">{{ poll_votes.get(option[0], [])|length }}</td> <td class="optionVotes">{# poll_votes.get(option[0], [])|length #}</td>
</tr> </tr>
{% endfor #} {% endfor %}
</table> </table>
{# if post.id == quest.open_post_id and post.id|is_write_in %} {# if post.id == quest.open_post_id and post.id|is_write_in %}
<div id="writeinContainer"> <div id="writeinContainer">

View File

@ -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(),
),
]

View File

@ -73,7 +73,7 @@ class DiceCall(models.Model):
MinValueValidator(1) MinValueValidator(1)
] ]
) )
open = models.BooleanField(default=False) open = models.BooleanField()
class DiceRoll(models.Model): class DiceRoll(models.Model):
@ -91,6 +91,41 @@ class DiceRoll(models.Model):
total = models.IntegerField() 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): class PageTitle(models.Model):
""" """
Represents the title of a quest page. Represents the title of a quest page.

View File

@ -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 = '<div><input type="text" name="pollOption-' + num + '" class="pollOption" placeholder="Option ' + num + '" maxlength="200" /></div>';
opts.appendChild(temp.content);
}
function removePollOption() {
let opts = document.getElementById('pollOptions');
if (opts.children.length == 0) { return; }
opts.children[opts.children.length-1].outerHTML = '';
}

View File

@ -5,7 +5,7 @@ Quest and quest accessory views.
from django.shortcuts import render from django.shortcuts import render
from django.http import HttpResponse from django.http import HttpResponse
from .models import Quest, DiceRoll from .models import Quest, DiceRoll, PollOption, PollVote
def index(request): def index(request):
""" """
@ -23,5 +23,7 @@ def quest(request, quest_id, page_num=1):
messages = quest.message_set.all() messages = quest.message_set.all()
posts = quest.post_set.all() posts = quest.post_set.all()
dice_rolls = DiceRoll.objects.filter(dicecall__post__quest__id=quest_id) 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() context = locals()
return render(request, 'quest/quest.html', context) return render(request, 'quest/quest.html', context)