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 bleach
from django.db import IntegrityError
from django.utils.timezone import localtime
from quest.models import *
@ -341,12 +342,45 @@ def vote(socket, data):
)
if user.username:
v.user = user
v.save()
try:
v.save()
except IntegrityError: # shouldn't we check this first?
return
data = {}
data['option_id'] = option_id
data['polarity'] = polarity
socket.send('vote', data)
data = {}
data['option_id'] = option_id
data['polarity'] = polarity
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 = {}

View File

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

View File

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

View File

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