Compare commits

...

2 Commits

Author SHA1 Message Date
6117fbe1e7 added writeins 2018-09-05 08:41:53 -04:00
1652b23590 prevent samefagging, show user votes on pageload, add todo list 2018-09-04 08:30:20 -04:00
7 changed files with 123 additions and 24 deletions

View File

@ -11,6 +11,7 @@ import types
import random import random
import bleach import bleach
from django.db import IntegrityError
from django.utils.timezone import localtime from django.utils.timezone import localtime
from quest.models import * from quest.models import *
@ -341,12 +342,45 @@ def vote(socket, data):
) )
if user.username: if user.username:
v.user = user v.user = user
v.save() try:
v.save()
except IntegrityError: # shouldn't we check this first?
return
data = {} data = {}
data['option_id'] = option_id data['option_id'] = option_id
data['polarity'] = polarity data['polarity'] = polarity
socket.send('vote', data) socket.send('vote', data)
def write_in(socket, data):
"""
Called when a player creates a new write-in.
"""
post_id = data.get('post_id')
option_text = data.get('option_text', '')
user = socket.scope['user']
option_text = option_text.strip()
if not option_text:
return
option_text = "Write in: " + bleach.clean(option_text)
if len(option_text) > 200:
# error message?
return
p = Poll.objects.get(post_id=post_id)
o = PollOption(
poll=p,
text=option_text
)
o.save()
data = {}
data['post_id'] = post_id
data['post_type'] = 'poll'
data['option_id'] = o.id
data['option_text'] = option_text
socket.send('update_post', data)
events = {} events = {}

View File

@ -71,7 +71,7 @@
{% for option in poll_options.filter(poll=post.poll).order_by("id") %} {% for option in poll_options.filter(poll=post.poll).order_by("id") %}
<tr id="optionRow-{{ option.id }}"> <tr id="optionRow-{{ option.id }}">
<td class="pollCheckBox"> <td class="pollCheckBox">
<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 %}/> <input type="checkbox" {% if poll_votes.filter(option=option, ip_address=ip_address) %}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>
@ -79,12 +79,12 @@
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
{# if post.id == quest.open_post_id and post.id|is_write_in %} {% if post.poll.open and post.poll.allow_writein %}
<div id="writeinContainer"> <div id="writeinContainer-{{ post.id }}">
Write-in: <input type="text" id="writeinInput" placeholder="Custom choice..." maxlength="200" /><br /> Write-in: <input type="text" id="writeinInput-{{ post.id }}" placeholder="Custom choice..." maxlength="200" /><br />
<input type="submit" id="writeinSubmit" value="Submit" onclick="submitWritein({{ post.id }});"/> <input type="submit" id="writeinSubmit-{{ post.id }}" value="Submit" onclick="submitWritein({{ post.id }});"/>
</div> </div>
{% endif #} {% endif %}
{% endif %} {% endif %}
</div> </div>
</div><br /> </div><br />

View File

@ -0,0 +1,17 @@
# Generated by Django 2.1 on 2018-09-04 11:32
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('quest', '0011_auto_20180902_2007'),
]
operations = [
migrations.AlterUniqueTogether(
name='pollvote',
unique_together={('option', 'ip_address')},
),
]

View File

@ -126,6 +126,9 @@ class PollVote(models.Model):
null=True) null=True)
ip_address = models.GenericIPAddressField() ip_address = models.GenericIPAddressField()
class Meta:
unique_together = ('option', 'ip_address')
class PageTitle(models.Model): class PageTitle(models.Model):
""" """

View File

@ -70,8 +70,8 @@ socket.events['new_post'] = function(data) {
post_str += '</table>'; post_str += '</table>';
if (data.allow_writein) { if (data.allow_writein) {
post_str += '<div id="writeinContainer">'; post_str += '<div id="writeinContainer">';
post_str += 'Write-in: <input type="text" id="writeinInput" placeholder="Custom choice..." maxlength="200" /><br />'; post_str += 'Write-in: <input type="text" id="writeinInput-' + data.post_id + '" placeholder="Custom choice..." maxlength="200" /><br />';
post_str += '<input type="submit" id="writeinSubmit" value="Submit" onclick="submitWritein({{ quest_post[0] }});"/></div>'; post_str += '<input type="submit" id="writeinSubmit-' + data.post_id + '" value="Submit" onclick="submitWritein(' + data.post_id + ');"/></div>';
} }
} }
post_str += '</div></div><br />'; post_str += '</div></div><br />';
@ -95,16 +95,17 @@ socket.events['close_all_posts'] = function(data) {
} }
socket.events['update_post'] = function(data) { socket.events['update_post'] = function(data) {
let post = document.getElementById('questPostData-' + data.post_id); let post = document.getElementById('questPostData-' + data.post_id);
if (data.post_type === 'text') { if (data.post_type === 'text') { // edit post
post.innerHTML = data.post_text; post.innerHTML = data.post_text;
} else if (data.post_type === 'dice') { } else if (data.post_type === 'dice') { // diceroll
post.innerHTML += '<b>' + data.post_text + '</b><br>'; post.innerHTML += '<b>' + data.post_text + '</b><br>';
} else if (data.post_type === 'poll') { } else if (data.post_type === 'poll') { // write-in
let row = post.children[1].insertRow(-1); let row = post.children[1].insertRow(-1);
row.id = 'optionRow-' + data.option_id;
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="vote(' + data.post_id + ',' + data.options_id + ')"/>'; cell.innerHTML = '<input type="checkbox" id="pollInput-' + data.option_id + '" onchange="vote(' + data.post_id + ',' + data.option_id + ')"/>';
cell.innerHTML += '<label for="pollInput-' + data.options_id + '"></label>'; cell.innerHTML += '<label for="pollInput-' + data.option_id + '"></label>';
cell = row.insertCell(1); cell = row.insertCell(1);
cell.className = 'option_text'; cell.className = 'option_text';
@ -140,6 +141,14 @@ function vote(post_id, option_id) {
let polarity = document.getElementById('pollInput-' + option_id).checked; 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}); socket.send('vote', {post_id: post_id, option_id: option_id, polarity: polarity, quest_id: quest_id});
} }
function submitWritein(post_id) {
let writeinInput = document.getElementById('writeinInput-' + post_id);
if (!writeinInput) { return; }
let option_text = writeinInput.value;
writeinInput.value = '';
if (!option_text) { return; }
socket.send('write_in', {option_text: option_text, post_id: post_id});
}
/* Helpers */ /* Helpers */
function padToTwo(number) { function padToTwo(number) {
@ -193,7 +202,7 @@ function close_post(post_id) {
for (let i = 0; i < boxes.length; i++) { for (let i = 0; i < boxes.length; i++) {
boxes[i].disabled = true; boxes[i].disabled = true;
} }
let writein = document.getElementById('writeinContainer'); let writein = document.getElementById('writeinContainer-' + post_id);
if (writein) { if (writein) {
writein.style.display = 'none'; writein.style.display = 'none';
} }
@ -209,7 +218,7 @@ function open_post(post_id) {
for (let i = 0; i < boxes.length; i++) { for (let i = 0; i < boxes.length; i++) {
boxes[i].disabled = false; boxes[i].disabled = false;
} }
let writein = document.getElementById('writeinContainer'); let writein = document.getElementById('writeinContainer-' + post_id);
if (writein) { if (writein) {
writein.style.display = 'initial'; writein.style.display = 'initial';
} }

View File

@ -37,8 +37,8 @@ socket.events['new_post'] = function(data) {
post_str += '</table>'; post_str += '</table>';
if (data.allow_writein) { if (data.allow_writein) {
post_str += '<div id="writeinContainer">'; post_str += '<div id="writeinContainer">';
post_str += 'Write-in: <input type="text" id="writeinInput" placeholder="Custom choice..." maxlength="200" /><br />'; post_str += 'Write-in: <input type="text" id="writeinInput-' + data.post_id + '" placeholder="Custom choice..." maxlength="200" /><br />';
post_str += '<input type="submit" id="writeinSubmit" value="Submit" onclick="submitWritein({{ quest_post[0] }});"/></div>'; post_str += '<input type="submit" id="writeinSubmit-' + data.post_id + '" value="Submit" onclick="submitWritein(' + data.post_id + ');"/></div>';
} }
} }
post_str += '</div></div><br />'; post_str += '</div></div><br />';
@ -111,7 +111,7 @@ function close_post(post_id) {
for (let i = 0; i < boxes.length; i++) { for (let i = 0; i < boxes.length; i++) {
boxes[i].disabled = true; boxes[i].disabled = true;
} }
let writein = document.getElementById('writeinContainer'); let writein = document.getElementById('writeinContainer-' + post_id);
if (writein) { if (writein) {
writein.style.display = 'none'; writein.style.display = 'none';
} }
@ -131,7 +131,7 @@ function open_post(post_id) {
for (let i = 0; i < boxes.length; i++) { for (let i = 0; i < boxes.length; i++) {
boxes[i].disabled = false; boxes[i].disabled = false;
} }
let writein = document.getElementById('writeinContainer'); let writein = document.getElementById('writeinContainer-' + post_id);
if (writein) { if (writein) {
writein.style.display = 'initial'; writein.style.display = 'initial';
} }

36
todo Normal file
View File

@ -0,0 +1,36 @@
New Features:
Pages/appendixes
Live indicator/countdown
Notifications
Anonymous names
Banner images
Search page
Front page to show new quests
Webm posting
(you) counter
Enable namefagging
Account managament/logout
Display profile link in header bar
Tagging system
Quote backlinks
Make chat hideable
Improvements:
Revamp post editing
More options for text posts (lists and so on)
More rigorous input checking in events.py
New post displays chat message
Record email on signup
Change urls
Poll vote highlights entire option
Poll vote doesn't disappear checkbox
Total voters per poll
Chat archives
Only last 100 (50?) chat messages are loaded on page load
Adjust quote preview postioning
Port from old code:
Edit post
Edit quest
Pages
Images