Compare commits
1 Commits
develop
...
nvb/create
Author | SHA1 | Date |
---|---|---|
Nikolai | 5b3e5663b7 |
|
@ -2,19 +2,19 @@
|
||||||
Post query interface
|
Post query interface
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Optional, Sequence, Tuple
|
import re
|
||||||
|
|
||||||
from sqlalchemy import select, update, func, or_, DateTime
|
from sqlalchemy import select
|
||||||
|
|
||||||
from amanuensis.db import DbContext, Post
|
from amanuensis.db import DbContext, Post
|
||||||
from amanuensis.db.models import Lexicon, Membership
|
from amanuensis.db.models import Lexicon
|
||||||
from amanuensis.errors import ArgumentError, BackendArgumentTypeError
|
from amanuensis.errors import ArgumentError, BackendArgumentTypeError
|
||||||
|
|
||||||
|
|
||||||
def create(
|
def create(
|
||||||
db: DbContext,
|
db: DbContext,
|
||||||
lexicon_id: int,
|
lexicon_id: int,
|
||||||
user_id: Optional[int],
|
user_id: int,
|
||||||
body: str,
|
body: str,
|
||||||
) -> Post:
|
) -> Post:
|
||||||
"""
|
"""
|
||||||
|
@ -47,57 +47,3 @@ def create(
|
||||||
db.session.add(new_post)
|
db.session.add(new_post)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return new_post
|
return new_post
|
||||||
|
|
||||||
|
|
||||||
def get_posts_for_membership(
|
|
||||||
db: DbContext, membership_id: int
|
|
||||||
) -> Tuple[Sequence[Post], Sequence[Post]]:
|
|
||||||
"""
|
|
||||||
Returns posts for the membership's lexicon, split into posts that
|
|
||||||
are new since the last view and posts that were previously seen.
|
|
||||||
"""
|
|
||||||
# Save the current timestamp, so we don't miss posts created between now
|
|
||||||
# and when we finish looking stuff up
|
|
||||||
now: DateTime = db(select(func.now())).scalar_one()
|
|
||||||
|
|
||||||
# Save the previous last-seen timestamp for splitting new from old posts,
|
|
||||||
# then update the membership with the current time
|
|
||||||
last_seen: DateTime = db(
|
|
||||||
select(Membership.last_post_seen).where(Membership.id == membership_id)
|
|
||||||
).scalar_one()
|
|
||||||
db(
|
|
||||||
update(Membership)
|
|
||||||
.where(Membership.id == membership_id)
|
|
||||||
.values(last_post_seen=now)
|
|
||||||
)
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
# Fetch posts in two groups, new ones after the last-seen time and old ones
|
|
||||||
# If last-seen is null, then just return everything as new
|
|
||||||
new_posts = db(
|
|
||||||
select(Post)
|
|
||||||
.where(last_seen is None or Post.created > last_seen)
|
|
||||||
.order_by(Post.created.desc())
|
|
||||||
).scalars()
|
|
||||||
old_posts = db(
|
|
||||||
select(Post)
|
|
||||||
.where(last_seen is not None and Post.created <= last_seen)
|
|
||||||
.order_by(Post.created.desc())
|
|
||||||
).scalars()
|
|
||||||
|
|
||||||
return new_posts, old_posts
|
|
||||||
|
|
||||||
|
|
||||||
def get_unread_count(db: DbContext, membership_id: int) -> int:
|
|
||||||
"""Get the number of posts that the member has not seen"""
|
|
||||||
return db(
|
|
||||||
select(func.count(Post.id))
|
|
||||||
.join(Membership, Membership.lexicon_id == Post.lexicon_id)
|
|
||||||
.where(
|
|
||||||
or_(
|
|
||||||
Membership.last_post_seen.is_(None),
|
|
||||||
Post.created > Membership.last_post_seen,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.where(Membership.id == membership_id)
|
|
||||||
).scalar()
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import amanuensis.cli.admin
|
||||||
import amanuensis.cli.character
|
import amanuensis.cli.character
|
||||||
import amanuensis.cli.index
|
import amanuensis.cli.index
|
||||||
import amanuensis.cli.lexicon
|
import amanuensis.cli.lexicon
|
||||||
import amanuensis.cli.post
|
|
||||||
import amanuensis.cli.user
|
import amanuensis.cli.user
|
||||||
from amanuensis.db import DbContext
|
from amanuensis.db import DbContext
|
||||||
|
|
||||||
|
@ -114,7 +113,6 @@ def main():
|
||||||
add_subcommand(subparsers, amanuensis.cli.character)
|
add_subcommand(subparsers, amanuensis.cli.character)
|
||||||
add_subcommand(subparsers, amanuensis.cli.index)
|
add_subcommand(subparsers, amanuensis.cli.index)
|
||||||
add_subcommand(subparsers, amanuensis.cli.lexicon)
|
add_subcommand(subparsers, amanuensis.cli.lexicon)
|
||||||
add_subcommand(subparsers, amanuensis.cli.post)
|
|
||||||
add_subcommand(subparsers, amanuensis.cli.user)
|
add_subcommand(subparsers, amanuensis.cli.user)
|
||||||
|
|
||||||
# Parse args and perform top-level arg processing
|
# Parse args and perform top-level arg processing
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
import logging
|
|
||||||
|
|
||||||
from amanuensis.backend import *
|
|
||||||
from amanuensis.db import *
|
|
||||||
|
|
||||||
from .helpers import add_argument
|
|
||||||
|
|
||||||
|
|
||||||
COMMAND_NAME = "post"
|
|
||||||
COMMAND_HELP = "Interact with posts."
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
@add_argument("--lexicon", required=True, help="The lexicon's name")
|
|
||||||
@add_argument("--by", help="The character's public id")
|
|
||||||
@add_argument("--text", help="The text of the post")
|
|
||||||
def command_create(args) -> int:
|
|
||||||
"""
|
|
||||||
Create a post in a lexicon.
|
|
||||||
"""
|
|
||||||
db: DbContext = args.get_db()
|
|
||||||
lexicon = lexiq.try_from_name(db, args.lexicon)
|
|
||||||
if not lexicon:
|
|
||||||
raise ValueError("Lexicon does not exist")
|
|
||||||
user = userq.try_from_username(db, args.by)
|
|
||||||
user_id = user.id if user else None
|
|
||||||
post: Post = postq.create(db, lexicon.id, user_id, args.text)
|
|
||||||
preview = post.body[:20] + "..." if len(post.body) > 20 else post.body
|
|
||||||
LOG.info(f"Posted '{preview}' in {lexicon.full_title}")
|
|
||||||
return 0
|
|
|
@ -181,7 +181,7 @@ class Lexicon(ModelBase):
|
||||||
################################
|
################################
|
||||||
|
|
||||||
# Whether players can join the game
|
# Whether players can join the game
|
||||||
joinable = Column(Boolean, nullable=False, default=False)
|
joinable = Column(Boolean, nullable=False, default=True)
|
||||||
|
|
||||||
# Whether the game is listed on public pages
|
# Whether the game is listed on public pages
|
||||||
public = Column(Boolean, nullable=False, default=False)
|
public = Column(Boolean, nullable=False, default=False)
|
||||||
|
@ -251,9 +251,7 @@ class Lexicon(ModelBase):
|
||||||
indices = relationship("ArticleIndex", back_populates="lexicon")
|
indices = relationship("ArticleIndex", back_populates="lexicon")
|
||||||
index_rules = relationship("ArticleIndexRule", back_populates="lexicon")
|
index_rules = relationship("ArticleIndexRule", back_populates="lexicon")
|
||||||
content_rules = relationship("ArticleContentRule", back_populates="lexicon")
|
content_rules = relationship("ArticleContentRule", back_populates="lexicon")
|
||||||
posts = relationship(
|
posts = relationship("Post", back_populates="lexicon")
|
||||||
"Post", back_populates="lexicon", order_by="Post.created.desc()"
|
|
||||||
)
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# Derived information #
|
# Derived information #
|
||||||
|
|
|
@ -17,7 +17,7 @@ div#editor-left {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
div#editor-left section {
|
div#editor-left div.contentblock {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin: 10px 5px 10px 10px;
|
margin: 10px 5px 10px 10px;
|
||||||
|
@ -48,7 +48,7 @@ textarea#editor-content {
|
||||||
div#editor-right {
|
div#editor-right {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
div#editor-right section {
|
div#editor-right div.contentblock {
|
||||||
margin: 10px 5px 10px 10px;
|
margin: 10px 5px 10px 10px;
|
||||||
}
|
}
|
||||||
span.message-warning {
|
span.message-warning {
|
||||||
|
|
|
@ -8,14 +8,14 @@ body {
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
main {
|
div#wrapper {
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
header {
|
div#header {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
|
@ -24,7 +24,7 @@ header {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
header p, header h2 {
|
div#header p, div#header h2 {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
}
|
}
|
||||||
div#login-status {
|
div#login-status {
|
||||||
|
@ -33,7 +33,7 @@ div#login-status {
|
||||||
top: 10px;
|
top: 10px;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
}
|
}
|
||||||
nav {
|
div#sidebar {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
float:left;
|
float:left;
|
||||||
margin:5px;
|
margin:5px;
|
||||||
|
@ -46,7 +46,7 @@ nav {
|
||||||
img#logo {
|
img#logo {
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
}
|
}
|
||||||
nav table {
|
div#sidebar table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
|
@ -63,32 +63,32 @@ table a {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
nav table a {
|
div#sidebar table a {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
table a:hover {
|
table a:hover {
|
||||||
background-color: var(--button-hover);
|
background-color: var(--button-hover);
|
||||||
}
|
}
|
||||||
nav table a.current-page {
|
div#sidebar table a.current-page {
|
||||||
background-color: var(--button-current);
|
background-color: var(--button-current);
|
||||||
}
|
}
|
||||||
nav table a.current-page:hover {
|
div#sidebar table a.current-page:hover {
|
||||||
background-color: var(--button-current);
|
background-color: var(--button-current);
|
||||||
}
|
}
|
||||||
nav table td {
|
div#sidebar table td {
|
||||||
padding: 0px; margin: 3px 0;
|
padding: 0px; margin: 3px 0;
|
||||||
border-bottom: 8px solid transparent;
|
border-bottom: 8px solid transparent;
|
||||||
}
|
}
|
||||||
article {
|
div#content {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
}
|
}
|
||||||
article.content-2col {
|
div.content-2col {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0px;
|
right: 0px;
|
||||||
left: 226px;
|
left: 226px;
|
||||||
max-width: 564px;
|
max-width: 564px;
|
||||||
}
|
}
|
||||||
section {
|
div.contentblock {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
box-shadow: 2px 2px 10px #888888;
|
box-shadow: 2px 2px 10px #888888;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
|
@ -215,35 +215,27 @@ details.setting-help {
|
||||||
#index-definition-table td input[type=number] {
|
#index-definition-table td input[type=number] {
|
||||||
width: 4em;
|
width: 4em;
|
||||||
}
|
}
|
||||||
section.new-post {
|
|
||||||
padding: 9px;
|
|
||||||
border: 1px dashed red;
|
|
||||||
}
|
|
||||||
p.post-byline {
|
|
||||||
color: #606060;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
@media only screen and (max-width: 816px) {
|
@media only screen and (max-width: 816px) {
|
||||||
main {
|
div#wrapper {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
header {
|
div#header {
|
||||||
max-width: 554px;
|
max-width: 554px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
nav {
|
div#sidebar {
|
||||||
max-width: 548px;
|
max-width: 548px;
|
||||||
width: inherit;
|
width: inherit;
|
||||||
float: inherit;
|
float: inherit;
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
}
|
}
|
||||||
article{
|
div#content{
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
}
|
}
|
||||||
article.content-1col {
|
div.content-1col {
|
||||||
max-width: 564px;
|
max-width: 564px;
|
||||||
}
|
}
|
||||||
article.content-2col {
|
div.content-2col {
|
||||||
max-width: 564px;
|
max-width: 564px;
|
||||||
position: static;
|
position: static;
|
||||||
right: inherit;
|
right: inherit;
|
||||||
|
|
|
@ -76,7 +76,6 @@ def get_app(
|
||||||
"memq": memq,
|
"memq": memq,
|
||||||
"charq": charq,
|
"charq": charq,
|
||||||
"indq": indq,
|
"indq": indq,
|
||||||
"postq": postq,
|
|
||||||
"current_lexicon": current_lexicon,
|
"current_lexicon": current_lexicon,
|
||||||
"current_membership": current_membership
|
"current_membership": current_membership
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
{% block header %}<h2>Amanuensis - Login</h2>{% endblock %}
|
{% block header %}<h2>Amanuensis - Login</h2>{% endblock %}
|
||||||
{% block login_status_attr %}style="display:none"{% endblock %}
|
{% block login_status_attr %}style="display:none"{% endblock %}
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<section>
|
|
||||||
<form action="" method="post" novalidate>
|
<form action="" method="post" novalidate>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
<p>{{ form.username.label }}<br>{{ form.username(size=32) }}
|
<p>{{ form.username.label }}<br>{{ form.username(size=32) }}
|
||||||
|
@ -20,5 +19,5 @@
|
||||||
{% for message in get_flashed_messages() %}
|
{% for message in get_flashed_messages() %}
|
||||||
<span style="color: #ff0000">{{ message }}</span><br>
|
<span style="color: #ff0000">{{ message }}</span><br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</section>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% set template_content_blocks = [self.main()] %}
|
|
@ -99,7 +99,7 @@ def admin_required(route):
|
||||||
@wraps(route)
|
@wraps(route)
|
||||||
def admin_route(*args, **kwargs):
|
def admin_route(*args, **kwargs):
|
||||||
user: User = current_user
|
user: User = current_user
|
||||||
if not user.is_authenticated or not user.is_site_admin:
|
if not user.is_site_admin:
|
||||||
flash("You must be an admin to view this page")
|
flash("You must be an admin to view this page")
|
||||||
return redirect(url_for('home.home'))
|
return redirect(url_for('home.home'))
|
||||||
return route(*args, **kwargs)
|
return route(*args, **kwargs)
|
||||||
|
@ -114,13 +114,7 @@ def player_required(route):
|
||||||
def player_route(*args, **kwargs):
|
def player_route(*args, **kwargs):
|
||||||
db: DbContext = g.db
|
db: DbContext = g.db
|
||||||
user: User = current_user
|
user: User = current_user
|
||||||
lexicon: Lexicon = current_lexicon
|
lexicon: Lexicon = g.lexicon
|
||||||
if not user.is_authenticated:
|
|
||||||
flash("You must be a player to view this page")
|
|
||||||
if lexicon.public:
|
|
||||||
return redirect(url_for('lexicon.contents', lexicon_name=lexicon.name))
|
|
||||||
else:
|
|
||||||
return redirect(url_for('home.home'))
|
|
||||||
mem: Optional[Membership] = memq.try_from_ids(db, user.id, lexicon.id)
|
mem: Optional[Membership] = memq.try_from_ids(db, user.id, lexicon.id)
|
||||||
if not mem:
|
if not mem:
|
||||||
flash("You must be a player to view this page")
|
flash("You must be a player to view this page")
|
||||||
|
@ -140,8 +134,8 @@ def player_required_if_not_public(route):
|
||||||
def player_route(*args, **kwargs):
|
def player_route(*args, **kwargs):
|
||||||
db: DbContext = g.db
|
db: DbContext = g.db
|
||||||
user: User = current_user
|
user: User = current_user
|
||||||
lexicon: Lexicon = current_lexicon
|
lexicon: Lexicon = g.lexicon
|
||||||
if not user.is_authenticated and not lexicon.public:
|
if not lexicon.public:
|
||||||
mem: Optional[Membership] = memq.try_from_ids(db, user.id, lexicon.id)
|
mem: Optional[Membership] = memq.try_from_ids(db, user.id, lexicon.id)
|
||||||
if not mem:
|
if not mem:
|
||||||
flash("You must be a player to view this page")
|
flash("You must be a player to view this page")
|
||||||
|
@ -158,13 +152,7 @@ def editor_required(route):
|
||||||
def editor_route(*args, **kwargs):
|
def editor_route(*args, **kwargs):
|
||||||
db: DbContext = g.db
|
db: DbContext = g.db
|
||||||
user: User = current_user
|
user: User = current_user
|
||||||
lexicon: Lexicon = current_lexicon
|
lexicon: Lexicon = g.lexicon
|
||||||
if not user.is_authenticated:
|
|
||||||
flash("You must be a player to view this page")
|
|
||||||
if lexicon.public:
|
|
||||||
return redirect(url_for('lexicon.contents', lexicon_name=lexicon.name))
|
|
||||||
else:
|
|
||||||
return redirect(url_for('home.home'))
|
|
||||||
mem: Optional[Membership] = memq.try_from_ids(db, user.id, lexicon.id)
|
mem: Optional[Membership] = memq.try_from_ids(db, user.id, lexicon.id)
|
||||||
if not mem or not mem.is_editor:
|
if not mem or not mem.is_editor:
|
||||||
flash("You must be the editor to view this page")
|
flash("You must be the editor to view this page")
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
from flask import Blueprint, render_template, g
|
from operator import le
|
||||||
|
|
||||||
from amanuensis.backend import userq, lexiq
|
from sqlalchemy.sql.expression import true
|
||||||
|
from amanuensis.db.models import Lexicon
|
||||||
|
from flask import Blueprint, render_template, g, url_for, redirect
|
||||||
|
|
||||||
# from .forms import LexiconCreateForm
|
from amanuensis.backend import userq, lexiq, memq
|
||||||
|
|
||||||
|
from .forms import LexiconCreateForm
|
||||||
|
|
||||||
bp = Blueprint("home", __name__, url_prefix="/home", template_folder=".")
|
bp = Blueprint("home", __name__, url_prefix="/home", template_folder=".")
|
||||||
|
|
||||||
|
@ -18,6 +22,34 @@ def home():
|
||||||
def admin():
|
def admin():
|
||||||
return render_template("home.admin.jinja", userq=userq, lexiq=lexiq)
|
return render_template("home.admin.jinja", userq=userq, lexiq=lexiq)
|
||||||
|
|
||||||
|
@bp.get("/admin/create/")
|
||||||
|
def create():
|
||||||
|
form = LexiconCreateForm()
|
||||||
|
return render_template("home.create.jinja", form=form)
|
||||||
|
|
||||||
|
@bp.post("/admin/create/")
|
||||||
|
def create_post():
|
||||||
|
form = LexiconCreateForm()
|
||||||
|
if form.validate():
|
||||||
|
name = form.lexicon.data
|
||||||
|
editor = userq.try_from_username(g.db, form.editor.data)
|
||||||
|
prompt = form.prompt.data
|
||||||
|
|
||||||
|
assert editor is not None
|
||||||
|
|
||||||
|
lexicon = lexiq.create(g.db, name, None, prompt)
|
||||||
|
new_membership = memq.create(g.db, editor.id, lexicon.id, is_editor=True)
|
||||||
|
|
||||||
|
lexicon.joinable = False
|
||||||
|
g.db.session.commit()
|
||||||
|
|
||||||
|
return redirect(url_for("home.admin"))
|
||||||
|
|
||||||
|
else:
|
||||||
|
return render_template("home.create.jinja", form=form)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# @bp_home.route("/admin/create/", methods=['GET', 'POST'])
|
# @bp_home.route("/admin/create/", methods=['GET', 'POST'])
|
||||||
# @login_required
|
# @login_required
|
||||||
|
|
|
@ -2,16 +2,13 @@ from flask_wtf import FlaskForm
|
||||||
from wtforms import StringField, SubmitField, TextAreaField
|
from wtforms import StringField, SubmitField, TextAreaField
|
||||||
from wtforms.validators import DataRequired
|
from wtforms.validators import DataRequired
|
||||||
|
|
||||||
# from amanuensis.server.forms import User, Lexicon
|
class LexiconCreateForm(FlaskForm):
|
||||||
|
"""/admin/create/"""
|
||||||
|
lexicon = StringField(
|
||||||
# class LexiconCreateForm(FlaskForm):
|
'Lexicon name',
|
||||||
# """/admin/create/"""
|
validators=[DataRequired()])
|
||||||
# lexiconName = StringField(
|
editor = StringField(
|
||||||
# 'Lexicon name',
|
'Username of editor',
|
||||||
# validators=[DataRequired(), Lexicon(should_exist=False)])
|
validators=[DataRequired()])
|
||||||
# editorName = StringField(
|
prompt = TextAreaField('Prompt')
|
||||||
# 'Username of editor',
|
submit = SubmitField('Create')
|
||||||
# validators=[DataRequired(), User(should_exist=True)])
|
|
||||||
# promptText = TextAreaField('Prompt')
|
|
||||||
# submit = SubmitField('Create')
|
|
||||||
|
|
|
@ -3,13 +3,11 @@
|
||||||
{% block title %}Admin | Amanuensis{% endblock %}
|
{% block title %}Admin | Amanuensis{% endblock %}
|
||||||
{% block header %}<h2>Amanuensis - Admin Dashboard</h2>{% endblock %}
|
{% block header %}<h2>Amanuensis - Admin Dashboard</h2>{% endblock %}
|
||||||
|
|
||||||
{# TODO #}
|
|
||||||
{% block sb_home %}<a href="{{ url_for('home.home') }}">Home</a>{% endblock %}
|
{% block sb_home %}<a href="{{ url_for('home.home') }}">Home</a>{% endblock %}
|
||||||
{% block sb_create %}<a href="#{#{ url_for('home.admin_create') }#}">Create a lexicon</a>{% endblock %}
|
{% block sb_create %}<a href="{{ url_for('home.create') }}">Create a lexicon</a>{% endblock %}
|
||||||
{% set template_sidebar_rows = [self.sb_home(), self.sb_create()] %}
|
{% set template_sidebar_rows = [self.sb_home(), self.sb_create()] %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<section>
|
|
||||||
<p>Users:</p>
|
<p>Users:</p>
|
||||||
{% for user in userq.get_all(db) %}
|
{% for user in userq.get_all(db) %}
|
||||||
{{ macros.dashboard_user_item(user) }}
|
{{ macros.dashboard_user_item(user) }}
|
||||||
|
@ -18,5 +16,5 @@
|
||||||
{% for lexicon in lexiq.get_all(db) %}
|
{% for lexicon in lexiq.get_all(db) %}
|
||||||
{{ macros.dashboard_lexicon_item(lexicon) }}
|
{{ macros.dashboard_lexicon_item(lexicon) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</section>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% set template_content_blocks = [self.main()] %}
|
|
@ -8,22 +8,24 @@
|
||||||
{% set template_sidebar_rows = [self.sb_home(), self.sb_admin()] %}
|
{% set template_sidebar_rows = [self.sb_home(), self.sb_admin()] %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<form action="" method="post" novalidate>
|
<form action="" method="post" novalidate>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
<p>{{ form.lexiconName.label }}<br>{{ form.lexiconName(size=32) }}
|
<p>{{ form.lexicon.label }}<br>{{ form.lexicon(size=32) }}
|
||||||
{% for error in form.lexiconName.errors %}
|
{% for error in form.lexicon.errors %}
|
||||||
<br><span style="color: #ff0000">{{ error }}</span>
|
<br><span style="color: #ff0000">{{ error }}</span>
|
||||||
{% endfor %}</p>
|
{% endfor %}</p>
|
||||||
|
|
||||||
<p>{{ form.editorName.label }}<br>{{ form.editorName(size=32) }}
|
<p>{{ form.editor.label }}<br>{{ form.editor(size=32) }}
|
||||||
{% for error in form.editorName.errors %}
|
{% for error in form.editor.errors %}
|
||||||
<br><span style="color: #ff0000">{{ error }}</span>
|
<br><span style="color: #ff0000">{{ error }}</span>
|
||||||
{% endfor %}</p>
|
{% endfor %}</p>
|
||||||
|
|
||||||
<p>{{ form.promptText.label }}<br>{{ form.promptText(class_="fullwidth") }}</p>
|
<p>{{ form.prompt.label }}<br>{{ form.prompt(class_="fullwidth") }}</p>
|
||||||
|
|
||||||
<p>{{ form.submit() }}</p>
|
<p>{{ form.submit() }}</p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% for message in get_flashed_messages() %}
|
{% for message in get_flashed_messages() %}
|
||||||
<span style="color: #ff0000">{{ message }}</span><br>
|
<span style="color: #ff0000">{{ message }}</span><br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -4,13 +4,6 @@
|
||||||
{% block header %}<h2>Amanuensis - Home</h2>{% endblock %}
|
{% block header %}<h2>Amanuensis - Home</h2>{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
{% if current_user.is_site_admin %}
|
|
||||||
<section>
|
|
||||||
<a href="{{ url_for('home.admin') }}" style="display:block; text-align:center;">Admin dashboard</a>
|
|
||||||
</section>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<h1>Welcome to Amanuensis!</h1>
|
<h1>Welcome to Amanuensis!</h1>
|
||||||
<p>Amanuensis is a hub for playing Lexicon, the encyclopedia RPG. Log in to access your Lexicon games. If you do not have an account, contact the administrator.</p>
|
<p>Amanuensis is a hub for playing Lexicon, the encyclopedia RPG. Log in to access your Lexicon games. If you do not have an account, contact the administrator.</p>
|
||||||
|
|
||||||
|
@ -44,5 +37,13 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>No public games available.</p>
|
<p>No public games available.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</section>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% set template_content_blocks = [self.main()] %}
|
||||||
|
|
||||||
|
{% if current_user.is_site_admin %}
|
||||||
|
{% block admin_dash %}
|
||||||
|
<a href="{{ url_for('home.admin') }}" style="display:block; text-align:center;">Admin dashboard</a>
|
||||||
|
{% endblock %}
|
||||||
|
{% set template_content_blocks = [self.admin_dash()] + template_content_blocks %}
|
||||||
|
{% endif %}
|
|
@ -15,10 +15,6 @@
|
||||||
{% if current_page == "contents" %}class="current-page"
|
{% if current_page == "contents" %}class="current-page"
|
||||||
{% else %}href="{{ url_for('lexicon.contents', lexicon_name=g.lexicon.name) }}"
|
{% else %}href="{{ url_for('lexicon.contents', lexicon_name=g.lexicon.name) }}"
|
||||||
{% endif %}>Contents</a>{% endblock %}
|
{% endif %}>Contents</a>{% endblock %}
|
||||||
{% block sb_posts %}<a
|
|
||||||
{% if current_page == "posts" %}class="current-page"
|
|
||||||
{% else %}href="{{ url_for('lexicon.posts.list', lexicon_name=g.lexicon.name) }}"
|
|
||||||
{% endif %}>Posts{% set unread_count = postq.get_unread_count(g.db, current_membership.id) if current_membership else None %}{% if unread_count %} ({{ unread_count }}){% endif %}</a>{% endblock %}
|
|
||||||
{% block sb_rules %}<a
|
{% block sb_rules %}<a
|
||||||
{% if current_page == "rules" %}class="current-page"
|
{% if current_page == "rules" %}class="current-page"
|
||||||
{% else %}href="{{ url_for('lexicon.rules', lexicon_name=g.lexicon.name) }}"
|
{% else %}href="{{ url_for('lexicon.rules', lexicon_name=g.lexicon.name) }}"
|
||||||
|
@ -35,7 +31,6 @@
|
||||||
{% set template_sidebar_rows = [
|
{% set template_sidebar_rows = [
|
||||||
self.sb_characters(),
|
self.sb_characters(),
|
||||||
self.sb_contents(),
|
self.sb_contents(),
|
||||||
self.sb_posts(),
|
|
||||||
self.sb_rules(),
|
self.sb_rules(),
|
||||||
self.sb_settings(),
|
self.sb_settings(),
|
||||||
self.sb_stats()] %}
|
self.sb_stats()] %}
|
||||||
|
|
|
@ -8,7 +8,6 @@ from amanuensis.server.helpers import lexicon_param, player_required_if_not_publ
|
||||||
|
|
||||||
from .characters import bp as characters_bp
|
from .characters import bp as characters_bp
|
||||||
from .forms import LexiconJoinForm
|
from .forms import LexiconJoinForm
|
||||||
from .posts import bp as posts_bp
|
|
||||||
from .settings import bp as settings_bp
|
from .settings import bp as settings_bp
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +15,6 @@ bp = Blueprint(
|
||||||
"lexicon", __name__, url_prefix="/lexicon/<lexicon_name>", template_folder="."
|
"lexicon", __name__, url_prefix="/lexicon/<lexicon_name>", template_folder="."
|
||||||
)
|
)
|
||||||
bp.register_blueprint(characters_bp)
|
bp.register_blueprint(characters_bp)
|
||||||
bp.register_blueprint(posts_bp)
|
|
||||||
bp.register_blueprint(settings_bp)
|
bp.register_blueprint(settings_bp)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
{% block title %}Edit {{ character.name }} | {{ lexicon_title }}{% endblock %}
|
{% block title %}Edit {{ character.name }} | {{ lexicon_title }}{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<section>
|
|
||||||
<form action="" method="post" novalidate>
|
<form action="" method="post" novalidate>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
<p>
|
<p>
|
||||||
|
@ -20,5 +19,6 @@
|
||||||
{% for message in get_flashed_messages() %}
|
{% for message in get_flashed_messages() %}
|
||||||
<span style="color:#ff0000">{{ message }}</span><br>
|
<span style="color:#ff0000">{{ message }}</span><br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</section>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% set template_content_blocks = [self.main()] %}
|
|
@ -3,7 +3,6 @@
|
||||||
{% block title %}Character | {{ lexicon_title }}{% endblock %}
|
{% block title %}Character | {{ lexicon_title }}{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<section>
|
|
||||||
<h1>Characters</h1>
|
<h1>Characters</h1>
|
||||||
{% set players = memq.get_players_in_lexicon(db, g.lexicon.id)|list %}
|
{% set players = memq.get_players_in_lexicon(db, g.lexicon.id)|list %}
|
||||||
{% set characters = charq.get_in_lexicon(db, g.lexicon.id)|list %}
|
{% set characters = charq.get_in_lexicon(db, g.lexicon.id)|list %}
|
||||||
|
@ -31,5 +30,5 @@
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% set template_content_blocks = [self.main()] %}
|
|
@ -2,15 +2,17 @@
|
||||||
{% block title %}{{ article.title }} | {{ lexicon_title }}{% endblock %}
|
{% block title %}{{ article.title }} | {{ lexicon_title }}{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<section>
|
|
||||||
{% for message in get_flashed_messages() %}
|
{% for message in get_flashed_messages() %}
|
||||||
<span style="color:#ff0000">{{ message }}</span><br>
|
<span style="color:#ff0000">{{ message }}</span><br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<h1>{{ article.title }}</h1>
|
<h1>{{ article.title }}</h1>
|
||||||
{{ article.html }}
|
{{ article.html }}
|
||||||
</section>
|
|
||||||
<section>
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block citations %}
|
||||||
<p>
|
<p>
|
||||||
{% for citation in article.cites %}
|
{% for citation in article.cites %}
|
||||||
<a href="{{ citation|articlelink }}">{{ citation }}</a>{% if not loop.last %} / {% endif %}
|
<a href="{{ citation|articlelink }}">{{ citation }}</a>{% if not loop.last %} / {% endif %}
|
||||||
|
@ -21,5 +23,6 @@
|
||||||
<a href="{{ citation|articlelink }}">{{ citation }}</a>{% if not loop.last %} / {% endif %}
|
<a href="{{ citation|articlelink }}">{{ citation }}</a>{% if not loop.last %} / {% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
</section>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% set template_content_blocks = [self.main(), self.citations()] %}
|
|
@ -3,7 +3,7 @@
|
||||||
{% block title %}Index | {{ lexicon_title }}{% endblock %}
|
{% block title %}Index | {{ lexicon_title }}{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<section>
|
|
||||||
{% for message in get_flashed_messages() %}
|
{% for message in get_flashed_messages() %}
|
||||||
<span style="color:#ff0000">{{ message }}</span><br>
|
<span style="color:#ff0000">{{ message }}</span><br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -20,5 +20,6 @@
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</section>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% set template_content_blocks = [self.main()] %}
|
|
@ -2,7 +2,7 @@
|
||||||
{% block title %}Join | {{ g.lexicon.full_title }}{% endblock %}
|
{% block title %}Join | {{ g.lexicon.full_title }}{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<section>
|
|
||||||
<form id="lexicon-join" action="" method="post" novalidate>
|
<form id="lexicon-join" action="" method="post" novalidate>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{% if g.lexicon.join_password %}
|
{% if g.lexicon.join_password %}
|
||||||
|
@ -16,5 +16,6 @@
|
||||||
{% for message in get_flashed_messages() %}
|
{% for message in get_flashed_messages() %}
|
||||||
<span style="color:#ff0000">{{ message }}</span><br>
|
<span style="color:#ff0000">{{ message }}</span><br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</section>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% set template_content_blocks = [self.main()] %}
|
|
@ -3,7 +3,8 @@
|
||||||
{% block title %}Rules | {{ lexicon_title }}{% endblock %}
|
{% block title %}Rules | {{ lexicon_title }}{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<section>
|
|
||||||
Placeholder text
|
Placeholder text
|
||||||
</section>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% set template_content_blocks = [self.main()] %}
|
|
@ -3,7 +3,8 @@
|
||||||
{% block title %}Session | {{ lexicon_title }}{% endblock %}
|
{% block title %}Session | {{ lexicon_title }}{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<section>
|
|
||||||
Placeholder text
|
Placeholder text
|
||||||
</section>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% set template_content_blocks = [self.main()] %}
|
|
@ -1,95 +0,0 @@
|
||||||
from flask import Blueprint, render_template, g
|
|
||||||
from flask.helpers import url_for
|
|
||||||
from flask_login import current_user
|
|
||||||
from werkzeug.utils import redirect
|
|
||||||
|
|
||||||
from amanuensis.backend import postq
|
|
||||||
from amanuensis.db import Post
|
|
||||||
from amanuensis.parser import RenderableVisitor, parse_raw_markdown
|
|
||||||
from amanuensis.parser.core import *
|
|
||||||
from amanuensis.server.helpers import (
|
|
||||||
lexicon_param,
|
|
||||||
player_required,
|
|
||||||
current_lexicon,
|
|
||||||
current_membership,
|
|
||||||
)
|
|
||||||
|
|
||||||
from .forms import CreatePostForm
|
|
||||||
|
|
||||||
|
|
||||||
bp = Blueprint("posts", __name__, url_prefix="/posts", template_folder=".")
|
|
||||||
|
|
||||||
|
|
||||||
class PostFormatter(RenderableVisitor):
|
|
||||||
"""Parses stylistic markdown into HTML without links."""
|
|
||||||
|
|
||||||
def TextSpan(self, span: TextSpan):
|
|
||||||
return span.innertext
|
|
||||||
|
|
||||||
def LineBreak(self, span: LineBreak):
|
|
||||||
return "<br>"
|
|
||||||
|
|
||||||
def ParsedArticle(self, span: ParsedArticle):
|
|
||||||
return "\n".join(span.recurse(self))
|
|
||||||
|
|
||||||
def BodyParagraph(self, span: BodyParagraph):
|
|
||||||
return f'<p>{"".join(span.recurse(self))}</p>'
|
|
||||||
|
|
||||||
def SignatureParagraph(self, span: SignatureParagraph):
|
|
||||||
return (
|
|
||||||
'<hr><span class="signature"><p>'
|
|
||||||
f'{"".join(span.recurse(self))}'
|
|
||||||
"</p></span>"
|
|
||||||
)
|
|
||||||
|
|
||||||
def BoldSpan(self, span: BoldSpan):
|
|
||||||
return f'<b>{"".join(span.recurse(self))}</b>'
|
|
||||||
|
|
||||||
def ItalicSpan(self, span: ItalicSpan):
|
|
||||||
return f'<i>{"".join(span.recurse(self))}</i>'
|
|
||||||
|
|
||||||
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()
|
|
||||||
new_posts, old_posts = postq.get_posts_for_membership(g.db, current_membership.id)
|
|
||||||
return render_template(
|
|
||||||
"posts.jinja",
|
|
||||||
lexicon_name=lexicon_name,
|
|
||||||
form=form,
|
|
||||||
render_post_body=render_post_body,
|
|
||||||
new_posts=new_posts,
|
|
||||||
old_posts=old_posts,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@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,
|
|
||||||
)
|
|
|
@ -1,10 +0,0 @@
|
||||||
from flask_wtf import FlaskForm
|
|
||||||
from wtforms import SubmitField, TextAreaField
|
|
||||||
from wtforms.validators import DataRequired
|
|
||||||
|
|
||||||
|
|
||||||
class CreatePostForm(FlaskForm):
|
|
||||||
"""/lexicon/<name>/posts/"""
|
|
||||||
|
|
||||||
body = TextAreaField(validators=[DataRequired()])
|
|
||||||
submit = SubmitField("Post")
|
|
|
@ -1,28 +0,0 @@
|
||||||
{% extends "lexicon.jinja" %}
|
|
||||||
{% set current_page = "posts" %}
|
|
||||||
{% block title %}Character | {{ lexicon_title }}{% endblock %}
|
|
||||||
|
|
||||||
{% macro make_post(post, is_new) %}
|
|
||||||
<section{% if is_new %} class="new-post"{% endif %}>
|
|
||||||
<p>{{ render_post_body(post) }}</p>
|
|
||||||
<p class="post-byline">Posted {% if post.user_id %}by {{ post.user.display_name }} {% endif %}at {{ post.created }}</p>
|
|
||||||
</section>
|
|
||||||
{% endmacro %}
|
|
||||||
|
|
||||||
{% block main %}
|
|
||||||
{% if current_lexicon.allow_post %}
|
|
||||||
<section>
|
|
||||||
<form action="" method="post" novalidate>
|
|
||||||
{{ form.hidden_tag() }}
|
|
||||||
<p>{{ form.body(class_='fullwidth') }}</p>
|
|
||||||
<p>{{ form.submit() }}</p>
|
|
||||||
</form>
|
|
||||||
</section>
|
|
||||||
{% endif %}
|
|
||||||
{% for post in new_posts %}
|
|
||||||
{{ make_post(post, True) }}
|
|
||||||
{% endfor %}
|
|
||||||
{% for post in old_posts %}
|
|
||||||
{{ make_post(post, False) }}
|
|
||||||
{% endfor %}
|
|
||||||
{% endblock %}
|
|
|
@ -89,7 +89,6 @@ def setup(lexicon_name):
|
||||||
form.turn_count.data = lexicon.turn_count
|
form.turn_count.data = lexicon.turn_count
|
||||||
form.player_limit.data = lexicon.player_limit
|
form.player_limit.data = lexicon.player_limit
|
||||||
form.character_limit.data = lexicon.character_limit
|
form.character_limit.data = lexicon.character_limit
|
||||||
form.allow_post.data = lexicon.allow_post
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"settings.jinja",
|
"settings.jinja",
|
||||||
lexicon_name=lexicon_name,
|
lexicon_name=lexicon_name,
|
||||||
|
@ -110,7 +109,6 @@ def setup(lexicon_name):
|
||||||
lexicon.turn_count = form.turn_count.data
|
lexicon.turn_count = form.turn_count.data
|
||||||
lexicon.player_limit = form.player_limit.data
|
lexicon.player_limit = form.player_limit.data
|
||||||
lexicon.character_limit = form.character_limit.data
|
lexicon.character_limit = form.character_limit.data
|
||||||
lexicon.allow_post = form.allow_post.data
|
|
||||||
g.db.session.commit() # TODO refactor into backend
|
g.db.session.commit() # TODO refactor into backend
|
||||||
flash("Settings saved")
|
flash("Settings saved")
|
||||||
return redirect(
|
return redirect(
|
||||||
|
|
|
@ -49,7 +49,6 @@ class SetupSettingsForm(FlaskForm):
|
||||||
widget=NumberInput(),
|
widget=NumberInput(),
|
||||||
validators=[Optional()],
|
validators=[Optional()],
|
||||||
)
|
)
|
||||||
allow_post = BooleanField("Allow players to make posts")
|
|
||||||
submit = SubmitField("Submit")
|
submit = SubmitField("Submit")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
{% extends "lexicon.jinja" %}
|
{% extends "lexicon.jinja" %}
|
||||||
{% set current_page = "settings" %}
|
|
||||||
{% block title %}Edit | {{ lexicon_title }}{% endblock %}
|
{% block title %}Edit | {{ lexicon_title }}{% endblock %}
|
||||||
|
|
||||||
{% macro settings_page_link(page, text) -%}
|
{% macro settings_page_link(page, text) -%}
|
||||||
|
@ -20,7 +19,6 @@
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<section>
|
|
||||||
{% if current_membership.is_editor %}
|
{% if current_membership.is_editor %}
|
||||||
<ul class="unordered-tabs">
|
<ul class="unordered-tabs">
|
||||||
<li>{{ settings_page_link("player", "Player Settings") }}</li>
|
<li>{{ settings_page_link("player", "Player Settings") }}</li>
|
||||||
|
@ -80,7 +78,6 @@
|
||||||
<p>
|
<p>
|
||||||
{{ number_setting(form.character_limit) }}
|
{{ number_setting(form.character_limit) }}
|
||||||
</p>
|
</p>
|
||||||
<p>{{ flag_setting(form.allow_post) }}</p>
|
|
||||||
<p>{{ form.submit() }}</p>
|
<p>{{ form.submit() }}</p>
|
||||||
</form>
|
</form>
|
||||||
{% for message in get_flashed_messages() %}
|
{% for message in get_flashed_messages() %}
|
||||||
|
@ -175,5 +172,6 @@
|
||||||
{% if page_name == "article" %}
|
{% if page_name == "article" %}
|
||||||
<h3>Article Requirements</h3>
|
<h3>Article Requirements</h3>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</section>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% set template_content_blocks = [self.main()] %}
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='page.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='page.css') }}">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main>
|
<div id="wrapper">
|
||||||
<header>
|
<div id="header">
|
||||||
<div id="login-status" {% block login_status_attr %}{% endblock %}>
|
<div id="login-status" {% block login_status_attr %}{% endblock %}>
|
||||||
{% if current_user.is_authenticated %}
|
{% if current_user.is_authenticated %}
|
||||||
<b>{{ current_user.username -}}</b>
|
<b>{{ current_user.username -}}</b>
|
||||||
|
@ -24,11 +24,15 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% block header %}{% endblock %}
|
{% block header %}{% endblock %}
|
||||||
</header>
|
</div>
|
||||||
{% block sidebar %}{% endblock %}
|
{% block sidebar %}{% endblock %}
|
||||||
<article class="{% block content_class %}{% endblock %}">
|
<div id="content" class="{% block content_class %}{% endblock %}">
|
||||||
{% block main %}{% endblock %}
|
{% if not template_content_blocks %}{% set template_content_blocks = [] %}{% endif %}
|
||||||
</article>
|
{% if not content_blocks %}{% set content_blocks = [] %}{% endif %}
|
||||||
</main>
|
{% for content_block in template_content_blocks + content_blocks %}<div class="contentblock">
|
||||||
|
{{ content_block|safe }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{% extends "page.jinja" %}
|
{% extends "page.jinja" %}
|
||||||
{% block sidebar %}
|
{% block sidebar %}
|
||||||
<nav>
|
<div id="sidebar">
|
||||||
{% if not template_sidebar_rows %}{% set template_sidebar_rows = [] %}{% endif %}
|
{% if not template_sidebar_rows %}{% set template_sidebar_rows = [] %}{% endif %}
|
||||||
{% if not sidebar_rows %}{% set sidebar_rows = [] %}{% endif %}
|
{% if not sidebar_rows %}{% set sidebar_rows = [] %}{% endif %}
|
||||||
<table>
|
<table>
|
||||||
{% for row in template_sidebar_rows + sidebar_rows %}
|
{% for row in template_sidebar_rows + sidebar_rows %}
|
||||||
<tr><td>{{ row|safe }}</td></tr>{% endfor %}
|
<tr><td>{{ row|safe }}</td></tr>{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
</nav>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content_class %}content-2col{% endblock %}
|
{% block content_class %}content-2col{% endblock %}
|
|
@ -34,7 +34,7 @@
|
||||||
<body>
|
<body>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<div id="editor-left" class="column">
|
<div id="editor-left" class="column">
|
||||||
<section>
|
<div class="contentblock">
|
||||||
{# Thin header bar #}
|
{# Thin header bar #}
|
||||||
<div id="editor-header">
|
<div id="editor-header">
|
||||||
{# Header always includes backlink to lexicon #}
|
{# Header always includes backlink to lexicon #}
|
||||||
|
@ -103,16 +103,16 @@
|
||||||
{# #}{{ article.contents }}{#
|
{# #}{{ article.contents }}{#
|
||||||
#}</textarea>
|
#}</textarea>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</section>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="editor-right" class="column">
|
<div id="editor-right" class="column">
|
||||||
<section id="preview">
|
<div id="preview" class="contentblock">
|
||||||
<p>This editor requires Javascript to function.</p>
|
<p>This editor requires Javascript to function.</p>
|
||||||
</div>
|
</div>
|
||||||
<section id="preview-citations">
|
<div id="preview-citations" class="contentblock">
|
||||||
<p> </p>
|
<p> </p>
|
||||||
</div>
|
</div>
|
||||||
<section id="preview-control">
|
<div id="preview-control" class="contentblock">
|
||||||
<p> </p>
|
<p> </p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue