Compare commits

..

1 Commits

Author SHA1 Message Date
Tim Van Baak fd5773b521 tmp 2021-08-19 17:11:27 -07:00
13 changed files with 63 additions and 173 deletions

View File

@ -2,8 +2,7 @@
Character query interface Character query interface
""" """
from typing import Optional, Sequence from typing import Optional
from uuid import UUID
from sqlalchemy import select, func from sqlalchemy import select, func
@ -69,13 +68,3 @@ def create(
db.session.add(new_character) db.session.add(new_character)
db.session.commit() db.session.commit()
return new_character return new_character
def get_in_lexicon(db: DbContext, lexicon_id: int) -> Sequence[Character]:
"""Get all characters in a lexicon."""
return db(select(Character).where(Character.lexicon_id == lexicon_id)).scalars()
def try_from_public_id(db: DbContext, public_id: UUID) -> Optional[Character]:
"""Get a character by its public id."""
return db(select(Character).where(Character.public_id == public_id)).scalar_one_or_none()

View File

@ -2,8 +2,6 @@
Membership query interface Membership query interface
""" """
from typing import Sequence
from sqlalchemy import select, func from sqlalchemy import select, func
from amanuensis.db import DbContext, Membership from amanuensis.db import DbContext, Membership
@ -68,11 +66,6 @@ def create(
return new_membership return new_membership
def get_players_in_lexicon(db: DbContext, lexicon_id: int) -> Sequence[Membership]:
"""Get all users who are members of a lexicon."""
return db(select(Membership).where(Membership.lexicon_id == lexicon_id)).scalars()
def try_from_ids(db: DbContext, user_id: int, lexicon_id: int) -> Membership: def try_from_ids(db: DbContext, user_id: int, lexicon_id: int) -> Membership:
"""Get a membership by the user and lexicon ids, or None if no such membership was found.""" """Get a membership by the user and lexicon ids, or None if no such membership was found."""
return db( return db(

View File

@ -5,7 +5,6 @@ import os
from typing import Callable from typing import Callable
import amanuensis.cli.admin import amanuensis.cli.admin
import amanuensis.cli.character
import amanuensis.cli.lexicon import amanuensis.cli.lexicon
import amanuensis.cli.user import amanuensis.cli.user
from amanuensis.db import DbContext from amanuensis.db import DbContext
@ -109,7 +108,6 @@ def main():
# Add commands from cli submodules # Add commands from cli submodules
subparsers = parser.add_subparsers(metavar="COMMAND") subparsers = parser.add_subparsers(metavar="COMMAND")
add_subcommand(subparsers, amanuensis.cli.admin) add_subcommand(subparsers, amanuensis.cli.admin)
add_subcommand(subparsers, amanuensis.cli.character)
add_subcommand(subparsers, amanuensis.cli.lexicon) add_subcommand(subparsers, amanuensis.cli.lexicon)
add_subcommand(subparsers, amanuensis.cli.user) add_subcommand(subparsers, amanuensis.cli.user)

View File

@ -1,31 +0,0 @@
import logging
from amanuensis.backend import lexiq, userq, charq
from amanuensis.db import DbContext, Character
from .helpers import add_argument
COMMAND_NAME = "char"
COMMAND_HELP = "Interact with characters."
LOG = logging.getLogger(__name__)
@add_argument("--lexicon", required=True)
@add_argument("--user", required=True)
@add_argument("--name", required=True)
def command_create(args) -> int:
"""
Create a character.
"""
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.user)
if not user:
raise ValueError("User does not exist")
char: Character = charq.create(db, lexicon.id, user.id, args.name, signature=None)
LOG.info(f"Created {char.name} in {lexicon.full_title}")
return 0

View File

@ -126,23 +126,6 @@ div.dashboard-lexicon-item {
padding: 0 10px; padding: 0 10px;
border-left: 3px solid black; border-left: 3px solid black;
} }
ul.blockitem-list {
list-style: none;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0.5em;
margin-inline-end: 0.5em;
padding-inline-start: 0;
padding-inline-end: 0;
}
ul.blockitem-list li {
border-inline-start: 3px solid black;
padding-inline-start: 0.5em;
}
ul.blockitem-list p {
margin-block-start: 0.5em;
margin-block-end: 0.5em;
}
div.dashboard-lexicon-unstarted { div.dashboard-lexicon-unstarted {
border-left-color: blue; border-left-color: blue;
} }

View File

@ -4,7 +4,7 @@ import os
from flask import Flask, g, url_for, redirect from flask import Flask, g, url_for, redirect
from amanuensis.backend import * from amanuensis.backend import lexiq, userq, memq
from amanuensis.config import AmanuensisConfig, CommandLineConfig 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
@ -68,7 +68,7 @@ def get_app(
# Configure jinja options # Configure jinja options
def include_backend(): def include_backend():
return {"db": db, "lexiq": lexiq, "userq": userq, "memq": memq, "charq": charq} return {"db": db, "lexiq": lexiq, "userq": userq, "memq": memq}
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)

View File

@ -88,7 +88,7 @@ def editor_required(route):
user: User = current_user user: User = current_user
lexicon: Lexicon = g.lexicon lexicon: Lexicon = g.lexicon
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.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', name=lexicon.name)) return redirect(url_for('lexicon.contents', name=lexicon.name))
return route(*args, **kwargs) return route(*args, **kwargs)

View File

@ -7,6 +7,8 @@
{% endblock %} {% endblock %}
{% block sb_logo %}{% endblock %} {% block sb_logo %}{% endblock %}
{% block sb_home %}<a href="{{ url_for('home.home') }}">Home</a>
{% 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.characters', name=g.lexicon.name) }}" {% else %}href="{{ url_for('lexicon.characters.characters', name=g.lexicon.name) }}"
@ -34,6 +36,7 @@
) %} ) %}
{# self.sb_logo(), #} {# self.sb_logo(), #}
{% set template_sidebar_rows = [ {% set template_sidebar_rows = [
self.sb_home(),
self.sb_characters(), self.sb_characters(),
self.sb_contents(), self.sb_contents(),
self.sb_rules(), self.sb_rules(),
@ -42,6 +45,7 @@
{% else %} {% else %}
{# self.sb_logo(), #} {# self.sb_logo(), #}
{% set template_sidebar_rows = [ {% set template_sidebar_rows = [
self.sb_home(),
self.sb_characters(), self.sb_characters(),
self.sb_contents(), self.sb_contents(),
self.sb_rules(), self.sb_rules(),

View File

@ -1,60 +1,52 @@
from typing import Optional from flask import Blueprint, render_template
import uuid
from flask import Blueprint, render_template, url_for, g, flash
from werkzeug.utils import redirect
from amanuensis.backend import charq
from amanuensis.db import Character
from amanuensis.server.helpers import lexicon_param, player_required from amanuensis.server.helpers import lexicon_param, player_required
from .forms import CharacterCreateForm
bp = Blueprint("characters", __name__, url_prefix="/characters", template_folder=".") bp = Blueprint("characters", __name__, url_prefix="/characters", template_folder=".")
@bp.get('/') @bp.route('/', methods=['GET', 'POST'])
@lexicon_param @lexicon_param
@player_required @player_required
def characters(name): def characters(name):
return render_template('characters.jinja') return render_template("characters.jinja")
# form = LexiconCharacterForm()
# cid = request.args.get('cid')
# if not cid:
# # No character specified, creating a new character
# return create_character(name, form)
# character = g.lexicon.cfg.character.get(cid)
# if not character:
# # Bad character id, abort
# flash('Character not found')
# return redirect(url_for('session.session', name=name))
# if current_user.uid not in (character.player, g.lexicon.cfg.editor):
# # Only its owner and the editor can edit a character
# flash('Access denied')
# return redirect(url_for('session.session', name=name))
# # Edit allowed
# return edit_character(name, form, character)
@bp.route('/edit/<character_id>', methods=['GET', 'POST']) # def edit_character(name, form, character):
@lexicon_param # if not form.is_submitted():
@player_required # # GET, populate with values
def edit(name, character_id): # return render_template(
try: # 'session.character.jinja', form=form.for_character(character))
char_uuid = uuid.UUID(character_id)
except:
flash("Character not found")
return redirect(url_for('lexicon.characters.characters', name=name))
character: Optional[Character] = charq.try_from_public_id(g.db, char_uuid)
if not character:
flash("Character not found")
return redirect(url_for('lexicon.characters.characters', name=name))
form = CharacterCreateForm() # if not form.validate():
# # POST with invalid data, return unchanged
# return render_template('session.character.jinja', form=form)
if not form.is_submitted(): # # POST with valid data, update character
# GET # with g.lexicon.ctx.edit_config() as cfg:
form.name.data = character.name # char = cfg.character[character.cid]
form.signature.data = character.signature # char.name = form.characterName.data
return render_template('characters.edit.jinja', character=character, form=form) # char.signature = form.defaultSignature.data
# flash('Character updated')
else: # return redirect(url_for('session.session', name=name))
# POST
if form.validate():
# Data is valid
character.name = form.name.data
character.signature = form.signature.data
g.db.session.commit()
return redirect(url_for('lexicon.characters.characters', name=name))
else:
# POST submitted invalid data
return render_template('characters.edit.jinja', character=character, form=form)
# def create_character(name: str, form: LexiconCharacterForm): # def create_character(name: str, form: LexiconCharacterForm):

View File

@ -1,24 +0,0 @@
{% extends "lexicon.jinja" %}
{% block title %}Edit {{ character.name }} | {{ lexicon_title }}{% endblock %}
{% block main %}
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.name.label }}<br>{{ form.name(size=32) }}
</p>
{% for error in form.name.errors %}
<span style="color: #ff0000">{{ error }}</span><br>
{% endfor %}</p>
<p>
{{ form.signature.label }}<br>{{ form.signature(class_='fullwidth') }}
</p>
<p>{{ form.submit() }}</p>
</form>
{% for message in get_flashed_messages() %}
<span style="color:#ff0000">{{ message }}</span><br>
{% endfor %}
{% endblock %}
{% set template_content_blocks = [self.main()] %}

View File

@ -2,23 +2,25 @@
{% block title %}Character | {{ lexicon_title }}{% endblock %} {% block title %}Character | {{ lexicon_title }}{% endblock %}
{% block main %} {% block main %}
<h1>Characters</h1>
{% set players = memq.get_players_in_lexicon(db, g.lexicon.id)|list %} <h1>Character</h1>
{% set characters = charq.get_in_lexicon(db, g.lexicon.id)|list %} {# <form action="" method="post" novalidate>
<p>This lexicon has <b>{{ players|count }}</b> player{% if players|count > 1 %}s{% endif %} and <b>{{ characters|count }}</b> character{% if characters|count > 1 %}s{% endif %}.</p> {{ form.hidden_tag() }}
{% for message in get_flashed_messages() %} <p>
{{ form.characterName.label }}<br>{{ form.characterName(size=32) }}
</p>
{% for error in form.characterName.errors %}
<span style="color: #ff0000">{{ error }}</span><br>
{% endfor %}</p>
<p>
{{ form.defaultSignature.label }}<br>{{ form.defaultSignature(class_='fullwidth') }}
</p>
<p>{{ form.submit() }}</p>
</form> #}
{# {% for message in get_flashed_messages() %}
<span style="color:#ff0000">{{ message }}</span><br> <span style="color:#ff0000">{{ message }}</span><br>
{% endfor %} {% endfor %} #}
<ul class="blockitem-list">
{% for character in characters %}
<li>
<h3>{{ character.name }}</h3>
<p>Player: {{ character.user.username }}</p>
{% if character.user == current_user %}
<p><a href="{{ url_for('lexicon.characters.edit', name=g.lexicon.name, character_id=character.public_id) }}">Edit this character</a></p>
{% endif %}
</li>
{% endfor %}
</ul>
{% endblock %} {% endblock %}
{% set template_content_blocks = [self.main()] %} {% set template_content_blocks = [self.main()] %}

View File

@ -1,11 +0,0 @@
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, TextAreaField
from wtforms.validators import DataRequired
class CharacterCreateForm(FlaskForm):
"""/lexicon/<name>/characters/edit/<character_id>"""
name = StringField("Character name", validators=[DataRequired()])
signature = TextAreaField("Signature")
submit = SubmitField("Submit")

View File

@ -13,13 +13,8 @@
<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>
&#8231; (<a href="{{ url_for('auth.logout') }}">Logout</a>)
<a href="{{ url_for('home.home') }}">Home</a>
&#8231;
<a href="{{ url_for('auth.logout') }}">Logout</a>
{% else %} {% else %}
<a href="{{ url_for('home.home') }}">Home</a>
&#8231;
<a href="{{ url_for('auth.login') }}">Login</a> <a href="{{ url_for('auth.login') }}">Login</a>
{% endif %} {% endif %}
</div> </div>