fix: delete issues, ePub reader (JSZip, linear cover, fonts), Pico dialog, UI polish
- Add POST /issues/<id>/delete route with file cleanup - Fix ePub reader: add JSZip dependency, make cover linear in spine, inject system fonts into rendition - Replace browser confirm() with Pico CSS dialog component - Fix dashboard button sizing and consistency - Add favicon, override Pico font stack to suppress Firefox warnings - Compact issue action buttons Made-with: Cursor
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
from datetime import date
|
||||
from datetime import date, datetime
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
from ebooklib import epub
|
||||
@@ -67,6 +67,7 @@ def build_epub(
|
||||
issue_type: str = "weekly",
|
||||
) -> str:
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
ts = datetime.now().strftime("%Y%m%d%H%M%S")
|
||||
|
||||
articles = (
|
||||
Article.query
|
||||
@@ -91,7 +92,7 @@ def build_epub(
|
||||
)
|
||||
|
||||
book = epub.EpubBook()
|
||||
book.set_identifier(f"pi-{week_start.isoformat()}")
|
||||
book.set_identifier(f"pi-{week_start.isoformat()}-{issue_type}-{ts}")
|
||||
book.set_title(title)
|
||||
book.set_language("en")
|
||||
book.add_author("Plymouth Independent")
|
||||
@@ -99,6 +100,11 @@ def build_epub(
|
||||
with open(cover_path, "rb") as f:
|
||||
book.set_cover("cover.jpg", f.read())
|
||||
|
||||
for item in book.get_items():
|
||||
if item.get_name() == "cover.xhtml":
|
||||
item.is_linear = True
|
||||
break
|
||||
|
||||
style = epub.EpubItem(
|
||||
uid="style", file_name="style/default.css",
|
||||
media_type="text/css", content=EPUB_CSS.encode("utf-8"),
|
||||
@@ -162,10 +168,16 @@ def build_epub(
|
||||
book.add_item(epub.EpubNcx())
|
||||
book.add_item(epub.EpubNav())
|
||||
|
||||
book.spine = ["nav"] + chapters
|
||||
book.spine = ["cover", "nav"] + chapters
|
||||
|
||||
iso_week = week_start.isocalendar()[1]
|
||||
filename = f"plymouth-independent-{week_start.year}-W{iso_week:02d}.epub"
|
||||
if issue_type == "multi_week":
|
||||
w2 = week_end.isocalendar()[1]
|
||||
filename = f"plymouth-independent-{week_start.year}-W{iso_week:02d}-W{w2:02d}-{ts}.epub"
|
||||
elif issue_type == "single_article":
|
||||
filename = f"plymouth-independent-single-{ts}.epub"
|
||||
else:
|
||||
filename = f"plymouth-independent-{week_start.year}-W{iso_week:02d}-{ts}.epub"
|
||||
epub_path = os.path.join(output_dir, filename)
|
||||
epub.write_epub(epub_path, book)
|
||||
|
||||
|
||||
@@ -37,6 +37,15 @@ def download(issue_id):
|
||||
)
|
||||
|
||||
|
||||
@issues_bp.route("/issues/<int:issue_id>/epub")
|
||||
def epub_file(issue_id):
|
||||
issue = Issue.query.get_or_404(issue_id)
|
||||
if not os.path.exists(issue.epub_path):
|
||||
flash("ePub file not found.", "error")
|
||||
return redirect(url_for("issues.index"))
|
||||
return send_file(issue.epub_path, mimetype="application/epub+zip")
|
||||
|
||||
|
||||
@issues_bp.route("/issues/<int:issue_id>/cover")
|
||||
def cover_image(issue_id):
|
||||
issue = Issue.query.get_or_404(issue_id)
|
||||
@@ -73,6 +82,22 @@ def read(issue_id):
|
||||
)
|
||||
|
||||
|
||||
@issues_bp.route("/issues/<int:issue_id>/delete", methods=["POST"])
|
||||
def delete(issue_id):
|
||||
issue = Issue.query.get_or_404(issue_id)
|
||||
|
||||
if issue.epub_path and os.path.exists(issue.epub_path):
|
||||
os.remove(issue.epub_path)
|
||||
if issue.cover_path and os.path.exists(issue.cover_path):
|
||||
os.remove(issue.cover_path)
|
||||
|
||||
db.session.delete(issue)
|
||||
db.session.commit()
|
||||
|
||||
flash("Issue deleted.")
|
||||
return redirect(url_for("issues.index"))
|
||||
|
||||
|
||||
@issues_bp.route("/issues/<int:issue_id>/regenerate", methods=["POST"])
|
||||
def regenerate(issue_id):
|
||||
issue = Issue.query.get_or_404(issue_id)
|
||||
|
||||
Reference in New Issue
Block a user