kanban-app/backend/app/routes/kanban/boards.py

142 lines
4.3 KiB
Python
Raw Normal View History

from datetime import UTC, datetime
from flask import request
from flask_jwt_extended import jwt_required
from flask_pydantic import validate
from app import db
from app.decorators import get_current_user_id, load_board_owned
from app.models import Board, Card, CardLabel, Label, List
from app.schemas import (BoardCreateRequest, BoardResponse,
BoardWithDetailsResponse)
from . import kanban_bp
@kanban_bp.route("/boards", methods=["GET"])
@jwt_required()
def get_boards():
"""Get all boards for current user"""
user_id = get_current_user_id()
boards = Board.query.filter_by(user_id=user_id).all()
return [BoardResponse.model_validate(board).model_dump() for board in boards], 200
@kanban_bp.route("/boards/<int:board_id>", methods=["GET"])
@jwt_required()
@load_board_owned
def get_board(board_id, board):
"""Get a single board with all its details"""
2026-02-27 19:25:34 +00:00
from app.models import User
# Get all lists for this board
lists_data = []
for lst in board.lists.filter_by(closed=False).order_by(List.pos).all():
cards_data = []
for card in lst.cards.filter_by(closed=False).order_by(Card.pos).all():
card_dict = card.to_dict()
2026-02-27 19:25:34 +00:00
# Add labels for this card
card_dict["labels"] = [
label.to_dict()
for label in (
db.session.query(Label)
.join(CardLabel)
.filter(CardLabel.card_id == card.id)
.all()
)
]
2026-02-27 19:25:34 +00:00
# Add comments for this card
card_dict["comments"] = []
for comment in card.comments.all():
comment_dict = comment.to_dict()
user = db.session.get(User, comment.user_id)
comment_dict["user"] = user.to_dict() if user else None
card_dict["comments"].append(comment_dict)
# Add checklists with items for this card
card_dict["checklists"] = [
{
**checklist.to_dict(),
"items": [item.to_dict() for item in checklist.check_items.all()],
}
for checklist in card.checklists.all()
]
cards_data.append(card_dict)
lists_data.append({**lst.to_dict(), "cards": cards_data})
board_dict = board.to_dict()
board_dict["lists"] = lists_data
board_dict["labels"] = [label.to_dict() for label in board.labels.all()]
response = BoardWithDetailsResponse(**board_dict)
return response.model_dump(), 200
@kanban_bp.route("/boards", methods=["POST"])
@jwt_required()
@validate(body=BoardCreateRequest)
def create_board(body: BoardCreateRequest):
"""Create a new board"""
user_id = get_current_user_id()
board = Board(
name=body.name,
description=body.description,
user_id=user_id,
url=body.url,
short_link=body.short_link,
short_url=body.short_url,
prefs=body.prefs,
label_names=body.label_names,
limits=body.limits,
)
db.session.add(board)
db.session.commit()
return BoardResponse.model_validate(board).model_dump(), 201
@kanban_bp.route("/boards/<int:board_id>", methods=["PUT"])
@jwt_required()
@load_board_owned
@validate(body=BoardCreateRequest)
def update_board(board_id, board, body: BoardCreateRequest):
"""Update a board"""
board.name = body.name
if body.description is not None:
board.description = body.description
if request.json.get("closed") is not None:
board.closed = request.json.get("closed")
if body.url is not None:
board.url = body.url
if body.short_url is not None:
board.short_url = body.short_url
if body.prefs is not None:
board.prefs = body.prefs
if body.label_names is not None:
board.label_names = body.label_names
if body.limits is not None:
board.limits = body.limits
board.date_last_activity = datetime.now(UTC)
db.session.commit()
return BoardResponse.model_validate(board).model_dump(), 200
@kanban_bp.route("/boards/<int:board_id>", methods=["DELETE"])
@jwt_required()
@load_board_owned
def delete_board(board_id, board):
"""Delete a board"""
db.session.delete(board)
db.session.commit()
return {"message": "Board deleted"}, 200