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

@@ -23,10 +23,9 @@ SEED_IDS = {
"meeting": "a0000000-0000-0000-0000-000000000007",
"decision": "a0000000-0000-0000-0000-000000000008",
"appointment": "a0000000-0000-0000-0000-000000000009",
"weblink_folder": "a0000000-0000-0000-0000-00000000000a",
"link_folder": "a0000000-0000-0000-0000-00000000000a",
"list": "a0000000-0000-0000-0000-00000000000b",
"link": "a0000000-0000-0000-0000-00000000000c",
"weblink": "a0000000-0000-0000-0000-00000000000d",
"capture": "a0000000-0000-0000-0000-00000000000e",
"focus": "a0000000-0000-0000-0000-00000000000f",
"process": "a0000000-0000-0000-0000-000000000010",
@@ -153,12 +152,12 @@ def all_seeds(sync_conn):
ON CONFLICT (id) DO NOTHING
""", (d["appointment"],))
# Weblink folder
# Link folder
cur.execute("""
INSERT INTO weblink_folders (id, name, is_deleted, created_at, updated_at)
INSERT INTO link_folders (id, name, is_deleted, created_at, updated_at)
VALUES (%s, 'Test Folder', false, now(), now())
ON CONFLICT (id) DO NOTHING
""", (d["weblink_folder"],))
""", (d["link_folder"],))
# List
cur.execute("""
@@ -174,18 +173,11 @@ def all_seeds(sync_conn):
ON CONFLICT (id) DO NOTHING
""", (d["link"], d["domain"]))
# Weblink
# Link folder junction
cur.execute("""
INSERT INTO weblinks (id, label, url, is_deleted, created_at, updated_at)
VALUES (%s, 'Test Weblink', 'https://example.com/wl', false, now(), now())
ON CONFLICT (id) DO NOTHING
""", (d["weblink"],))
# Link weblink to folder via junction table
cur.execute("""
INSERT INTO folder_weblinks (folder_id, weblink_id)
INSERT INTO folder_links (folder_id, link_id)
VALUES (%s, %s) ON CONFLICT DO NOTHING
""", (d["weblink_folder"], d["weblink"]))
""", (d["link_folder"], d["link"]))
# Capture
cur.execute("""
@@ -285,11 +277,10 @@ def all_seeds(sync_conn):
cur.execute("DELETE FROM processes WHERE id = %s", (d["process"],))
cur.execute("DELETE FROM daily_focus WHERE id = %s", (d["focus"],))
cur.execute("DELETE FROM capture WHERE id = %s", (d["capture"],))
cur.execute("DELETE FROM folder_weblinks WHERE weblink_id = %s", (d["weblink"],))
cur.execute("DELETE FROM weblinks WHERE id = %s", (d["weblink"],))
cur.execute("DELETE FROM folder_links WHERE link_id = %s", (d["link"],))
cur.execute("DELETE FROM links WHERE id = %s", (d["link"],))
cur.execute("DELETE FROM lists WHERE id = %s", (d["list"],))
cur.execute("DELETE FROM weblink_folders WHERE id = %s", (d["weblink_folder"],))
cur.execute("DELETE FROM link_folders WHERE id = %s", (d["link_folder"],))
cur.execute("DELETE FROM appointments WHERE id = %s", (d["appointment"],))
cur.execute("DELETE FROM decisions WHERE id = %s", (d["decision"],))
cur.execute("DELETE FROM meetings WHERE id = %s", (d["meeting"],))

View File

@@ -35,8 +35,8 @@ PREFIX_TO_SEED = {
"/lists": "list",
"/meetings": "meeting",
"/decisions": "decision",
"/weblinks": "weblink",
"/weblinks/folders": "weblink_folder",
"/weblinks": "link",
"/weblinks/folders": "link_folder",
"/appointments": "appointment",
"/focus": "focus",
"/capture": "capture",

View File

@@ -520,11 +520,11 @@ class TestCaptureConversions:
assert dec.impact == "medium"
@pytest.mark.asyncio
async def test_convert_to_weblink(
async def test_convert_to_link(
self, client: AsyncClient, db_session: AsyncSession,
):
cap_id = await _create_capture(db_session, "Check https://example.com/test for details")
r = await client.post(f"/capture/{cap_id}/to-weblink", data={}, follow_redirects=False)
r = await client.post(f"/capture/{cap_id}/to-link", data={}, follow_redirects=False)
assert r.status_code == 303
result = await db_session.execute(
@@ -532,10 +532,10 @@ class TestCaptureConversions:
{"id": cap_id},
)
row = result.first()
assert row.converted_to_type == "weblink"
assert row.converted_to_type == "link"
# URL should be extracted
result = await db_session.execute(
text("SELECT url FROM weblinks WHERE id = :id"), {"id": row.converted_to_id},
text("SELECT url FROM links WHERE id = :id"), {"id": row.converted_to_id},
)
assert "https://example.com/test" in result.first().url
@@ -1912,7 +1912,7 @@ class TestTaskDetailTabs:
@pytest.mark.asyncio
async def test_all_tabs_return_200(self, client: AsyncClient, seed_task: dict):
"""Every tab on task detail returns 200."""
for tab in ("overview", "notes", "weblinks", "files", "lists", "decisions", "processes", "contacts"):
for tab in ("overview", "notes", "links", "files", "lists", "decisions", "processes", "contacts"):
r = await client.get(f"/tasks/{seed_task['id']}?tab={tab}")
assert r.status_code == 200, f"Tab '{tab}' returned {r.status_code}"
@@ -2141,7 +2141,7 @@ class TestMeetingDetailTabs:
@pytest.mark.asyncio
async def test_all_meeting_tabs_return_200(self, client: AsyncClient, seed_meeting: dict):
"""Every tab on meeting detail returns 200."""
for tab in ("overview", "notes", "weblinks", "files", "lists", "processes", "contacts"):
for tab in ("overview", "notes", "links", "files", "lists", "processes", "contacts"):
r = await client.get(f"/meetings/{seed_meeting['id']}?tab={tab}")
assert r.status_code == 200, f"Meeting tab '{tab}' returned {r.status_code}"
@@ -2554,28 +2554,28 @@ class TestEntityCreateWithParentContext:
assert seed_task["id"] in r.text
@pytest.mark.asyncio
async def test_create_weblink_with_task_id(
async def test_create_link_with_task_id(
self, client: AsyncClient, db_session: AsyncSession, seed_task: dict,
):
"""Creating a weblink with task_id sets the FK."""
"""Creating a link with task_id sets the FK."""
tag = _uid()
r = await client.post("/weblinks/create", data={
"label": f"TaskWeblink-{tag}",
"label": f"TaskLink-{tag}",
"url": "https://example.com/test",
"task_id": seed_task["id"],
}, follow_redirects=False)
assert r.status_code == 303
result = await db_session.execute(
text("SELECT task_id FROM weblinks WHERE label = :l AND is_deleted = false"),
{"l": f"TaskWeblink-{tag}"},
text("SELECT task_id FROM links WHERE label = :l AND is_deleted = false"),
{"l": f"TaskLink-{tag}"},
)
row = result.first()
assert row is not None
assert str(row.task_id) == seed_task["id"]
await db_session.execute(
text("DELETE FROM weblinks WHERE label = :l"), {"l": f"TaskWeblink-{tag}"}
text("DELETE FROM links WHERE label = :l"), {"l": f"TaskLink-{tag}"}
)
await db_session.commit()