Refactor rendering into views (sigh)

This commit is contained in:
John Doty 2024-11-23 15:30:06 -08:00
parent 112de55124
commit 002a8cc543
2 changed files with 85 additions and 74 deletions

80
cry/views.py Normal file
View file

@ -0,0 +1,80 @@
import typing
import dominate.tags as tags
from . import feed
def _standard_header(title: str) -> tags.head:
head = tags.head(
tags.meta(charset="utf8"),
tags.title(title),
tags.link(rel="stylesheet", href="/style.css", type="text/css"),
)
assert isinstance(head, tags.head)
return head
def feed_view(feeds: list[feed.Feed]) -> tags.html:
document = tags.html(
_standard_header("Subscribed Feeds"),
tags.h1("Feeds"),
tags.div(
tags.form(
{"method": "post", "action": "/refresh"},
tags.input_(type="submit", value="Refresh"),
),
tags.form(
{"method": "post", "action": "/subscribe"},
tags.label({"for": "url"}, "Feed url:"),
tags.input_(type="url", name="url"),
tags.input_(type="submit", value="Subscribe"),
),
(
tags.div(
{"class": "feed"},
tags.h2(tags.a(f.title, href=f.link, target="_blank")),
(
tags.ul(
tags.li(
{"class": "entry"},
tags.a(
entry.title, href=entry.link, target="_blank"
),
f" ({entry.time_ago()})",
)
for entry in f.entries
)
if len(f.entries) > 0
else tags.i("No entries...")
),
)
for f in feeds
),
),
)
assert isinstance(document, tags.html)
return document
def subscribe_choose_view(candidates: typing.Iterable[tuple[str,str]]) -> tags.html:
document = tags.html(
_standard_header("Choose Feed"),
tags.h1("Choose Feed"),
tags.p("More than one feed was found. Choose the feed to subscribe to."),
tags.table(
tags.caption("Potential feeds"),
tags.thead(tags.tr(tags.th("Title"), tags.th("URL"), tags.th())),
tags.tbody(
tags.form(
{"action": "/subscribe", "method":"post"},
tags.tr(
tags.td(title), tags.td(url), tags.td(
tags.input_({"type":"hidden", "name":"url", "value":url}),
tags.input_({"type":"submit", "value":"Subscribe"}),
),
),
)
for title, url in candidates
),
),
)
assert isinstance(document, tags.html)
return document

View file

@ -1,7 +1,7 @@
import asyncio
import contextlib
import dataclasses
import dominate.tags as d
import dominate.tags as tags
import functools
import http.server
import io
@ -15,7 +15,7 @@ from typing import Callable, Concatenate, ParamSpec
from . import database
from . import feed
from . import views
class DeadlineCondition:
"""A condition variable that allows you to wait with a timeout."""
@ -296,7 +296,6 @@ def refresh_feeds(sink: EventChannel):
REFRESH_TASK: BackgroundTask | None = None
@background_task
def subscribe(sink: EventChannel, url: str):
"""Subscribe to a feed."""
@ -497,36 +496,7 @@ class Handler(http.server.BaseHTTPRequestHandler):
feeds.sort(key=feed.sort_key, reverse=True)
document = d.html()
with document:
with d.head():
d.meta(charset="utf8")
d.title("Subscribed Feeds")
d.link(rel="stylesheet", href="/style.css", type="text/css")
d.h1("Feeds")
with d.div():
with d.form(method="post", action="/refresh"):
d.input_(type="submit", value="Refresh")
with d.form(method="post", action="/subscribe"):
d.label("Feed url:", fr="url")
d.input_(type="url", name="url")
d.input_(type="submit", value="Subscribe")
for f in feeds:
with d.div(cls="feed"):
d.h2(d.a(f.title, href=f.link, target="_blank"))
if len(f.entries) > 0:
d.ul(
d.li(
d.a(entry.title, href=entry.link, target="_blank"),
f" ({entry.time_ago()})",
cls="entry",
)
for entry in f.entries
)
else:
d.i("No entries...")
document = views.feed_view(feeds)
self.write_html(document.render())
def serve_subscribe_choose(self):
@ -541,47 +511,8 @@ class Handler(http.server.BaseHTTPRequestHandler):
self.send_error(400, explain=tb)
return
buffer = io.StringIO()
buffer.write(
"""
<!doctype html>
<head>
<meta charset="utf8">
<title>Choose Feed</title>
<link rel="stylesheet" href="/style.css" type="text/css" />
</head>
<h1>Choose Feed</h1>
<p>More than one feed was found. Choose the feed to subscribe to.</p>
<table>
<caption>Potential feeds</caption>
<thead>
<tr><th>Title</th><th>URL</th><th></th>
</thead>
<tbody>
"""
)
for title, url in candidates:
buffer.write(
f"""
<form action="/subscribe" method="post"><tr>
<td>{title}</td>
<td>{url}</td>
<td>
<input type="hidden" name="url" value="{url}" />
<input type="submit" value="Subscribe" />
</td>
</tr></form>
"""
)
buffer.write(
"""
</tbody>
</table>
"""
)
buffer.flush()
self.write_html(buffer.getvalue())
document = views.subscribe_choose_view(candidates)
self.write_html(document.render())
def write_html(self, html: str):
response = html.encode("utf-8")