diff --git a/pyproject.toml b/pyproject.toml index 8060659..13c0936 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,10 +18,11 @@ typer = "^0.9.0" python-dotenv = "^0.21.0" rich = "^13.7.0" jinja2 = "^3.1.3" +tw2-forms = "^2.2.6" +mako = "^1.3.0" #"tg.devtools" = "^2.4.3" #repoze-who = "^3.0.0" -# tw2-forms = "^2.2.6" [build-system] diff --git a/ttfrog/assets/templates/character_sheet.html b/ttfrog/assets/templates/character_sheet.html new file mode 100644 index 0000000..1dd43d1 --- /dev/null +++ b/ttfrog/assets/templates/character_sheet.html @@ -0,0 +1,5 @@ +
+{{ character }}
+
diff --git a/ttfrog/db/bootstrap.py b/ttfrog/db/bootstrap.py
index c1c17c5..37dec18 100644
--- a/ttfrog/db/bootstrap.py
+++ b/ttfrog/db/bootstrap.py
@@ -10,7 +10,11 @@ data = {
'ancestry': [
{'name': 'human'},
{'name': 'dragonborn'},
+ {'name': 'tiefling'},
],
+ 'character': [
+ {'name': 'Sabetha', 'ancestry_name': 'tiefling', 'level': 10, 'str': 10, 'dex': 10, 'con': 10, 'int': 10, 'wis': 10, 'cha': 10},
+ ]
}
diff --git a/ttfrog/db/manager.py b/ttfrog/db/manager.py
index cad2fb3..12cdf22 100644
--- a/ttfrog/db/manager.py
+++ b/ttfrog/db/manager.py
@@ -1,4 +1,5 @@
from functools import cached_property
+import logging
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
@@ -31,6 +32,13 @@ class SQLDatabaseManager:
def query(self, *args, **kwargs):
return self.DBSession.query(*args, **kwargs)
+ def update(self, table, **kwargs):
+ stmt = table.update().values(**kwargs)
+ logging.debug(stmt)
+ result = self.DBSession.execute(stmt)
+ self.DBSession.commit()
+ return result
+
def init_model(self, engine=None):
metadata.create_all(bind=engine or self.engine)
return self.DBSession
diff --git a/ttfrog/db/schema.py b/ttfrog/db/schema.py
index df8f28c..995e453 100644
--- a/ttfrog/db/schema.py
+++ b/ttfrog/db/schema.py
@@ -5,18 +5,17 @@ from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy import UnicodeText
from sqlalchemy import ForeignKey
+from sqlalchemy import CheckConstraint
# from sqlalchemy import PrimaryKeyConstraint
# from sqlalchemy import DateTime
-
metadata = MetaData()
Ancestry = Table(
"ancestry",
metadata,
- Column("id", Integer, primary_key=True, autoincrement=True),
+ Column("name", String, primary_key=True),
Column("slug", String, index=True, unique=True),
- Column("name", String, index=True, unique=True),
Column("description", UnicodeText),
)
@@ -25,6 +24,13 @@ Character = Table(
metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("slug", String, index=True, unique=True),
+ Column("ancestry_name", Integer, ForeignKey("ancestry.name")),
Column("name", String),
- Column("ancestry_id", Integer, ForeignKey("ancestry.id")),
+ Column("level", Integer, CheckConstraint('level > 0 AND level <= 20')),
+ Column("str", Integer, CheckConstraint('str >=0')),
+ Column("dex", Integer, CheckConstraint('dex >=0')),
+ Column("con", Integer, CheckConstraint('con >=0')),
+ Column("int", Integer, CheckConstraint('int >=0')),
+ Column("wis", Integer, CheckConstraint('wis >=0')),
+ Column("cha", Integer, CheckConstraint('cha >=0')),
)
diff --git a/ttfrog/webserver/application.py b/ttfrog/webserver/application.py
index 10be26c..c681686 100644
--- a/ttfrog/webserver/application.py
+++ b/ttfrog/webserver/application.py
@@ -7,8 +7,9 @@ from tg.util.bunch import Bunch
from wsgiref.simple_server import make_server
import webhelpers2
+import tw2.core
-from ttfrog.webserver import controllers
+from ttfrog.webserver.controllers import RootController
from ttfrog.db import db
import ttfrog.path
@@ -28,7 +29,7 @@ def application():
config.update_blueprint({
# rendering
- 'root_controller': controllers.RootController(),
+ 'root_controller': RootController(),
'default_renderer': 'jinja',
'renderers': ['jinja'],
'tg.jinja_filters': {},
@@ -37,7 +38,7 @@ def application():
# helpers
'app_globals': app_globals,
'helpers': webhelpers2,
- 'tw2.enabled': True,
+ 'use_toscawidgets2': True,
# assets
'serve_static': True,
@@ -51,7 +52,9 @@ def application():
'sqlalchemy.url': db.url,
'model': db,
})
- return config.make_wsgi_app()
+
+ # wrap the core wsgi app in a ToscaWidgets2 app
+ return tw2.core.make_middleware(config.make_wsgi_app(), default_engine='jinja')
def start(host: str, port: int, debug: bool = False) -> None:
diff --git a/ttfrog/webserver/controllers/__init__.py b/ttfrog/webserver/controllers/__init__.py
new file mode 100644
index 0000000..c4f55f7
--- /dev/null
+++ b/ttfrog/webserver/controllers/__init__.py
@@ -0,0 +1,3 @@
+from .root import RootController
+
+__ALL__ = [RootController]
diff --git a/ttfrog/webserver/controllers/character_sheet.py b/ttfrog/webserver/controllers/character_sheet.py
new file mode 100644
index 0000000..08a0e84
--- /dev/null
+++ b/ttfrog/webserver/controllers/character_sheet.py
@@ -0,0 +1,29 @@
+from tg import expose
+from tg import TGController
+from ttfrog.db import db
+from ttfrog.db.schema import Character
+from ttfrog.webserver.widgets import CharacterSheet
+
+
+class CharacterSheetController(TGController):
+ @expose()
+ def _lookup(self, *parts):
+ return FormController(parts[0]), parts[1:]
+
+
+class FormController:
+
+ def __init__(self, slug: str):
+ self.character = dict()
+ if slug:
+ self.load(slug)
+
+ def load(self, slug: str) -> None:
+ self.character = db.query(Character).filter(Character.columns.slug == slug)[0]._mapping
+
+ @expose('character_sheet.html')
+ def _default(self, *args, **kwargs):
+ if kwargs:
+ db.update(Character, **kwargs)
+ self.load(self.character['slug'])
+ return dict(page='sheet', form=CharacterSheet, character=self.character)
diff --git a/ttfrog/webserver/controllers.py b/ttfrog/webserver/controllers/root.py
similarity index 77%
rename from ttfrog/webserver/controllers.py
rename to ttfrog/webserver/controllers/root.py
index 84eef31..bec9a01 100644
--- a/ttfrog/webserver/controllers.py
+++ b/ttfrog/webserver/controllers/root.py
@@ -2,11 +2,13 @@ from tg import expose
from tg import TGController
from tg import tmpl_context
from ttfrog.db import db
-from ttfrog.db.schema import Character
+from ttfrog.webserver.controllers.character_sheet import CharacterSheetController
class RootController(TGController):
+ sheet = CharacterSheetController()
+
def _before(self, *args, **kwargs):
tmpl_context.project_name = 'TableTop Frog'
diff --git a/ttfrog/webserver/widgets.py b/ttfrog/webserver/widgets.py
new file mode 100644
index 0000000..5cb71ea
--- /dev/null
+++ b/ttfrog/webserver/widgets.py
@@ -0,0 +1,13 @@
+import tw2.core
+import tw2.forms
+from tg import lurl
+
+
+class CharacterSheet(tw2.forms.Form):
+ class child(tw2.forms.TableLayout):
+ name = tw2.forms.TextField()
+ level = tw2.forms.TextField()
+ ancestry_name = tw2.forms.TextField(label='Ancestry')
+ id = tw2.forms.HiddenField()
+
+ action = ''