198 lines
6.1 KiB
Python
198 lines
6.1 KiB
Python
"""
|
|
Templates API Endpoints
|
|
Handles template CRUD operations and application.
|
|
"""
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Request, status
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from typing import List
|
|
|
|
from app.core.auth import get_current_user_id
|
|
from app.core.database import get_db, AuditLogRepository
|
|
from app.services.metadata_service import get_metadata_service, MetadataService
|
|
from app.models.file import (
|
|
TemplateCreate,
|
|
TemplateResponse,
|
|
TemplateApply,
|
|
TemplatePreview
|
|
)
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/", response_model=List[TemplateResponse])
|
|
async def list_templates(
|
|
metadata_service: MetadataService = Depends(get_metadata_service),
|
|
user_id: int = Depends(get_current_user_id)
|
|
):
|
|
"""List all available templates."""
|
|
templates = metadata_service.template_manager.list_templates()
|
|
return [TemplateResponse(**template) for template in templates]
|
|
|
|
|
|
@router.post("/", status_code=status.HTTP_201_CREATED)
|
|
async def create_template(
|
|
template_data: TemplateCreate,
|
|
db: AsyncSession = Depends(get_db),
|
|
metadata_service: MetadataService = Depends(get_metadata_service),
|
|
user_id: int = Depends(get_current_user_id)
|
|
):
|
|
"""Create a new template."""
|
|
template = {
|
|
"name": template_data.name,
|
|
"title": template_data.title,
|
|
"subject": template_data.subject,
|
|
"keywords": template_data.keywords,
|
|
"description": template_data.description
|
|
}
|
|
|
|
metadata_service.template_manager.save_template(template)
|
|
|
|
await AuditLogRepository.log_action(
|
|
db,
|
|
user_id=user_id,
|
|
action="template_create",
|
|
details=f"Created template: {template_data.name}"
|
|
)
|
|
|
|
return {"success": True, "message": "Template created", "template": template}
|
|
|
|
|
|
@router.get("/{template_name}", response_model=TemplateResponse)
|
|
async def get_template(
|
|
template_name: str,
|
|
metadata_service: MetadataService = Depends(get_metadata_service),
|
|
user_id: int = Depends(get_current_user_id)
|
|
):
|
|
"""Get template by name."""
|
|
template = metadata_service.template_manager.load_template(template_name)
|
|
if not template:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Template '{template_name}' not found"
|
|
)
|
|
return TemplateResponse(**template)
|
|
|
|
|
|
@router.delete("/{template_name}")
|
|
async def delete_template(
|
|
template_name: str,
|
|
db: AsyncSession = Depends(get_db),
|
|
metadata_service: MetadataService = Depends(get_metadata_service),
|
|
user_id: int = Depends(get_current_user_id)
|
|
):
|
|
"""Delete template."""
|
|
success = metadata_service.template_manager.delete_template(template_name)
|
|
|
|
if not success:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Template '{template_name}' not found"
|
|
)
|
|
|
|
await AuditLogRepository.log_action(
|
|
db,
|
|
user_id=user_id,
|
|
action="template_delete",
|
|
details=f"Deleted template: {template_name}"
|
|
)
|
|
|
|
return {"success": True, "message": "Template deleted"}
|
|
|
|
|
|
@router.post("/preview")
|
|
async def preview_template(
|
|
preview_data: TemplatePreview,
|
|
metadata_service: MetadataService = Depends(get_metadata_service),
|
|
user_id: int = Depends(get_current_user_id)
|
|
):
|
|
"""Preview template output."""
|
|
template = {
|
|
"title": preview_data.title,
|
|
"subject": preview_data.subject,
|
|
"keywords": preview_data.keywords
|
|
}
|
|
|
|
result = metadata_service.template_manager.apply_template(
|
|
template=template,
|
|
filename=preview_data.sample_filename,
|
|
user="user",
|
|
custom_vars=preview_data.custom_vars or {}
|
|
)
|
|
|
|
return {"preview": result}
|
|
|
|
|
|
@router.post("/apply")
|
|
async def apply_template(
|
|
apply_data: TemplateApply,
|
|
request: Request,
|
|
db: AsyncSession = Depends(get_db),
|
|
metadata_service: MetadataService = Depends(get_metadata_service),
|
|
user_id: int = Depends(get_current_user_id)
|
|
):
|
|
"""
|
|
Apply template to files in session with variable substitution.
|
|
|
|
Loads template, applies to each file with variable substitution,
|
|
updates session with suggested metadata.
|
|
"""
|
|
# Load template
|
|
template = metadata_service.template_manager.load_template(apply_data.template_name)
|
|
if not template:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Template '{apply_data.template_name}' not found"
|
|
)
|
|
|
|
# Get file session from Redis
|
|
redis = request.app.state.redis
|
|
file_session = await redis.get_file_session(apply_data.session_id)
|
|
if not file_session:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Session not found or expired"
|
|
)
|
|
|
|
files = file_session.get("files", [])
|
|
results = []
|
|
|
|
# Apply template to each selected file
|
|
for file_index in apply_data.file_indices:
|
|
if file_index >= len(files):
|
|
results.append({"index": file_index, "success": False, "error": "Invalid file index"})
|
|
continue
|
|
|
|
file_info = files[file_index]
|
|
filename = file_info.get("filename", "")
|
|
|
|
# Apply template with variable substitution
|
|
try:
|
|
metadata = metadata_service.template_manager.apply_template(
|
|
template=template,
|
|
filename=filename,
|
|
user=f"user_{user_id}",
|
|
custom_vars=apply_data.custom_vars or {}
|
|
)
|
|
|
|
# Update file's suggested metadata in session
|
|
file_info["suggested_metadata"] = metadata
|
|
results.append({"index": file_index, "success": True, "metadata": metadata})
|
|
|
|
except Exception as e:
|
|
results.append({"index": file_index, "success": False, "error": str(e)})
|
|
|
|
# Update session with modified files
|
|
file_session["files"] = files
|
|
await redis.update_file_session(apply_data.session_id, file_session)
|
|
|
|
# Log action
|
|
await AuditLogRepository.log_action(
|
|
db,
|
|
user_id=user_id,
|
|
action="template_apply",
|
|
details=f"Applied template '{apply_data.template_name}' to {len(apply_data.file_indices)} files"
|
|
)
|
|
|
|
return {"success": True, "results": results}
|