Compare commits
1 Commits
7e54b14b7f
...
1b5ac23b77
Author | SHA1 | Date |
---|---|---|
Tim Van Baak | 1b5ac23b77 |
|
@ -84,11 +84,7 @@ def password_check(db: DbContext, lexicon_id: int, password: str) -> bool:
|
||||||
def password_set(db: DbContext, lexicon_id: int, new_password: Optional[str]) -> None:
|
def password_set(db: DbContext, lexicon_id: int, new_password: Optional[str]) -> None:
|
||||||
"""Set or clear a lexicon's password."""
|
"""Set or clear a lexicon's password."""
|
||||||
password_hash = generate_password_hash(new_password) if new_password else None
|
password_hash = generate_password_hash(new_password) if new_password else None
|
||||||
db(
|
db(update(Lexicon).where(Lexicon.id == lexicon_id).values(password=password_hash))
|
||||||
update(Lexicon)
|
|
||||||
.where(Lexicon.id == lexicon_id)
|
|
||||||
.values(join_password=password_hash)
|
|
||||||
)
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,3 @@
|
||||||
:root {
|
|
||||||
--button-default: #dddddd;
|
|
||||||
--button-hover: #cccccc;
|
|
||||||
--button-current: #bbbbbb;
|
|
||||||
}
|
|
||||||
body {
|
body {
|
||||||
background-color: #eeeeee;
|
background-color: #eeeeee;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
|
@ -62,7 +57,7 @@ div.misclinks table td a {
|
||||||
table a {
|
table a {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
background-color: var(--button-default);
|
background-color: #dddddd;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
@ -70,13 +65,13 @@ div#sidebar table a {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
table a:hover {
|
table a:hover {
|
||||||
background-color: var(--button-hover);
|
background-color: #cccccc;
|
||||||
}
|
}
|
||||||
div#sidebar table a.current-page {
|
div#sidebar table a.current-page {
|
||||||
background-color: var(--button-current);
|
background-color: #bbbbbb;
|
||||||
}
|
}
|
||||||
div#sidebar table a.current-page:hover {
|
div#sidebar table a.current-page:hover {
|
||||||
background-color: var(--button-current);
|
background-color: #bbbbbb;
|
||||||
}
|
}
|
||||||
div#sidebar table td {
|
div#sidebar table td {
|
||||||
padding: 0px; margin: 3px 0;
|
padding: 0px; margin: 3px 0;
|
||||||
|
@ -114,10 +109,6 @@ textarea.fullwidth {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
input.fullwidth {
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
input.smallnumber {
|
input.smallnumber {
|
||||||
width: 4em;
|
width: 4em;
|
||||||
}
|
}
|
||||||
|
@ -177,36 +168,6 @@ div.dashboard-lexicon-item p {
|
||||||
margin-block-start: 0.5em;
|
margin-block-start: 0.5em;
|
||||||
margin-block-end: 0.5em;
|
margin-block-end: 0.5em;
|
||||||
}
|
}
|
||||||
ul.unordered-tabs {
|
|
||||||
list-style: none;
|
|
||||||
margin-block-start: 0;
|
|
||||||
margin-block-end: 0;
|
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
padding-block-start: 0;
|
|
||||||
padding-block-end: 0;
|
|
||||||
padding-inline-start: 0;
|
|
||||||
padding-inline-end: 0;
|
|
||||||
}
|
|
||||||
ul.unordered-tabs li {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 3px;
|
|
||||||
}
|
|
||||||
ul.unordered-tabs li a {
|
|
||||||
background-color: var(--button-current);
|
|
||||||
display: flex;
|
|
||||||
border: 5px solid var(--button-current);
|
|
||||||
border-radius: 5px;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
ul.unordered-tabs li a[href] {
|
|
||||||
background-color: var(--button-default);
|
|
||||||
border-color: var(--button-default);
|
|
||||||
}
|
|
||||||
ul.unordered-tabs li a[href]:hover {
|
|
||||||
background-color: var(--button-hover);
|
|
||||||
border-color: var(--button-hover);
|
|
||||||
}
|
|
||||||
@media only screen and (max-width: 816px) {
|
@media only screen and (max-width: 816px) {
|
||||||
div#wrapper {
|
div#wrapper {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
|
|
@ -9,7 +9,7 @@ from amanuensis.config import AmanuensisConfig, CommandLineConfig
|
||||||
from amanuensis.db import DbContext
|
from amanuensis.db import DbContext
|
||||||
from amanuensis.parser import filesafe_title
|
from amanuensis.parser import filesafe_title
|
||||||
import amanuensis.server.auth as auth
|
import amanuensis.server.auth as auth
|
||||||
from amanuensis.server.helpers import UuidConverter, current_lexicon, current_membership
|
from amanuensis.server.helpers import UuidConverter
|
||||||
import amanuensis.server.home as home
|
import amanuensis.server.home as home
|
||||||
import amanuensis.server.lexicon as lexicon
|
import amanuensis.server.lexicon as lexicon
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ def article_link(title):
|
||||||
"""Get the url for a lexicon by its title"""
|
"""Get the url for a lexicon by its title"""
|
||||||
return url_for(
|
return url_for(
|
||||||
'lexicon.article',
|
'lexicon.article',
|
||||||
lexicon_name=g.lexicon.name,
|
name=g.lexicon.name,
|
||||||
title=filesafe_title(title))
|
title=filesafe_title(title))
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,21 +68,13 @@ def get_app(
|
||||||
app.teardown_appcontext(db_teardown)
|
app.teardown_appcontext(db_teardown)
|
||||||
|
|
||||||
# Configure jinja options
|
# Configure jinja options
|
||||||
def add_jinja_context():
|
def include_backend():
|
||||||
return {
|
return {"db": db, "lexiq": lexiq, "userq": userq, "memq": memq, "charq": charq}
|
||||||
"db": db,
|
|
||||||
"lexiq": lexiq,
|
|
||||||
"userq": userq,
|
|
||||||
"memq": memq,
|
|
||||||
"charq": charq,
|
|
||||||
"current_lexicon": current_lexicon,
|
|
||||||
"current_membership": current_membership
|
|
||||||
}
|
|
||||||
|
|
||||||
app.jinja_options.update(trim_blocks=True, lstrip_blocks=True)
|
app.jinja_options.update(trim_blocks=True, lstrip_blocks=True)
|
||||||
app.template_filter("date")(date_format)
|
app.template_filter("date")(date_format)
|
||||||
app.template_filter("articlelink")(article_link)
|
app.template_filter("articlelink")(article_link)
|
||||||
app.context_processor(add_jinja_context)
|
app.context_processor(include_backend)
|
||||||
|
|
||||||
# Set up uuid route converter
|
# Set up uuid route converter
|
||||||
app.url_map.converters["uuid"] = UuidConverter
|
app.url_map.converters["uuid"] = UuidConverter
|
||||||
|
|
|
@ -2,17 +2,8 @@ from functools import wraps
|
||||||
from typing import Optional, Any
|
from typing import Optional, Any
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from flask import (
|
from flask import g, flash, redirect, url_for
|
||||||
_request_ctx_stack,
|
|
||||||
flash,
|
|
||||||
g,
|
|
||||||
has_request_context,
|
|
||||||
redirect,
|
|
||||||
request,
|
|
||||||
url_for,
|
|
||||||
)
|
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
from werkzeug.local import LocalProxy
|
|
||||||
from werkzeug.routing import BaseConverter, ValidationError
|
from werkzeug.routing import BaseConverter, ValidationError
|
||||||
|
|
||||||
from amanuensis.backend import lexiq, memq
|
from amanuensis.backend import lexiq, memq
|
||||||
|
@ -35,45 +26,6 @@ class UuidConverter(BaseConverter):
|
||||||
return str(value)
|
return str(value)
|
||||||
|
|
||||||
|
|
||||||
def get_current_lexicon():
|
|
||||||
# Check if the request context is for a lexicon page
|
|
||||||
if not has_request_context():
|
|
||||||
return None
|
|
||||||
lexicon_name = request.view_args.get("lexicon_name")
|
|
||||||
if not lexicon_name:
|
|
||||||
return None
|
|
||||||
# Pull up the lexicon if it exists and cache it in the request context
|
|
||||||
if not hasattr(_request_ctx_stack.top, "lexicon"):
|
|
||||||
db: DbContext = g.db
|
|
||||||
lexicon: Optional[Lexicon] = lexiq.try_from_name(db, lexicon_name)
|
|
||||||
setattr(_request_ctx_stack.top, "lexicon", lexicon)
|
|
||||||
# Return the cached lexicon
|
|
||||||
return getattr(_request_ctx_stack.top, "lexicon", None)
|
|
||||||
|
|
||||||
|
|
||||||
current_lexicon = LocalProxy(get_current_lexicon)
|
|
||||||
|
|
||||||
|
|
||||||
def get_current_membership():
|
|
||||||
# Base the current membership on the current user and the current lexicon
|
|
||||||
user: User = current_user
|
|
||||||
if not user or not user.is_authenticated:
|
|
||||||
return None
|
|
||||||
lexicon: Lexicon = current_lexicon
|
|
||||||
if not lexicon:
|
|
||||||
return None
|
|
||||||
# Pull up the membership and cache it in the request context
|
|
||||||
if not hasattr(_request_ctx_stack.top, "membership"):
|
|
||||||
db: DbContext = g.db
|
|
||||||
mem: Membership = memq.try_from_ids(db, user.id, lexicon.id)
|
|
||||||
setattr(_request_ctx_stack.top, "membership", mem)
|
|
||||||
# Return cached membership
|
|
||||||
return getattr(_request_ctx_stack.top, "membership", None)
|
|
||||||
|
|
||||||
|
|
||||||
current_membership = LocalProxy(get_current_membership)
|
|
||||||
|
|
||||||
|
|
||||||
def lexicon_param(route):
|
def lexicon_param(route):
|
||||||
"""
|
"""
|
||||||
Wrapper for loading a route's lexicon to `g`.
|
Wrapper for loading a route's lexicon to `g`.
|
||||||
|
@ -82,7 +34,7 @@ def lexicon_param(route):
|
||||||
@wraps(route)
|
@wraps(route)
|
||||||
def with_lexicon(*args, **kwargs):
|
def with_lexicon(*args, **kwargs):
|
||||||
db: DbContext = g.db
|
db: DbContext = g.db
|
||||||
name: str = kwargs.get('lexicon_name')
|
name: str = kwargs.get('name')
|
||||||
lexicon: Optional[Lexicon] = lexiq.try_from_name(db, name)
|
lexicon: Optional[Lexicon] = lexiq.try_from_name(db, name)
|
||||||
if lexicon is None:
|
if lexicon is None:
|
||||||
flash(f"Couldn't find a lexicon with the name \"{name}\"")
|
flash(f"Couldn't find a lexicon with the name \"{name}\"")
|
||||||
|
@ -119,7 +71,7 @@ def player_required(route):
|
||||||
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")
|
||||||
if lexicon.public:
|
if lexicon.public:
|
||||||
return redirect(url_for('lexicon.contents', lexicon_name=lexicon.name))
|
return redirect(url_for('lexicon.contents', name=lexicon.name))
|
||||||
else:
|
else:
|
||||||
return redirect(url_for('home.home'))
|
return redirect(url_for('home.home'))
|
||||||
return route(*args, **kwargs)
|
return route(*args, **kwargs)
|
||||||
|
@ -156,6 +108,6 @@ def editor_required(route):
|
||||||
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")
|
||||||
return redirect(url_for('lexicon.contents', lexicon_name=lexicon.name))
|
return redirect(url_for('lexicon.contents', name=lexicon.name))
|
||||||
return route(*args, **kwargs)
|
return route(*args, **kwargs)
|
||||||
return editor_route
|
return editor_route
|
||||||
|
|
|
@ -9,28 +9,41 @@
|
||||||
{% block sb_logo %}{% endblock %}
|
{% block sb_logo %}{% endblock %}
|
||||||
{% block sb_characters %}<a
|
{% block sb_characters %}<a
|
||||||
{% if current_page == "characters" %}class="current-page"
|
{% if current_page == "characters" %}class="current-page"
|
||||||
{% else %}href="{{ url_for('lexicon.characters.list', lexicon_name=g.lexicon.name) }}"
|
{% else %}href="{{ url_for('lexicon.characters.list', name=g.lexicon.name) }}"
|
||||||
{% endif %}>Characters</a>{% endblock %}
|
{% endif %}>Characters</a>{% endblock %}
|
||||||
{% block sb_contents %}<a
|
{% block sb_contents %}<a
|
||||||
{% 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', name=g.lexicon.name) }}"
|
||||||
{% endif %}>Contents</a>{% endblock %}
|
{% endif %}>Contents</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', name=g.lexicon.name) }}"
|
||||||
{% endif %}>Rules</a>{% endblock %}
|
{% endif %}>Rules</a>{% endblock %}
|
||||||
{% block sb_settings %}<a
|
{% block sb_session %}<a
|
||||||
{% if current_page == "settings" %}class="current-page"
|
{% if current_page == "session" %}class="current-page"
|
||||||
{% else %}href="{{ url_for('lexicon.settings.page', lexicon_name=g.lexicon.name) }}"
|
{% else %}href="#{#{ url_for('session.session', name=g.lexicon.name) }#}"
|
||||||
{% endif %}>Settings</a>{% endblock %}
|
{% endif %}>Session</a>{% endblock %}
|
||||||
{% block sb_stats %}<a
|
{% block sb_stats %}<a
|
||||||
{% if current_page == "statistics" %}class="current-page"
|
{% if current_page == "statistics" %}class="current-page"
|
||||||
{% else %}href="{{ url_for('lexicon.stats', lexicon_name=g.lexicon.name) }}"
|
{% else %}href="{{ url_for('lexicon.stats', name=g.lexicon.name) }}"
|
||||||
{% endif %}>Statistics</a>{% endblock %}
|
{% endif %}>Statistics</a>{% endblock %}
|
||||||
|
|
||||||
|
{% if current_user.is_authenticated and (
|
||||||
|
current_user.is_site_admin
|
||||||
|
or memq.try_from_ids(g.db, current_user.id, g.lexicon.id)
|
||||||
|
) %}
|
||||||
|
{# self.sb_logo(), #}
|
||||||
{% set template_sidebar_rows = [
|
{% set template_sidebar_rows = [
|
||||||
self.sb_characters(),
|
self.sb_characters(),
|
||||||
self.sb_contents(),
|
self.sb_contents(),
|
||||||
self.sb_rules(),
|
self.sb_rules(),
|
||||||
self.sb_settings(),
|
self.sb_session(),
|
||||||
self.sb_stats()] %}
|
self.sb_stats()] %}
|
||||||
|
{% else %}
|
||||||
|
{# self.sb_logo(), #}
|
||||||
|
{% set template_sidebar_rows = [
|
||||||
|
self.sb_characters(),
|
||||||
|
self.sb_contents(),
|
||||||
|
self.sb_rules(),
|
||||||
|
self.sb_stats()] %}
|
||||||
|
{% endif %}
|
||||||
|
|
|
@ -8,20 +8,16 @@ 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 .settings import bp as settings_bp
|
|
||||||
|
|
||||||
|
|
||||||
bp = Blueprint(
|
bp = Blueprint("lexicon", __name__, url_prefix="/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(settings_bp)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/join/", methods=["GET", "POST"])
|
@bp.route("/join/", methods=["GET", "POST"])
|
||||||
@lexicon_param
|
@lexicon_param
|
||||||
@login_required
|
@login_required
|
||||||
def join(lexicon_name):
|
def join(name):
|
||||||
lexicon: Lexicon = g.lexicon
|
lexicon: Lexicon = g.lexicon
|
||||||
if not lexicon.joinable:
|
if not lexicon.joinable:
|
||||||
flash("This game isn't open for joining")
|
flash("This game isn't open for joining")
|
||||||
|
@ -31,9 +27,7 @@ def join(lexicon_name):
|
||||||
|
|
||||||
if not form.validate_on_submit():
|
if not form.validate_on_submit():
|
||||||
# GET or POST with invalid form data
|
# GET or POST with invalid form data
|
||||||
return render_template(
|
return render_template("lexicon.join.jinja", form=form)
|
||||||
"lexicon.join.jinja", lexicon_name=lexicon_name, form=form
|
|
||||||
)
|
|
||||||
|
|
||||||
# POST with valid data
|
# POST with valid data
|
||||||
# If the game is passworded, check password
|
# If the game is passworded, check password
|
||||||
|
@ -43,48 +37,48 @@ def join(lexicon_name):
|
||||||
):
|
):
|
||||||
# Bad creds, try again
|
# Bad creds, try again
|
||||||
flash("Incorrect password")
|
flash("Incorrect password")
|
||||||
return redirect(url_for("lexicon.join", lexicon_name=lexicon_name))
|
return redirect(url_for("lexicon.join", name=name))
|
||||||
|
|
||||||
# If the password was correct, check if the user can join
|
# If the password was correct, check if the user can join
|
||||||
user: User = current_user
|
user: User = current_user
|
||||||
try:
|
try:
|
||||||
memq.create(db, user.id, lexicon.id, is_editor=False)
|
memq.create(db, user.id, lexicon.id, is_editor=False)
|
||||||
return redirect(url_for("session.session", lexicon_name=lexicon_name))
|
return redirect(url_for("session.session", name=name))
|
||||||
except ArgumentError:
|
except ArgumentError:
|
||||||
flash("Could not join game")
|
flash("Could not join game")
|
||||||
return redirect(url_for("home.home", lexicon_name=lexicon_name))
|
return redirect(url_for("home.home", name=name))
|
||||||
|
|
||||||
|
|
||||||
@bp.get("/contents/")
|
@bp.get("/contents/")
|
||||||
@lexicon_param
|
@lexicon_param
|
||||||
@player_required_if_not_public
|
@player_required_if_not_public
|
||||||
def contents(lexicon_name):
|
def contents(name):
|
||||||
# indexed = sort_by_index_spec(info, g.lexicon.cfg.article.index.list)
|
# indexed = sort_by_index_spec(info, g.lexicon.cfg.article.index.list)
|
||||||
# for articles in indexed.values():
|
# for articles in indexed.values():
|
||||||
# for i in range(len(articles)):
|
# for i in range(len(articles)):
|
||||||
# articles[i] = {
|
# articles[i] = {
|
||||||
# 'title': articles[i],
|
# 'title': articles[i],
|
||||||
# **info.get(articles[i])}
|
# **info.get(articles[i])}
|
||||||
return render_template("lexicon.contents.jinja", lexicon_name=lexicon_name)
|
return render_template("lexicon.contents.jinja")
|
||||||
|
|
||||||
|
|
||||||
@bp.get("/article/<title>")
|
@bp.get("/article/<title>")
|
||||||
@lexicon_param
|
@lexicon_param
|
||||||
@player_required_if_not_public
|
@player_required_if_not_public
|
||||||
def article(lexicon_name, title):
|
def article(name, title):
|
||||||
# article = {**a, 'html': Markup(a['html'])}
|
# article = {**a, 'html': Markup(a['html'])}
|
||||||
return render_template("lexicon.article.jinja", lexicon_name=lexicon_name)
|
return render_template("lexicon.article.jinja")
|
||||||
|
|
||||||
|
|
||||||
@bp.get("/rules/")
|
@bp.get("/rules/")
|
||||||
@lexicon_param
|
@lexicon_param
|
||||||
@player_required_if_not_public
|
@player_required_if_not_public
|
||||||
def rules(lexicon_name):
|
def rules(name):
|
||||||
return render_template("lexicon.rules.jinja", lexicon_name=lexicon_name)
|
return render_template("lexicon.rules.jinja")
|
||||||
|
|
||||||
|
|
||||||
@bp.get("/statistics/")
|
@bp.get("/statistics/")
|
||||||
@lexicon_param
|
@lexicon_param
|
||||||
@player_required_if_not_public
|
@player_required_if_not_public
|
||||||
def stats(lexicon_name):
|
def stats(name):
|
||||||
return render_template("lexicon.statistics.jinja", lexicon_name=lexicon_name)
|
return render_template("lexicon.statistics.jinja")
|
||||||
|
|
|
@ -18,18 +18,18 @@ bp = Blueprint("characters", __name__, url_prefix="/characters", template_folder
|
||||||
@bp.get("/")
|
@bp.get("/")
|
||||||
@lexicon_param
|
@lexicon_param
|
||||||
@player_required
|
@player_required
|
||||||
def list(lexicon_name):
|
def list(name):
|
||||||
return render_template("characters.jinja", lexicon_name=lexicon_name)
|
return render_template("characters.jinja", name=name)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/edit/<uuid:character_id>", methods=["GET", "POST"])
|
@bp.route("/edit/<uuid:character_id>", methods=["GET", "POST"])
|
||||||
@lexicon_param
|
@lexicon_param
|
||||||
@player_required
|
@player_required
|
||||||
def edit(lexicon_name, character_id: uuid.UUID):
|
def edit(name, character_id: uuid.UUID):
|
||||||
character: Optional[Character] = charq.try_from_public_id(g.db, character_id)
|
character: Optional[Character] = charq.try_from_public_id(g.db, character_id)
|
||||||
if not character:
|
if not character:
|
||||||
flash("Character not found")
|
flash("Character not found")
|
||||||
return redirect(url_for("lexicon.characters.list", lexicon_name=lexicon_name))
|
return redirect(url_for("lexicon.characters.list", name=name))
|
||||||
|
|
||||||
form = CharacterCreateForm()
|
form = CharacterCreateForm()
|
||||||
|
|
||||||
|
@ -37,12 +37,7 @@ def edit(lexicon_name, character_id: uuid.UUID):
|
||||||
# GET
|
# GET
|
||||||
form.name.data = character.name
|
form.name.data = character.name
|
||||||
form.signature.data = character.signature
|
form.signature.data = character.signature
|
||||||
return render_template(
|
return render_template("characters.edit.jinja", character=character, form=form)
|
||||||
"characters.edit.jinja",
|
|
||||||
lexicon_name=lexicon_name,
|
|
||||||
character=character,
|
|
||||||
form=form,
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# POST
|
# POST
|
||||||
|
@ -50,34 +45,25 @@ def edit(lexicon_name, character_id: uuid.UUID):
|
||||||
# Data is valid
|
# Data is valid
|
||||||
character.name = form.name.data
|
character.name = form.name.data
|
||||||
character.signature = form.signature.data
|
character.signature = form.signature.data
|
||||||
g.db.session.commit() # TODO refactor into backend
|
g.db.session.commit()
|
||||||
return redirect(
|
return redirect(url_for("lexicon.characters.list", name=name))
|
||||||
url_for("lexicon.characters.list", lexicon_name=lexicon_name)
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# POST submitted invalid data
|
# POST submitted invalid data
|
||||||
return render_template(
|
return render_template(
|
||||||
"characters.edit.jinja",
|
"characters.edit.jinja", character=character, form=form
|
||||||
lexicon_name=lexicon_name,
|
|
||||||
character=character,
|
|
||||||
form=form,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.get("/new/")
|
@bp.get("/new/")
|
||||||
@lexicon_param
|
@lexicon_param
|
||||||
@player_required
|
@player_required
|
||||||
def new(lexicon_name):
|
def new(name):
|
||||||
dummy_name = f"{current_user.username}'s new character"
|
dummy_name = f"{current_user.username}'s new character"
|
||||||
dummy_signature = "~"
|
dummy_signature = "~"
|
||||||
char = charq.create(
|
char = charq.create(
|
||||||
g.db, g.lexicon.id, current_user.id, dummy_name, dummy_signature
|
g.db, g.lexicon.id, current_user.id, dummy_name, dummy_signature
|
||||||
)
|
)
|
||||||
return redirect(
|
return redirect(
|
||||||
url_for(
|
url_for("lexicon.characters.edit", name=name, character_id=char.public_id)
|
||||||
"lexicon.characters.edit",
|
|
||||||
lexicon_name=lexicon_name,
|
|
||||||
character_id=char.public_id,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<ul class="blockitem-list">
|
<ul class="blockitem-list">
|
||||||
{% if characters|map(attribute="user_id")|select("equalto", current_user.id)|list|count < g.lexicon.character_limit %}
|
{% if characters|map(attribute="user_id")|select("equalto", current_user.id)|list|count < g.lexicon.character_limit %}
|
||||||
<li>
|
<li>
|
||||||
<h3><a href="{{ url_for('lexicon.characters.new', lexicon_name=lexicon_name) }}">Create a new character</a></h3>
|
<h3><a href="{{ url_for('lexicon.characters.new', name=name) }}">Create a new character</a></h3>
|
||||||
<p>You have created {{ characters|map(attribute="user_id")|select("equalto", current_user.id)|list|count }} out of {{ g.lexicon.character_limit }} allowed characters.</p>
|
<p>You have created {{ characters|map(attribute="user_id")|select("equalto", current_user.id)|list|count }} out of {{ g.lexicon.character_limit }} allowed characters.</p>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<p>Player: {{ character.user.username }}</p>
|
<p>Player: {{ character.user.username }}</p>
|
||||||
{% if character.user == current_user %}
|
{% if character.user == current_user %}
|
||||||
<p><a href="{{ url_for('lexicon.characters.edit', lexicon_name=lexicon_name, character_id=character.public_id) }}">Edit this character</a></p>
|
<p><a href="{{ url_for('lexicon.characters.edit', name=g.lexicon.name, character_id=character.public_id) }}">Edit this character</a></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
from flask import Blueprint, render_template, url_for, g, flash, redirect
|
from typing import Optional
|
||||||
|
import uuid
|
||||||
|
|
||||||
from amanuensis.backend import *
|
from flask import Blueprint, render_template, url_for, g, flash
|
||||||
from amanuensis.db import *
|
from flask_login import current_user
|
||||||
from amanuensis.server.helpers import (
|
from werkzeug.utils import redirect
|
||||||
editor_required,
|
|
||||||
lexicon_param,
|
|
||||||
player_required,
|
|
||||||
current_membership,
|
|
||||||
current_lexicon,
|
|
||||||
)
|
|
||||||
|
|
||||||
from .forms import PlayerSettingsForm, SetupSettingsForm
|
from amanuensis.backend import charq
|
||||||
|
from amanuensis.db import Character
|
||||||
|
from amanuensis.server.helpers import editor_required, lexicon_param, player_required
|
||||||
|
|
||||||
|
# from .forms import CharacterCreateForm
|
||||||
|
|
||||||
|
|
||||||
bp = Blueprint("settings", __name__, url_prefix="/settings", template_folder=".")
|
bp = Blueprint("settings", __name__, url_prefix="/settings", template_folder=".")
|
||||||
|
@ -18,128 +17,6 @@ bp = Blueprint("settings", __name__, url_prefix="/settings", template_folder="."
|
||||||
|
|
||||||
@bp.get("/")
|
@bp.get("/")
|
||||||
@lexicon_param
|
@lexicon_param
|
||||||
@player_required
|
|
||||||
def page(lexicon_name):
|
|
||||||
return redirect(url_for("lexicon.settings.player", lexicon_name=lexicon_name))
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/player/", methods=["GET", "POST"])
|
|
||||||
@lexicon_param
|
|
||||||
@player_required
|
|
||||||
def player(lexicon_name):
|
|
||||||
form = PlayerSettingsForm()
|
|
||||||
mem: Membership = current_membership
|
|
||||||
|
|
||||||
if not form.is_submitted():
|
|
||||||
# GET
|
|
||||||
form.notify_ready.data = mem.notify_ready
|
|
||||||
form.notify_reject.data = mem.notify_reject
|
|
||||||
form.notify_approve.data = mem.notify_approve
|
|
||||||
return render_template(
|
|
||||||
"settings.jinja",
|
|
||||||
lexicon_name=lexicon_name,
|
|
||||||
page_name=player.__name__,
|
|
||||||
form=form,
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# POST
|
|
||||||
if form.validate():
|
|
||||||
# Data is valid
|
|
||||||
mem.notify_ready = form.notify_ready.data
|
|
||||||
mem.notify_reject = form.notify_reject.data
|
|
||||||
mem.notify_approve = form.notify_approve.data
|
|
||||||
g.db.session.commit() # TODO refactor into backend
|
|
||||||
flash("Settings saved")
|
|
||||||
return redirect(
|
|
||||||
url_for("lexicon.settings.player", lexicon_name=lexicon_name)
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# Invalid POST data
|
|
||||||
return render_template(
|
|
||||||
"settings.jinja",
|
|
||||||
lexicon_name=lexicon_name,
|
|
||||||
page_name=player.__name__,
|
|
||||||
form=form,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/setup/", methods=["GET", "POST"])
|
|
||||||
@lexicon_param
|
|
||||||
@editor_required
|
@editor_required
|
||||||
def setup(lexicon_name):
|
def page(name):
|
||||||
form = SetupSettingsForm()
|
return render_template("settings.jinja", name=name)
|
||||||
lexicon: Lexicon = current_lexicon
|
|
||||||
|
|
||||||
if not form.is_submitted():
|
|
||||||
# GET
|
|
||||||
form.title.data = lexicon.title
|
|
||||||
form.prompt.data = lexicon.prompt
|
|
||||||
form.public.data = lexicon.public
|
|
||||||
form.joinable.data = lexicon.joinable
|
|
||||||
form.has_password.data = lexicon.join_password is not None
|
|
||||||
form.turn_count.data = lexicon.turn_count
|
|
||||||
form.player_limit.data = lexicon.player_limit
|
|
||||||
form.character_limit.data = lexicon.character_limit
|
|
||||||
return render_template(
|
|
||||||
"settings.jinja",
|
|
||||||
lexicon_name=lexicon_name,
|
|
||||||
page_name=setup.__name__,
|
|
||||||
form=form,
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# POST
|
|
||||||
if form.validate():
|
|
||||||
# Data is valid
|
|
||||||
lexicon.title = form.title.data
|
|
||||||
lexicon.prompt = form.prompt.data
|
|
||||||
lexicon.public = form.public.data
|
|
||||||
lexicon.joinable = form.joinable.data
|
|
||||||
new_password = form.password.data if form.has_password.data else None
|
|
||||||
lexiq.password_set(g.db, lexicon.id, new_password)
|
|
||||||
lexicon.turn_count = form.turn_count.data
|
|
||||||
lexicon.player_limit = form.player_limit.data
|
|
||||||
lexicon.character_limit = form.character_limit.data
|
|
||||||
g.db.session.commit() # TODO refactor into backend
|
|
||||||
flash("Settings saved")
|
|
||||||
return redirect(
|
|
||||||
url_for("lexicon.settings.setup", lexicon_name=lexicon_name)
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# Invalid POST data
|
|
||||||
return render_template(
|
|
||||||
"settings.jinja",
|
|
||||||
lexicon_name=lexicon_name,
|
|
||||||
page_name=setup.__name__,
|
|
||||||
form=form,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.get("/progress/")
|
|
||||||
@lexicon_param
|
|
||||||
@editor_required
|
|
||||||
def progress(lexicon_name):
|
|
||||||
return render_template(
|
|
||||||
"settings.jinja", lexicon_name=lexicon_name, page_name=progress.__name__
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.get("/publish/")
|
|
||||||
@lexicon_param
|
|
||||||
@editor_required
|
|
||||||
def publish(lexicon_name):
|
|
||||||
return render_template(
|
|
||||||
"settings.jinja", lexicon_name=lexicon_name, page_name=publish.__name__
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.get("/article/")
|
|
||||||
@lexicon_param
|
|
||||||
@editor_required
|
|
||||||
def article(lexicon_name):
|
|
||||||
return render_template(
|
|
||||||
"settings.jinja", lexicon_name=lexicon_name, page_name=article.__name__
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
from flask_wtf import FlaskForm
|
|
||||||
from wtforms import (
|
|
||||||
BooleanField,
|
|
||||||
IntegerField,
|
|
||||||
PasswordField,
|
|
||||||
StringField,
|
|
||||||
SubmitField,
|
|
||||||
TextAreaField,
|
|
||||||
)
|
|
||||||
from wtforms.validators import Optional, DataRequired
|
|
||||||
from wtforms.widgets.html5 import NumberInput
|
|
||||||
|
|
||||||
|
|
||||||
class PlayerSettingsForm(FlaskForm):
|
|
||||||
"""/lexicon/<name>/settings/player/"""
|
|
||||||
|
|
||||||
notify_ready = BooleanField("Notify me when an article is submitted for review")
|
|
||||||
notify_reject = BooleanField("Notify me when an editor rejects one of my articles")
|
|
||||||
notify_approve = BooleanField(
|
|
||||||
"Notify me when an editor approves one of my articles"
|
|
||||||
)
|
|
||||||
submit = SubmitField("Submit")
|
|
||||||
|
|
||||||
|
|
||||||
class SetupSettingsForm(FlaskForm):
|
|
||||||
"""/lexicon/<name>/settings/setup/"""
|
|
||||||
|
|
||||||
title = StringField("Title override")
|
|
||||||
prompt = TextAreaField("Prompt", validators=[DataRequired()])
|
|
||||||
public = BooleanField("Make game publicly visible")
|
|
||||||
joinable = BooleanField("Allow players to join game")
|
|
||||||
has_password = BooleanField("Require password to join the game")
|
|
||||||
password = PasswordField("Game password")
|
|
||||||
turn_count = IntegerField(
|
|
||||||
"Number of turns", widget=NumberInput(), validators=[DataRequired()]
|
|
||||||
)
|
|
||||||
player_limit = IntegerField(
|
|
||||||
"Maximum number of players", widget=NumberInput(), validators=[Optional()]
|
|
||||||
)
|
|
||||||
character_limit = IntegerField(
|
|
||||||
"Maximum number of characters per player",
|
|
||||||
widget=NumberInput(),
|
|
||||||
validators=[Optional()],
|
|
||||||
)
|
|
||||||
submit = SubmitField("Submit")
|
|
|
@ -1,14 +1,33 @@
|
||||||
{% extends "lexicon.jinja" %}
|
{% extends "lexicon.jinja" %}
|
||||||
{% block title %}Edit | {{ lexicon_title }}{% endblock %}
|
{% block title %}Edit | {{ lexicon_title }}{% endblock %}
|
||||||
|
|
||||||
{% macro settings_page_link(page, text) -%}
|
{% block main %}
|
||||||
<a{% if page_name != page %} href="{{ url_for('lexicon.settings.' + page, lexicon_name=lexicon_name) }}"{% endif %}>{{ text }}</a>
|
<p>
|
||||||
{%- endmacro %}
|
|
||||||
|
|
||||||
{% macro flag_setting(field) %}
|
|
||||||
{{ field() }}
|
<p>
|
||||||
{{ field.label }}<br>
|
Id: {{ g.lexicon.lid }}<br>
|
||||||
{% endmacro %}
|
Name: {{ g.lexicon.cfg.name }}<br>
|
||||||
|
Created: {{ g.lexicon.cfg.time.created|asdate }}<br>
|
||||||
|
Completed: {{ g.lexicon.cfg.time.completed|asdate }}<br>
|
||||||
|
Players:
|
||||||
|
{% for uid in g.lexicon.cfg.join.joined %}
|
||||||
|
{{ uid|user_attr('username') }}{% if not loop.last %},{% endif %}
|
||||||
|
{% endfor %}<br>
|
||||||
|
Characters:
|
||||||
|
{% for char in g.lexicon.cfg.character.values() %}
|
||||||
|
{{ char.name }}{% if char.player %}
|
||||||
|
({{ char.player|user_attr('username') }}){% endif %}
|
||||||
|
{% if not loop.last %},{% endif %}
|
||||||
|
{% endfor %}<br>
|
||||||
|
</p>
|
||||||
|
<div style="width: 100%; height: 10em; overflow-y:auto; resize: vertical;
|
||||||
|
border: 1px solid #bbbbbb; font-size: 0.7em; padding:3px; box-sizing: border-box;">
|
||||||
|
{% for log_entry in g.lexicon.cfg.log %}
|
||||||
|
[{{ log_entry[0]|asdate }}] {{ log_entry[1] }}<br>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% macro number_setting(field) %}
|
{% macro number_setting(field) %}
|
||||||
{{ field(autocomplete="off", class_="smallnumber") }}
|
{{ field(autocomplete="off", class_="smallnumber") }}
|
||||||
|
@ -16,84 +35,91 @@
|
||||||
{% for error in field.errors %}
|
{% for error in field.errors %}
|
||||||
<span style="color: #ff0000">{{ error }}</span><br>
|
<span style="color: #ff0000">{{ error }}</span><br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endmacro %}
|
||||||
|
{% macro flag_setting(field) %}
|
||||||
|
{{ field() }}
|
||||||
|
{{ field.label }}<br>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% block main %}
|
{% block settings %}
|
||||||
{% if current_membership.is_editor %}
|
<form id="session-settings" action="" method="post" novalidate>
|
||||||
<ul class="unordered-tabs">
|
{{ form.hidden_tag() }}
|
||||||
<li>{{ settings_page_link("player", "Player") }}</li>
|
|
||||||
<li>{{ settings_page_link("setup", "Game Setup") }}</li>
|
|
||||||
<li>{{ settings_page_link("progress", "Game Progress") }}</li>
|
|
||||||
<li>{{ settings_page_link("publish", "Turn Publishing") }}</li>
|
|
||||||
<li>{{ settings_page_link("article", "Article Requirements") }}</li>
|
|
||||||
</ul>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if page_name == "player" %}
|
<h3>General</h3>
|
||||||
<h3>Player Settings</h3>
|
<p>
|
||||||
<form action="" method="post" novalidate>
|
{{ form.title.label }}:<br>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.title(autocomplete="off", size=32, style="width:100%") }}<br>
|
||||||
<p>
|
{{ form.editor.label }}: {{ form.editor(autocomplete="off") }}<br>
|
||||||
{% if current_membership.is_editor %}{{ flag_setting(form.notify_ready) }}{% endif %}
|
{% for error in form.editor.errors %}
|
||||||
{{ flag_setting(form.notify_reject) }}
|
<span style="color: #ff0000">{{ error }}</span><br>
|
||||||
{{ flag_setting(form.notify_approve) }}
|
{% endfor %}
|
||||||
</p>
|
{{ form.prompt.label }}: {{ form.prompt(class_="fullwidth") }}
|
||||||
<p>{{ form.submit() }}</p>
|
{% for error in form.prompt.errors %}
|
||||||
</form>
|
<span style="color: #ff0000">{{ error }}</span><br>
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
|
||||||
{% for message in get_flashed_messages() %}
|
|
||||||
<span style="color:#ff0000">{{ message }}</span><br>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if page_name == "setup" %}
|
|
||||||
<h3>Game Setup</h3>
|
|
||||||
<form action="" method="post" novalidate>
|
|
||||||
{{ form.hidden_tag() }}
|
|
||||||
<p>
|
|
||||||
{{ form.title.label }}:<br>
|
|
||||||
{{ form.title(autocomplete="off", placeholder="Lexicon " + lexicon_name, class_="fullwidth") }}<br>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{{ form.prompt.label }}: {{ form.prompt(class_="fullwidth") }}
|
|
||||||
{% for error in form.prompt.errors %}
|
|
||||||
<span style="color: #ff0000">{{ error }}</span><br>
|
|
||||||
{% endfor %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{{ flag_setting(form.public) }}
|
|
||||||
{{ flag_setting(form.joinable) }}
|
|
||||||
{{ form.has_password() }}
|
|
||||||
{{ form.has_password.label }}:<br>
|
|
||||||
{{ form.password(autocomplete="off") }}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{{ number_setting(form.turn_count) }}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{{ number_setting(form.player_limit) }}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{{ number_setting(form.character_limit) }}
|
|
||||||
</p>
|
|
||||||
<p>{{ form.submit() }}</p>
|
|
||||||
</form>
|
|
||||||
{% for message in get_flashed_messages() %}
|
|
||||||
<span style="color:#ff0000">{{ message }}</span><br>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if page_name == "progress" %}
|
|
||||||
<h3>Game Progress</h3>
|
<h3>Game Progress</h3>
|
||||||
{% endif %}
|
<p>
|
||||||
|
{{ number_setting(form.turnCurrent) }}
|
||||||
|
{{ number_setting(form.turnMax) }}
|
||||||
|
{{ form.articleIndexList.label }}:<br>
|
||||||
|
{{ form.articleIndexList(class_="fullwidth", rows=10) }}
|
||||||
|
{% for error in form.articleIndexList.errors %}
|
||||||
|
<span style="color: #ff0000">{{ error }}</span><br>
|
||||||
|
{% endfor %}
|
||||||
|
{{ number_setting(form.articleIndexCapacity) }}
|
||||||
|
{{ form.turnAssignment.label }}:<br>
|
||||||
|
{{ form.turnAssignment(class_="fullwidth", rows=10) }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Visibility and Joining</h3>
|
||||||
|
<p>
|
||||||
|
{{ flag_setting(form.joinPublic) }}
|
||||||
|
{{ flag_setting(form.joinOpen) }}
|
||||||
|
{{ form.joinPassword(autocomplete="off") }}
|
||||||
|
{{ form.joinPassword.label }}<br>
|
||||||
|
{{ number_setting(form.joinMaxPlayers) }}
|
||||||
|
{{ number_setting(form.joinCharsPerPlayer) }}
|
||||||
|
</p>
|
||||||
|
|
||||||
{% if page_name == "publish" %}
|
|
||||||
<h3>Turn Publishing</h3>
|
<h3>Turn Publishing</h3>
|
||||||
{% endif %}
|
<p>
|
||||||
|
{{ flag_setting(form.publishNotifyEditorOnReady) }}
|
||||||
|
{{ flag_setting(form.publishNotifyPlayerOnReject) }}
|
||||||
|
{{ flag_setting(form.publishNotifyPlayerOnAccept) }}
|
||||||
|
{{ form.publishDeadlines(autocomplete="off") }}
|
||||||
|
{{ form.publishDeadlines.label }}<br>
|
||||||
|
{{ flag_setting(form.publishAsap) }}
|
||||||
|
{% for error in form.publishDeadlines.errors %}
|
||||||
|
<span style="color: #ff0000">{{ error }}</span><br>
|
||||||
|
{% endfor %}
|
||||||
|
{{ flag_setting(form.publishBlockOnReady) }}
|
||||||
|
{{ number_setting(form.publishQuorum) }}
|
||||||
|
</p>
|
||||||
|
|
||||||
{% if page_name == "article" %}
|
|
||||||
<h3>Article Requirements</h3>
|
<h3>Article Requirements</h3>
|
||||||
{% endif %}
|
<p>
|
||||||
|
{{ flag_setting(form.articleCitationAllowSelf) }}
|
||||||
|
{{ number_setting(form.articleCitationMinExtant)}}
|
||||||
|
{{ number_setting(form.articleCitationMaxExtant)}}
|
||||||
|
{{ number_setting(form.articleCitationMinPhantom)}}
|
||||||
|
{{ number_setting(form.articleCitationMaxPhantom)}}
|
||||||
|
{{ number_setting(form.articleCitationMinTotal)}}
|
||||||
|
{{ number_setting(form.articleCitationMaxTotal)}}
|
||||||
|
{{ number_setting(form.articleCitationMinChars)}}
|
||||||
|
{{ number_setting(form.articleCitationMaxChars)}}
|
||||||
|
{{ number_setting(form.articleWordLimitSoft)}}
|
||||||
|
{{ number_setting(form.articleWordLimitHard)}}
|
||||||
|
{{ flag_setting(form.articleAddendumAllowed) }}
|
||||||
|
{{ number_setting(form.articleAddendumMax) }}
|
||||||
|
</p>
|
||||||
|
<!--character-->
|
||||||
|
<p>{{ form.submit() }}</p>
|
||||||
|
</form>
|
||||||
|
{% for message in get_flashed_messages() %}
|
||||||
|
<span style="color: #ff0000">{{ message }}</span><br>
|
||||||
|
{% endfor %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% set template_content_blocks = [self.info(), self.settings()] %}
|
||||||
{% set template_content_blocks = [self.main()] %}
|
|
|
@ -3,7 +3,7 @@
|
||||||
<div class="dashboard-lexicon-item dashboard-lexicon-{{ status }}">
|
<div class="dashboard-lexicon-item dashboard-lexicon-{{ status }}">
|
||||||
<p>
|
<p>
|
||||||
<span class="dashboard-lexicon-item-title">
|
<span class="dashboard-lexicon-item-title">
|
||||||
<a href="{{ url_for('lexicon.contents', lexicon_name=lexicon.name) }}">{{ lexicon.full_title }}</a>
|
<a href="{{ url_for('lexicon.contents', name=lexicon.name) }}">{{ lexicon.full_title }}</a>
|
||||||
</span>
|
</span>
|
||||||
[{{ status.capitalize() }}]
|
[{{ status.capitalize() }}]
|
||||||
</p>
|
</p>
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
Players: {{ lexicon.memberships|count }}{% if lexicon.player_limit is not none %} / {{ lexicon.player_limit }}{% endif -%}
|
Players: {{ lexicon.memberships|count }}{% if lexicon.player_limit is not none %} / {{ lexicon.player_limit }}{% endif -%}
|
||||||
{%-
|
{%-
|
||||||
if lexicon.public and lexicon.joinable
|
if lexicon.public and lexicon.joinable
|
||||||
%} / <a href="{{ url_for('lexicon.join', lexicon_name=lexicon.name) }}">Join game</a>
|
%} / <a href="{{ url_for('lexicon.join', name=lexicon.name) }}">Join game</a>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -32,12 +32,12 @@ def test_character_view(db: DbContext, app: Flask, make: ObjectFactory):
|
||||||
assert mem
|
assert mem
|
||||||
|
|
||||||
# The character page exists
|
# The character page exists
|
||||||
list_url = url_for("lexicon.characters.list", lexicon_name=lexicon.name)
|
list_url = url_for("lexicon.characters.list", name=lexicon.name)
|
||||||
response = client.get(list_url)
|
response = client.get(list_url)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert charname.encode("utf8") not in response.data
|
assert charname.encode("utf8") not in response.data
|
||||||
assert char_sig.encode("utf8") not in response.data
|
assert char_sig.encode("utf8") not in response.data
|
||||||
new_url = url_for("lexicon.characters.new", lexicon_name=lexicon.name)
|
new_url = url_for("lexicon.characters.new", name=lexicon.name)
|
||||||
assert new_url.encode("utf8") in response.data
|
assert new_url.encode("utf8") in response.data
|
||||||
|
|
||||||
# The character creation endpoint works
|
# The character creation endpoint works
|
||||||
|
|
Loading…
Reference in New Issue