diff options
-rw-r--r-- | apioforum/auth.py | 5 | ||||
-rw-r--r-- | apioforum/forum.py | 19 | ||||
-rw-r--r-- | apioforum/mdrender.py | 1 | ||||
-rw-r--r-- | apioforum/static/style.css | 97 | ||||
-rw-r--r-- | apioforum/templates/auth/register.html | 2 | ||||
-rw-r--r-- | apioforum/templates/common.html | 6 | ||||
-rw-r--r-- | apioforum/templates/user_settings.html | 4 | ||||
-rw-r--r-- | apioforum/templates/view_forum.html | 85 |
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"> & 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%} |