various enhancements for new tabs and bug fixes

This commit is contained in:
2026-03-02 17:35:00 +00:00
parent 9dedf6dbf2
commit cf84d6d2dd
32 changed files with 4501 additions and 296 deletions

View File

@@ -70,6 +70,8 @@ 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)
@@ -87,6 +89,8 @@ async def create_form(
"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 "",
})
@@ -97,6 +101,8 @@ async def create_list(
domain_id: str = Form(...),
area_id: Optional[str] = Form(None),
project_id: Optional[str] = Form(None),
task_id: Optional[str] = Form(None),
meeting_id: Optional[str] = Form(None),
list_type: str = Form("checklist"),
description: Optional[str] = Form(None),
tags: Optional[str] = Form(None),
@@ -112,10 +118,18 @@ async def create_list(
data["area_id"] = area_id
if project_id and project_id.strip():
data["project_id"] = project_id
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()]
new_list = await repo.create(data)
if task_id and task_id.strip():
return RedirectResponse(url=f"/tasks/{task_id}?tab=lists", status_code=303)
if meeting_id and meeting_id.strip():
return RedirectResponse(url=f"/meetings/{meeting_id}?tab=lists", status_code=303)
return RedirectResponse(url=f"/lists/{new_list['id']}", status_code=303)
@@ -156,10 +170,28 @@ async def list_detail(list_id: str, request: Request, db: AsyncSession = Depends
if pid:
child_map.setdefault(str(pid), []).append(i)
# Contacts linked to this list
result = await db.execute(text("""
SELECT c.*, cl.role, cl.created_at as linked_at
FROM contacts c
JOIN contact_lists cl ON cl.contact_id = c.id
WHERE cl.list_id = :lid AND c.is_deleted = false
ORDER BY c.first_name
"""), {"lid": list_id})
contacts = [dict(r._mapping) for r in result]
# All contacts for add dropdown
result = await db.execute(text("""
SELECT id, first_name, last_name FROM contacts
WHERE is_deleted = false ORDER BY first_name
"""))
all_contacts = [dict(r._mapping) for r in result]
return templates.TemplateResponse("list_detail.html", {
"request": request, "sidebar": sidebar, "item": item,
"domain": domain, "project": project,
"list_items": top_items, "child_map": child_map,
"contacts": contacts, "all_contacts": all_contacts,
"page_title": item["name"], "active_nav": "lists",
})
@@ -273,3 +305,30 @@ async def edit_item(
repo = BaseRepository("list_items", db)
await repo.update(item_id, {"content": content})
return RedirectResponse(url=f"/lists/{list_id}", status_code=303)
# ---- Contact linking ----
@router.post("/{list_id}/contacts/add")
async def add_contact(
list_id: str,
contact_id: str = Form(...),
role: Optional[str] = Form(None),
db: AsyncSession = Depends(get_db),
):
await db.execute(text("""
INSERT INTO contact_lists (contact_id, list_id, role)
VALUES (:cid, :lid, :role) ON CONFLICT DO NOTHING
"""), {"cid": contact_id, "lid": list_id, "role": role if role and role.strip() else None})
return RedirectResponse(url=f"/lists/{list_id}", status_code=303)
@router.post("/{list_id}/contacts/{contact_id}/remove")
async def remove_contact(
list_id: str, contact_id: str,
db: AsyncSession = Depends(get_db),
):
await db.execute(text(
"DELETE FROM contact_lists WHERE contact_id = :cid AND list_id = :lid"
), {"cid": contact_id, "lid": list_id})
return RedirectResponse(url=f"/lists/{list_id}", status_code=303)