Links and Other Enhancements

This commit is contained in:
2026-03-02 19:55:04 +00:00
parent cf84d6d2dd
commit 0ed86ee2dc
24 changed files with 475 additions and 153 deletions

View File

@@ -1,4 +1,4 @@
"""Links: URL references attached to domains/projects."""
"""Links: URL references attached to domains/projects/tasks/meetings."""
from fastapi import APIRouter, Request, Form, Depends
from fastapi.templating import Jinja2Templates
@@ -10,6 +10,7 @@ from typing import Optional
from core.database import get_db
from core.base_repository import BaseRepository
from core.sidebar import get_sidebar_data
from routers.weblinks import get_default_folder_id
router = APIRouter(prefix="/links", tags=["links"])
templates = Jinja2Templates(directory="templates")
@@ -45,7 +46,14 @@ async def list_links(request: Request, domain_id: Optional[str] = None, db: Asyn
@router.get("/create")
async def create_form(request: Request, domain_id: Optional[str] = None, project_id: Optional[str] = None, db: AsyncSession = Depends(get_db)):
async def create_form(
request: Request,
domain_id: Optional[str] = None,
project_id: Optional[str] = None,
task_id: Optional[str] = None,
meeting_id: Optional[str] = None,
db: AsyncSession = Depends(get_db),
):
sidebar = await get_sidebar_data(db)
domains_repo = BaseRepository("domains", db)
domains = await domains_repo.list()
@@ -54,22 +62,48 @@ async def create_form(request: Request, domain_id: Optional[str] = None, project
return templates.TemplateResponse("link_form.html", {
"request": request, "sidebar": sidebar, "domains": domains, "projects": projects,
"page_title": "New Link", "active_nav": "links",
"item": None, "prefill_domain_id": domain_id or "", "prefill_project_id": project_id or "",
"item": None,
"prefill_domain_id": domain_id or "",
"prefill_project_id": project_id or "",
"prefill_task_id": task_id or "",
"prefill_meeting_id": meeting_id or "",
})
@router.post("/create")
async def create_link(
request: Request, label: str = Form(...), url: str = Form(...),
domain_id: str = Form(...), project_id: Optional[str] = Form(None),
description: Optional[str] = Form(None), db: AsyncSession = Depends(get_db),
domain_id: Optional[str] = Form(None), project_id: Optional[str] = Form(None),
task_id: Optional[str] = Form(None), meeting_id: Optional[str] = Form(None),
description: Optional[str] = Form(None), tags: Optional[str] = Form(None),
db: AsyncSession = Depends(get_db),
):
repo = BaseRepository("links", db)
data = {"label": label, "url": url, "domain_id": domain_id, "description": description}
data = {"label": label, "url": url, "description": description}
if domain_id and domain_id.strip():
data["domain_id"] = domain_id
if project_id and project_id.strip():
data["project_id"] = project_id
await repo.create(data)
referer = request.headers.get("referer", "/links")
if task_id and task_id.strip():
data["task_id"] = task_id
if meeting_id and meeting_id.strip():
data["meeting_id"] = meeting_id
if tags and tags.strip():
data["tags"] = [t.strip() for t in tags.split(",") if t.strip()]
link = await repo.create(data)
# Assign to Default folder
default_fid = await get_default_folder_id(db)
await db.execute(text("""
INSERT INTO folder_links (folder_id, link_id)
VALUES (:fid, :lid) ON CONFLICT DO NOTHING
"""), {"fid": default_fid, "lid": link["id"]})
# Redirect back to context if created from task/meeting
if task_id and task_id.strip():
return RedirectResponse(url=f"/tasks/{task_id}?tab=links", status_code=303)
if meeting_id and meeting_id.strip():
return RedirectResponse(url=f"/meetings/{meeting_id}?tab=links", status_code=303)
return RedirectResponse(url="/links", status_code=303)
@@ -87,22 +121,31 @@ async def edit_form(link_id: str, request: Request, db: AsyncSession = Depends(g
return templates.TemplateResponse("link_form.html", {
"request": request, "sidebar": sidebar, "domains": domains, "projects": projects,
"page_title": "Edit Link", "active_nav": "links",
"item": item, "prefill_domain_id": "", "prefill_project_id": "",
"item": item,
"prefill_domain_id": "", "prefill_project_id": "",
"prefill_task_id": "", "prefill_meeting_id": "",
})
@router.post("/{link_id}/edit")
async def update_link(
link_id: str, label: str = Form(...), url: str = Form(...),
domain_id: str = Form(...), project_id: Optional[str] = Form(None),
description: Optional[str] = Form(None), db: AsyncSession = Depends(get_db),
domain_id: Optional[str] = Form(None), project_id: Optional[str] = Form(None),
description: Optional[str] = Form(None), tags: Optional[str] = Form(None),
db: AsyncSession = Depends(get_db),
):
repo = BaseRepository("links", db)
await repo.update(link_id, {
"label": label, "url": url, "domain_id": domain_id,
data = {
"label": label, "url": url,
"domain_id": domain_id if domain_id and domain_id.strip() else None,
"project_id": project_id if project_id and project_id.strip() else None,
"description": description,
})
}
if tags and tags.strip():
data["tags"] = [t.strip() for t in tags.split(",") if t.strip()]
else:
data["tags"] = None
await repo.update(link_id, data)
return RedirectResponse(url="/links", status_code=303)