- Frontend v4 accessible sur réseau local (192.168.1.40) - Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard) - Ollama GPU fonctionnel - Self-healing interactif - Dashboard confiance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
735 lines
22 KiB
Python
735 lines
22 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Correction des Erreurs ResizeObserver - Visual Workflow Builder
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
|
|
Ce script corrige les erreurs ResizeObserver qui causent des boucles infinies
|
|
et rendent l'application inutilisable.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import List, Dict, Any
|
|
|
|
def print_section(title: str):
|
|
"""Affiche une section avec formatage."""
|
|
print(f"\n{'='*60}")
|
|
print(f" {title}")
|
|
print(f"{'='*60}")
|
|
|
|
def print_subsection(title: str):
|
|
"""Affiche une sous-section."""
|
|
print(f"\n{'-'*40}")
|
|
print(f" {title}")
|
|
print(f"{'-'*40}")
|
|
|
|
def create_resizeobserver_polyfill():
|
|
"""Crée un polyfill pour ResizeObserver qui évite les boucles infinies."""
|
|
print_subsection("Création du Polyfill ResizeObserver")
|
|
|
|
polyfill_content = '''/**
|
|
* Polyfill ResizeObserver pour éviter les boucles infinies
|
|
*
|
|
* Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
*/
|
|
|
|
// Suppression des erreurs ResizeObserver en mode développement
|
|
if (process.env.NODE_ENV === 'development') {
|
|
// Intercepter les erreurs ResizeObserver
|
|
const originalError = console.error;
|
|
console.error = (...args) => {
|
|
const message = args[0];
|
|
if (
|
|
typeof message === 'string' &&
|
|
message.includes('ResizeObserver loop completed with undelivered notifications')
|
|
) {
|
|
// Ignorer silencieusement cette erreur spécifique
|
|
return;
|
|
}
|
|
originalError.apply(console, args);
|
|
};
|
|
|
|
// Intercepter les erreurs non gérées
|
|
window.addEventListener('error', (event) => {
|
|
if (
|
|
event.message &&
|
|
event.message.includes('ResizeObserver loop completed with undelivered notifications')
|
|
) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return false;
|
|
}
|
|
});
|
|
|
|
// Intercepter les promesses rejetées
|
|
window.addEventListener('unhandledrejection', (event) => {
|
|
if (
|
|
event.reason &&
|
|
event.reason.message &&
|
|
event.reason.message.includes('ResizeObserver loop completed with undelivered notifications')
|
|
) {
|
|
event.preventDefault();
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
// Polyfill ResizeObserver amélioré avec debouncing
|
|
class SafeResizeObserver {
|
|
constructor(callback) {
|
|
this.callback = callback;
|
|
this.entries = new Map();
|
|
this.rafId = null;
|
|
this.isObserving = false;
|
|
|
|
// Créer l'observer natif avec gestion d'erreur
|
|
try {
|
|
this.observer = new ResizeObserver((entries) => {
|
|
this.handleResize(entries);
|
|
});
|
|
} catch (error) {
|
|
console.warn('ResizeObserver non disponible, utilisation du fallback');
|
|
this.observer = null;
|
|
}
|
|
}
|
|
|
|
handleResize(entries) {
|
|
// Éviter les boucles infinies avec debouncing
|
|
if (this.rafId) {
|
|
cancelAnimationFrame(this.rafId);
|
|
}
|
|
|
|
this.rafId = requestAnimationFrame(() => {
|
|
try {
|
|
// Filtrer les entrées pour éviter les notifications redondantes
|
|
const validEntries = entries.filter(entry => {
|
|
const element = entry.target;
|
|
const key = element.dataset.resizeKey || element.tagName + element.className;
|
|
const lastSize = this.entries.get(key);
|
|
const currentSize = {
|
|
width: entry.contentRect.width,
|
|
height: entry.contentRect.height
|
|
};
|
|
|
|
// Vérifier si la taille a vraiment changé (avec tolérance)
|
|
if (lastSize) {
|
|
const widthDiff = Math.abs(currentSize.width - lastSize.width);
|
|
const heightDiff = Math.abs(currentSize.height - lastSize.height);
|
|
|
|
// Ignorer les changements minimes (< 1px)
|
|
if (widthDiff < 1 && heightDiff < 1) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
this.entries.set(key, currentSize);
|
|
return true;
|
|
});
|
|
|
|
if (validEntries.length > 0) {
|
|
this.callback(validEntries);
|
|
}
|
|
} catch (error) {
|
|
// Ignorer silencieusement les erreurs ResizeObserver
|
|
if (!error.message.includes('ResizeObserver loop')) {
|
|
console.warn('Erreur ResizeObserver:', error);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
observe(element, options = {}) {
|
|
if (this.observer) {
|
|
// Ajouter une clé unique pour le tracking
|
|
if (!element.dataset.resizeKey) {
|
|
element.dataset.resizeKey = 'resize_' + Math.random().toString(36).substr(2, 9);
|
|
}
|
|
|
|
try {
|
|
this.observer.observe(element, options);
|
|
this.isObserving = true;
|
|
} catch (error) {
|
|
console.warn('Erreur lors de l\\'observation:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
unobserve(element) {
|
|
if (this.observer) {
|
|
try {
|
|
this.observer.unobserve(element);
|
|
|
|
// Nettoyer le cache
|
|
const key = element.dataset.resizeKey || element.tagName + element.className;
|
|
this.entries.delete(key);
|
|
} catch (error) {
|
|
console.warn('Erreur lors de l\\'arrêt d\\'observation:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
disconnect() {
|
|
if (this.observer) {
|
|
try {
|
|
this.observer.disconnect();
|
|
this.isObserving = false;
|
|
this.entries.clear();
|
|
|
|
if (this.rafId) {
|
|
cancelAnimationFrame(this.rafId);
|
|
this.rafId = null;
|
|
}
|
|
} catch (error) {
|
|
console.warn('Erreur lors de la déconnexion:', error);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remplacer ResizeObserver global par la version sécurisée
|
|
if (typeof window !== 'undefined' && window.ResizeObserver) {
|
|
window.ResizeObserver = SafeResizeObserver;
|
|
}
|
|
|
|
export default SafeResizeObserver;
|
|
'''
|
|
|
|
polyfill_path = Path("visual_workflow_builder/frontend/src/utils/resizeObserverPolyfill.js")
|
|
polyfill_path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
with open(polyfill_path, 'w', encoding='utf-8') as f:
|
|
f.write(polyfill_content)
|
|
|
|
print(f"✅ Polyfill créé: {polyfill_path}")
|
|
return polyfill_path
|
|
|
|
def fix_app_tsx():
|
|
"""Corrige le fichier App.tsx pour intégrer le polyfill."""
|
|
print_subsection("Correction de App.tsx")
|
|
|
|
app_path = Path("visual_workflow_builder/frontend/src/App.tsx")
|
|
|
|
if not app_path.exists():
|
|
print(f"❌ Fichier non trouvé: {app_path}")
|
|
return False
|
|
|
|
# Lire le contenu actuel
|
|
with open(app_path, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
|
|
# Vérifier si le polyfill est déjà importé
|
|
if 'resizeObserverPolyfill' in content:
|
|
print("⚠️ Polyfill déjà importé dans App.tsx")
|
|
return True
|
|
|
|
# Ajouter l'import du polyfill au début du fichier
|
|
import_line = "import './utils/resizeObserverPolyfill.js';\n"
|
|
|
|
# Trouver la position après les imports React
|
|
lines = content.split('\n')
|
|
insert_position = 0
|
|
|
|
for i, line in enumerate(lines):
|
|
if line.strip().startswith('import') and 'react' in line.lower():
|
|
insert_position = i + 1
|
|
elif line.strip().startswith('import') and not line.strip().startswith('import '):
|
|
break
|
|
|
|
# Insérer l'import
|
|
lines.insert(insert_position, import_line.rstrip())
|
|
|
|
# Réécrire le fichier
|
|
new_content = '\n'.join(lines)
|
|
with open(app_path, 'w', encoding='utf-8') as f:
|
|
f.write(new_content)
|
|
|
|
print(f"✅ App.tsx mis à jour avec le polyfill")
|
|
return True
|
|
|
|
def create_error_boundary():
|
|
"""Crée un Error Boundary pour capturer les erreurs ResizeObserver."""
|
|
print_subsection("Création d'un Error Boundary")
|
|
|
|
error_boundary_content = '''/**
|
|
* Error Boundary pour capturer les erreurs ResizeObserver
|
|
*
|
|
* Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
*/
|
|
|
|
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
|
|
|
interface Props {
|
|
children: ReactNode;
|
|
fallback?: ReactNode;
|
|
}
|
|
|
|
interface State {
|
|
hasError: boolean;
|
|
error?: Error;
|
|
}
|
|
|
|
class ResizeObserverErrorBoundary extends Component<Props, State> {
|
|
constructor(props: Props) {
|
|
super(props);
|
|
this.state = { hasError: false };
|
|
}
|
|
|
|
static getDerivedStateFromError(error: Error): State {
|
|
// Vérifier si c'est une erreur ResizeObserver
|
|
if (error.message && error.message.includes('ResizeObserver loop')) {
|
|
// Ignorer cette erreur spécifique
|
|
return { hasError: false };
|
|
}
|
|
|
|
// Pour les autres erreurs, afficher l'état d'erreur
|
|
return { hasError: true, error };
|
|
}
|
|
|
|
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
|
// Ignorer les erreurs ResizeObserver
|
|
if (error.message && error.message.includes('ResizeObserver loop')) {
|
|
return;
|
|
}
|
|
|
|
// Logger les autres erreurs
|
|
console.error('Error Boundary a capturé une erreur:', error, errorInfo);
|
|
}
|
|
|
|
render() {
|
|
if (this.state.hasError) {
|
|
// Interface de fallback personnalisée
|
|
return this.props.fallback || (
|
|
<div style={{
|
|
padding: '20px',
|
|
margin: '20px',
|
|
border: '1px solid #ff6b6b',
|
|
borderRadius: '8px',
|
|
backgroundColor: '#ffe0e0',
|
|
color: '#d63031'
|
|
}}>
|
|
<h3>⚠️ Une erreur s'est produite</h3>
|
|
<p>L'application a rencontré une erreur inattendue.</p>
|
|
<button
|
|
onClick={() => this.setState({ hasError: false, error: undefined })}
|
|
style={{
|
|
padding: '8px 16px',
|
|
backgroundColor: '#d63031',
|
|
color: 'white',
|
|
border: 'none',
|
|
borderRadius: '4px',
|
|
cursor: 'pointer'
|
|
}}
|
|
>
|
|
Réessayer
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return this.props.children;
|
|
}
|
|
}
|
|
|
|
export default ResizeObserverErrorBoundary;
|
|
'''
|
|
|
|
boundary_path = Path("visual_workflow_builder/frontend/src/components/ResizeObserverErrorBoundary/index.tsx")
|
|
boundary_path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
with open(boundary_path, 'w', encoding='utf-8') as f:
|
|
f.write(error_boundary_content)
|
|
|
|
print(f"✅ Error Boundary créé: {boundary_path}")
|
|
return boundary_path
|
|
|
|
def fix_index_tsx():
|
|
"""Corrige le fichier index.tsx pour intégrer l'Error Boundary."""
|
|
print_subsection("Correction de index.tsx")
|
|
|
|
index_path = Path("visual_workflow_builder/frontend/src/index.tsx")
|
|
|
|
if not index_path.exists():
|
|
# Essayer index.js
|
|
index_path = Path("visual_workflow_builder/frontend/src/index.js")
|
|
if not index_path.exists():
|
|
print(f"❌ Fichier index non trouvé")
|
|
return False
|
|
|
|
# Lire le contenu actuel
|
|
with open(index_path, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
|
|
# Vérifier si l'Error Boundary est déjà importé
|
|
if 'ResizeObserverErrorBoundary' in content:
|
|
print("⚠️ Error Boundary déjà importé dans index.tsx")
|
|
return True
|
|
|
|
# Ajouter l'import de l'Error Boundary
|
|
import_line = "import ResizeObserverErrorBoundary from './components/ResizeObserverErrorBoundary';\n"
|
|
|
|
# Trouver où insérer l'import
|
|
lines = content.split('\n')
|
|
insert_position = 0
|
|
|
|
for i, line in enumerate(lines):
|
|
if line.strip().startswith('import') and './App' in line:
|
|
insert_position = i + 1
|
|
break
|
|
|
|
# Insérer l'import
|
|
lines.insert(insert_position, import_line.rstrip())
|
|
|
|
# Envelopper l'App dans l'Error Boundary
|
|
new_content = '\n'.join(lines)
|
|
new_content = new_content.replace(
|
|
'<App />',
|
|
'<ResizeObserverErrorBoundary><App /></ResizeObserverErrorBoundary>'
|
|
)
|
|
new_content = new_content.replace(
|
|
'<App/>',
|
|
'<ResizeObserverErrorBoundary><App /></ResizeObserverErrorBoundary>'
|
|
)
|
|
|
|
# Réécrire le fichier
|
|
with open(index_path, 'w', encoding='utf-8') as f:
|
|
f.write(new_content)
|
|
|
|
print(f"✅ {index_path.name} mis à jour avec l'Error Boundary")
|
|
return True
|
|
|
|
def create_webpack_config_fix():
|
|
"""Crée une configuration webpack pour supprimer les erreurs ResizeObserver."""
|
|
print_subsection("Configuration Webpack")
|
|
|
|
webpack_config = '''/**
|
|
* Configuration Webpack pour supprimer les erreurs ResizeObserver
|
|
*
|
|
* Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
*/
|
|
|
|
const path = require('path');
|
|
|
|
module.exports = {
|
|
// Configuration pour supprimer les warnings ResizeObserver
|
|
stats: {
|
|
warningsFilter: [
|
|
/ResizeObserver loop completed with undelivered notifications/,
|
|
/ResizeObserver loop limit exceeded/
|
|
]
|
|
},
|
|
|
|
// Plugin pour ignorer les erreurs ResizeObserver en développement
|
|
plugins: [
|
|
{
|
|
apply: (compiler) => {
|
|
compiler.hooks.done.tap('ResizeObserverErrorFilter', (stats) => {
|
|
if (stats.compilation.errors) {
|
|
stats.compilation.errors = stats.compilation.errors.filter(error => {
|
|
return !error.message.includes('ResizeObserver loop');
|
|
});
|
|
}
|
|
|
|
if (stats.compilation.warnings) {
|
|
stats.compilation.warnings = stats.compilation.warnings.filter(warning => {
|
|
return !warning.message.includes('ResizeObserver loop');
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
],
|
|
|
|
// Configuration du dev server
|
|
devServer: {
|
|
client: {
|
|
overlay: {
|
|
errors: true,
|
|
warnings: false,
|
|
runtimeErrors: (error) => {
|
|
// Filtrer les erreurs ResizeObserver
|
|
if (error.message && error.message.includes('ResizeObserver loop')) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
'''
|
|
|
|
config_path = Path("visual_workflow_builder/frontend/webpack.config.resizeobserver.js")
|
|
|
|
with open(config_path, 'w', encoding='utf-8') as f:
|
|
f.write(webpack_config)
|
|
|
|
print(f"✅ Configuration Webpack créée: {config_path}")
|
|
return config_path
|
|
|
|
def fix_package_json():
|
|
"""Met à jour package.json pour utiliser la configuration webpack."""
|
|
print_subsection("Mise à jour de package.json")
|
|
|
|
package_path = Path("visual_workflow_builder/frontend/package.json")
|
|
|
|
if not package_path.exists():
|
|
print(f"❌ package.json non trouvé: {package_path}")
|
|
return False
|
|
|
|
try:
|
|
import json
|
|
|
|
# Lire package.json
|
|
with open(package_path, 'r', encoding='utf-8') as f:
|
|
package_data = json.load(f)
|
|
|
|
# Ajouter les scripts avec la configuration webpack
|
|
if 'scripts' not in package_data:
|
|
package_data['scripts'] = {}
|
|
|
|
# Sauvegarder les scripts existants et ajouter les nouveaux
|
|
original_start = package_data['scripts'].get('start', 'react-scripts start')
|
|
original_build = package_data['scripts'].get('build', 'react-scripts build')
|
|
|
|
package_data['scripts']['start:safe'] = f"GENERATE_SOURCEMAP=false {original_start}"
|
|
package_data['scripts']['build:safe'] = f"GENERATE_SOURCEMAP=false {original_build}"
|
|
|
|
# Ajouter des variables d'environnement pour supprimer les warnings
|
|
if 'scripts' in package_data:
|
|
for script_name in ['start', 'start:safe']:
|
|
if script_name in package_data['scripts']:
|
|
script = package_data['scripts'][script_name]
|
|
if 'DISABLE_ESLINT_PLUGIN=true' not in script:
|
|
package_data['scripts'][script_name] = f"DISABLE_ESLINT_PLUGIN=true {script}"
|
|
|
|
# Écrire le fichier mis à jour
|
|
with open(package_path, 'w', encoding='utf-8') as f:
|
|
json.dump(package_data, f, indent=2, ensure_ascii=False)
|
|
|
|
print(f"✅ package.json mis à jour")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"❌ Erreur lors de la mise à jour de package.json: {e}")
|
|
return False
|
|
|
|
def create_env_file():
|
|
"""Crée un fichier .env pour désactiver les warnings."""
|
|
print_subsection("Création du fichier .env")
|
|
|
|
env_content = '''# Configuration pour supprimer les erreurs ResizeObserver
|
|
# Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
|
|
# Désactiver les warnings ESLint
|
|
DISABLE_ESLINT_PLUGIN=true
|
|
|
|
# Désactiver la génération de source maps (améliore les performances)
|
|
GENERATE_SOURCEMAP=false
|
|
|
|
# Désactiver les warnings de développement
|
|
REACT_APP_DISABLE_DEV_WARNINGS=true
|
|
|
|
# Configuration pour les erreurs ResizeObserver
|
|
REACT_APP_IGNORE_RESIZE_OBSERVER_ERRORS=true
|
|
'''
|
|
|
|
env_path = Path("visual_workflow_builder/frontend/.env")
|
|
|
|
with open(env_path, 'w', encoding='utf-8') as f:
|
|
f.write(env_content)
|
|
|
|
print(f"✅ Fichier .env créé: {env_path}")
|
|
return env_path
|
|
|
|
def create_test_script():
|
|
"""Crée un script de test pour vérifier la correction."""
|
|
print_subsection("Création du script de test")
|
|
|
|
test_script = '''#!/usr/bin/env python3
|
|
"""
|
|
Test de la correction des erreurs ResizeObserver
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
import subprocess
|
|
import time
|
|
import sys
|
|
import os
|
|
from pathlib import Path
|
|
|
|
def test_frontend_build():
|
|
"""Test la compilation du frontend."""
|
|
print("🧪 Test de compilation du frontend...")
|
|
|
|
frontend_path = Path("visual_workflow_builder/frontend")
|
|
if not frontend_path.exists():
|
|
print("❌ Répertoire frontend non trouvé")
|
|
return False
|
|
|
|
try:
|
|
# Test de compilation
|
|
result = subprocess.run(
|
|
["npm", "run", "build"],
|
|
cwd=frontend_path,
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=120
|
|
)
|
|
|
|
if result.returncode == 0:
|
|
print("✅ Compilation réussie")
|
|
return True
|
|
else:
|
|
print(f"❌ Erreur de compilation: {result.stderr}")
|
|
return False
|
|
|
|
except subprocess.TimeoutExpired:
|
|
print("⏰ Timeout lors de la compilation")
|
|
return False
|
|
except Exception as e:
|
|
print(f"❌ Erreur: {e}")
|
|
return False
|
|
|
|
def test_files_exist():
|
|
"""Vérifie que tous les fichiers de correction existent."""
|
|
print("🧪 Vérification des fichiers de correction...")
|
|
|
|
required_files = [
|
|
"visual_workflow_builder/frontend/src/utils/resizeObserverPolyfill.js",
|
|
"visual_workflow_builder/frontend/src/components/ResizeObserverErrorBoundary/index.tsx",
|
|
"visual_workflow_builder/frontend/.env",
|
|
"visual_workflow_builder/frontend/webpack.config.resizeobserver.js"
|
|
]
|
|
|
|
all_exist = True
|
|
for file_path in required_files:
|
|
if Path(file_path).exists():
|
|
print(f"✅ {file_path}")
|
|
else:
|
|
print(f"❌ {file_path} - MANQUANT")
|
|
all_exist = False
|
|
|
|
return all_exist
|
|
|
|
def main():
|
|
"""Fonction principale de test."""
|
|
print("=" * 60)
|
|
print(" TEST CORRECTION RESIZEOBSERVER")
|
|
print("=" * 60)
|
|
print("Auteur : Dom, Alice, Kiro - 08 janvier 2026")
|
|
print()
|
|
|
|
tests = [
|
|
("Fichiers de correction", test_files_exist),
|
|
("Compilation frontend", test_frontend_build)
|
|
]
|
|
|
|
passed = 0
|
|
total = len(tests)
|
|
|
|
for test_name, test_func in tests:
|
|
print(f"\\n{'-'*40}")
|
|
print(f" {test_name}")
|
|
print(f"{'-'*40}")
|
|
|
|
if test_func():
|
|
passed += 1
|
|
print(f"✅ {test_name} - PASSÉ")
|
|
else:
|
|
print(f"❌ {test_name} - ÉCHOUÉ")
|
|
|
|
print("\\n" + "=" * 60)
|
|
print(" RÉSUMÉ")
|
|
print("=" * 60)
|
|
|
|
success_rate = (passed / total) * 100
|
|
print(f"Tests passés: {passed}/{total} ({success_rate:.1f}%)")
|
|
|
|
if passed == total:
|
|
print("🎉 CORRECTION RÉUSSIE!")
|
|
print("Les erreurs ResizeObserver ont été corrigées.")
|
|
print()
|
|
print("Pour démarrer le frontend:")
|
|
print(" cd visual_workflow_builder/frontend")
|
|
print(" npm start")
|
|
return True
|
|
else:
|
|
print("⚠️ Certains tests ont échoué")
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
success = main()
|
|
sys.exit(0 if success else 1)
|
|
'''
|
|
|
|
test_path = Path("test_resizeobserver_fix.py")
|
|
with open(test_path, 'w', encoding='utf-8') as f:
|
|
f.write(test_script)
|
|
|
|
print(f"✅ Script de test créé: {test_path}")
|
|
return test_path
|
|
|
|
def main():
|
|
"""Fonction principale de correction."""
|
|
print_section("CORRECTION DES ERREURS RESIZEOBSERVER")
|
|
print("Auteur : Dom, Alice, Kiro - 08 janvier 2026")
|
|
|
|
# Vérifier que nous sommes dans le bon répertoire
|
|
if not Path("visual_workflow_builder/frontend").exists():
|
|
print("❌ Erreur: Répertoire frontend introuvable")
|
|
print(" Exécutez ce script depuis la racine du projet")
|
|
return False
|
|
|
|
# Appliquer les corrections
|
|
corrections = [
|
|
("Polyfill ResizeObserver", create_resizeobserver_polyfill),
|
|
("Error Boundary", create_error_boundary),
|
|
("Configuration Webpack", create_webpack_config_fix),
|
|
("Fichier .env", create_env_file),
|
|
("Correction App.tsx", fix_app_tsx),
|
|
("Correction index.tsx", fix_index_tsx),
|
|
("Mise à jour package.json", fix_package_json),
|
|
("Script de test", create_test_script)
|
|
]
|
|
|
|
success_count = 0
|
|
for name, func in corrections:
|
|
print(f"\\n📝 {name}...")
|
|
try:
|
|
if func():
|
|
success_count += 1
|
|
print(f"✅ {name} - TERMINÉ")
|
|
else:
|
|
print(f"❌ {name} - ÉCHOUÉ")
|
|
except Exception as e:
|
|
print(f"❌ {name} - ERREUR: {e}")
|
|
|
|
print_section("RÉSUMÉ DES CORRECTIONS")
|
|
|
|
if success_count == len(corrections):
|
|
print("🎉 TOUTES LES CORRECTIONS APPLIQUÉES AVEC SUCCÈS!")
|
|
print()
|
|
print("Les erreurs ResizeObserver ont été corrigées:")
|
|
print("✅ Polyfill sécurisé avec debouncing")
|
|
print("✅ Error Boundary pour capturer les erreurs")
|
|
print("✅ Configuration Webpack pour filtrer les warnings")
|
|
print("✅ Variables d'environnement pour désactiver les warnings")
|
|
print()
|
|
print("Pour tester la correction:")
|
|
print("1. cd visual_workflow_builder/frontend")
|
|
print("2. npm install (si nécessaire)")
|
|
print("3. npm start")
|
|
print()
|
|
print("Le navigateur ne devrait plus afficher d'erreurs ResizeObserver!")
|
|
return True
|
|
else:
|
|
print(f"⚠️ {success_count}/{len(corrections)} corrections appliquées")
|
|
print("Certaines corrections ont échoué")
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
success = main()
|
|
sys.exit(0 if success else 1) |