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