poll voting works
This commit is contained in:
parent
738591b05e
commit
a485a36897
|
@ -65,6 +65,14 @@ class QuestConsumer(WebsocketConsumer):
|
||||||
'message': data
|
'message': data
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def self_send(self, event, data={}):
|
||||||
|
"""
|
||||||
|
Like `send`, except only sends events to the paired websocket
|
||||||
|
instead of the entire group.
|
||||||
|
"""
|
||||||
|
data = json.dumps({'event': event, 'data': data})
|
||||||
|
self.dispatch_send({'message': data})
|
||||||
|
|
||||||
def dispatch_send(self, event):
|
def dispatch_send(self, event):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -4,6 +4,7 @@ Individual functions for handling WebSocket events. Gets called by the
|
||||||
QuestConsumer object in consumers.py.
|
QuestConsumer object in consumers.py.
|
||||||
"""
|
"""
|
||||||
# TODO: quest owner only events
|
# TODO: quest owner only events
|
||||||
|
# TODO: try/except on database calls
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import types
|
import types
|
||||||
|
@ -43,9 +44,9 @@ def message(socket, data):
|
||||||
for quote in quotes:
|
for quote in quotes:
|
||||||
msg_id = quote.replace(">>", "")
|
msg_id = quote.replace(">>", "")
|
||||||
msg = '<a class="quotelink" '
|
msg = '<a class="quotelink" '
|
||||||
msg += 'href="javascript:scrollToMsg(\'' + msg_id + '\')" '
|
msg += 'href="javascript:scroll_to_msg(\'' + msg_id + '\')" '
|
||||||
msg += 'onmousemove="showPreview(event, \'' + msg_id + '\')" '
|
msg += 'onmousemove="show_preview(event, \'' + msg_id + '\')" '
|
||||||
msg += 'onmouseout="clearPreview()">' + quote + '</a>'
|
msg += 'onmouseout="clear_preview()">' + quote + '</a>'
|
||||||
message = message.replace(quote, msg)
|
message = message.replace(quote, msg)
|
||||||
|
|
||||||
# handle image
|
# handle image
|
||||||
|
@ -255,7 +256,7 @@ def poll_post(socket, data):
|
||||||
data['post_id'] = p.id
|
data['post_id'] = p.id
|
||||||
data['post_text'] = "Poll"
|
data['post_text'] = "Poll"
|
||||||
data['date'] = localtime(p.timestamp).strftime('%Y-%m-%d %H:%M')
|
data['date'] = localtime(p.timestamp).strftime('%Y-%m-%d %H:%M')
|
||||||
data['options'] = [o.text for o in options]
|
data['options'] = [(o.id, o.text) for o in options]
|
||||||
socket.send('new_post', data)
|
socket.send('new_post', data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -305,6 +306,49 @@ def open_post(socket, data):
|
||||||
socket.send('open_post', data)
|
socket.send('open_post', data)
|
||||||
|
|
||||||
|
|
||||||
|
def vote(socket, data):
|
||||||
|
"""
|
||||||
|
Called when a player votes in a poll.
|
||||||
|
"""
|
||||||
|
quest_id = data.get('quest_id')
|
||||||
|
post_id = data.get('post_id')
|
||||||
|
option_id = data.get('option_id')
|
||||||
|
polarity = data.get('polarity')
|
||||||
|
ip_address = socket.scope['client'][0]
|
||||||
|
user = socket.scope['user']
|
||||||
|
|
||||||
|
if polarity == False:
|
||||||
|
v = PollVote.objects.get(ip_address=ip_address, option__id=option_id)
|
||||||
|
v.delete()
|
||||||
|
else:
|
||||||
|
p = Poll.objects.get(post_id=post_id)
|
||||||
|
if p.multi_choice == False:
|
||||||
|
votes = PollVote.objects.filter(
|
||||||
|
ip_address=ip_address,
|
||||||
|
option__poll=p
|
||||||
|
)
|
||||||
|
for vote in votes:
|
||||||
|
vote.delete()
|
||||||
|
|
||||||
|
data = {}
|
||||||
|
data['option_id'] = vote.option.id
|
||||||
|
data['polarity'] = False
|
||||||
|
socket.send('vote', data)
|
||||||
|
socket.self_send('set_option_box', data)
|
||||||
|
v = PollVote(
|
||||||
|
option=PollOption.objects.get(id=option_id),
|
||||||
|
ip_address=ip_address
|
||||||
|
)
|
||||||
|
if user.username:
|
||||||
|
v.user = user
|
||||||
|
v.save()
|
||||||
|
|
||||||
|
data = {}
|
||||||
|
data['option_id'] = option_id
|
||||||
|
data['polarity'] = polarity
|
||||||
|
socket.send('vote', data)
|
||||||
|
|
||||||
|
|
||||||
events = {}
|
events = {}
|
||||||
for obj in dir():
|
for obj in dir():
|
||||||
if type(locals()[obj]) == types.FunctionType:
|
if type(locals()[obj]) == types.FunctionType:
|
||||||
|
|
|
@ -68,14 +68,14 @@
|
||||||
{% 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 poll_options.filter(poll=post.poll) %}
|
{% for option in poll_options.filter(poll=post.poll).order_by("id") %}
|
||||||
<tr id="optionRow-{{ post.id }}">
|
<tr id="optionRow-{{ option.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.id }}" onchange="pollVote({{ post.id }}, {{ option.id }})"{% if not post.poll.open %} disabled{% endif %}/>
|
<input type="checkbox" {# if ip_address in poll_votes.get(option.id) %}checked="true"{% endif #} id="pollInput-{{ option.id }}" onchange="vote({{ post.id }}, {{ option.id }})"{% if not post.poll.open %} disabled{% endif %}/>
|
||||||
<label for="pollInput-{{ option.id }}"></label>
|
<label for="pollInput-{{ option.id }}"></label>
|
||||||
</td>
|
</td>
|
||||||
<td class="option_text">{{ option.text }}</td>
|
<td class="option_text">{{ option.text }}</td>
|
||||||
<td class="optionVotes">{# poll_votes.get(option[0], [])|length #}</td>
|
<td class="optionVotes">{{ poll_votes.filter(option=option).count() }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
@ -130,8 +130,8 @@
|
||||||
<div><input type="text" name="pollOption-2" class="pollOption" placeholder="Option 2" maxlength="200" /></div>
|
<div><input type="text" name="pollOption-2" class="pollOption" placeholder="Option 2" maxlength="200" /></div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<input type="checkbox" name="pollAllowMultipleChoices" />Allow multiple choices<br />
|
<input type="checkbox" name="multi_choice" />Allow multiple choices<br />
|
||||||
<input type="checkbox" name="pollAllowUserOptions" />Allow user-created options<br />
|
<input type="checkbox" name="allow_writein" />Allow user-created options<br />
|
||||||
<input type="submit" name="submit" value="Submit" />
|
<input type="submit" name="submit" value="Submit" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
20
quest/migrations/0011_auto_20180902_2007.py
Normal file
20
quest/migrations/0011_auto_20180902_2007.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 2.1 on 2018-09-03 00:07
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('quest', '0010_auto_20180829_1308'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='pollvote',
|
||||||
|
name='user',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
]
|
|
@ -121,8 +121,9 @@ class PollVote(models.Model):
|
||||||
option = models.ForeignKey(PollOption, on_delete=models.CASCADE)
|
option = models.ForeignKey(PollOption, on_delete=models.CASCADE)
|
||||||
user = models.ForeignKey(
|
user = models.ForeignKey(
|
||||||
settings.AUTH_USER_MODEL,
|
settings.AUTH_USER_MODEL,
|
||||||
on_delete=models.CASCADE
|
on_delete=models.CASCADE,
|
||||||
)
|
blank=True,
|
||||||
|
null=True)
|
||||||
ip_address = models.GenericIPAddressField()
|
ip_address = models.GenericIPAddressField()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,6 @@ socket.events['message'] = function(data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
socket.events['new_post'] = function(data) {
|
socket.events['new_post'] = function(data) {
|
||||||
//deactivate_post();
|
|
||||||
let qposts = document.getElementById('questPosts');
|
let qposts = document.getElementById('questPosts');
|
||||||
let post_str = '<div class="questPost ';
|
let post_str = '<div class="questPost ';
|
||||||
if (data.post_type === 'text') {
|
if (data.post_type === 'text') {
|
||||||
|
@ -61,10 +60,9 @@ socket.events['new_post'] = function(data) {
|
||||||
} else if (data.post_type === 'poll') {
|
} else if (data.post_type === 'poll') {
|
||||||
post_str += '<h3>' + data.post_text + ' - Open</h3>';
|
post_str += '<h3>' + data.post_text + ' - Open</h3>';
|
||||||
post_str += '<table class="poll" id="poll-' + data.post_id + '">';
|
post_str += '<table class="poll" id="poll-' + data.post_id + '">';
|
||||||
post_str += '<col/><col/><col/>';
|
for (let i = 0; i < data.options.length; i++) {
|
||||||
for (i = 0; i < data.options.length; i++) {
|
post_str += '<tr id="optionRow-' + data.options[i] + '">';
|
||||||
post_str += '<tr id="optionRow-' + data.options[i][0] + '">';
|
post_str += '<td class="pollCheckBox"><input type="checkbox" id="pollInput-' + data.options[i][0] + '" onchange="vote(' + data.post_id + ',' + data.options[i][0] + ')"/>';
|
||||||
post_str += '<td class="pollCheckBox"><input type="checkbox" id="pollInput-' + data.options[i][0] + '" onchange="pollVote(' + data.post_id + ',' + data.options[i][0] + ')"/>';
|
|
||||||
post_str += '<label for="pollInput-' + data.options[i][0] + '"></label></td>';
|
post_str += '<label for="pollInput-' + data.options[i][0] + '"></label></td>';
|
||||||
post_str += '<td class="option_text">' + data.options[i][1] + '</td>';
|
post_str += '<td class="option_text">' + data.options[i][1] + '</td>';
|
||||||
post_str += '<td class="optionVotes">0</td></tr>';
|
post_str += '<td class="optionVotes">0</td></tr>';
|
||||||
|
@ -105,7 +103,7 @@ socket.events['update_post'] = function(data) {
|
||||||
let row = post.children[1].insertRow(-1);
|
let row = post.children[1].insertRow(-1);
|
||||||
let cell = row.insertCell(0);
|
let cell = row.insertCell(0);
|
||||||
cell.className = 'pollCheckBox';
|
cell.className = 'pollCheckBox';
|
||||||
cell.innerHTML = '<input type="checkbox" id="pollInput-' + data.options_id + '" onchange="pollVote(' + data.post_id + ',' + data.options_id + ')"/>';
|
cell.innerHTML = '<input type="checkbox" id="pollInput-' + data.options_id + '" onchange="vote(' + data.post_id + ',' + data.options_id + ')"/>';
|
||||||
cell.innerHTML += '<label for="pollInput-' + data.options_id + '"></label>';
|
cell.innerHTML += '<label for="pollInput-' + data.options_id + '"></label>';
|
||||||
|
|
||||||
cell = row.insertCell(1);
|
cell = row.insertCell(1);
|
||||||
|
@ -117,6 +115,31 @@ socket.events['update_post'] = function(data) {
|
||||||
cell.innerHTML = "0";
|
cell.innerHTML = "0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
socket.events['vote'] = function(data) {
|
||||||
|
let row = document.getElementById('optionRow-' + data.option_id);
|
||||||
|
if (data.polarity) {
|
||||||
|
row.cells[2].textContent = Number(row.cells[2].textContent) + 1;
|
||||||
|
} else {
|
||||||
|
row.cells[2].textContent = Number(row.cells[2].textContent) - 1;
|
||||||
|
}
|
||||||
|
let table = row.parentElement.parentElement;
|
||||||
|
arr = Array.prototype.slice.call(table.rows);
|
||||||
|
arr.sort(sort_by_votes);
|
||||||
|
let new_tbody = document.createElement('tbody');
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
new_tbody.appendChild(arr[i]);
|
||||||
|
}
|
||||||
|
table.replaceChild(new_tbody, table.children[0]);
|
||||||
|
}
|
||||||
|
socket.events['set_option_box'] = function(data) {
|
||||||
|
document.getElementById('pollInput-' + data.option_id).checked = data.polarity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Websocket send */
|
||||||
|
function vote(post_id, option_id) {
|
||||||
|
let polarity = document.getElementById('pollInput-' + option_id).checked;
|
||||||
|
socket.send('vote', {post_id: post_id, option_id: option_id, polarity: polarity, quest_id: quest_id});
|
||||||
|
}
|
||||||
|
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
function padToTwo(number) {
|
function padToTwo(number) {
|
||||||
|
@ -129,6 +152,9 @@ function strftime(date) {
|
||||||
date_str += padToTwo(date.getHours()) + ':' + padToTwo(date.getMinutes()) + ':' + padToTwo(date.getSeconds());
|
date_str += padToTwo(date.getHours()) + ':' + padToTwo(date.getMinutes()) + ':' + padToTwo(date.getSeconds());
|
||||||
return date_str;
|
return date_str;
|
||||||
}
|
}
|
||||||
|
function sort_by_votes(a, b) {
|
||||||
|
return b.cells[2].textContent.localeCompare(a.cells[2].textContent);
|
||||||
|
}
|
||||||
|
|
||||||
/* DOM editing */
|
/* DOM editing */
|
||||||
function quote(message_id) {
|
function quote(message_id) {
|
||||||
|
@ -136,7 +162,7 @@ function quote(message_id) {
|
||||||
textbox.value += '>>' + message_id + '\n';
|
textbox.value += '>>' + message_id + '\n';
|
||||||
textbox.focus();
|
textbox.focus();
|
||||||
}
|
}
|
||||||
function showPreview(event, message_id) {
|
function show_preview(event, message_id) {
|
||||||
let elem = document.getElementById('msg-' + message_id);
|
let elem = document.getElementById('msg-' + message_id);
|
||||||
if (!elem) { return; }
|
if (!elem) { return; }
|
||||||
let preview = document.getElementById('preview');
|
let preview = document.getElementById('preview');
|
||||||
|
@ -149,11 +175,11 @@ function showPreview(event, message_id) {
|
||||||
preview.style.left = x;
|
preview.style.left = x;
|
||||||
preview.style.maxWidth = maxWidth;
|
preview.style.maxWidth = maxWidth;
|
||||||
}
|
}
|
||||||
function clearPreview() {
|
function clear_preview() {
|
||||||
document.getElementById('preview').innerHTML = '';
|
document.getElementById('preview').innerHTML = '';
|
||||||
document.getElementById('preview').style.display = 'none';
|
document.getElementById('preview').style.display = 'none';
|
||||||
}
|
}
|
||||||
function scrollToMsg(message_id) {
|
function scroll_to_msg(message_id) {
|
||||||
let elem = document.getElementById('msg-' + message_id);
|
let elem = document.getElementById('msg-' + message_id);
|
||||||
if (!elem) { return; }
|
if (!elem) { return; }
|
||||||
elem.scrollIntoView();
|
elem.scrollIntoView();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* Websocket receive */
|
/* Websocket receive */
|
||||||
socket.events['new_post'] = function(data) {
|
socket.events['new_post'] = function(data) {
|
||||||
//deactivate_post();
|
|
||||||
let qposts = document.getElementById('questPosts');
|
let qposts = document.getElementById('questPosts');
|
||||||
let post_str = '<div class="questPost ';
|
let post_str = '<div class="questPost ';
|
||||||
if (data.post_type === 'text') {
|
if (data.post_type === 'text') {
|
||||||
|
@ -28,10 +27,9 @@ socket.events['new_post'] = function(data) {
|
||||||
} else if (data.post_type === 'poll') {
|
} else if (data.post_type === 'poll') {
|
||||||
post_str += '<h3>' + data.post_text + ' - Open</h3>';
|
post_str += '<h3>' + data.post_text + ' - Open</h3>';
|
||||||
post_str += '<table class="poll" id="poll-' + data.post_id + '">';
|
post_str += '<table class="poll" id="poll-' + data.post_id + '">';
|
||||||
post_str += '<col/><col/><col/>';
|
|
||||||
for (i = 0; i < data.options.length; i++) {
|
for (i = 0; i < data.options.length; i++) {
|
||||||
post_str += '<tr id="optionRow-' + data.options[i][0] + '">';
|
post_str += '<tr id="optionRow-' + data.options[i][0] + '">';
|
||||||
post_str += '<td class="pollCheckBox"><input type="checkbox" id="pollInput-' + data.options[i][0] + '" onchange="pollVote(' + data.post_id + ',' + data.options[i][0] + ')"/>';
|
post_str += '<td class="pollCheckBox"><input type="checkbox" id="pollInput-' + data.options[i][0] + '" onchange="vote(' + data.post_id + ',' + data.options[i][0] + ')"/>';
|
||||||
post_str += '<label for="pollInput-' + data.options[i][0] + '"></label></td>';
|
post_str += '<label for="pollInput-' + data.options[i][0] + '"></label></td>';
|
||||||
post_str += '<td class="option_text">' + data.options[i][1] + '</td>';
|
post_str += '<td class="option_text">' + data.options[i][1] + '</td>';
|
||||||
post_str += '<td class="optionVotes">0</td></tr>';
|
post_str += '<td class="optionVotes">0</td></tr>';
|
||||||
|
|
|
@ -25,5 +25,6 @@ def quest(request, quest_id, page_num=1):
|
||||||
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_options = PollOption.objects.filter(poll__post__quest__id=quest_id)
|
||||||
poll_votes = PollVote.objects.filter(option__poll__post__quest__id=quest_id)
|
poll_votes = PollVote.objects.filter(option__poll__post__quest__id=quest_id)
|
||||||
|
ip_address = request.META['REMOTE_ADDR']
|
||||||
context = locals()
|
context = locals()
|
||||||
return render(request, 'quest/quest.html', context)
|
return render(request, 'quest/quest.html', context)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user