Add sorting by date or name
Adds a sort dropdown offering newest/oldest first and name A-Z/Z-A. Sorting applies to plain listings, text search, and semantic search results, and the sidebar facet links preserve the current choice. Invalid sort values fall back to the default. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
42
app/main.py
42
app/main.py
@@ -75,6 +75,28 @@ def facets(db: Session, user: User) -> dict:
|
||||
}
|
||||
|
||||
|
||||
# Auswahl für die Sortierung: Wert -> Beschriftung in der Oberfläche.
|
||||
SORT_OPTIONS = {
|
||||
"date_desc": "Neueste zuerst",
|
||||
"date_asc": "Älteste zuerst",
|
||||
"name_asc": "Name A–Z",
|
||||
"name_desc": "Name Z–A",
|
||||
}
|
||||
DEFAULT_SORT = "date_desc"
|
||||
|
||||
|
||||
def sort_links(links: list[Link], sort: str) -> list[Link]:
|
||||
if sort == "date_asc":
|
||||
return sorted(links, key=lambda link: link.created_at)
|
||||
if sort == "name_asc":
|
||||
return sorted(links, key=lambda link: (link.title or link.url).lower())
|
||||
if sort == "name_desc":
|
||||
return sorted(
|
||||
links, key=lambda link: (link.title or link.url).lower(), reverse=True
|
||||
)
|
||||
return sorted(links, key=lambda link: link.created_at, reverse=True)
|
||||
|
||||
|
||||
def query_links(
|
||||
db: Session,
|
||||
user: User,
|
||||
@@ -82,6 +104,7 @@ def query_links(
|
||||
category: str = "",
|
||||
manufacturer: str = "",
|
||||
semantic: bool = False,
|
||||
sort: str = DEFAULT_SORT,
|
||||
) -> list[Link]:
|
||||
stmt = select(Link).where(Link.user_id == user.id)
|
||||
if category:
|
||||
@@ -92,18 +115,18 @@ def query_links(
|
||||
|
||||
q = (q or "").strip()
|
||||
if not q:
|
||||
return links
|
||||
return sort_links(links, sort)
|
||||
|
||||
if semantic and config.AI_ENABLED:
|
||||
query_vec = ai.embed(q)
|
||||
ranked = search.cosine_rank(query_vec, links)
|
||||
result = [link for link, score in ranked if score > 0.20][:50]
|
||||
if result:
|
||||
return result
|
||||
return sort_links(result, sort)
|
||||
# Fallback auf Textsuche, falls keine Embeddings vorhanden sind.
|
||||
|
||||
ql = q.lower()
|
||||
return [
|
||||
matches = [
|
||||
link
|
||||
for link in links
|
||||
if ql
|
||||
@@ -111,6 +134,7 @@ def query_links(
|
||||
[link.title, link.summary, link.tags, link.category, link.manufacturer]
|
||||
).lower()
|
||||
]
|
||||
return sort_links(matches, sort)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -192,14 +216,17 @@ def index(
|
||||
category: str = "",
|
||||
manufacturer: str = "",
|
||||
semantic: str = "",
|
||||
sort: str = DEFAULT_SORT,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
user = current_user(request, db)
|
||||
if not user:
|
||||
return RedirectResponse("/login", status_code=303)
|
||||
|
||||
if sort not in SORT_OPTIONS:
|
||||
sort = DEFAULT_SORT
|
||||
is_semantic = semantic in ("1", "on", "true")
|
||||
links = query_links(db, user, q, category, manufacturer, is_semantic)
|
||||
links = query_links(db, user, q, category, manufacturer, is_semantic, sort)
|
||||
return templates.TemplateResponse(
|
||||
"index.html",
|
||||
{
|
||||
@@ -212,6 +239,8 @@ def index(
|
||||
"active_manufacturer": manufacturer,
|
||||
"semantic": is_semantic,
|
||||
"ai_enabled": config.AI_ENABLED,
|
||||
"sort": sort,
|
||||
"sort_options": SORT_OPTIONS,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -223,14 +252,17 @@ def search_links(
|
||||
category: str = "",
|
||||
manufacturer: str = "",
|
||||
semantic: str = "",
|
||||
sort: str = DEFAULT_SORT,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
user = current_user(request, db)
|
||||
if not user:
|
||||
return Response(status_code=401, headers={"HX-Redirect": "/login"})
|
||||
|
||||
if sort not in SORT_OPTIONS:
|
||||
sort = DEFAULT_SORT
|
||||
is_semantic = semantic in ("1", "on", "true")
|
||||
links = query_links(db, user, q, category, manufacturer, is_semantic)
|
||||
links = query_links(db, user, q, category, manufacturer, is_semantic, sort)
|
||||
return templates.TemplateResponse(
|
||||
"_links_list.html", {"request": request, "links": links}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user