creating threads
This commit is contained in:
parent
c7fb6784c4
commit
604f9d6aba
@ -70,10 +70,12 @@ def create_app():
|
||||
|
||||
from app.routes.app import bp as app_bp
|
||||
from app.routes.topics import bp as topics_bp
|
||||
from app.routes.threads import bp as threads_bp
|
||||
from app.routes.users import bp as users_bp
|
||||
from app.routes.mod import bp as mod_bp
|
||||
app.register_blueprint(app_bp)
|
||||
app.register_blueprint(topics_bp)
|
||||
app.register_blueprint(threads_bp)
|
||||
app.register_blueprint(users_bp)
|
||||
app.register_blueprint(mod_bp)
|
||||
|
||||
|
@ -5,3 +5,8 @@ bp = Blueprint("app", __name__, url_prefix = "/")
|
||||
@bp.route("/")
|
||||
def index():
|
||||
return redirect(url_for("topics.all_topics"))
|
||||
|
||||
|
||||
@bp.route("/babycode")
|
||||
def babycode_guide():
|
||||
return "not yet"
|
||||
|
26
app/routes/posts.py
Normal file
26
app/routes/posts.py
Normal file
@ -0,0 +1,26 @@
|
||||
from flask import Blueprint, redirect, url_for
|
||||
from ..lib.babycode import babycode_to_html
|
||||
from ..db import db
|
||||
from ..models import Posts, PostHistory
|
||||
|
||||
bp = Blueprint("posts", __name__, url_prefix = "/posts")
|
||||
|
||||
def create_post(thread_id, user_id, content, markup_language="babycode"):
|
||||
with db.transaction():
|
||||
post = Posts.create({
|
||||
"thread_id": thread_id,
|
||||
"user_id": user_id,
|
||||
"current_revision_id": None,
|
||||
})
|
||||
|
||||
revision = PostHistory.create({
|
||||
"post_id": post.id,
|
||||
"content": babycode_to_html(content),
|
||||
"is_initial_revision": True,
|
||||
"original_markup": content,
|
||||
"markup_language": markup_language,
|
||||
})
|
||||
|
||||
post.update({"current_revision_id": revision.id})
|
||||
return post
|
||||
|
@ -1,7 +1,49 @@
|
||||
from flask import Blueprint, render_template
|
||||
from flask import (
|
||||
Blueprint, render_template, request, redirect, url_for
|
||||
)
|
||||
from .users import login_required, get_active_user
|
||||
from ..models import Threads, Topics
|
||||
from .posts import create_post
|
||||
from slugify import slugify
|
||||
import time
|
||||
|
||||
bp = Blueprint("threads", __name__, url_prefix = "/threads/")
|
||||
|
||||
bp = Blueprint("topics", __name__, url_prefix = "/threads/")
|
||||
|
||||
@bp.get("/<slug>")
|
||||
def thread(slug):
|
||||
return slug
|
||||
|
||||
|
||||
@bp.get("/create")
|
||||
@login_required
|
||||
def create():
|
||||
all_topics = Topics.select()
|
||||
return render_template("threads/create.html", all_topics = all_topics)
|
||||
|
||||
|
||||
@bp.post("/create")
|
||||
@login_required
|
||||
def create_form():
|
||||
topic = Topics.find({"id": request.form['topic_id']})
|
||||
user = get_active_user()
|
||||
if not topic:
|
||||
return "no"
|
||||
|
||||
if topic.is_locked and not get_active_user().is_mod():
|
||||
return "no"
|
||||
|
||||
title = request.form['title'].strip()
|
||||
now = int(time.time())
|
||||
slug = f"{slugify(title)}-{now}"
|
||||
|
||||
post_content = request.form['initial_post']
|
||||
thread = Threads.create({
|
||||
"topic_id": topic.id,
|
||||
"user_id": user.id,
|
||||
"title": title,
|
||||
"slug": slug,
|
||||
"created_at": now,
|
||||
})
|
||||
post = create_post(thread.id, user.id, post_content)
|
||||
return redirect(url_for(".thread", slug = thread.slug))
|
||||
|
@ -1,7 +1,6 @@
|
||||
{% macro pager(current_page, page_count) %}
|
||||
{% set left_start = (1, current_page - 5) | max %}
|
||||
{% set right_end = (page_count, current_page + 5) | min %}
|
||||
|
||||
<div class="pager">
|
||||
<span>Page:</span>
|
||||
{% if current_page > 5 %}
|
||||
@ -42,3 +41,50 @@
|
||||
{% macro timestamp(unix_ts) %}
|
||||
<span class="timestamp" data-utc="{{ unix_ts }}">{{ unix_ts | ts_datetime('%Y-%m-%d %H:%M')}} ST</span>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro babycode_editor_component(ta_name, ta_placeholder="Post body", optional=False, prefill="") %}
|
||||
<div class="babycode-editor-container">
|
||||
<div class="tab-buttons">
|
||||
<button type=button class="tab-button active" data-target-id="tab-edit">Write</button>
|
||||
<button type=button class="tab-button" data-target-id="tab-preview">Preview</button>
|
||||
</div>
|
||||
<div class="tab-content active" id="tab-edit">
|
||||
<span class="babycode-button-container">
|
||||
<button class="babycode-button" type=button id="post-editor-bold" title="Insert Bold"><strong>B</strong></button>
|
||||
<button class="babycode-button" type=button id="post-editor-italics" title="Insert Italics"><em>I</em></button>
|
||||
<button class="babycode-button" type=button id="post-editor-strike" title="Insert Strikethrough"><del>S</del></button>
|
||||
<button class="babycode-button" type=button id="post-editor-url" title="Insert Link"><code>://</code></button>
|
||||
<button class="babycode-button" type=button id="post-editor-code" title="Insert Code block"><code></></code></button>
|
||||
<button class="babycode-button contain-svg full" type=button id="post-editor-img" title="Insert Image"><img src="/static/misc/image.svg"></button>
|
||||
<button class="babycode-button" type=button id="post-editor-ol" title="Insert Ordered list">1.</button>
|
||||
<button class="babycode-button" type=button id="post-editor-ul" title="Insert Unordered list">•</button>
|
||||
</span>
|
||||
<textarea class="babycode-editor" name="{{ ta_name }}" id="babycode-content" placeholder="{{ ta_placeholder }}" {{ "required" if not optional else "" }}>{{ prefill }}</textarea>
|
||||
<a href="{{ url_for("app.babycode_guide") }}" target="_blank">babycode guide</a>
|
||||
</div>
|
||||
<div class="tab-content" id="tab-preview">
|
||||
<div id="babycode-preview-errors-container">Type something!</div>
|
||||
<div id="babycode-preview-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/babycode-editor.js?v=1"></script>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro babycode_editor_form(ta_name, prefill = "", cancel_url="", endpoint="") %}
|
||||
{% set save_button_text = "Post reply" if not cancel_url else "Save" %}
|
||||
<form class="post-edit-form" method="post" action={{ endpoint }}>
|
||||
{{babycode_editor_component(ta_name, prefill = prefill)}}
|
||||
{% if not cancel_url %}
|
||||
<span>
|
||||
<input type="checkbox" id="subscribe" name="subscribe" {{ "checked" if session['subscribe_by_default'] else "" }}>
|
||||
<label for="subscribe">Subscribe to thread</label>
|
||||
</span>
|
||||
{% endif %}
|
||||
<span>
|
||||
<input type="submit" value="{{ save_button_text }}">
|
||||
{% if cancel_url %}
|
||||
<a class="linkbutton warn" href="{{ cancel_url }}">Cancel</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
</form>
|
||||
{% endmacro %}
|
||||
|
21
app/templates/threads/create.html
Normal file
21
app/templates/threads/create.html
Normal file
@ -0,0 +1,21 @@
|
||||
{% from "common/macros.html" import babycode_editor_component %}
|
||||
{% extends "base.html" %}
|
||||
{% block title %}drafting a thread{% endblock %}
|
||||
{% block content %}
|
||||
<div class="darkbg settings-container">
|
||||
<h1>New thread</h1>
|
||||
<form method="post">
|
||||
<label for="topic_id">Topic</label>
|
||||
<select name="topic_id" id="topic_id" autocomplete="off">
|
||||
{% for topic in all_topics %}
|
||||
<option value="{{ topic['id'] }}" {{"selected" if (request.args.get('topic_id')) == (topic['id'] | string) else ""}}>{{ topic['name'] }}</option>
|
||||
{% endfor %}
|
||||
</select><br>
|
||||
<label for="title">Thread title</label>
|
||||
<input type="text" id="title" name="title" placeholder="Required" required>
|
||||
<label for="initial_post">Post body</label><br>
|
||||
{{ babycode_editor_component("initial_post") }}
|
||||
<input type="submit" value="Create thread">
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
@ -6,13 +6,18 @@
|
||||
<h1 class="thread-title">All threads in "{{topic['name']}}"</h1>
|
||||
<span>{{topic['description']}}</span>
|
||||
<div>
|
||||
{% if active_user and active_user.is_mod() %}
|
||||
<a class="linkbutton" href="{{url_for("topics.edit", slug=topic['slug'])}}">Edit topic</a>
|
||||
<form class="modform" method="post" action="{{url_for("topics.edit", slug=topic['slug']) }}">
|
||||
<input type="hidden" name="is_locked" value="{{ (not topic.is_locked) | int }}">
|
||||
<input class="warn" type="submit" id="lock" value="{{"Unlock topic" if topic['is_locked'] else "Lock topic"}}">
|
||||
</form>
|
||||
<button type="button" class="critical" id="topic-delete-dialog-open">Delete</button>
|
||||
{% if active_user %}
|
||||
{% if not (topic['is_locked']) | int or active_user.is_mod() %}
|
||||
<a class="linkbutton" href="{{ url_for("threads.create", topic_id=topic['id']) }}">New thread</a>
|
||||
{% endif %}
|
||||
{% if active_user.is_mod() %}
|
||||
<a class="linkbutton" href="{{url_for("topics.edit", slug=topic['slug'])}}">Edit topic</a>
|
||||
<form class="modform" method="post" action="{{url_for("topics.edit", slug=topic['slug']) }}">
|
||||
<input type="hidden" name="is_locked" value="{{ (not topic.is_locked) | int }}">
|
||||
<input class="warn" type="submit" id="lock" value="{{"Unlock topic" if topic['is_locked'] else "Lock topic"}}">
|
||||
</form>
|
||||
<button type="button" class="critical" id="topic-delete-dialog-open">Delete</button>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</nav>
|
||||
|
@ -467,6 +467,10 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus, select:focus
|
||||
height: 50%;
|
||||
width: 50%;
|
||||
}
|
||||
.contain-svg.full > svg, .contain-svg img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.block-img {
|
||||
object-fit: contain;
|
||||
|
@ -476,6 +476,10 @@ input[type="text"], input[type="password"], textarea, select {
|
||||
height: 50%;
|
||||
width: 50%;
|
||||
}
|
||||
&.full > svg, img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.block-img {
|
||||
|
Loading…
Reference in New Issue
Block a user