Compare commits

...

1 Commits

Author SHA1 Message Date
311b4723ea split quests table, added ability to update quest 2018-06-20 13:45:31 -04:00
7 changed files with 132 additions and 33 deletions

View File

@ -1,17 +1,22 @@
CREATE TABLE `users` ( CREATE TABLE `users` (
`id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, `user_id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
`username` VARCHAR(20) NOT NULL, `username` VARCHAR(20) NOT NULL,
`password_hash` CHAR(73) NOT NULL, `password_hash` CHAR(73) NOT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`user_id`)
) ENGINE=InnoDB CHARSET utf8mb4; ) ENGINE=InnoDB CHARSET utf8mb4;
CREATE TABLE `quests` ( CREATE TABLE `quest_meta` (
`id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, `quest_id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
`canon_title` VARCHAR(300) DEFAULT NULL, `canon_title` VARCHAR(300) DEFAULT NULL,
`ident_title` VARCHAR(300) DEFAULT NULL, `ident_title` VARCHAR(300) DEFAULT NULL,
`owner_id` SMALLINT UNSIGNED DEFAULT NULL, `owner_id` SMALLINT UNSIGNED DEFAULT NULL,
`quest_data` MEDIUMTEXT DEFAULT NULL, PRIMARY KEY (`quest_id`)
PRIMARY KEY (`id`) ) ENGINE=InnoDB CHARSET utf8mb4;
CREATE TABLE `quest_data` (
`quest_id` SMALLINT UNSIGNED NOT NULL,
`post` MEDIUMTEXT NOT NULL,
`timestamp` INT UNSIGNED NOT NULL
) ENGINE=InnoDB CHARSET utf8mb4; ) ENGINE=InnoDB CHARSET utf8mb4;
CREATE TABLE `chat_messages` ( CREATE TABLE `chat_messages` (

View File

@ -111,3 +111,43 @@ def get_chat_messages(room_id):
"SELECT * FROM `chat_messages` WHERE `room_id` = %s " \ "SELECT * FROM `chat_messages` WHERE `room_id` = %s " \
+ "ORDER BY `date` ASC", (room_id,)).fetchall() + "ORDER BY `date` ASC", (room_id,)).fetchall()
return res return res
def insert_quest(canon_title, ident_title, owner_id):
"""
Creates a new quest entry.
"""
_DB.execute(
"INSERT INTO `quest_meta` (`canon_title`, `ident_title`, `owner_id`) "\
+ "VALUES (%s, %s, %s)", (canon_title, ident_title, owner_id))
quest_id = _DB.execute(
"SELECT `quest_id` FROM `quest_meta` WHERE `ident_title` = %s",
(ident_title,)).fetchone()[0]
return quest_id
def insert_quest_post(quest_id, post, timestamp):
"""
Insers a new quest post.
"""
_DB.execute(
"INSERT INTO `quest_data` (`quest_id`, `post`, `timestamp`) " \
"VALUES (%s, %s, %s)", (quest_id, post, timestamp))
def get_quest_meta(ident_title):
"""
Retrieves all meta info about a quest.
"""
data = _DB.execute("SELECT * FROM `quest_meta` WHERE `ident_title` = %s",
(ident_title,)).fetchone()
return data
def get_quest_data(quest_id):
"""
Retrieves all quest posts.
"""
data = _DB.execute("SELECT * FROM `quest_data` WHERE `quest_id` = %s",
(quest_id,)).fetchall()
return data

View File

@ -11,7 +11,7 @@ import database as db
socketio = SocketIO() socketio = SocketIO()
@socketio.on('joined', namespace="/chat") @socketio.on('joined')
def joined(data): def joined(data):
""" """
Sent by clients when they enter a room. Sent by clients when they enter a room.
@ -20,8 +20,8 @@ def joined(data):
join_room(room) join_room(room)
@socketio.on('message', namespace="/chat") @socketio.on('message')
def text(data): def message(data):
""" """
Sent by a client when the user entered a new message. Sent by a client when the user entered a new message.
""" """
@ -46,3 +46,19 @@ def text(data):
db.log_chat_message(data) db.log_chat_message(data)
emit("message", data, room=room) emit("message", data, room=room)
@socketio.on("new_post")
def new_post(data):
"""
Called when the QM makes a new post.
"""
room = data["room"]
post = data["post"]
post = bleach.clean(post.strip())
post = post.replace("\n", "<br />")
data["post"] = [post]
db.insert_quest_post(int(room), post, int(time.time()))
emit("new_post", data, room=room)

View File

@ -1,4 +1,5 @@
#header { .header {
display: initial;
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
@ -9,10 +10,15 @@
background-color: #dddddd; background-color: #dddddd;
} }
#header li { .header li {
display: inline; display: inline;
} }
#headerHidden {
display: none;
width: auto;
}
#questContainer { #questContainer {
display: flex; display: flex;
overflow: auto; overflow: auto;
@ -23,6 +29,9 @@
padding-right: 32%; padding-right: 32%;
} }
#newQPostArea {
}
#chatPane { #chatPane {
height: 100%; height: 100%;
width: 30%; width: 30%;
@ -38,14 +47,14 @@
flex: 1; flex: 1;
} }
#messageBox { #messageTextDiv {
padding-bottom: 10px; padding-bottom: 10px;
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
#messageTextarea { #messageTextArea {
resize: none; resize: none;
box-sizing: border-box; box-sizing: border-box;
} }

View File

@ -21,9 +21,7 @@
<ul id="header" class="header" style="display:initial;"> <ul id="header" class="header" style="display:initial;">
<li><a onclick="toggleHeader();" href="javascript:void(0);">^</a></li> <li><a onclick="toggleHeader();" href="javascript:void(0);">^</a></li>
<li><a href="{{ url_for('views.index') }}">Home</a></li> <li><a href="{{ url_for('views.index') }}">Home</a></li>
{% if session.get("user_id") == owner_id %} {% block header %}{% endblock %}
<li><a href="{{ url_for('views.edit_quest') }}">Edit Quest</a></li>
{% endif %}
</ul> </ul>
<ul id="headerHidden" class="header" style="display:none;"> <ul id="headerHidden" class="header" style="display:none;">
<li><a onclick="toggleHeader();" href="javascript:void(0);">^</a></li> <li><a onclick="toggleHeader();" href="javascript:void(0);">^</a></li>

View File

@ -8,7 +8,7 @@
if ( document.readyState !== 'complete' ) return; if ( document.readyState !== 'complete' ) return;
clearInterval( tid ); clearInterval( tid );
socket = io.connect('https://' + document.domain + ':' + location.port + '/chat'); socket = io.connect('https://' + document.domain + ':' + location.port);
socket.on('connect', function() { socket.on('connect', function() {
socket.emit('joined', {room: '{{ room_id }}' }); socket.emit('joined', {room: '{{ room_id }}' });
}); });
@ -25,7 +25,11 @@
mbox.innerHTML = mbox.innerHTML + msg_str; mbox.innerHTML = mbox.innerHTML + msg_str;
mbox.scrollTop = mbox.scrollHeight; mbox.scrollTop = mbox.scrollHeight;
}); });
mtarea = document.getElementById('messageTextarea'); socket.on('new_post', function(data) {
qposts = document.getElementById('questPosts');
qposts.innerHTML = qposts.innerHTML + '<div class="questPost">' + data.post + '</div>';
});
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(); text = mtarea.value.trim();
@ -42,14 +46,42 @@
return number; return number;
} }
</script> </script>
{% if session.get("user_id") == owner_id %}
<script>
function makePost() {
qparea = document.getElementById('postTextArea');
text = qparea.value.trim();
qparea.value = '';
if (text == '') { return; }
socket.emit('new_post', {post: text, room: '{{ room_id }}'});
}
</script>
{% endif %}
{% endblock %}
{% block header %}
{% if session.get("user_id") == owner_id %}
<li><a href="{{ url_for('views.edit_quest') }}">Edit Quest</a></li>
{% endif %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div id="questContainer"> <div id="questContainer">
<div id="questBody"> <div id="questBody">
<h1>{{ quest_title }}</h1> <h1>{{ quest_title }}</h1>
<div id="questPosts">
{% for quest_post in quest_posts %}
{% autoescape false %} {% autoescape false %}
{{ quest_body }} <div class="questPost">
{{ quest_post[1] }}
</div>
{% endautoescape %} {% endautoescape %}
{% endfor %}
</div>
{% if session.get("user_id") == owner_id %}
<div id="postTextDiv">
<textarea id="postTextArea"></textarea><br />
<input type="submit" name="newPost" value="Post" onclick="makePost();"/>
</div>
{% endif %}
</div> </div>
<div id="chatPane"> <div id="chatPane">
<h1>Chat</h1> <h1>Chat</h1>
@ -65,7 +97,7 @@
{% endfor %} {% endfor %}
{% endautoescape %} {% endautoescape %}
</div> </div>
<div id="messageBox"><textarea id="messageTextarea"></textarea></div> <div id="messageTextDiv"><textarea id="messageTextArea"></textarea></div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -2,6 +2,7 @@
""" """
Database tools and functions. Database tools and functions.
""" """
import time
import string import string
import urllib import urllib
import functools import functools
@ -55,17 +56,16 @@ def quest(quest_title):
""" """
An arbituary quest page. An arbituary quest page.
""" """
quest_title, _, extra = quest_title.partition("/") ident_title, _, extra = quest_title.partition("/")
res = db._DB.execute("SELECT * FROM `quests` WHERE `ident_title` = %s", data = db.get_quest_meta(ident_title)
(quest_title,))
data = res.fetchone()
if not data: if not data:
abort(404) abort(404)
quest_id, quest_title, _, owner_id, quest_data = data quest_id, quest_title, _, owner_id = data
quest_posts = db.get_quest_data(quest_id)
messages = db.get_chat_messages(quest_id) messages = db.get_chat_messages(quest_id)
return render_template('quest.html', return render_template('quest.html',
quest_title=quest_title, quest_title=quest_title,
quest_body=quest_data, quest_posts=quest_posts,
owner_id=owner_id, owner_id=owner_id,
room_id=quest_id, room_id=quest_id,
messages=messages) messages=messages)
@ -87,12 +87,11 @@ def create_quest():
quest_body = quest_body.replace("\n", "<br />") quest_body = quest_body.replace("\n", "<br />")
owner_id = session.get("user_id") owner_id = session.get("user_id")
timestamp = int(time.time())
quest_id = db.insert_quest(canon_title, ident_title, owner_id)
db.insert_quest_post(quest_id, quest_body, timestamp)
db._DB.execute(
"INSERT INTO `quests` " \
+ "(`canon_title`, `ident_title`, `owner_id`, `quest_data`) " \
+ "VALUES (%s, %s, %s, %s)",
(canon_title, ident_title, owner_id, quest_body))
return redirect(url_for('views.quest', quest_title=ident_title)) return redirect(url_for('views.quest', quest_title=ident_title))