summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--apioforum/auth.py5
-rw-r--r--apioforum/forum.py19
-rw-r--r--apioforum/mdrender.py1
-rw-r--r--apioforum/static/style.css97
-rw-r--r--apioforum/templates/auth/register.html2
-rw-r--r--apioforum/templates/common.html6
-rw-r--r--apioforum/templates/user_settings.html4
-rw-r--r--apioforum/templates/view_forum.html85
8 files changed, 118 insertions, 101 deletions
diff --git a/apioforum/auth.py b/apioforum/auth.py
index 8a34700..39cf1f8 100644
--- a/apioforum/auth.py
+++ b/apioforum/auth.py
@@ -54,6 +54,10 @@ def register():
"SELECT 1 FROM users WHERE username = ?;", (username,)
).fetchone() is not None:
err = f"User {username} is already registered."
+ elif len(username) > 20:
+ err = "username can't be longer than 20 characters"
+ elif not username.isalnum():
+ err = "username must be alphanumeric"
if err is None:
db.execute(
@@ -63,7 +67,6 @@ def register():
db.commit()
flash("successfully created account")
session['user'] = username
- flash("registered successfully")
return redirect(get_next())
flash(err)
diff --git a/apioforum/forum.py b/apioforum/forum.py
index e2e5474..09d3166 100644
--- a/apioforum/forum.py
+++ b/apioforum/forum.py
@@ -11,6 +11,8 @@ from .mdrender import render
from sqlite3 import OperationalError
+from sqlite3 import OperationalError
+
bp = Blueprint("forum", __name__, url_prefix="/")
@bp.route("/")
@@ -31,6 +33,7 @@ def view_forum(forum_id):
ORDER BY threads.updated DESC;
""",(forum_id,)).fetchall()
thread_tags = {}
+ preview_post = {}
#todo: somehow optimise this
for thread in threads:
thread_tags[thread['id']] = db.execute(
@@ -39,12 +42,16 @@ def view_forum(forum_id):
WHERE thread_tags.thread = ?
ORDER BY tags.id;
""",(thread['id'],)).fetchall()
- return render_template(
- "view_forum.html",
- threads=threads,
- thread_tags=thread_tags,
- forum=forum
- )
+ preview_post[thread['id']] = db.execute(
+ """SELECT * FROM posts WHERE thread = ?
+ ORDER BY created DESC;
+ """,(thread['id'],)).fetchone()
+ return render_template("view_forum.html",
+ forum=forum,
+ threads=threads,
+ thread_tags=thread_tags,
+ preview_post=preview_post
+ )
@bp.route("/<int:forum_id>/create_thread",methods=("GET","POST"))
def create_thread(forum_id):
diff --git a/apioforum/mdrender.py b/apioforum/mdrender.py
index 5f5292d..8c59c42 100644
--- a/apioforum/mdrender.py
+++ b/apioforum/mdrender.py
@@ -12,6 +12,7 @@ allowed_tags = [
'del',
'mark',
'img',
+ 'marquee'
]
allowed_attributes = bleach.sanitizer.ALLOWED_ATTRIBUTES.copy()
diff --git a/apioforum/static/style.css b/apioforum/static/style.css
index 21fc5ef..86611f6 100644
--- a/apioforum/static/style.css
+++ b/apioforum/static/style.css
@@ -88,53 +88,66 @@ nav#navbar .links { display: flex; }
/* todo: make the navbar less bad */
.flashmsg { border: 1px solid black; background-color: yellow; max-width: max-content; padding: 5px; clear: both;}
-.threadlisting:nth-child(even) { background-color: var(--alternating-colour-even) }
-.threadlisting:nth-child(odd) { background-color: var(--alternating-colour-odd) }
-
+.thread-listing:nth-child(even) { background-color: var(--alternating-colour-even) }
+.thread-listing:nth-child(odd) { background-color: var(--alternating-colour-odd) }
+.thread-listing {
+ border-left: 1px solid black;
+ border-right: 1px solid black;
+ border-top: 1px solid black;
+ padding: 10px;
+}
+.thread-listing:last-of-type { border-bottom: 1px solid black; }
+.thread-listing-main {
+ display: flex;
+ align-items: center;
+}
+.thread-listing-title {
+ overflow: hidden;
+ font-size: larger;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ flex-grow: 1;
+}
+.thread-listing-tags {
+ display: flex;
+ align-items: center;
+ flex-wrap: nowrap;
+ flex-shrink: 0;
+}
+.thread-listing-tags .tag { margin-left: 5px; }
+.thread-listing-creation {
+ display: flex;
+ margin-left: 5px;
+ flex-wrap: nowrap;
+}
+.thread-listing-creator { margin-right: 5px; }
+.thread-preview {
+ overflow: hidden;
+ font-size: smaller;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ margin-top: 10px;
+}
+.thread-preview-post a, .thread-preview-post a:visited {
+ color: black;
+ text-decoration: none;
+}
+.thread-preview-post { font-style: italic; }
+.thread-preview-ts { font-weight: bold; }
/* wide screens */
-@media all and (min-width: 800px) {
- .threadlisting { display: contents }
- .threadlistings {
- display: grid;
- grid-template-columns: 2fr repeat(5,1fr) 0.4fr;
- }
-
- .threadlisting-part {
- border-left: 1px solid black;
- border-top: 1px solid black;
- }
- .threadlistings {
- border-right: 1px solid black;
- border-bottom: 1px solid black;
- }
-
- .only-small { display: none !important }
-
-
-}
+@media all and (min-width: 600px) { }
/* small screens */
-@media not all and (min-width: 800px) {
- .threadlisting {
- display: grid;
- grid-template-columns: repeat(5,1fr);
- margin-bottom: 5px;
- }
- .threadlisting-part-title {
- grid-column: 1 / -1;
- }
- .threadlisting-part {
- border-left: 1px solid black;
- border-top: 1px solid black;
- }
- .threadlisting {
- border-right: 1px solid black;
- border-bottom: 1px solid black;
- }
-
- .only-big { display: none !important }
+@media not all and (min-width: 600px) {
+ .thread-listing-creation { font-size: small; }
+ .thread-listing-creator {
+ max-width: 75px;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
}
diff --git a/apioforum/templates/auth/register.html b/apioforum/templates/auth/register.html
index 7d079c2..5d27b90 100644
--- a/apioforum/templates/auth/register.html
+++ b/apioforum/templates/auth/register.html
@@ -7,7 +7,7 @@
<p>create a new account here. if you already have an account, <a href="{{url_for('auth.login')}}">login</a> instead.</p>
<form method="post">
<label for="username">Username</label>
- <input name="username" id="username" required>
+ <input name="username" id="username" maxlength="20" required>
<br>
<label for="password">Password</label>
<input type="password" name="password" id="password" required>
diff --git a/apioforum/templates/common.html b/apioforum/templates/common.html
index 28598e7..9301a49 100644
--- a/apioforum/templates/common.html
+++ b/apioforum/templates/common.html
@@ -2,6 +2,10 @@
<a href="{{url_for('user.view_user',username=username)}}" class="username">{{username}}</a>
{%- endmacro %}
+{% macro post_url(post) -%}
+ {{url_for('thread.view_thread', thread_id=post.thread)}}#post_{{post.id}}
+{%- endmacro %}
+
{% macro disp_post(post, buttons=False) %}
<div class="post" id="post_{{post.id}}">
<div class="post-heading">
@@ -19,7 +23,7 @@
<a class="actionbutton"
href="{{url_for('thread.delete_post',post_id=post.id)}}">delete</a>
{% endif %}
- <a class="post-anchor-link" href="{{url_for('thread.view_thread', thread_id=post.thread)}}#post_{{post.id}}">#{{post.id}}</a>
+ <a class="post-anchor-link" href="{{post_url(post)}}">#{{post.id}}</a>
</span>
</div>
<div class="post-content">
diff --git a/apioforum/templates/user_settings.html b/apioforum/templates/user_settings.html
index cac613a..d463eee 100644
--- a/apioforum/templates/user_settings.html
+++ b/apioforum/templates/user_settings.html
@@ -5,9 +5,9 @@
<fieldset>
<legend>change password</legend>
<label for="password">current password</label>
-<input type="text" id="password" name="password"><br>
+<input type="password" id="password" name="password"><br>
<label for="new_password">new password</label>
-<input type="text" id="new_password" name="new_password">
+<input type="password" id="new_password" name="new_password">
</fieldset>
<fieldset>
<legend>change bio</legend>
diff --git a/apioforum/templates/view_forum.html b/apioforum/templates/view_forum.html
index c5bcef1..f83503b 100644
--- a/apioforum/templates/view_forum.html
+++ b/apioforum/templates/view_forum.html
@@ -1,5 +1,5 @@
{% extends 'base.html' %}
-{% from 'common.html' import ts, tag, disp_user %}
+{% from 'common.html' import ts, tag, disp_user, post_url %}
{% block header %}<h1>{% block title %}{{forum.name}}{%endblock%}</h1>{%endblock%}
{%block nmcontent%}
<main class="widemain">
@@ -9,53 +9,42 @@
{% else %}
<p>please log in to create a new thread</p>
{% endif %}
-<div class="threadlistings">
-<div class="threadlisting">
- <div class="threadlisting-part threadlisting-part-title threadlisting-header">
- name<span class="only-small"> &amp; tags</span>
- </div>
- <div class="threadlisting-part threadlisting-part-tags threadlisting-header only-big">
- tags
- </div>
- <div class="threadlisting-part threadlisting-part-creator threadlisting-header">
- creator
- </div>
- <div class="threadlisting-part threadlisting-part-created threadlisting-header">
- created
- </div>
- <div class="threadlisting-part threadlisting-part-updated threadlisting-header">
- last updated
- </div>
- <div class="threadlisting-part threadlisting-part-lastactivityby threadlisting-header">
- last post by
- </div>
- <div class="threadlisting-part threadlisting-part-numreplies threadlisting-header">
- posts
- </div>
-</div>
-{%for thread in threads%}
-<div class="threadlisting">
- <div class="threadlisting-part threadlisting-part-title"><a href="{{url_for('thread.view_thread',thread_id=thread.id)}}">{{thread.title}}</a>
- {% if thread_tags[thread.id]|length > 0 %}
- <span class="only-small">
- {% for the_tag in thread_tags[thread.id] %}
- {{tag(the_tag)}}
- {% endfor %}
- </span>
- {%endif%}
- </div>
- <div class="threadlisting-part threadlisting-part-tags only-big">
- {% for the_tag in thread_tags[thread.id] %}
- {{tag(the_tag)}}
- {% endfor %}
- </div>
- <div class="threadlisting-part threadlisting-part-creator">{{disp_user(thread.creator)}}</div>
- <div class="threadlisting-part threadlisting-part-created">{{ts(thread.created)}}</div>
- <div class="threadlisting-part threadlisting-part-updated">{{ts(thread.updated)}}</div>
- <div class="threadlisting-part threadlisting-part-lastactivityby">{{disp_user(thread.last_user)}}</div>
- <div class="threadlisting-part threadlisting-part-numreplies">{{thread.num_replies}}</div>
-</div>
-{%endfor%}
+<div class="thread-list">
+ {%for thread in threads%}
+ <div class="thread-listing">
+ <div class="thread-listing-main">
+ <div class="thread-listing-title">
+ <a href="{{url_for('thread.view_thread',thread_id=thread.id)}}">
+ {{- thread.title -}}
+ </a>
+ </div>
+ <div class="thread-listing-tags">
+ {% for the_tag in thread_tags[thread.id] %}
+ {{tag(the_tag)}}
+ {% endfor %}
+ </div>
+ <div class="thread-listing-creation">
+ <div class="thread-listing-creator">
+ {{ disp_user(thread.creator) }}
+ </div>
+ {{ ts(thread.created) }}
+ </div>
+ </div>
+ {% if preview_post[thread.id] %}
+ <div class="thread-preview">
+ {{ disp_user(preview_post[thread.id].author) }}
+ <span class="thread-preview-ts">
+ {{ ts(preview_post[thread.id].created) }}
+ </span>
+ <span class="thread-preview-post">
+ <a href="{{post_url(preview_post[thread.id])}}">
+ {{ preview_post[thread.id].content[:500]|e }}
+ </a>
+ </span>
+ </div>
+ {% endif %}
+ </div>
+ {%endfor%}
</div>
</main>
{%endblock%}