127 lines
3.4 KiB
Python
127 lines
3.4 KiB
Python
"""Routes for Wiki CRUD operations."""
|
|
|
|
import re
|
|
|
|
from flask_jwt_extended import get_jwt_identity, jwt_required
|
|
from flask_pydantic import validate
|
|
|
|
from app import db
|
|
from app.models import Board, Wiki
|
|
from app.schemas import WikiCreateRequest, WikiResponse, WikiUpdateRequest
|
|
|
|
from . import kanban_bp
|
|
|
|
|
|
def generate_slug(name):
|
|
"""Generate URL-friendly slug from name."""
|
|
slug = name.lower()
|
|
slug = re.sub(r"[^a-z0-9\s-]", "", slug)
|
|
slug = re.sub(r"\s+", "-", slug)
|
|
slug = slug.strip("-")
|
|
return slug
|
|
|
|
|
|
@kanban_bp.route("/boards/<int:board_id>/wikis", methods=["GET"])
|
|
@jwt_required()
|
|
def get_board_wikis(board_id):
|
|
"""Get all wikis for a board."""
|
|
board = db.session.get(Board, board_id)
|
|
if not board:
|
|
return {"error": "Board not found"}, 404
|
|
|
|
wikis = Wiki.query.filter_by(board_id=board_id).all()
|
|
return [WikiResponse.model_validate(wiki).model_dump() for wiki in wikis], 200
|
|
|
|
|
|
@kanban_bp.route("/boards/<int:board_id>/wikis", methods=["POST"])
|
|
@jwt_required()
|
|
@validate(body=WikiCreateRequest)
|
|
def create_wiki(board_id, body: WikiCreateRequest):
|
|
"""Create a new wiki for a board."""
|
|
board = db.session.get(Board, board_id)
|
|
if not board:
|
|
return {"error": "Board not found"}, 404
|
|
|
|
# Generate slug if not provided
|
|
slug = body.slug
|
|
if not slug:
|
|
slug = generate_slug(body.name)
|
|
|
|
# Ensure uniqueness
|
|
counter = 1
|
|
original_slug = slug
|
|
while Wiki.query.filter_by(slug=slug).first():
|
|
slug = f"{original_slug}-{counter}"
|
|
counter += 1
|
|
|
|
wiki = Wiki(
|
|
board_id=board_id,
|
|
name=body.name,
|
|
slug=slug,
|
|
content=body.content,
|
|
summary=body.summary,
|
|
category=body.category,
|
|
tags=body.tags,
|
|
created_by=get_jwt_identity(),
|
|
updated_by=get_jwt_identity(),
|
|
)
|
|
|
|
db.session.add(wiki)
|
|
db.session.commit()
|
|
|
|
return WikiResponse.model_validate(wiki).model_dump(), 201
|
|
|
|
|
|
@kanban_bp.route("/wikis/<int:wiki_id>", methods=["GET"])
|
|
@jwt_required()
|
|
def get_wiki(wiki_id):
|
|
"""Get a specific wiki with details."""
|
|
wiki = db.session.get(Wiki, wiki_id)
|
|
if not wiki:
|
|
return {"error": "Wiki not found"}, 404
|
|
|
|
return WikiResponse.model_validate(wiki).model_dump(), 200
|
|
|
|
|
|
@kanban_bp.route("/wikis/<int:wiki_id>", methods=["PUT"])
|
|
@jwt_required()
|
|
@validate(body=WikiUpdateRequest)
|
|
def update_wiki(wiki_id, body: WikiUpdateRequest):
|
|
"""Update a wiki."""
|
|
wiki = db.session.get(Wiki, wiki_id)
|
|
if not wiki:
|
|
return {"error": "Wiki not found"}, 404
|
|
|
|
# Update fields
|
|
if body.name is not None:
|
|
wiki.name = body.name
|
|
if body.slug is not None:
|
|
wiki.slug = body.slug
|
|
if body.content is not None:
|
|
wiki.content = body.content
|
|
if body.summary is not None:
|
|
wiki.summary = body.summary
|
|
if body.category is not None:
|
|
wiki.category = body.category
|
|
if body.tags is not None:
|
|
wiki.tags = body.tags
|
|
|
|
wiki.updated_by = get_jwt_identity()
|
|
db.session.commit()
|
|
|
|
return WikiResponse.model_validate(wiki).model_dump(), 200
|
|
|
|
|
|
@kanban_bp.route("/wikis/<int:wiki_id>", methods=["DELETE"])
|
|
@jwt_required()
|
|
def delete_wiki(wiki_id):
|
|
"""Delete a wiki."""
|
|
wiki = db.session.get(Wiki, wiki_id)
|
|
if not wiki:
|
|
return {"error": "Wiki not found"}, 404
|
|
|
|
# Delete wiki (cascades to wiki_entity_links)
|
|
db.session.delete(wiki)
|
|
db.session.commit()
|
|
|
|
return {"message": "Wiki deleted successfully"}, 200
|