added editing posts in place

This commit is contained in:
iou1name 2018-06-21 20:44:43 -04:00
parent 7d19270a69
commit fdf7643f08
6 changed files with 90 additions and 21 deletions

View File

@ -15,9 +15,11 @@ CREATE TABLE `quest_meta` (
) ENGINE=InnoDB CHARSET utf8mb4; ) ENGINE=InnoDB CHARSET utf8mb4;
CREATE TABLE `quest_data` ( CREATE TABLE `quest_data` (
`post_id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
`quest_id` SMALLINT UNSIGNED NOT NULL, `quest_id` SMALLINT UNSIGNED NOT NULL,
`post` MEDIUMTEXT NOT NULL, `post` MEDIUMTEXT NOT NULL,
`timestamp` INT UNSIGNED NOT NULL `timestamp` INT UNSIGNED NOT NULL,
PRIMARY KEY (`post_id`)
) ENGINE=InnoDB CHARSET utf8mb4; ) ENGINE=InnoDB CHARSET utf8mb4;
CREATE TABLE `chat_messages` ( CREATE TABLE `chat_messages` (

View File

@ -65,7 +65,7 @@ def verify_password(username, password):
if not user: if not user:
return False return False
user_id, _, pw_hash = user user_id, _, pw_hash, _ = user
if argon2.verify(password, pw_hash): if argon2.verify(password, pw_hash):
session["user_id"] = user_id session["user_id"] = user_id
@ -135,12 +135,20 @@ def insert_quest_post(quest_id, post, timestamp):
"VALUES (%s, %s, %s)", (quest_id, post, timestamp)) "VALUES (%s, %s, %s)", (quest_id, post, timestamp))
def get_quest_meta(ident_title): def get_quest_meta(quest_id=None, ident_title=None):
""" """
Retrieves all meta info about a quest. Retrieves all meta info about a quest. Allows searching by either
quest_id or ident_title.
""" """
data = _DB.execute("SELECT * FROM `quest_meta` WHERE `ident_title` = %s", statement = "SELECT * FROM `quest_meta` WHERE "
(ident_title,)).fetchone() if quest_id:
statement += "`quest_id` = %s"
data = _DB.execute(statement, (quest_id,)).fetchone()
elif ident_title:
statement += "`ident_title` = %s"
data = _DB.execute(statement, (ident_title,)).fetchone()
else:
return
return data return data
@ -171,3 +179,12 @@ def get_user_quests(user_id):
"SELECT * FROM `quest_meta` WHERE `owner_id` = %s", "SELECT * FROM `quest_meta` WHERE `owner_id` = %s",
(user_id,)).fetchall() (user_id,)).fetchall()
return data return data
def update_quest_post(post_id, new_post):
"""
Updates a quest post.
"""
_DB.execute(
"UPDATE `quest_data` SET `post` = %s WHERE `post_id` = %s",
(new_post, post_id))

View File

@ -5,6 +5,7 @@ SocketIO events.
import time import time
import bleach import bleach
from flask import session
from flask_socketio import SocketIO, emit, join_room from flask_socketio import SocketIO, emit, join_room
import database as db import database as db
@ -54,11 +55,34 @@ def new_post(data):
Called when the QM makes a new post. Called when the QM makes a new post.
""" """
room = data["room"] room = data["room"]
post = data["post"] res = db.get_quest_meta(quest_id=room)
if not res:
return
if session.get("user_id") != res[3]:
return
post = data["post"]
post = bleach.clean(post.strip()) post = bleach.clean(post.strip())
post = post.replace("\n", "<br />") post = post.replace("\n", "<br />")
data["post"] = [post] data["post"] = [post]
db.insert_quest_post(room, post, int(time.time())) db.insert_quest_post(room, post, int(time.time()))
emit("new_post", data, room=room) emit("new_post", data, room=room)
@socketio.on("update_post")
def update_post(data):
"""
Called when the QM edits and saves a post.
"""
room = data["room"]
res = db.get_quest_meta(quest_id=room)
if not res:
return
if session.get("user_id") != res[3]:
return
post = data["post"]
post_id = data["post_id"]
db.update_quest_post(post_id, post)
emit("update_post", data, room=room)

View File

@ -30,7 +30,7 @@
} }
#questPosts { #questPosts {
border-spacing: 10px; border-spacing: 15px;
} }
.questPostTime { .questPostTime {
@ -38,6 +38,10 @@
white-space: nowrap; white-space: nowrap;
} }
.questPostData {
vertical-align: top;
}
#newQPostArea { #newQPostArea {
} }

View File

@ -13,26 +13,30 @@
socket.emit('joined', {room: {{ room_id }}}); socket.emit('joined', {room: {{ room_id }}});
}); });
socket.on('message', function(data) { socket.on('message', function(data) {
date = new Date(data.date * 1000); var date = new Date(data.date * 1000);
date_str = date.getFullYear() + '-' + padToTwo(date.getMonth()+1) + '-' + padToTwo(date.getDate()) + ' '; var date_str = date.getFullYear() + '-' + padToTwo(date.getMonth()+1) + '-' + padToTwo(date.getDate()) + ' ';
date_str += padToTwo(date.getHours()) + ':' + padToTwo(date.getMinutes()) + ':' + padToTwo(date.getSeconds()); date_str += padToTwo(date.getHours()) + ':' + padToTwo(date.getMinutes()) + ':' + padToTwo(date.getSeconds());
msg_str = '<div class="messageHeader">\n<span class="messageName">' + data.name + '</span> '; var msg_str = '<div class="messageHeader">\n<span class="messageName">' + data.name + '</span> ';
msg_str += '<span class="messageDate">' + date_str + '</span>\n</div>\n'; msg_str += '<span class="messageDate">' + date_str + '</span>\n</div>\n';
msg_str += '<div class="message">' + data.message + '</div>\n'; msg_str += '<div class="message">' + data.message + '</div>\n';
mbox = document.getElementById('chatWindow'); var mbox = document.getElementById('chatWindow');
mbox.innerHTML = mbox.innerHTML + msg_str; mbox.innerHTML = mbox.innerHTML + msg_str;
mbox.scrollTop = mbox.scrollHeight; mbox.scrollTop = mbox.scrollHeight;
}); });
socket.on('new_post', function(data) { socket.on('new_post', function(data) {
qposts = document.getElementById('questPosts'); var qposts = document.getElementById('questPosts');
qposts.innerHTML = qposts.innerHTML + '<div class="questPost">' + data.post + '</div>'; qposts.innerHTML = qposts.innerHTML + '<div class="questPost">' + data.post + '</div>';
}); });
mtarea = document.getElementById('messageTextArea'); socket.on('update_post', function(data) {
var post_id = data.post_id;
document.getElementById('questPostData-' + post_id).innerHTML = data.post;
});
var mtarea = document.getElementById('messageTextArea');
mtarea.addEventListener('keypress', function(event) { mtarea.addEventListener('keypress', function(event) {
if (event.key == 'Enter' && !event.shiftKey) { if (event.key == 'Enter' && !event.shiftKey) {
text = mtarea.value.trim(); var text = mtarea.value.trim();
mtarea.value = ''; mtarea.value = '';
if (text == '') { return; } if (text == '') { return; }
socket.emit('message', {message: text, name: 'Anonymous', room: {{ room_id }}}); socket.emit('message', {message: text, name: 'Anonymous', room: {{ room_id }}});
@ -49,12 +53,24 @@
{% if session.get("user_id") == owner_id %} {% if session.get("user_id") == owner_id %}
<script> <script>
function makePost() { function makePost() {
qparea = document.getElementById('postTextArea'); var qparea = document.getElementById('postTextArea');
text = qparea.value.trim(); var text = qparea.value.trim();
qparea.value = ''; qparea.value = '';
if (text == '') { return; } if (text == '') { return; }
socket.emit('new_post', {post: text, room: {{ room_id }}}); socket.emit('new_post', {post: text, room: {{ room_id }}});
} }
function edit_post(post_id) {
document.getElementById('questPostData-' + post_id).contentEditable = 'true';
document.getElementById('questPostData-' + post_id).style.border = '1px solid #ccc'
document.getElementById('savePost-' + post_id).style.display = 'initial';
}
function save_post(post_id) {
document.getElementById('questPostData-' + post_id).contentEditable = 'false';
document.getElementById('questPostData-' + post_id).style.border = null;
var text = document.getElementById('questPostData-' + post_id).innerHTML;
socket.emit('update_post', {post_id: post_id, post: text, room: {{ room_id }}});
document.getElementById('savePost-' + post_id).style.display = 'none';
}
</script> </script>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
@ -70,10 +86,16 @@
<table id="questPosts"> <table id="questPosts">
{% for quest_post in quest_posts %} {% for quest_post in quest_posts %}
<tr> <tr>
<td class="questPostTime">{{ quest_post[2] | strftime }}</td> <td class="questPostTime">
<td class="questPostData"> {{ quest_post[3] | strftime }}
{% if session.get("user_id") == owner_id %}
<br /><a href="javascript:void(0);" onclick="edit_post('{{ quest_post[0] }}')">Edit</a>
<a href="javascript:void(0);" id="savePost-{{ quest_post[0] }}" onclick="save_post('{{ quest_post[0] }}')" style="display:none;">Save</a>
{% endif %}
</td>
<td class="questPostData" id="questPostData-{{ quest_post[0] }}">
{% autoescape false %} {% autoescape false %}
{{ quest_post[1] }} {{ quest_post[2] }}
{% endautoescape %} {% endautoescape %}
</td> </td>
</tr> </tr>

View File

@ -57,7 +57,7 @@ def quest(quest_title):
An arbituary quest page. An arbituary quest page.
""" """
ident_title, _, extra = quest_title.partition("/") ident_title, _, extra = quest_title.partition("/")
data = db.get_quest_meta(ident_title) data = db.get_quest_meta(ident_title=ident_title)
if not data: if not data:
abort(404) abort(404)
quest_id, quest_title, _, owner_id = data quest_id, quest_title, _, owner_id = data