Compare commits
No commits in common. "aaa7982f67a1ffdd8dd672e25e6e0ad6f6a66240" and "e097917633260623a7190159ec25a92df9bcba71" have entirely different histories.
aaa7982f67
...
e097917633
|
@ -3,7 +3,6 @@ Lexicon query interface
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import Sequence
|
|
||||||
|
|
||||||
from sqlalchemy import select, func
|
from sqlalchemy import select, func
|
||||||
|
|
||||||
|
@ -53,8 +52,3 @@ def create(
|
||||||
db.session.add(new_lexicon)
|
db.session.add(new_lexicon)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return new_lexicon
|
return new_lexicon
|
||||||
|
|
||||||
|
|
||||||
def get_all_lexicons(db: DbContext) -> Sequence[Lexicon]:
|
|
||||||
"""Get all lexicons."""
|
|
||||||
return db(select(Lexicon)).scalars()
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ User query interface
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import Sequence
|
import uuid
|
||||||
|
|
||||||
from sqlalchemy import select, func
|
from sqlalchemy import select, func
|
||||||
|
|
||||||
|
@ -67,8 +67,3 @@ def create(
|
||||||
db.session.add(new_user)
|
db.session.add(new_user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return new_user
|
return new_user
|
||||||
|
|
||||||
|
|
||||||
def get_all_users(db: DbContext) -> Sequence[User]:
|
|
||||||
"""Get all users."""
|
|
||||||
return db(select(User)).scalars()
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ class AmanuensisConfig:
|
||||||
# If CONFIG_FILE is defined, the config file it points to may override
|
# If CONFIG_FILE is defined, the config file it points to may override
|
||||||
# config values defined on the config object itself.
|
# config values defined on the config object itself.
|
||||||
CONFIG_FILE: Optional[str] = None
|
CONFIG_FILE: Optional[str] = None
|
||||||
STATIC_ROOT: Optional[str] = "../resources"
|
STATIC_ROOT: Optional[str] = "static"
|
||||||
SECRET_KEY: Optional[str] = "secret"
|
SECRET_KEY: Optional[str] = "secret"
|
||||||
DATABASE_URI: Optional[str] = "sqlite:///:memory:"
|
DATABASE_URI: Optional[str] = "sqlite:///:memory:"
|
||||||
TESTING: bool = False
|
TESTING: bool = False
|
||||||
|
|
|
@ -13,6 +13,7 @@ from sqlalchemy import (
|
||||||
ForeignKey,
|
ForeignKey,
|
||||||
Integer,
|
Integer,
|
||||||
String,
|
String,
|
||||||
|
Table,
|
||||||
Text,
|
Text,
|
||||||
text,
|
text,
|
||||||
TypeDecorator,
|
TypeDecorator,
|
||||||
|
@ -233,14 +234,6 @@ class Lexicon(ModelBase):
|
||||||
content_rules = relationship("ArticleContentRule", back_populates="lexicon")
|
content_rules = relationship("ArticleContentRule", back_populates="lexicon")
|
||||||
posts = relationship("Post", back_populates="lexicon")
|
posts = relationship("Post", back_populates="lexicon")
|
||||||
|
|
||||||
#######################
|
|
||||||
# Derived information #
|
|
||||||
#######################
|
|
||||||
|
|
||||||
@property
|
|
||||||
def full_title(self: "Lexicon") -> str:
|
|
||||||
return self.title if self.title else f"Lexicon {self.name}"
|
|
||||||
|
|
||||||
|
|
||||||
class Membership(ModelBase):
|
class Membership(ModelBase):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import json
|
import json
|
||||||
import os
|
|
||||||
|
|
||||||
from flask import Flask, g
|
from flask import Flask, g
|
||||||
|
|
||||||
from amanuensis.config import AmanuensisConfig, CommandLineConfig
|
from amanuensis.config import AmanuensisConfig, CommandLineConfig
|
||||||
from amanuensis.db import DbContext
|
from amanuensis.db import DbContext
|
||||||
import amanuensis.server.home
|
|
||||||
|
|
||||||
|
|
||||||
def get_app(
|
def get_app(
|
||||||
|
@ -20,8 +18,8 @@ def get_app(
|
||||||
app.config.from_object(config)
|
app.config.from_object(config)
|
||||||
|
|
||||||
# If a config file is now specified, also load keys from there
|
# If a config file is now specified, also load keys from there
|
||||||
if config_path := app.config.get("CONFIG_FILE", None):
|
if app.config.get("CONFIG_FILE", None):
|
||||||
app.config.from_file(os.path.abspath(config_path), json.load)
|
app.config.from_file(app.config["CONFIG_FILE"], json.load)
|
||||||
|
|
||||||
# Assert that all required config values are now set
|
# Assert that all required config values are now set
|
||||||
for config_key in ("SECRET_KEY", "DATABASE_URI"):
|
for config_key in ("SECRET_KEY", "DATABASE_URI"):
|
||||||
|
@ -35,13 +33,11 @@ def get_app(
|
||||||
# Make the database connection available to requests via g
|
# Make the database connection available to requests via g
|
||||||
def db_setup():
|
def db_setup():
|
||||||
g.db = db
|
g.db = db
|
||||||
|
|
||||||
app.before_request(db_setup)
|
app.before_request(db_setup)
|
||||||
|
|
||||||
# Tear down the session on request teardown
|
# Tear down the session on request teardown
|
||||||
def db_teardown(response_or_exc):
|
def db_teardown(response_or_exc):
|
||||||
db.session.remove()
|
db.session.remove()
|
||||||
|
|
||||||
app.teardown_appcontext(db_teardown)
|
app.teardown_appcontext(db_teardown)
|
||||||
|
|
||||||
# Configure jinja options
|
# Configure jinja options
|
||||||
|
@ -51,11 +47,10 @@ def get_app(
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
# Register blueprints
|
# Register blueprints
|
||||||
app.register_blueprint(amanuensis.server.home.bp)
|
# TODO
|
||||||
|
|
||||||
def test():
|
def test():
|
||||||
return "Hello, world!"
|
return "Hello, world!"
|
||||||
|
|
||||||
app.route("/")(test)
|
app.route("/")(test)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
@ -64,5 +59,4 @@ def get_app(
|
||||||
def run():
|
def run():
|
||||||
"""Run the server, populating the config from the command line."""
|
"""Run the server, populating the config from the command line."""
|
||||||
config = CommandLineConfig()
|
config = CommandLineConfig()
|
||||||
app = get_app(config)
|
get_app(config).run(debug=config.TESTING)
|
||||||
app.run(debug=app.testing)
|
|
||||||
|
|
|
@ -1,64 +1,64 @@
|
||||||
from flask import Blueprint, render_template, g
|
from flask import Blueprint, render_template, redirect, url_for, current_app
|
||||||
|
from flask_login import login_required, current_user
|
||||||
|
|
||||||
# from flask import Blueprint, render_template, redirect, url_for, current_app
|
from amanuensis.config import RootConfigDirectoryContext
|
||||||
# from flask_login import login_required, current_user
|
from amanuensis.lexicon import create_lexicon, load_all_lexicons
|
||||||
|
from amanuensis.models import UserModel, ModelFactory
|
||||||
|
from amanuensis.server.helpers import admin_required
|
||||||
|
|
||||||
import amanuensis.backend.user as userq
|
from .forms import LexiconCreateForm
|
||||||
import amanuensis.backend.lexicon as lexiq
|
|
||||||
|
|
||||||
# from amanuensis.config import RootConfigDirectoryContext
|
bp_home = Blueprint('home', __name__,
|
||||||
# from amanuensis.lexicon import create_lexicon, load_all_lexicons
|
url_prefix='/home',
|
||||||
# from amanuensis.models import UserModel, ModelFactory
|
template_folder='.')
|
||||||
# from amanuensis.server.helpers import admin_required
|
|
||||||
|
|
||||||
# from .forms import LexiconCreateForm
|
|
||||||
|
|
||||||
bp = Blueprint("home", __name__, url_prefix="/home", template_folder=".")
|
|
||||||
|
|
||||||
|
|
||||||
# @bp.get("/")
|
@bp_home.route('/', methods=['GET'])
|
||||||
# def home():
|
def home():
|
||||||
# Show lexicons that are visible to the current user
|
root: RootConfigDirectoryContext = current_app.config['root']
|
||||||
# return "TODO"
|
user: UserModel = current_user
|
||||||
# user_lexicons = []
|
user_lexicons = []
|
||||||
# public_lexicons = []
|
public_lexicons = []
|
||||||
# for lexicon in load_all_lexicons(root):
|
for lexicon in load_all_lexicons(root):
|
||||||
# if user.uid in lexicon.cfg.join.joined:
|
if user.uid in lexicon.cfg.join.joined:
|
||||||
# user_lexicons.append(lexicon)
|
user_lexicons.append(lexicon)
|
||||||
# elif lexicon.cfg.join.public:
|
elif lexicon.cfg.join.public:
|
||||||
# public_lexicons.append(lexicon)
|
public_lexicons.append(lexicon)
|
||||||
# return render_template(
|
return render_template(
|
||||||
# 'home.root.jinja',
|
'home.root.jinja',
|
||||||
# user_lexicons=user_lexicons,
|
user_lexicons=user_lexicons,
|
||||||
# public_lexicons=public_lexicons)
|
public_lexicons=public_lexicons)
|
||||||
|
|
||||||
|
|
||||||
@bp.get("/admin/")
|
@bp_home.route('/admin/', methods=['GET'])
|
||||||
# @login_required
|
@login_required
|
||||||
# @admin_required
|
@admin_required
|
||||||
def admin():
|
def admin():
|
||||||
return render_template("home.admin.jinja", db=g.db, userq=userq, lexiq=lexiq)
|
root: RootConfigDirectoryContext = current_app.config['root']
|
||||||
|
users = []
|
||||||
|
lexicons = list(load_all_lexicons(root))
|
||||||
|
return render_template('home.admin.jinja', users=users, lexicons=lexicons)
|
||||||
|
|
||||||
|
|
||||||
# @bp_home.route("/admin/create/", methods=['GET', 'POST'])
|
@bp_home.route("/admin/create/", methods=['GET', 'POST'])
|
||||||
# @login_required
|
@login_required
|
||||||
# @admin_required
|
@admin_required
|
||||||
# def admin_create():
|
def admin_create():
|
||||||
# form = LexiconCreateForm()
|
form = LexiconCreateForm()
|
||||||
|
|
||||||
# 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('home.create.jinja', form=form)
|
return render_template('home.create.jinja', form=form)
|
||||||
|
|
||||||
# # POST with valid data
|
# POST with valid data
|
||||||
# root: RootConfigDirectoryContext = current_app.config['root']
|
root: RootConfigDirectoryContext = current_app.config['root']
|
||||||
# model_factory: ModelFactory = current_app.config['model_factory']
|
model_factory: ModelFactory = current_app.config['model_factory']
|
||||||
# lexicon_name = form.lexiconName.data
|
lexicon_name = form.lexiconName.data
|
||||||
# editor_name = form.editorName.data
|
editor_name = form.editorName.data
|
||||||
# prompt = form.promptText.data
|
prompt = form.promptText.data
|
||||||
# # Editor's existence was checked by form validators
|
# Editor's existence was checked by form validators
|
||||||
# editor = model_factory.user(editor_name)
|
editor = model_factory.user(editor_name)
|
||||||
# lexicon = create_lexicon(root, lexicon_name, editor)
|
lexicon = create_lexicon(root, lexicon_name, editor)
|
||||||
# with lexicon.ctx.edit_config() as cfg:
|
with lexicon.ctx.edit_config() as cfg:
|
||||||
# cfg.prompt = prompt
|
cfg.prompt = prompt
|
||||||
# return redirect(url_for('session.session', name=lexicon_name))
|
return redirect(url_for('session.session', name=lexicon_name))
|
||||||
|
|
|
@ -3,18 +3,17 @@
|
||||||
{% 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.admin_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 %}
|
||||||
<p>Users:</p>
|
<p>Users:</p>
|
||||||
{% for user in userq.get_all_users(db) %}
|
{% for user in users %}
|
||||||
{{ macros.dashboard_user_item(user) }}
|
{{ macros.dashboard_user_item(user) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<p>Lexicons:</p>
|
<p>Lexicons:</p>
|
||||||
{% for lexicon in lexiq.get_all_lexicons(db) %}
|
{% for lexicon in lexicons %}
|
||||||
{{ macros.dashboard_lexicon_item(lexicon) }}
|
{{ macros.dashboard_lexicon_item(lexicon) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,47 +1,45 @@
|
||||||
{% macro dashboard_lexicon_item(lexicon) %}
|
{% macro dashboard_lexicon_item(lexicon) %}
|
||||||
{% set status = "completed" if lexicon.completed else "ongoing" if lexicon.started else "unstarted" %}
|
<div class="dashboard-lexicon-item dashboard-lexicon-{{ 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', name=lexicon.cfg.name) }#}">
|
<a href="{{ url_for('lexicon.contents', name=lexicon.cfg.name) }}">
|
||||||
{{ lexicon.full_title }}</a>
|
Lexicon {{ lexicon.cfg.name }}</a>
|
||||||
</span>
|
</span>
|
||||||
[{{ lexicon.status.capitalize() }}]
|
[{{ lexicon.status.capitalize() }}]
|
||||||
</p>
|
</p>
|
||||||
<p><i>{{ lexicon.prompt }}</i></p>
|
<p><i>{{ lexicon.cfg.prompt }}</i></p>
|
||||||
{# {% if current_user.is_authenticated %} #}
|
{% if current_user.is_authenticated %}
|
||||||
<p>
|
<p>
|
||||||
{# TODO #}
|
{%
|
||||||
{# {%
|
|
||||||
if current_user.uid in lexicon.cfg.join.joined
|
if current_user.uid in lexicon.cfg.join.joined
|
||||||
or current_user.cfg.is_admin
|
or current_user.cfg.is_admin
|
||||||
%} #}
|
%}
|
||||||
Editor: {#{ lexicon.cfg.editor|user_attr('username') }#} /
|
Editor: {{ lexicon.cfg.editor|user_attr('username') }} /
|
||||||
Players:
|
Players:
|
||||||
{# {% for uid in lexicon.cfg.join.joined %} #}
|
{% for uid in lexicon.cfg.join.joined %}
|
||||||
{# {{ uid|user_attr('username') }}{% if not loop.last %}, {% endif %} #}
|
{{ uid|user_attr('username') }}{% if not loop.last %}, {% endif %}
|
||||||
{# {% endfor %} #}
|
{% endfor %}
|
||||||
{# ({{ lexicon.cfg.join.joined|count }}/{{ lexicon.cfg.join.max_players }}) #}
|
({{ lexicon.cfg.join.joined|count }}/{{ lexicon.cfg.join.max_players }})
|
||||||
{# {% else %} #}
|
{% else %}
|
||||||
{# Players: {{ lexicon.cfg.join.joined|count }}/{{ lexicon.cfg.join.max_players }} #}
|
Players: {{ lexicon.cfg.join.joined|count }}/{{ lexicon.cfg.join.max_players }}
|
||||||
{# {% if lexicon.cfg.join.public and lexicon.cfg.join.open %} #}
|
{% if lexicon.cfg.join.public and lexicon.cfg.join.open %}
|
||||||
{# / <a href="{{ url_for('lexicon.join', name=lexicon.cfg.name) }}"> #}
|
/ <a href="{{ url_for('lexicon.join', name=lexicon.cfg.name) }}">
|
||||||
{# Join game #}
|
Join game
|
||||||
{# </a> #}
|
</a>
|
||||||
{# {% endif %} #}
|
{% endif %}
|
||||||
{# {% endif %} #}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
{# {% endif %} #}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro dashboard_user_item(user) %}
|
{% macro dashboard_user_item(user) %}
|
||||||
<div class="dashboard-lexicon-item">
|
<div class="dashboard-lexicon-item">
|
||||||
<p>
|
<p>
|
||||||
<b>{{ user.username }}</b>
|
<b>{{ user.cfg.username }}</b>
|
||||||
{% if user.username != user.display_name %} / {{ user.display_name }}{% endif %}
|
{% if user.cfg.username != user.cfg.displayname %} / {{ user.cfg.displayname }}{% endif %}
|
||||||
(id #{{user.id}})
|
({{user.uid}})
|
||||||
</p>
|
</p>
|
||||||
<p>Last activity: {{ user.last_activity }} — Last login: {{ user.last_login }}</p>
|
<p>Last activity: {{ user.cfg.last_activity|asdate }} — Last login: {{ user.cfg.last_login|asdate }}</p>
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
|
@ -5,19 +5,18 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>{% block title %}{% endblock %}</title>
|
<title>{% block title %}{% endblock %}</title>
|
||||||
<link rel="icon" type="image/png" href="{{ url_for('static', filename='amanuensis.png') }}">
|
<link rel="icon" type="image/png" href="{{ url_for('static', filename='amanuensis.png') }}">
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='page.css') }}">
|
<link rel="stylesheet" href="{{ url_for("static", filename="page.css") }}">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<div id="login-status" {% block login_status_attr %}{% endblock %}>
|
<div id="login-status" {% block login_status_attr %}{% endblock %}>
|
||||||
{# TODO #}
|
{% if current_user.is_authenticated %}
|
||||||
{# {% if current_user.is_authenticated %}
|
|
||||||
<b>{{ current_user.cfg.username -}}</b>
|
<b>{{ current_user.cfg.username -}}</b>
|
||||||
(<a href="{{ url_for('auth.logout') }}">Logout</a>)
|
(<a href="{{ url_for('auth.logout') }}">Logout</a>)
|
||||||
{% else %} #}
|
{% else %}
|
||||||
<a href="#{#{ url_for('auth.login') }#}">Login</a>
|
<a href="{{ url_for('auth.login') }}">Login</a>
|
||||||
{# {% endif %} #}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% block header %}{% endblock %}
|
{% block header %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue