Refine runs table state layout
This commit is contained in:
parent
db1d9b44b7
commit
ba33491479
6 changed files with 241 additions and 31 deletions
|
|
@ -53,6 +53,93 @@ def _queue_icon(direction: str) -> Renderable:
|
|||
]
|
||||
|
||||
|
||||
def _icon(path: str, *, class_name: str = "size-4") -> Renderable:
|
||||
return h.svg(
|
||||
xmlns="http://www.w3.org/2000/svg",
|
||||
fill="none",
|
||||
viewBox="0 0 24 24",
|
||||
stroke_width="1.5",
|
||||
stroke="currentColor",
|
||||
class_=class_name,
|
||||
)[
|
||||
h.path(
|
||||
stroke_linecap="round",
|
||||
stroke_linejoin="round",
|
||||
d=path,
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def _clock_icon() -> Renderable:
|
||||
return _icon("M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z")
|
||||
|
||||
|
||||
def _calendar_icon() -> Renderable:
|
||||
return _icon(
|
||||
"M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5m-9-6h.008v.008H12v-.008ZM12 15h.008v.008H12V15Zm0 2.25h.008v.008H12v-.008ZM9.75 15h.008v.008H9.75V15Zm0 2.25h.008v.008H9.75v-.008ZM7.5 15h.008v.008H7.5V15Zm0 2.25h.008v.008H7.5v-.008Zm6.75-4.5h.008v.008h-.008v-.008Zm0 2.25h.008v.008h-.008V15Zm0 2.25h.008v.008h-.008v-.008Zm2.25-4.5h.008v.008H16.5v-.008Zm0 2.25h.008v.008H16.5V15Z"
|
||||
)
|
||||
|
||||
|
||||
def _status_icon(tone: str) -> Renderable:
|
||||
return _icon(
|
||||
(
|
||||
"M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"
|
||||
if tone == "done"
|
||||
else "M9.75 9.75l4.5 4.5m0-4.5-4.5 4.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"
|
||||
),
|
||||
class_name="size-3.5",
|
||||
)
|
||||
|
||||
|
||||
def _status_tone_classes(tone: str) -> str:
|
||||
return {
|
||||
"running": "bg-emerald-100 text-emerald-800",
|
||||
"scheduled": "bg-sky-100 text-sky-800",
|
||||
"idle": "bg-slate-200 text-slate-700",
|
||||
"failed": "bg-rose-100 text-rose-800",
|
||||
"done": "bg-emerald-100 text-emerald-800",
|
||||
}[tone]
|
||||
|
||||
|
||||
def _completed_status_cell(execution: Mapping[str, object]) -> Node:
|
||||
duration = _maybe_text(execution, "duration") or "--:--:--"
|
||||
ended_at = _maybe_text(execution, "ended_at_iso")
|
||||
ended_at_label: Node = h.p(class_="truncate")[_text(execution, "ended_at")]
|
||||
if ended_at is not None:
|
||||
ended_at_label = h.time(
|
||||
{
|
||||
"data-ended-at": ended_at,
|
||||
"title": ended_at,
|
||||
},
|
||||
datetime=ended_at,
|
||||
class_="truncate",
|
||||
)[_text(execution, "ended_at")]
|
||||
|
||||
return h.div(class_="min-w-[10rem]")[
|
||||
h.div(class_="flex items-center gap-2")[
|
||||
h.span(class_="font-mono text-xs text-slate-500")[
|
||||
f"#{_text(execution, 'execution_id')}"
|
||||
],
|
||||
h.span(
|
||||
class_=(
|
||||
"inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs "
|
||||
f"font-semibold {_status_tone_classes(_text(execution, 'status_tone'))}"
|
||||
)
|
||||
)[
|
||||
_status_icon(_text(execution, "status_tone")),
|
||||
h.span[_text(execution, "status")],
|
||||
],
|
||||
],
|
||||
h.div(class_="mt-1.5 space-y-1 text-xs text-slate-500")[
|
||||
h.p(class_="flex items-center gap-1.5")[_clock_icon(), h.span[duration]],
|
||||
h.p(class_="flex items-center gap-1.5")[
|
||||
_calendar_icon(),
|
||||
ended_at_label,
|
||||
],
|
||||
],
|
||||
]
|
||||
|
||||
|
||||
def _queue_row_attrs(execution: Mapping[str, object]) -> dict[str, str]:
|
||||
return {
|
||||
"style": (
|
||||
|
|
@ -173,12 +260,12 @@ def _upcoming_row(job: Mapping[str, object]) -> tuple[Node, ...]:
|
|||
h.div(class_="font-semibold text-slate-950")[_text(job, "source")],
|
||||
h.p(class_="mt-0.5 font-mono text-xs text-slate-500")[_text(job, "slug")],
|
||||
],
|
||||
h.div[next_run_label,],
|
||||
h.p(class_="font-mono text-xs text-slate-600")[_text(job, "schedule")],
|
||||
status_badge(
|
||||
label=_text(job, "enabled_label"),
|
||||
tone=_text(job, "enabled_tone"),
|
||||
),
|
||||
h.div[next_run_label,],
|
||||
h.p(class_="font-mono text-xs text-slate-600")[_text(job, "schedule")],
|
||||
h.p(class_="max-w-32 whitespace-normal text-sm text-slate-500")[
|
||||
_text(job, "run_reason")
|
||||
],
|
||||
|
|
@ -202,35 +289,14 @@ def _upcoming_row(job: Mapping[str, object]) -> tuple[Node, ...]:
|
|||
|
||||
|
||||
def _completed_row(execution: Mapping[str, object]) -> tuple[Node, ...]:
|
||||
ended_at = _maybe_text(execution, "ended_at_iso")
|
||||
ended_at_label: Node = h.p(class_="font-medium text-slate-900")[
|
||||
_text(execution, "ended_at")
|
||||
]
|
||||
if ended_at is not None:
|
||||
ended_at_label = h.time(
|
||||
{
|
||||
"data-ended-at": ended_at,
|
||||
"title": ended_at,
|
||||
},
|
||||
datetime=ended_at,
|
||||
class_="font-medium text-slate-900",
|
||||
)[_text(execution, "ended_at")]
|
||||
|
||||
return (
|
||||
h.p(class_="w-px whitespace-nowrap font-medium text-slate-900")[
|
||||
f"#{_text(execution, 'execution_id')}"
|
||||
],
|
||||
_completed_status_cell(execution),
|
||||
h.div[
|
||||
h.div(class_="font-semibold text-slate-950")[_text(execution, "source")],
|
||||
h.p(class_="mt-0.5 font-mono text-xs text-slate-500")[
|
||||
_text(execution, "slug")
|
||||
],
|
||||
],
|
||||
h.div[ended_at_label,],
|
||||
status_badge(
|
||||
label=_text(execution, "status"),
|
||||
tone=_text(execution, "status_tone"),
|
||||
),
|
||||
h.div(class_="max-w-[14rem] whitespace-normal")[
|
||||
h.p(class_="font-medium text-slate-900")[_text(execution, "stats")]
|
||||
],
|
||||
|
|
@ -356,16 +422,12 @@ def _completed_history_section(
|
|||
title="Completed job executions",
|
||||
empty_message="No job executions have completed yet.",
|
||||
headers=(
|
||||
"#",
|
||||
"Source",
|
||||
"Ended",
|
||||
"State",
|
||||
"Source",
|
||||
"Summary",
|
||||
"Log",
|
||||
),
|
||||
rows=completed_rows,
|
||||
first_header_class="w-px py-2.5 pr-2 pl-3 text-left text-xs font-semibold uppercase tracking-[0.18em] whitespace-nowrap text-slate-500 sm:pl-3",
|
||||
first_cell_class="w-px py-3 pr-2 pl-3 text-sm font-medium text-slate-950 sm:pl-3",
|
||||
actions=(
|
||||
action_button(
|
||||
label="Clear history",
|
||||
|
|
@ -442,9 +504,9 @@ def runs_page(
|
|||
empty_message="No jobs are scheduled.",
|
||||
headers=(
|
||||
"Source",
|
||||
"State",
|
||||
"Next run",
|
||||
"Cron",
|
||||
"State",
|
||||
"Run now",
|
||||
"Actions",
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue