diff --git a/amanuensis/db/models.py b/amanuensis/db/models.py index e951309..cc5d2c1 100644 --- a/amanuensis/db/models.py +++ b/amanuensis/db/models.py @@ -251,7 +251,7 @@ class Lexicon(ModelBase): indices = relationship("ArticleIndex", back_populates="lexicon") index_rules = relationship("ArticleIndexRule", back_populates="lexicon") content_rules = relationship("ArticleContentRule", back_populates="lexicon") - posts = relationship("Post", back_populates="lexicon") + posts = relationship("Post", back_populates="lexicon", order_by="Post.created.desc()") ####################### # Derived information # diff --git a/amanuensis/resources/page.css b/amanuensis/resources/page.css index 8e68a98..8fb534b 100644 --- a/amanuensis/resources/page.css +++ b/amanuensis/resources/page.css @@ -215,6 +215,10 @@ details.setting-help { #index-definition-table td input[type=number] { width: 4em; } +p.post-byline { + color: #606060; + text-align: right; +} @media only screen and (max-width: 816px) { main { padding: 5px; diff --git a/amanuensis/server/lexicon.jinja b/amanuensis/server/lexicon.jinja index 46f18c4..7593601 100644 --- a/amanuensis/server/lexicon.jinja +++ b/amanuensis/server/lexicon.jinja @@ -15,6 +15,10 @@ {% if current_page == "contents" %}class="current-page" {% else %}href="{{ url_for('lexicon.contents', lexicon_name=g.lexicon.name) }}" {% endif %}>Contents{% endblock %} +{% block sb_posts %}Posts{% endblock %} {% block sb_rules %}' + + def ParsedArticle(self, span: ParsedArticle): + return '\n'.join(span.recurse(self)) + + def BodyParagraph(self, span: BodyParagraph): + return f'

{"".join(span.recurse(self))}

' + + def SignatureParagraph(self, span: SignatureParagraph): + return ( + '

' + f'{"".join(span.recurse(self))}' + '

' + ) + + def BoldSpan(self, span: BoldSpan): + return f'{"".join(span.recurse(self))}' + + def ItalicSpan(self, span: ItalicSpan): + return f'{"".join(span.recurse(self))}' + + def CitationSpan(self, span: CitationSpan): + return "".join(span.recurse(self)) + + +def render_post_body(post: Post) -> str: + """Parse and render the body of a post into post-safe HTML.""" + renderable: ParsedArticle = parse_raw_markdown(post.body) + rendered: str = renderable.render(PostFormatter()) + return rendered + + +@bp.get("/") +@lexicon_param +@player_required +def list(lexicon_name): + form = CreatePostForm() + return render_template( + "posts.jinja", + lexicon_name=lexicon_name, + form=form, + render_post_body=render_post_body, + ) + + +@bp.post("/") +@lexicon_param +@player_required +def create(lexicon_name): + form = CreatePostForm() + if form.validate(): + # Data is valid + postq.create(g.db, current_lexicon.id, current_user.id, form.body.data) + return redirect(url_for("lexicon.posts.list", lexicon_name=lexicon_name)) + + else: + # POST received invalid data + return render_template( + "posts.jinja", + lexicon_name=lexicon_name, + form=form, + render_post_body=render_post_body, + ) diff --git a/amanuensis/server/lexicon/posts/forms.py b/amanuensis/server/lexicon/posts/forms.py new file mode 100644 index 0000000..76ebd83 --- /dev/null +++ b/amanuensis/server/lexicon/posts/forms.py @@ -0,0 +1,10 @@ +from flask_wtf import FlaskForm +from wtforms import SubmitField, TextAreaField +from wtforms.validators import DataRequired + + +class CreatePostForm(FlaskForm): + """/lexicon//posts/""" + + body = TextAreaField(validators=[DataRequired()]) + submit = SubmitField("Post") diff --git a/amanuensis/server/lexicon/posts/posts.jinja b/amanuensis/server/lexicon/posts/posts.jinja new file mode 100644 index 0000000..f68b132 --- /dev/null +++ b/amanuensis/server/lexicon/posts/posts.jinja @@ -0,0 +1,20 @@ +{% extends "lexicon.jinja" %} +{% set current_page = "characters" %} +{% block title %}Character | {{ lexicon_title }}{% endblock %} + +{% block main %} +
+
+ {{ form.hidden_tag() }} +

{{ form.body(class_='fullwidth') }}

+

{{ form.submit() }}

+
+
+ +{% for post in current_lexicon.posts %} +
+

{{ render_post_body(post) }}

+ +
+{% endfor %} +{% endblock %}