dmslanes/lanes
Lanes - team task boards with roles, history and an MCP endpoint for Claude and ChatGPT
A remix template · 0 remixes · Remix dmslanes/lanes
app/application/views.py
"""Plain-dict views of the domain objects: the one JSON shape both doors return."""
from __future__ import annotations
from app.domain.model import Activity, Board, BoardList, Card, Membership
def card_view(c: Card, list_name: str | None = None, board_name: str | None = None) -> dict:
out = {"number": c.number, "id": c.id, "title": c.title, "description": c.description,
"assignee": c.assignee, "due_date": c.due_date.isoformat() if c.due_date else None,
"labels": c.labels, "blocked_by": c.blocked_by, "board_id": c.board_id, "list_id": c.list_id, "position": c.position,
"version": c.version, "updated_at": c.updated_at.isoformat() if c.updated_at else None}
if list_name:
out["list"] = list_name
if board_name:
out["board"] = board_name
return out
def board_view(b: Board) -> dict:
return {"id": b.id, "name": b.name, "workspace_id": b.workspace_id}
def list_view(l: BoardList) -> dict:
return {"id": l.id, "name": l.name, "position": l.position}
def member_view(m: Membership) -> dict:
return {"email": m.email, "role": m.role.value}
def activity_view(a: Activity) -> dict:
return {"card_id": a.card_id, "actor": a.actor, "at": a.at.isoformat(), "action": a.action,
"changes": a.changes}
def full_board_view(data: dict) -> dict:
b = data["board"]
return {**board_view(b), "your_role": data["role"].value,
"lists": [{**list_view(l), "cards": [card_view(c) for c in data["cards"][l.id]]} for l in data["lists"]]}
def cards_with_context(svc, cards: list[Card]) -> list[dict]:
"""Cards with their board and list names, for answers that span boards ("my plate")."""
boards, lists = {}, {}
out = []
for c in cards:
if c.board_id not in boards:
boards[c.board_id] = svc.repo.get_board(c.board_id)
if c.list_id not in lists:
lists[c.list_id] = svc.repo.get_list(c.list_id)
b, l = boards[c.board_id], lists[c.list_id]
out.append(card_view(c, l.name if l else None, b.name if b else None))
return out