diff --git a/visual_workflow_builder/backend/api_v3/dag_execute.py b/visual_workflow_builder/backend/api_v3/dag_execute.py index b9854e74f..5edcc7f72 100644 --- a/visual_workflow_builder/backend/api_v3/dag_execute.py +++ b/visual_workflow_builder/backend/api_v3/dag_execute.py @@ -12,6 +12,7 @@ Auteur : Dom, Claude — 16 mars 2026 import json import logging +import os import re import sys import traceback @@ -726,3 +727,51 @@ def get_dag_status(workflow_id: str): 'success': False, 'error': str(e) }), 500 + + +# --------------------------------------------------------------------------- +# Upload Excel — explorateur de fichier côté navigateur +# --------------------------------------------------------------------------- + +UPLOAD_DIR = os.path.join( + os.path.dirname(os.path.dirname(os.path.abspath(__file__))), + 'data', 'uploads' +) + + +@api_v3_bp.route('/upload-excel', methods=['POST']) +def upload_excel(): + """Reçoit un fichier Excel uploadé depuis le navigateur. + + Sauvegarde dans data/uploads/ et retourne le chemin serveur + + un nom de table suggéré basé sur le nom du fichier. + """ + if 'file' not in request.files: + return jsonify({'error': 'Aucun fichier reçu'}), 400 + + file = request.files['file'] + if not file.filename: + return jsonify({'error': 'Nom de fichier vide'}), 400 + + # Vérifier l'extension + ext = os.path.splitext(file.filename)[1].lower() + if ext not in ('.xlsx', '.xls'): + return jsonify({'error': f'Format non supporté : {ext}'}), 400 + + os.makedirs(UPLOAD_DIR, exist_ok=True) + save_path = os.path.join(UPLOAD_DIR, file.filename) + file.save(save_path) + + # Nom de table suggéré à partir du nom du fichier + import re as _re + base = os.path.splitext(file.filename)[0] + suggested = _re.sub(r'[^a-zA-Z0-9_]', '_', base).strip('_').lower() + if suggested and suggested[0].isdigit(): + suggested = 't_' + suggested + + logger.info(f"Excel uploadé : {save_path} → table suggérée : {suggested}") + return jsonify({ + 'path': save_path, + 'filename': file.filename, + 'suggested_table': suggested, + }) diff --git a/visual_workflow_builder/frontend_v4/src/components/PropertiesPanel.tsx b/visual_workflow_builder/frontend_v4/src/components/PropertiesPanel.tsx index dac634ec4..677ade892 100644 --- a/visual_workflow_builder/frontend_v4/src/components/PropertiesPanel.tsx +++ b/visual_workflow_builder/frontend_v4/src/components/PropertiesPanel.tsx @@ -1033,13 +1033,55 @@ export default function PropertiesPanel({ step, onUpdateParams, onDelete }: Prop 📥 Import Excel