2025-10-03 16:44:25 -07:00
|
|
|
from flask import Response, render_template, request
|
2025-09-27 16:20:08 -07:00
|
|
|
from tinydb import where
|
2025-09-28 14:14:16 -07:00
|
|
|
|
2025-10-03 16:44:25 -07:00
|
|
|
from ttfrog import app, schema
|
|
|
|
|
from ttfrog.forms import PageForm
|
2025-09-21 22:11:56 -07:00
|
|
|
|
2025-10-03 16:44:25 -07:00
|
|
|
STATIC = ["static"]
|
2025-09-21 22:11:56 -07:00
|
|
|
|
2025-10-03 16:44:25 -07:00
|
|
|
|
|
|
|
|
def relative_uri(path: str = ""):
|
|
|
|
|
"""
|
|
|
|
|
The request's URI relative to the VIEW_URI without the leading '/'.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
return (path or request.path).replace(app.config.VIEW_URI, "", 1).strip("/") or "/"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_parent(uri: str):
|
|
|
|
|
try:
|
|
|
|
|
parent_uri = uri.strip("/").split("/", -1)[0]
|
|
|
|
|
except IndexError:
|
|
|
|
|
return None
|
|
|
|
|
app.web.logger.debug(f"Looking for parent with {parent_uri = }")
|
|
|
|
|
return get_page(parent_uri or "/", create_okay=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_page(path: str = "", create_okay: bool = False):
|
2025-09-28 14:14:16 -07:00
|
|
|
"""
|
|
|
|
|
Get one page, including its subpages, but not recursively.
|
|
|
|
|
"""
|
2025-10-03 16:44:25 -07:00
|
|
|
uri = path or relative_uri(request.path)
|
|
|
|
|
matches = app.db.Page.search(where("uri") == uri, recurse=False)
|
|
|
|
|
app.web.logger.debug(f"Found {len(matches)} pages where {uri = }")
|
2025-09-28 14:14:16 -07:00
|
|
|
if not matches:
|
2025-10-03 16:44:25 -07:00
|
|
|
if not create_okay:
|
|
|
|
|
return None
|
|
|
|
|
return schema.Page(stub=uri.split("/")[-1], body="This page does not exist", parent=get_parent(uri))
|
2025-09-28 14:14:16 -07:00
|
|
|
uids = [pointer.split("::")[-1] for pointer in matches[0].pages]
|
|
|
|
|
subpages = app.db.Page.search(where("uid").one_of(uids), recurse=False)
|
|
|
|
|
matches[0].pages = subpages
|
|
|
|
|
return matches[0]
|
2025-09-21 22:11:56 -07:00
|
|
|
|
2025-09-27 16:20:08 -07:00
|
|
|
|
2025-10-03 16:44:25 -07:00
|
|
|
def rendered(page: schema.Record, template: str = "page.html"):
|
|
|
|
|
if not page:
|
|
|
|
|
return Response("Page not found", status=404)
|
|
|
|
|
return render_template(template, page=page, app=app, breadcrumbs=breadcrumbs())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_static(path):
|
|
|
|
|
return Response("OK", status=200)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def breadcrumbs():
|
|
|
|
|
"""
|
|
|
|
|
Return (uri, stub) pairs for the parents leading from the VIEW_URI to the current request.
|
|
|
|
|
"""
|
|
|
|
|
if app.config.VIEW_URI != "/":
|
|
|
|
|
root = get_page()
|
|
|
|
|
yield (app.config.VIEW_URI, root.stub)
|
|
|
|
|
uri = ""
|
|
|
|
|
for stub in relative_uri().split("/"):
|
|
|
|
|
uri = "/".join([uri, stub]).lstrip("/")
|
|
|
|
|
yield (uri, stub)
|
|
|
|
|
|
|
|
|
|
|
2025-09-27 16:20:08 -07:00
|
|
|
@app.web.route("/")
|
|
|
|
|
def index():
|
2025-10-03 16:44:25 -07:00
|
|
|
return rendered(get_page(create_okay=False))
|
2025-09-27 16:20:08 -07:00
|
|
|
|
|
|
|
|
|
2025-10-03 16:44:25 -07:00
|
|
|
@app.web.route(f"{app.config.VIEW_URI}/<path:path>", methods=["GET"])
|
|
|
|
|
def view(path):
|
|
|
|
|
return rendered(get_page(request.path, create_okay=True))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.web.route(f"{app.config.VIEW_URI}/<path:path>", methods=["POST"])
|
|
|
|
|
def edit(path):
|
|
|
|
|
uri = relative_uri()
|
|
|
|
|
parent = get_parent(uri)
|
|
|
|
|
app.web.logger.debug(f"Handling form submission: {uri = }, {parent = }, {request.form = }")
|
|
|
|
|
if not parent:
|
|
|
|
|
return Response(f"Parent for {uri} does not exist.", status=403)
|
|
|
|
|
|
|
|
|
|
page = get_page(uri, create_okay=True)
|
|
|
|
|
app.web.logger.debug(f"Editing {page.doc_id} for {uri = }")
|
|
|
|
|
if page.doc_id:
|
|
|
|
|
if page.uid != request.form["uid"]:
|
|
|
|
|
return Response("Invalid UID.", status=403)
|
|
|
|
|
|
|
|
|
|
form = PageForm(page, request.form)
|
|
|
|
|
page = app.db.save(form.prepare())
|
|
|
|
|
app.web.logger.debug(f"Saved {page.doc_id}; now updating parent {parent.doc_id}")
|
|
|
|
|
parent.pages.append(page)
|
|
|
|
|
app.db.save(parent)
|
|
|
|
|
return get_page(stub)
|
2025-09-28 14:14:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.web.after_request
|
|
|
|
|
def add_header(r):
|
|
|
|
|
r.headers["Cache-Control"] = "no-cache, no-store, must-revalidate, public, max-age=0"
|
|
|
|
|
r.headers["Pragma"] = "no-cache"
|
|
|
|
|
r.headers["Expires"] = "0"
|
|
|
|
|
return r
|