So much cleaner!

Give up on flexbox man, grids are how my brain works mostly.
This commit is contained in:
John Doty 2024-11-24 08:16:25 -08:00
parent c16fdde19a
commit 56d6c8e408
3 changed files with 135 additions and 68 deletions

View file

@ -2,6 +2,7 @@
import asyncio import asyncio
import calendar import calendar
import dataclasses import dataclasses
import datetime
import functools import functools
import hashlib import hashlib
import html.parser import html.parser
@ -132,6 +133,9 @@ class Entry:
link=link, link=link,
) )
def posted_time_iso(self) -> str:
return datetime.datetime.fromtimestamp(self.posted_at / 1000).isoformat()
def time_ago(self) -> str: def time_ago(self) -> str:
posted = int(self.posted_at / 1000) posted = int(self.posted_at / 1000)
seconds = int(time.time()) - posted seconds = int(time.time()) - posted

View file

@ -1,10 +1,9 @@
body { body {
box-sizing: border-box;
margin-right: 4rem; margin-right: 4rem;
margin-left: 4rem; margin-left: 4rem;
margin-top: 0; margin-top: 0;
margin-bottom: 0; margin-bottom: 0;
display: flex;
flex-direction: column;
height: 100vh; height: 100vh;
} }
@ -42,64 +41,91 @@ li.entry:before {
padding-right: 0.5rem; padding-right: 0.5rem;
} }
/* Feed summaries */ /*
ul.feed-summary-list { * FEED VIEW
list-style-type: none; */
margin: 0; .fv-body {
padding: 0 1rem 0 0; display: grid;
grid-template-columns: 1fr;
flex-basis: 10%; grid-template-rows: auto auto 1fr;
flex: 1;
width: 100%;
height: auto;
overflow-y: auto;
} }
li.feed-summary { .fv-title {
margin-bottom: 0.5rem; grid-row: 1;
flex: 1; }
.fv-subscribe {
grid-row: 2;
}
.fv-main-panel {
grid-row: 3;
margin-top: 1rem;
display: grid;
grid-template-rows: 1fr;
grid-template-columns: 1fr 3fr;
overflow-y: scroll;
}
.fv-summary-panel {
grid-column: 1;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto 1fr;
margin-right: 1rem;
overflow-y: scroll;
}
.fv-summary-refresh {
grid-row: 1;
width: 100%;
display: block;
}
.fv-summary-refresh input {
width: 100%;
padding: 0.5rem;
}
.fv-summary-list {
grid-row: 2;
list-style-type: none;
padding: 0;
overflow-y: scroll;
}
.fv-feed-panel {
grid-column: 2;
overflow-y: scroll;
}
/*
* FEED SUMMARY ITEM
*/
.feed-summary {
margin-bottom: 0.5rem;
overflow: hidden; overflow: hidden;
} }
li.feed-summary h2 {
.feed-summary-title {
margin: 0; margin: 0;
font-size: 100%; font-size: 100%;
flex: 1; font-weight: bold;
} }
li.feed-summary p {
.feed-summary-timestamp {
margin: 0; margin: 0;
} }
p.feed-title-summary {
height: 1.5rem; .feed-summary-entry {
margin: 0;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} white-space: nowrap;
/* The feed container */
div.feed-container {
flex: 1;
flex-basis: 40%;
height: 100%;
overflow-y: auto;
}
/* Group it all */
div.main-container {
margin-top: 1rem;
flex: 1;
display: flex;
flex-direction: row;
margin-left: auto;
margin-right: auto;
overflow-y: scroll; /*...but we don't scroll because our columns do first!*/
}
/* Uh */
body.feed-view {
display: flex;
flex-direction: column;
} }

View file

@ -1,11 +1,26 @@
import typing import typing
import dominate
import dominate.tags as tags import dominate.tags as tags
from . import feed from . import feed
class time(tags.html_tag):
"""The <time> HTML element represents a specific period in time. It may
include the datetime attribute to translate dates into machine-readable
format, allowing for better search engine results or custom features such
as reminders.
It may represent one of the following:
- A time on a 24-hour clock.
- A precise date in the Gregorian calendar (with optional time and timezone information).
- A valid time duration.
"""
pass
def _standard_header(title: str) -> tags.head: def _standard_header(title: str) -> tags.head:
head = tags.head( head = tags.head(
tags.meta(charset="utf8"), tags.meta(charset="utf8"),
@ -18,18 +33,25 @@ def _standard_header(title: str) -> tags.head:
def _feed_summary(f: feed.Feed) -> tags.li: def _feed_summary(f: feed.Feed) -> tags.li:
if len(f.entries) == 0: if len(f.entries) == 0:
last_entry = tags.p(tags.i("Never posted")) last_entry = tags.p({"class": "feed-summary-entry"}, tags.i("Never posted"))
else: else:
entry = f.entries[0] entry = f.entries[0]
last_entry = [ last_entry = [
tags.p(tags.i(f"Posted {entry.time_ago()} ago")), tags.p(
tags.p({"class": "feed-title-summary"}, entry.title), {"class": "feed-summary-timestamp"},
tags.i(
f"Posted ",
time(entry.time_ago(), datetime=entry.posted_time_iso()),
" ago",
),
),
tags.p({"class": "feed-summary-entry"}, entry.title),
] ]
result = tags.li( result = tags.li(
{"class": "feed-summary"}, {"class": "feed-summary"},
# TODO: Image! # TODO: Image!
tags.h2(f.title), tags.h2({"class": "feed-summary-title"}, f.title),
last_entry, last_entry,
) )
assert isinstance(result, tags.li) assert isinstance(result, tags.li)
@ -40,29 +62,40 @@ def feed_view(feeds: list[feed.Feed]) -> tags.html:
document = tags.html( document = tags.html(
_standard_header("Subscribed Feeds"), _standard_header("Subscribed Feeds"),
tags.body( tags.body(
{"class": "feed-view"}, {"class": "fv-body"},
tags.h1("Feeds"), tags.h1({"class": "fv-title"}, "Feeds"),
tags.form( tags.form(
{"method": "post", "action": "/refresh"}, {"class": "fv-subscribe", "method": "post", "action": "/subscribe"},
tags.input_(type="submit", value="Refresh"),
),
tags.form(
{"method": "post", "action": "/subscribe"},
tags.label({"for": "url"}, "Feed url:"), tags.label({"for": "url"}, "Feed url:"),
tags.input_(type="url", name="url"), tags.input_(type="url", name="url"),
tags.input_(type="submit", value="Subscribe"), tags.input_(type="submit", value="Subscribe"),
), ),
tags.div( tags.div(
{"class": "main-container"}, {"class": "fv-main-panel"},
tags.ul( tags.div(
{"class": "feed-summary-list"}, (_feed_summary(f) for f in feeds) {"class": "fv-summary-panel"},
tags.form(
{
"class": "fv-summary-refresh",
"method": "post",
"action": "/refresh",
},
tags.input_(type="submit", value="Refresh"),
),
tags.ul(
{"class": "fv-summary-list"},
(_feed_summary(f) for f in feeds),
),
), ),
tags.div( tags.div(
{"class": "feed-container"}, {"class": "fv-feed-panel"},
( (
tags.div( tags.div(
{"class": "feed"}, {"class": "fv-feed"},
tags.h2(tags.a(f.title, href=f.link, target="_blank")), tags.h2(
{"class": "fv-feed-title"},
tags.a(f.title, href=f.link, target="_blank"),
),
( (
tags.ul( tags.ul(
tags.li( tags.li(
@ -72,7 +105,11 @@ def feed_view(feeds: list[feed.Feed]) -> tags.html:
href=entry.link, href=entry.link,
target="_blank", target="_blank",
), ),
f" ({entry.time_ago()})", " ",
time(
f"({entry.time_ago()})",
datetime=entry.posted_time_iso(),
),
) )
for entry in f.entries for entry in f.entries
) )