141 lines
4.3 KiB
Python
141 lines
4.3 KiB
Python
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"""
|
|
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()
|
|
|
|
# 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()
|
|
)
|
|
]
|
|
|
|
# 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
|