diff options
| -rw-r--r-- | apioforum/db.py | 12 | ||||
| -rw-r--r-- | apioforum/forum.py | 14 | ||||
| -rw-r--r-- | apioforum/static/style.css | 30 | ||||
| -rw-r--r-- | apioforum/templates/base.html | 2 | ||||
| -rw-r--r-- | apioforum/templates/common.html | 4 | ||||
| -rw-r--r-- | apioforum/templates/config_thread.html | 21 | ||||
| -rw-r--r-- | apioforum/templates/view_forum.html | 26 | ||||
| -rw-r--r-- | apioforum/templates/view_thread.html | 21 | ||||
| -rw-r--r-- | apioforum/thread.py | 26 | 
9 files changed, 140 insertions, 16 deletions
diff --git a/apioforum/db.py b/apioforum/db.py index c24aa0e..1d7bd2b 100644 --- a/apioforum/db.py +++ b/apioforum/db.py @@ -65,7 +65,19 @@ CREATE TRIGGER posts_au AFTER UPDATE ON posts BEGIN      INSERT INTO posts_fts(posts_fts, rowid, content) VALUES('delete', old.id, old.content);      INSERT INTO posts_fts(rowid, content) VALUES (new.id, new.content);  END; +""",  """ +CREATE TABLE tags ( +    id INTEGER PRIMARY KEY, +    name TEXT NOT NULL, +    text_colour TEXT NOT NULL, +    bg_colour TEXT NOT NULL +); +CREATE TABLE thread_tags ( +    thread INTEGER NOT NULL REFERENCES threads(id), +    tag INTEGER NOT NULL REFERENCES tags(id) +); +""",  ]  def init_db(): diff --git a/apioforum/forum.py b/apioforum/forum.py index 81674a8..98c71f7 100644 --- a/apioforum/forum.py +++ b/apioforum/forum.py @@ -5,11 +5,13 @@ from flask import (      Blueprint, render_template, request,      g, redirect, url_for, flash  ) +  from .db import get_db  from .mdrender import render  bp = Blueprint("forum", __name__, url_prefix="/") +  @bp.route("/")  def view_forum():      db = get_db() @@ -21,7 +23,15 @@ def view_forum():          GROUP BY threads.id          ORDER BY threads.updated DESC;          """).fetchall() -    return render_template("view_forum.html",threads=threads) +    thread_tags = {} +    #todo: somehow optimise this +    for thread in threads: +        thread_tags[thread['id']] = db.execute( +            """SELECT tags.* FROM tags +            INNER JOIN thread_tags ON thread_tags.tag = tags.id +            WHERE thread_tags.thread = ?; +            """,(thread['id'],)).fetchall() +    return render_template("view_forum.html",threads=threads,thread_tags=thread_tags)  @bp.route("/create_thread",methods=("GET","POST"))  def create_thread(): @@ -77,4 +87,4 @@ def search():              display_thread_id[ix] = False          last_thread = result["thread"]      rendered_posts = [render(q['content']) for q in results] -    return render_template("search_results.html", results=results, query=query, rendered_posts=rendered_posts, display_thread_id=display_thread_id)
\ No newline at end of file +    return render_template("search_results.html", results=results, query=query, rendered_posts=rendered_posts, display_thread_id=display_thread_id) diff --git a/apioforum/static/style.css b/apioforum/static/style.css index df8ce7e..935bde1 100644 --- a/apioforum/static/style.css +++ b/apioforum/static/style.css @@ -30,6 +30,20 @@ body { font-family: sans-serif }  .post-anchor-link { color: hsl(0,0%,25%); } +.thread-top-bar { +    margin-bottom: 4px; +} + +.thread-top-bar-b { +    float: right; +    margin-right: -2px; +} + +.thread-top-bar-b .tag { +    font-size: .9rem; +} + +  .un-col-1 { color: hsl(0, 100%, 30%) }  .un-col-2 { color: hsl(22.5, 100%, 30%) }  .un-col-3 { color: hsl(45.0, 100%, 30%) } @@ -69,7 +83,7 @@ nav .links { display: flex; }      .threadlisting { display: contents }      .threadlistings {          display: grid; -        grid-template-columns: 2fr repeat(4,1fr) 0.4fr; +        grid-template-columns: 2fr repeat(5,1fr) 0.4fr;      }      .threadlisting-part { @@ -81,6 +95,9 @@ nav .links { display: flex; }          border-bottom: 1px solid black;      } +    .only-small { display: none !important } + +  }  /* small screens */ @@ -101,6 +118,8 @@ nav .links { display: flex; }          border-right: 1px solid black;          border-bottom: 1px solid black;      } + +    .only-big { display: none !important }  } @@ -141,6 +160,9 @@ main {      max-width: 60ch;      margin: auto;  } +main.widemain { +    max-width: 120ch; +}  blockquote {      margin-left: 10px; @@ -151,3 +173,9 @@ blockquote {  .search-form {      display: inline-block;  } + +.tag { +    font-size: .75rem; +    padding: 1px 3px; +    border: 1px solid black; +} diff --git a/apioforum/templates/base.html b/apioforum/templates/base.html index 87b142f..5121b85 100644 --- a/apioforum/templates/base.html +++ b/apioforum/templates/base.html @@ -49,9 +49,11 @@              <div class="flashmsg">{{ msg }}</div>          {% endfor %} +        {% block nmcontent %}          <main>              {%block content %}{% endblock %}          </main> +        {% endblock %}      <script>/* bees */</script>      </body>  </html> diff --git a/apioforum/templates/common.html b/apioforum/templates/common.html index 33aee0b..2e59b2c 100644 --- a/apioforum/templates/common.html +++ b/apioforum/templates/common.html @@ -26,3 +26,7 @@  {% macro ts(dt) -%}  <time title="{{dt.isoformat(' ')}}" datetime="{{dt.isoformat(' ')}}">{{dt | fuzzy}}</time>  {%- endmacro %} + +{% macro tag(the_tag) -%} +<span class="tag" style="color: {{the_tag.text_colour}}; background-color: {{the_tag.bg_colour}}">{{the_tag.name}}</span> +{%- endmacro %} diff --git a/apioforum/templates/config_thread.html b/apioforum/templates/config_thread.html index b0dd5f0..973fbf5 100644 --- a/apioforum/templates/config_thread.html +++ b/apioforum/templates/config_thread.html @@ -1,13 +1,30 @@  {% extends 'base.html' %} +{% from 'common.html' import tag %}  {% block header %}<h1>{% block title %}configure thread '{{thread.title}}'{% endblock %}</h1>{% endblock %}  {% block content %}  <form method="post"> +<fieldset> +<legend>title</legend>  <p>if you want to change the title of this thread, make sure you check the "change title?" box.</p>  <label for="do_title">change title?</label> -<input type="checkbox" name="do_title"><br> +<input type="checkbox" id="do_title" name="do_title"><br>  <label for="title">thread title</label>  <input type="text" id="title" name="title" value="{{thread.title}}"> -<br> +</fieldset> +<fieldset> +<legend>tags</legend> +<p>if you want to change the tags on this thread, make sure you check the "change tags?" box.</p> +<label for="do_chtags">change tags?</label> +<input type="checkbox" name="do_chtags" id="do_chtags"><br> +<ul> +    {% for the_tag in avail_tags %} +    <li> +        <input  type="checkbox" id="tag_{{the_tag.id}}" name="tag_{{the_tag.id}}" {%- if the_tag.id in thread_tags %} checked{% endif %}> +        <label for="tag_{{the_tag.id}}">#{{the_tag.id}} {{tag(the_tag)}}</label> +    </li> +    {% endfor %} +</ul> +</fieldset>  <p>confirm changes?</p>  <input type="submit" value="confirm">  <a href="{{url_for('thread.view_thread',thread_id=thread.id)}}">cancel</a> diff --git a/apioforum/templates/view_forum.html b/apioforum/templates/view_forum.html index dd3d7a8..3edb7f0 100644 --- a/apioforum/templates/view_forum.html +++ b/apioforum/templates/view_forum.html @@ -1,7 +1,8 @@  {% extends 'base.html' %} -{% from 'common.html' import ts %} +{% from 'common.html' import ts, tag %}  {% block header %}<h1>{% block title %}apioforum{%endblock%}</h1>{%endblock%} -{%block content%} +{%block nmcontent%} +<main class="widemain">  <p>welcome to the apioforum</p>  <p>forum rules: do not be a bad person. do not do bad things.</p>  {% if g.user %} @@ -12,7 +13,10 @@  <div class="threadlistings">  <div class="threadlisting">      <div class="threadlisting-part threadlisting-part-title threadlisting-header"> -        name +        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 @@ -32,7 +36,20 @@  </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></div> +    <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">{{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> @@ -41,4 +58,5 @@  </div>  {%endfor%}  </div> +</main>  {%endblock%} diff --git a/apioforum/templates/view_thread.html b/apioforum/templates/view_thread.html index eaaf581..abd6aaa 100644 --- a/apioforum/templates/view_thread.html +++ b/apioforum/templates/view_thread.html @@ -1,13 +1,24 @@ -{% from 'common.html' import disp_post %} +{% from 'common.html' import disp_post,tag %}  {% extends 'base.html' %}  {% block header %}  <h1>{%block title %}{{thread.title}}{% endblock %}</h1>  {% endblock %}  {%block content%} -{% if g.user == thread.creator %} -<a class="actionbutton" href="{{url_for('thread.config_thread',thread_id=thread_id)}}">configure thread</a> -{% endif %} +<div class="thread-top-bar"> +    <span class="thread-top-bar-a"> +        {% if g.user == thread.creator %} +        <a class="actionbutton" href="{{url_for('thread.config_thread',thread_id=thread.id)}}">configure thread</a> +        {% endif %} +    </span> +      +    <span class="thread-top-bar-b"> +        {% for the_tag in tags %} +            {{ tag(the_tag) }} +        {% endfor %} +    </span> +</div> +  <div class="posts">      {% for post in posts %}      {% call disp_post(post, True) %} @@ -16,7 +27,7 @@      {% endfor %}  </div>  {% if g.user %} -<form class="new-post" action="{{url_for('thread.create_post',thread_id=thread_id)}}" method="POST"> +<form class="new-post" action="{{url_for('thread.create_post',thread_id=thread.id)}}" method="POST">      <textarea class="new-post-box" placeholder="your post here..." name="content"></textarea>      <input type="submit" value="yes">  </form> diff --git a/apioforum/thread.py b/apioforum/thread.py index 14450af..292fd21 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -23,8 +23,12 @@ def view_thread(thread_id):              "SELECT * FROM posts WHERE thread = ? ORDER BY created ASC;",              (thread_id,)          ).fetchall() +        tags = db.execute( +            """SELECT tags.* FROM tags +            INNER JOIN thread_tags ON thread_tags.tag = tags.id +            WHERE thread_tags.thread = ?""",(thread_id,)).fetchall()          rendered_posts = [render(q['content']) for q in posts] -        return render_template("view_thread.html",posts=posts,thread=thread,thread_id=thread_id,rendered_posts=rendered_posts) +        return render_template("view_thread.html",posts=posts,thread=thread,rendered_posts=rendered_posts,tags=tags)  @bp.route("/<int:thread_id>/create_post", methods=("POST",))  def create_post(thread_id): @@ -109,6 +113,8 @@ def edit_post(post_id):  def config_thread(thread_id):      db = get_db()      thread = db.execute("select * from threads where id = ?",(thread_id,)).fetchone() +    thread_tags = [r['tag'] for r in db.execute("select tag from thread_tags where thread = ?",(thread_id,)).fetchall()] +    avail_tags = db.execute("select * from tags order by id").fetchall()      err = None      if g.user is None:          err = "you need to be logged in to do that" @@ -129,6 +135,22 @@ def config_thread(thread_id):                  db.execute("update threads set title = ? where id = ?;",(title,thread_id))                  flash("title updated successfully")                  db.commit() +        if 'do_chtags' in request.form: +            changed = False +            wanted_tags = [] +            for tagid in range(1,len(avail_tags)+1): +                current = tagid in thread_tags +                wanted  = f'tag_{tagid}' in request.form +                print(tagid, current, wanted) +                if wanted and not current: +                    db.execute("insert into thread_tags (thread, tag) values (?,?)",(thread_id,tagid)) +                    changed = True +                elif current and not wanted: +                    db.execute("delete from thread_tags where thread = ? and tag = ?",(thread_id,tagid)) +                    changed = True +            if changed: +                db.commit() +                flash("tags updated successfully")          if len(err) > 0:              for e in err: @@ -137,5 +159,5 @@ def config_thread(thread_id):              return redirect(url_for("thread.view_thread",thread_id=thread_id)) -    return render_template("config_thread.html", thread=thread) +    return render_template("config_thread.html", thread=thread,thread_tags=thread_tags,avail_tags=avail_tags)  | 
