feat: universal reorder grip handles and compact UI density
- Add generic move_in_order() to BaseRepository for reorder support - Add reusable reorder_arrows.html partial with grip dot handles - Add reorder routes to all 9 list routers (tasks, notes, links, contacts, meetings, decisions, appointments, lists, focus) - Compact row padding (6px 12px, gap 8px) on .list-row and .focus-item - Reduce font size to 0.80rem on row titles, sidebar nav, domain tree Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -300,3 +300,15 @@ async def delete_appointment(
|
||||
repo = BaseRepository("appointments", db)
|
||||
await repo.soft_delete(appointment_id)
|
||||
return RedirectResponse(url="/appointments", status_code=303)
|
||||
|
||||
|
||||
@router.post("/reorder")
|
||||
async def reorder_appointment(
|
||||
request: Request,
|
||||
item_id: str = Form(...),
|
||||
direction: str = Form(...),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
repo = BaseRepository("appointments", db)
|
||||
await repo.move_in_order(item_id, direction)
|
||||
return RedirectResponse(url=request.headers.get("referer", "/appointments"), status_code=303)
|
||||
|
||||
@@ -124,3 +124,15 @@ async def delete_contact(contact_id: str, db: AsyncSession = Depends(get_db)):
|
||||
repo = BaseRepository("contacts", db)
|
||||
await repo.soft_delete(contact_id)
|
||||
return RedirectResponse(url="/contacts", status_code=303)
|
||||
|
||||
|
||||
@router.post("/reorder")
|
||||
async def reorder_contact(
|
||||
request: Request,
|
||||
item_id: str = Form(...),
|
||||
direction: str = Form(...),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
repo = BaseRepository("contacts", db)
|
||||
await repo.move_in_order(item_id, direction)
|
||||
return RedirectResponse(url=request.headers.get("referer", "/contacts"), status_code=303)
|
||||
|
||||
@@ -216,3 +216,15 @@ async def delete_decision(decision_id: str, request: Request, db: AsyncSession =
|
||||
repo = BaseRepository("decisions", db)
|
||||
await repo.soft_delete(decision_id)
|
||||
return RedirectResponse(url="/decisions", status_code=303)
|
||||
|
||||
|
||||
@router.post("/reorder")
|
||||
async def reorder_decision(
|
||||
request: Request,
|
||||
item_id: str = Form(...),
|
||||
direction: str = Form(...),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
repo = BaseRepository("decisions", db)
|
||||
await repo.move_in_order(item_id, direction)
|
||||
return RedirectResponse(url=request.headers.get("referer", "/decisions"), status_code=303)
|
||||
|
||||
@@ -121,6 +121,20 @@ async def add_to_focus(
|
||||
return RedirectResponse(url=f"/focus?focus_date={focus_date}", status_code=303)
|
||||
|
||||
|
||||
@router.post("/reorder")
|
||||
async def reorder_focus(
|
||||
request: Request,
|
||||
item_id: str = Form(...),
|
||||
direction: str = Form(...),
|
||||
focus_date: str = Form(...),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
repo = BaseRepository("daily_focus", db)
|
||||
parsed_date = date.fromisoformat(focus_date)
|
||||
await repo.move_in_order(item_id, direction, filters={"focus_date": parsed_date})
|
||||
return RedirectResponse(url=f"/focus?focus_date={focus_date}", status_code=303)
|
||||
|
||||
|
||||
@router.post("/{focus_id}/toggle")
|
||||
async def toggle_focus(focus_id: str, request: Request, db: AsyncSession = Depends(get_db)):
|
||||
repo = BaseRepository("daily_focus", db)
|
||||
|
||||
@@ -154,3 +154,15 @@ async def delete_link(link_id: str, request: Request, db: AsyncSession = Depends
|
||||
repo = BaseRepository("links", db)
|
||||
await repo.soft_delete(link_id)
|
||||
return RedirectResponse(url=request.headers.get("referer", "/links"), status_code=303)
|
||||
|
||||
|
||||
@router.post("/reorder")
|
||||
async def reorder_link(
|
||||
request: Request,
|
||||
item_id: str = Form(...),
|
||||
direction: str = Form(...),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
repo = BaseRepository("links", db)
|
||||
await repo.move_in_order(item_id, direction)
|
||||
return RedirectResponse(url=request.headers.get("referer", "/links"), status_code=303)
|
||||
|
||||
@@ -332,3 +332,35 @@ async def remove_contact(
|
||||
"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)
|
||||
|
||||
|
||||
@router.post("/reorder")
|
||||
async def reorder_list(
|
||||
request: Request,
|
||||
item_id: str = Form(...),
|
||||
direction: str = Form(...),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
repo = BaseRepository("lists", db)
|
||||
await repo.move_in_order(item_id, direction)
|
||||
return RedirectResponse(url=request.headers.get("referer", "/lists"), status_code=303)
|
||||
|
||||
|
||||
@router.post("/{list_id}/items/reorder")
|
||||
async def reorder_list_item(
|
||||
list_id: str,
|
||||
request: Request,
|
||||
item_id: str = Form(...),
|
||||
direction: str = Form(...),
|
||||
parent_id: Optional[str] = Form(None),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
repo = BaseRepository("list_items", db)
|
||||
filters = {"list_id": list_id}
|
||||
if parent_id:
|
||||
filters["parent_item_id"] = parent_id
|
||||
else:
|
||||
# Top-level items only (no parent)
|
||||
filters["parent_item_id"] = None
|
||||
await repo.move_in_order(item_id, direction, filters=filters)
|
||||
return RedirectResponse(url=f"/lists/{list_id}", status_code=303)
|
||||
|
||||
@@ -404,3 +404,15 @@ async def remove_contact(
|
||||
"DELETE FROM contact_meetings WHERE contact_id = :cid AND meeting_id = :mid"
|
||||
), {"cid": contact_id, "mid": meeting_id})
|
||||
return RedirectResponse(url=f"/meetings/{meeting_id}?tab=contacts", status_code=303)
|
||||
|
||||
|
||||
@router.post("/reorder")
|
||||
async def reorder_meeting(
|
||||
request: Request,
|
||||
item_id: str = Form(...),
|
||||
direction: str = Form(...),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
repo = BaseRepository("meetings", db)
|
||||
await repo.move_in_order(item_id, direction)
|
||||
return RedirectResponse(url=request.headers.get("referer", "/meetings"), status_code=303)
|
||||
|
||||
@@ -193,3 +193,15 @@ async def delete_note(note_id: str, request: Request, db: AsyncSession = Depends
|
||||
await repo.soft_delete(note_id)
|
||||
referer = request.headers.get("referer", "/notes")
|
||||
return RedirectResponse(url=referer, status_code=303)
|
||||
|
||||
|
||||
@router.post("/reorder")
|
||||
async def reorder_note(
|
||||
request: Request,
|
||||
item_id: str = Form(...),
|
||||
direction: str = Form(...),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
repo = BaseRepository("notes", db)
|
||||
await repo.move_in_order(item_id, direction)
|
||||
return RedirectResponse(url=request.headers.get("referer", "/notes"), status_code=303)
|
||||
|
||||
@@ -481,3 +481,15 @@ async def remove_contact(
|
||||
"DELETE FROM contact_tasks WHERE contact_id = :cid AND task_id = :tid"
|
||||
), {"cid": contact_id, "tid": task_id})
|
||||
return RedirectResponse(url=f"/tasks/{task_id}?tab=contacts", status_code=303)
|
||||
|
||||
|
||||
@router.post("/reorder")
|
||||
async def reorder_task(
|
||||
request: Request,
|
||||
item_id: str = Form(...),
|
||||
direction: str = Form(...),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
repo = BaseRepository("tasks", db)
|
||||
await repo.move_in_order(item_id, direction)
|
||||
return RedirectResponse(url=request.headers.get("referer", "/tasks"), status_code=303)
|
||||
|
||||
Reference in New Issue
Block a user