improve ui

This commit is contained in:
Jake Walker 2025-01-14 18:38:12 +00:00
parent 7c0ba4c2aa
commit b18572ee56
9 changed files with 187 additions and 40 deletions

View file

@ -56,6 +56,39 @@ def admin_list_podcasts(session: SessionDep, request: Request):
)
@app.get("/admin/new")
def admin_create_podcast(request: Request):
return templates.TemplateResponse(
request=request,
name="admin_new.html.j2",
)
@app.post("/admin/new")
def admin_create_podcast_post(
session: SessionDep,
request: Request,
name: Annotated[str, Form()],
):
if name.strip() == "":
return templates.TemplateResponse(
request,
name="admin_error.html.j2",
status_code=400,
context={
"title": "Invalid entry",
"description": "Name must not be empty",
},
)
podcast = models.Podcast(name=name, description=name)
session.add(podcast)
session.commit()
return RedirectResponse(f"/admin/{podcast.id}", status_code=303)
@app.get("/admin/{podcast_id}")
def admin_list_podcast(session: SessionDep, request: Request, podcast_id: str):
podcast = session.exec(
@ -63,7 +96,15 @@ def admin_list_podcast(session: SessionDep, request: Request, podcast_id: str):
).first()
if podcast is None:
raise HTTPException(status_code=404, detail="Podcast not found")
return templates.TemplateResponse(
request,
name="admin_error.html.j2",
status_code=400,
context={
"title": "Not found",
"description": "The podcast was not found.",
},
)
episodes = podcast.episodes
episodes.sort(key=lambda e: e.publish_date, reverse=True)
@ -170,29 +211,11 @@ async def admin_upload_episode(
@app.get("/admin/{podcast_id}/{episode_id}/delete")
def admin_delete_episode(session: SessionDep, podcast_id: str, episode_id: str):
episode = session.exec(
select(models.PodcastEpisode).where(
and_(
models.PodcastEpisode.id == episode_id,
models.PodcastEpisode.podcast_id == podcast_id,
)
)
).first()
if episode is None:
raise HTTPException(status_code=404, detail="Episode or podcast not found")
(settings.directory / f"{episode_id}.m4a").unlink()
session.delete(episode)
session.commit()
return RedirectResponse(f"/admin/{podcast_id}", status_code=303)
@app.get("/admin/{podcast_id}/{episode_id}/edit")
def admin_edit_episode(
session: SessionDep, request: Request, podcast_id: str, episode_id: str
def admin_delete_episode(
session: SessionDep,
request: Request,
podcast_id: str,
episode_id: str,
):
episode = session.exec(
select(models.PodcastEpisode).where(
@ -204,7 +227,49 @@ def admin_edit_episode(
).first()
if episode is None:
raise HTTPException(status_code=404, detail="Episode or podcast not found")
return templates.TemplateResponse(
request,
name="admin_error.html.j2",
status_code=404,
context={
"title": "Not found",
"description": "The episode or podcast was not found.",
},
)
(settings.directory / f"{episode_id}.m4a").unlink()
session.delete(episode)
session.commit()
return RedirectResponse(f"/admin/{podcast_id}", status_code=303)
@app.get("/admin/{podcast_id}/{episode_id}/edit")
def admin_edit_episode(
session: SessionDep,
request: Request,
podcast_id: str,
episode_id: str,
):
episode = session.exec(
select(models.PodcastEpisode).where(
and_(
models.PodcastEpisode.id == episode_id,
models.PodcastEpisode.podcast_id == podcast_id,
)
)
).first()
if episode is None:
return templates.TemplateResponse(
request,
name="admin_error.html.j2",
status_code=404,
context={
"title": "Not found",
"description": "The episode or podcast was not found.",
},
)
return templates.TemplateResponse(
request=request,
@ -216,6 +281,7 @@ def admin_edit_episode(
@app.post("/admin/{podcast_id}/{episode_id}/edit")
def admin_edit_episode_post(
session: SessionDep,
request: Request,
podcast_id: str,
episode_id: str,
name: Annotated[str, Form()],
@ -231,7 +297,15 @@ def admin_edit_episode_post(
).first()
if episode is None:
raise HTTPException(status_code=404, detail="Episode or podcast not found")
return templates.TemplateResponse(
request,
name="admin_error.html.j2",
status_code=404,
context={
"title": "Not found",
"description": "The episode or podcast was not found.",
},
)
if name.strip() != "":
episode.name = name
@ -254,7 +328,15 @@ def admin_edit_podcast(session: SessionDep, request: Request, podcast_id: str):
).first()
if podcast is None:
raise HTTPException(status_code=404, detail="Podcast not found")
return templates.TemplateResponse(
request,
name="admin_error.html.j2",
status_code=404,
context={
"title": "Not found",
"description": "The podcast was not found.",
},
)
return templates.TemplateResponse(
request=request,
@ -266,6 +348,7 @@ def admin_edit_podcast(session: SessionDep, request: Request, podcast_id: str):
@app.post("/admin/{podcast_id}/edit")
def admin_edit_podcast_post(
session: SessionDep,
request: Request,
podcast_id: str,
name: Annotated[str, Form()],
description: Annotated[str, Form()],
@ -276,7 +359,15 @@ def admin_edit_podcast_post(
).first()
if podcast is None:
raise HTTPException(status_code=404, detail="Podcast not found")
return templates.TemplateResponse(
request,
name="admin_error.html.j2",
status_code=404,
context={
"title": "Not found",
"description": "The podcast was not found.",
},
)
if name.strip() != "":
podcast.name = name
@ -285,23 +376,38 @@ def admin_edit_podcast_post(
if image is not None and image.size > 0:
if not (image.filename.endswith(".jpg") or image.filename.endswith(".png")):
raise HTTPException(
return templates.TemplateResponse(
request,
name="admin_error.html.j2",
status_code=400,
detail="The uploaded podcast image must be a jpg or png",
context={
"title": "Invalid entry",
"description": "The uploaded podcast image must be a jpg or png.",
},
)
im = Image.open(image.file)
if im.size[0] != im.size[1] or im.size[0] < 1400 or im.size[0] > 3000:
raise HTTPException(
return templates.TemplateResponse(
request,
name="admin_error.html.j2",
status_code=400,
detail="The uploaded podcast image must be square and between 1400x1400px and 3000x3000px in size",
context={
"title": "Invalid entry",
"description": "The uploaded podcast image must be square and between 1400x1400px and 3000x3000px in size.",
},
)
if im.mode != "RGB":
raise HTTPException(
return templates.TemplateResponse(
request,
name="admin_error.html.j2",
status_code=400,
detail="The uploaded podcast image must be in RGB format",
context={
"title": "Invalid entry",
"description": "The uploaded podcast image must be in RGB format.",
},
)
if podcast.image_filename is not None:
@ -318,7 +424,7 @@ def admin_edit_podcast_post(
@app.get("/{podcast_id}.xml")
def get_feed(session: SessionDep, request: Request, podcast_id: str):
def get_podcast_feed(session: SessionDep, request: Request, podcast_id: str):
podcast = session.exec(
select(models.Podcast).where(models.Podcast.id == podcast_id)
).first()

View file

@ -14,7 +14,7 @@ class Podcast(SQLModel, table=True):
name: str
description: str
explicit: bool = Field(default=True)
image_filename: Optional[str] = Field(default=False)
image_filename: Optional[str] = Field(default=None)
episodes: list["PodcastEpisode"] = Relationship(back_populates="podcast")

View file

@ -1,5 +1,6 @@
{% extends 'layout.html.j2' %}
{% extends 'admin_layout.html.j2' %}
{% block content %}
{{ super() }}
<h1>{{ episode.name }}</h1>
<form method="post">
<fieldset>

View file

@ -0,0 +1,7 @@
{% extends 'admin_layout.html.j2' %}
{% block content %}
{{ super() }}
<h1>{{ title }}</h1>
<p>{{ description }}</p>
<p><a href="#" onclick="history.back()">Go Back</a></p>
{% endblock %}

View file

@ -1,5 +1,6 @@
{% extends 'layout.html.j2' %}
{% extends 'admin_layout.html.j2' %}
{% block content %}
{{ super() }}
{% if podcast.image_filename %}
<img src="/{{ podcast.id }}/{{ podcast.image_filename }}" width="256px" />
<br><br>
@ -74,6 +75,7 @@
function setFormEnabled(enabled) {
submitButton.disabled = !enabled;
fileInput.disabled = !enabled;
resp.setAttribute("aria-busy", JSON.stringify(!enabled));
}
window.go = () => {

View file

@ -1,5 +1,6 @@
{% extends 'layout.html.j2' %}
{% extends 'admin_layout.html.j2' %}
{% block content %}
{{ super() }}
<h1>{{ podcast.name }}</h1>
<form method="post" enctype="multipart/form-data">
<fieldset>

View file

@ -1,6 +1,10 @@
{% extends 'layout.html.j2' %}
{% extends 'admin_layout.html.j2' %}
{% block content %}
{{ super() }}
<h1>Podcasts</h1>
<p>
<b>Actions:</b> <a href="/admin/new">Create</a>
</p>
<ul>
{% for podcast in podcasts %}
<li><a href="/admin/{{ podcast.id }}">{{ podcast.name }}</a></li>

View file

@ -0,0 +1,11 @@
{% extends 'layout.html.j2' %}
{% block content %}
<nav>
<ul>
<li><strong>Podcast Server</strong></li>
</ul>
<ul>
<li><a href="/admin">Podcasts</a></li>
</ul>
</nav>
{% endblock %}

View file

@ -0,0 +1,15 @@
{% extends 'admin_layout.html.j2' %}
{% block content %}
{{ super() }}
<h1>New Podcast</h1>
<form method="post">
<fieldset>
<label>
Name
<input name="name" required />
</label>
</fieldset>
<input type="submit" value="Create" />
</form>
{% endblock %}