""" Templates API Blueprint Provides REST endpoints for workflow template management. """ from flask import Blueprint, request, jsonify import logging import sys import os sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from services.template_service import TemplateService from services.serialization import WorkflowSerializer from api.errors import handle_api_error templates_bp = Blueprint('templates', __name__) logger = logging.getLogger(__name__) # Initialize services template_service = TemplateService() workflow_serializer = WorkflowSerializer() @templates_bp.route('/', methods=['GET']) def list_templates(): """List all templates with optional filtering""" try: # Get query parameters category = request.args.get('category') difficulty = request.args.get('difficulty') # Get templates templates = template_service.list_templates(category=category, difficulty=difficulty) # Convert to dict format result = [] for template in templates: template_dict = template.to_dict() # Remove the full workflow from list view for performance template_dict.pop('workflow', None) result.append(template_dict) return jsonify({ 'templates': result, 'count': len(result) }) except Exception as e: logger.error(f"Error listing templates: {e}") return handle_api_error(e) @templates_bp.route('/', methods=['POST']) def create_template(): """Create a new template""" try: data = request.get_json() if not data: return jsonify({'error': 'No data provided'}), 400 # Create template template = template_service.create_template(data) logger.info(f"Created template: {template.id}") return jsonify(template.to_dict()), 201 except ValueError as e: logger.warning(f"Template validation error: {e}") return jsonify({'error': str(e)}), 400 except Exception as e: logger.error(f"Error creating template: {e}") return handle_api_error(e) @templates_bp.route('/', methods=['GET']) def get_template(template_id): """Get a specific template""" try: template = template_service.get_template(template_id) if not template: return jsonify({'error': 'Template not found'}), 404 return jsonify(template.to_dict()) except Exception as e: logger.error(f"Error getting template {template_id}: {e}") return handle_api_error(e) @templates_bp.route('/', methods=['PUT']) def update_template(template_id): """Update an existing template""" try: data = request.get_json() if not data: return jsonify({'error': 'No data provided'}), 400 template = template_service.update_template(template_id, data) if not template: return jsonify({'error': 'Template not found'}), 404 logger.info(f"Updated template: {template_id}") return jsonify(template.to_dict()) except ValueError as e: logger.warning(f"Template validation error: {e}") return jsonify({'error': str(e)}), 400 except Exception as e: logger.error(f"Error updating template {template_id}: {e}") return handle_api_error(e) @templates_bp.route('/', methods=['DELETE']) def delete_template(template_id): """Delete a template""" try: success = template_service.delete_template(template_id) if not success: return jsonify({'error': 'Template not found'}), 404 logger.info(f"Deleted template: {template_id}") return jsonify({'message': 'Template deleted successfully'}) except Exception as e: logger.error(f"Error deleting template {template_id}: {e}") return handle_api_error(e) @templates_bp.route('//instantiate', methods=['POST']) def instantiate_template(template_id): """Create a workflow from a template""" try: data = request.get_json() if not data: return jsonify({'error': 'No data provided'}), 400 # Extract parameters parameters = data.get('parameters', {}) workflow_name = data.get('name', f'Workflow from template {template_id}') created_by = data.get('created_by', 'user') # Create workflow instance workflow = template_service.instantiate_template( template_id, parameters, workflow_name, created_by ) if not workflow: return jsonify({'error': 'Template not found'}), 404 # Save the workflow workflow_data = workflow_serializer.serialize(workflow) workflow_id = workflow_serializer.save_workflow(workflow_data) logger.info(f"Instantiated template {template_id} as workflow {workflow_id}") return jsonify({ 'workflow_id': workflow_id, 'workflow': workflow.to_dict() }), 201 except ValueError as e: logger.warning(f"Template instantiation error: {e}") return jsonify({'error': str(e)}), 400 except Exception as e: logger.error(f"Error instantiating template {template_id}: {e}") return handle_api_error(e) @templates_bp.route('/from-workflow', methods=['POST']) def create_template_from_workflow(): """Create a template from an existing workflow""" try: data = request.get_json() if not data: return jsonify({'error': 'No data provided'}), 400 # Extract required fields workflow_id = data.get('workflow_id') template_name = data.get('template_name') template_description = data.get('template_description') category = data.get('category', 'Custom') parameters = data.get('parameters', []) if not all([workflow_id, template_name, template_description]): return jsonify({ 'error': 'workflow_id, template_name, and template_description are required' }), 400 # Load the workflow workflow_data = workflow_serializer.load_workflow(workflow_id) if not workflow_data: return jsonify({'error': 'Workflow not found'}), 404 workflow = workflow_serializer.deserialize(workflow_data) # Create template template = template_service.create_template_from_workflow( workflow, template_name, template_description, category, parameters ) logger.info(f"Created template {template.id} from workflow {workflow_id}") return jsonify(template.to_dict()), 201 except ValueError as e: logger.warning(f"Template creation error: {e}") return jsonify({'error': str(e)}), 400 except Exception as e: logger.error(f"Error creating template from workflow: {e}") return handle_api_error(e) @templates_bp.route('/categories', methods=['GET']) def get_template_categories(): """Get all available template categories""" try: templates = template_service.list_templates() categories = list(set(template.category for template in templates)) categories.sort() return jsonify({ 'categories': categories }) except Exception as e: logger.error(f"Error getting template categories: {e}") return handle_api_error(e)