related contact details

This commit is contained in:
2026-08-10 23:20:42 +02:00
parent 7b1acbb8bb
commit 3edcc99c61
4 changed files with 43 additions and 4 deletions
+24 -2
View File
@@ -66,6 +66,25 @@ def _row_to_contact_out(row: dict, group_names: list[str] | None = None) -> dict
return row
def _enrich_related_names(conn, contact: dict) -> None:
related = contact.get("related_names", [])
if not related:
return
uids = [r["value"] for r in related if r.get("value")]
if not uids:
return
resolved = db.resolve_related_names(conn, contact["account"], uids)
for r in related:
uid = r.get("value", "")
info = resolved.get(uid)
if info:
r["id"] = info["id"]
r["name"] = info["name"]
else:
r["id"] = None
r["name"] = uid
def _account_filter_clause(account_name: str | None) -> tuple[str, list]:
if account_name is None:
return "", []
@@ -146,7 +165,9 @@ def get_contact(contact_id: int, current_user: str = Depends(get_current_user)):
groups = db.get_groups_for_contact(conn, row["account"], row["uid"])
group_names = [g["name"] for g in groups if g.get("name")]
return _row_to_contact_out(row, group_names=group_names)
contact = _row_to_contact_out(row, group_names=group_names)
_enrich_related_names(conn, contact)
return contact
@app.get("/api/contacts/birthdays/today", response_model=list[ContactOut])
@@ -638,7 +659,8 @@ def web_contact(
groups = db.get_groups_for_contact(conn, row["account"], row["uid"])
group_names = [g["name"] for g in groups if g.get("name")]
contact = _row_to_contact_out(row, group_names=group_names)
contact = _row_to_contact_out(row, group_names=group_names)
_enrich_related_names(conn, contact)
homecity = ""
workcity = ""
+3 -1
View File
@@ -443,7 +443,9 @@
{% for rn in contact.related_names %}
<div class="tile">
<div class="tile-label">{{ rn.type }}</div>
<div class="tile-value">{{ rn.value }}</div>
<div class="tile-value">
{% if rn.id %}<a href="/contacts/{{ rn.id }}">{{ rn.name }}</a>{% else %}{{ rn.name }}{% endif %}
</div>
</div>
{% endfor %}
</div>
+12
View File
@@ -383,6 +383,18 @@ def get_groups_for_contact(conn, account: str, member_uid: str) -> list[dict]:
return cur.fetchall()
def resolve_related_names(conn, account: str, uids: list[str]) -> dict[str, dict]:
if not uids:
return {}
placeholders = ", ".join(["%s"] * len(uids))
with conn.cursor() as cur:
cur.execute(
f"SELECT uid, id, full_name FROM contacts WHERE account = %s AND uid IN ({placeholders})",
[account] + uids,
)
return {row["uid"]: {"id": row["id"], "name": row["full_name"]} for row in cur.fetchall()}
def get_group_count(conn, account: str | None) -> int:
where_clause, params = _account_filter_clause(account)
with conn.cursor() as cur:
+4 -1
View File
@@ -130,9 +130,12 @@ def parse_vcard(raw_text: str, account: str, etag: str | None = None) -> dict |
type_val = params.get("TYPE") or params.get("type") or "other"
if isinstance(type_val, list):
type_val = type_val[0] if type_val else "other"
value = r.value if r.value else ""
if value.startswith(_MEMBER_PREFIX):
value = value[len(_MEMBER_PREFIX):]
related_names.append({
"type": type_val,
"value": r.value if r.value else "",
"value": value,
})
photo_url = None