poll voting works
This commit is contained in:
parent
738591b05e
commit
a485a36897
|
@ -66,6 +66,14 @@ class QuestConsumer(WebsocketConsumer):
|
|||
}
|
||||
)
|
||||
|
||||
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):
|
||||
"""
|
||||
Receives events from other consumers in the group and relays the
|
||||
|
|
|
@ -4,6 +4,7 @@ Individual functions for handling WebSocket events. Gets called by the
|
|||
QuestConsumer object in consumers.py.
|
||||
"""
|
||||
# TODO: quest owner only events
|
||||
# TODO: try/except on database calls
|
||||
import re
|
||||
import time
|
||||
import types
|
||||
|
@ -43,9 +44,9 @@ def message(socket, data):
|
|||
for quote in quotes:
|
||||
msg_id = quote.replace(">>", "")
|
||||
msg = '<a class="quotelink" '
|
||||
msg += 'href="javascript:scrollToMsg(\'' + msg_id + '\')" '
|
||||
msg += 'onmousemove="showPreview(event, \'' + msg_id + '\')" '
|
||||
msg += 'onmouseout="clearPreview()">' + quote + '</a>'
|
||||
msg += 'href="javascript:scroll_to_msg(\'' + msg_id + '\')" '
|
||||
msg += 'onmousemove="show_preview(event, \'' + msg_id + '\')" '
|
||||
msg += 'onmouseout="clear_preview()">' + quote + '</a>'
|
||||
message = message.replace(quote, msg)
|
||||
|
||||
# handle image
|
||||
|
@ -255,7 +256,7 @@ def poll_post(socket, data):
|
|||
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]
|
||||
data['options'] = [(o.id, o.text) for o in options]
|
||||
socket.send('new_post', data)
|
||||
|
||||
|
||||
|
@ -305,6 +306,49 @@ def open_post(socket, 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 = {}
|
||||
for obj in dir():
|
||||
if type(locals()[obj]) == types.FunctionType:
|
||||
|
|
|
@ -68,14 +68,14 @@
|
|||
{% elif post.post_type == "poll" %}
|
||||
<h3>{{ post.post_text }} - {% if post.poll.open %}Open{% else %}Closed{% endif %}</h3>
|
||||
<table class="poll" id="poll-{{ post.id }}">
|
||||
{% for option in poll_options.filter(poll=post.poll) %}
|
||||
<tr id="optionRow-{{ post.id }}">
|
||||
{% for option in poll_options.filter(poll=post.poll).order_by("id") %}
|
||||
<tr id="optionRow-{{ option.id }}">
|
||||
<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>
|
||||
</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>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
@ -130,8 +130,8 @@
|
|||
<div><input type="text" name="pollOption-2" class="pollOption" placeholder="Option 2" maxlength="200" /></div>
|
||||
</div>
|
||||
<hr>
|
||||
<input type="checkbox" name="pollAllowMultipleChoices" />Allow multiple choices<br />
|
||||
<input type="checkbox" name="pollAllowUserOptions" />Allow user-created options<br />
|
||||
<input type="checkbox" name="multi_choice" />Allow multiple choices<br />
|
||||
<input type="checkbox" name="allow_writein" />Allow user-created options<br />
|
||||
<input type="submit" name="submit" value="Submit" />
|
||||
</form>
|
||||
</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)
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE
|
||||
)
|
||||
on_delete=models.CASCADE,
|
||||
blank=True,
|
||||
null=True)
|
||||
ip_address = models.GenericIPAddressField()
|
||||
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@ socket.events['message'] = function(data) {
|
|||
}
|
||||
}
|
||||
socket.events['new_post'] = function(data) {
|
||||
//deactivate_post();
|
||||
let qposts = document.getElementById('questPosts');
|
||||
let post_str = '<div class="questPost ';
|
||||
if (data.post_type === 'text') {
|
||||
|
@ -61,10 +60,9 @@ socket.events['new_post'] = function(data) {
|
|||
} else if (data.post_type === 'poll') {
|
||||
post_str += '<h3>' + data.post_text + ' - Open</h3>';
|
||||
post_str += '<table class="poll" id="poll-' + data.post_id + '">';
|
||||
post_str += '<col/><col/><col/>';
|
||||
for (i = 0; i < data.options.length; 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="pollVote(' + data.post_id + ',' + data.options[i][0] + ')"/>';
|
||||
for (let i = 0; i < data.options.length; i++) {
|
||||
post_str += '<tr id="optionRow-' + data.options[i] + '">';
|
||||
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 += '<td class="option_text">' + data.options[i][1] + '</td>';
|
||||
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 cell = row.insertCell(0);
|
||||
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 = row.insertCell(1);
|
||||
|
@ -117,6 +115,31 @@ socket.events['update_post'] = function(data) {
|
|||
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 */
|
||||
function padToTwo(number) {
|
||||
|
@ -129,6 +152,9 @@ function strftime(date) {
|
|||
date_str += padToTwo(date.getHours()) + ':' + padToTwo(date.getMinutes()) + ':' + padToTwo(date.getSeconds());
|
||||
return date_str;
|
||||
}
|
||||
function sort_by_votes(a, b) {
|
||||
return b.cells[2].textContent.localeCompare(a.cells[2].textContent);
|
||||
}
|
||||
|
||||
/* DOM editing */
|
||||
function quote(message_id) {
|
||||
|
@ -136,7 +162,7 @@ function quote(message_id) {
|
|||
textbox.value += '>>' + message_id + '\n';
|
||||
textbox.focus();
|
||||
}
|
||||
function showPreview(event, message_id) {
|
||||
function show_preview(event, message_id) {
|
||||
let elem = document.getElementById('msg-' + message_id);
|
||||
if (!elem) { return; }
|
||||
let preview = document.getElementById('preview');
|
||||
|
@ -149,11 +175,11 @@ function showPreview(event, message_id) {
|
|||
preview.style.left = x;
|
||||
preview.style.maxWidth = maxWidth;
|
||||
}
|
||||
function clearPreview() {
|
||||
function clear_preview() {
|
||||
document.getElementById('preview').innerHTML = '';
|
||||
document.getElementById('preview').style.display = 'none';
|
||||
}
|
||||
function scrollToMsg(message_id) {
|
||||
function scroll_to_msg(message_id) {
|
||||
let elem = document.getElementById('msg-' + message_id);
|
||||
if (!elem) { return; }
|
||||
elem.scrollIntoView();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* Websocket receive */
|
||||
socket.events['new_post'] = function(data) {
|
||||
//deactivate_post();
|
||||
let qposts = document.getElementById('questPosts');
|
||||
let post_str = '<div class="questPost ';
|
||||
if (data.post_type === 'text') {
|
||||
|
@ -28,10 +27,9 @@ socket.events['new_post'] = function(data) {
|
|||
} else if (data.post_type === 'poll') {
|
||||
post_str += '<h3>' + data.post_text + ' - Open</h3>';
|
||||
post_str += '<table class="poll" id="poll-' + data.post_id + '">';
|
||||
post_str += '<col/><col/><col/>';
|
||||
for (i = 0; i < data.options.length; 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="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 += '<td class="option_text">' + data.options[i][1] + '</td>';
|
||||
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)
|
||||
poll_options = PollOption.objects.filter(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()
|
||||
return render(request, 'quest/quest.html', context)
|
||||
|
|
Loading…
Reference in New Issue
Block a user