feat: create new links directly from contact pages
Contact detail: + New Link button redirects to link form with contact context. Contact create/edit form: inline new link rows (label/url/role) created on submit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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="/contacts", tags=["contacts"])
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
@@ -77,6 +78,27 @@ async def create_contact(
|
||||
INSERT INTO contact_links (contact_id, link_id, role)
|
||||
VALUES (:cid, :lid, :role) ON CONFLICT DO NOTHING
|
||||
"""), {"cid": contact["id"], "lid": lid, "role": lr if lr and lr.strip() else None})
|
||||
|
||||
# Process inline new link creation
|
||||
new_labels = form_data.getlist("new_link_labels")
|
||||
new_urls = form_data.getlist("new_link_urls")
|
||||
new_roles = form_data.getlist("new_link_roles")
|
||||
link_repo = BaseRepository("links", db)
|
||||
default_fid = await get_default_folder_id(db) if new_labels else None
|
||||
for i, label in enumerate(new_labels):
|
||||
url = new_urls[i] if i < len(new_urls) else ""
|
||||
if label and label.strip() and url and url.strip():
|
||||
new_link = await link_repo.create({"label": label.strip(), "url": url.strip()})
|
||||
await db.execute(text("""
|
||||
INSERT INTO folder_links (folder_id, link_id)
|
||||
VALUES (:fid, :lid) ON CONFLICT DO NOTHING
|
||||
"""), {"fid": default_fid, "lid": new_link["id"]})
|
||||
nr = new_roles[i] if i < len(new_roles) else None
|
||||
await db.execute(text("""
|
||||
INSERT INTO contact_links (contact_id, link_id, role)
|
||||
VALUES (:cid, :lid, :role) ON CONFLICT DO NOTHING
|
||||
"""), {"cid": contact["id"], "lid": new_link["id"], "role": nr if nr and nr.strip() else None})
|
||||
|
||||
await db.commit()
|
||||
|
||||
return RedirectResponse(url=f"/contacts/{contact['id']}", status_code=303)
|
||||
@@ -179,6 +201,27 @@ async def update_contact(
|
||||
INSERT INTO contact_links (contact_id, link_id, role)
|
||||
VALUES (:cid, :lid, :role) ON CONFLICT DO NOTHING
|
||||
"""), {"cid": contact_id, "lid": lid, "role": lr if lr and lr.strip() else None})
|
||||
|
||||
# Process inline new link creation
|
||||
new_labels = form_data.getlist("new_link_labels")
|
||||
new_urls = form_data.getlist("new_link_urls")
|
||||
new_roles = form_data.getlist("new_link_roles")
|
||||
link_repo = BaseRepository("links", db)
|
||||
default_fid = await get_default_folder_id(db) if new_labels else None
|
||||
for i, label in enumerate(new_labels):
|
||||
url = new_urls[i] if i < len(new_urls) else ""
|
||||
if label and label.strip() and url and url.strip():
|
||||
new_link = await link_repo.create({"label": label.strip(), "url": url.strip()})
|
||||
await db.execute(text("""
|
||||
INSERT INTO folder_links (folder_id, link_id)
|
||||
VALUES (:fid, :lid) ON CONFLICT DO NOTHING
|
||||
"""), {"fid": default_fid, "lid": new_link["id"]})
|
||||
nr = new_roles[i] if i < len(new_roles) else None
|
||||
await db.execute(text("""
|
||||
INSERT INTO contact_links (contact_id, link_id, role)
|
||||
VALUES (:cid, :lid, :role) ON CONFLICT DO NOTHING
|
||||
"""), {"cid": contact_id, "lid": new_link["id"], "role": nr if nr and nr.strip() else None})
|
||||
|
||||
await db.commit()
|
||||
|
||||
return RedirectResponse(url=f"/contacts/{contact_id}", status_code=303)
|
||||
|
||||
@@ -52,6 +52,7 @@ async def create_form(
|
||||
project_id: Optional[str] = None,
|
||||
task_id: Optional[str] = None,
|
||||
meeting_id: Optional[str] = None,
|
||||
contact_id: Optional[str] = None,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
sidebar = await get_sidebar_data(db)
|
||||
@@ -67,6 +68,7 @@ async def create_form(
|
||||
"prefill_project_id": project_id or "",
|
||||
"prefill_task_id": task_id or "",
|
||||
"prefill_meeting_id": meeting_id or "",
|
||||
"prefill_contact_id": contact_id or "",
|
||||
})
|
||||
|
||||
|
||||
@@ -75,6 +77,7 @@ async def create_link(
|
||||
request: Request, label: str = Form(...), url: str = Form(...),
|
||||
domain_id: Optional[str] = Form(None), project_id: Optional[str] = Form(None),
|
||||
task_id: Optional[str] = Form(None), meeting_id: Optional[str] = Form(None),
|
||||
contact_id: Optional[str] = Form(None),
|
||||
description: Optional[str] = Form(None), tags: Optional[str] = Form(None),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -99,6 +102,15 @@ async def create_link(
|
||||
VALUES (:fid, :lid) ON CONFLICT DO NOTHING
|
||||
"""), {"fid": default_fid, "lid": link["id"]})
|
||||
|
||||
# Attach to contact if created from contact context
|
||||
if contact_id and contact_id.strip():
|
||||
await db.execute(text("""
|
||||
INSERT INTO contact_links (contact_id, link_id)
|
||||
VALUES (:cid, :lid) ON CONFLICT DO NOTHING
|
||||
"""), {"cid": contact_id, "lid": link["id"]})
|
||||
await db.commit()
|
||||
return RedirectResponse(url=f"/contacts/{contact_id}", status_code=303)
|
||||
|
||||
# Redirect back to context if created from task/meeting/project
|
||||
if task_id and task_id.strip():
|
||||
return RedirectResponse(url=f"/tasks/{task_id}?tab=links", status_code=303)
|
||||
|
||||
Reference in New Issue
Block a user