<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Validateur de Workflows n8n</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
padding-top: 20px;
padding-bottom: 20px;
}
.header {
padding-bottom: 20px;
border-bottom: 1px solid #e5e5e5;
margin-bottom: 30px;
}
.workflow-card {
margin-bottom: 20px;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.validation-result {
margin-top: 20px;
padding: 15px;
border-radius: 5px;
}
.validation-success {
background-color: #d4edda;
border: 1px solid #c3e6cb;
color: #155724;
}
.validation-warning {
background-color: #fff3cd;
border: 1px solid #ffeeba;
color: #856404;
}
.validation-error {
background-color: #f8d7da;
border: 1px solid #f5c6cb;
color: #721c24;
}
.nav-link {
color: #495057;
font-weight: 500;
}
.nav-link.active {
color: #007bff;
font-weight: 700;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<div class="d-flex justify-content-between align-items-center">
<h1>Validateur de Workflows n8n</h1>
<nav>
<ul class="nav">
<li class="nav-item"><a href="/" class="nav-link">Accueil</a></li>
<li class="nav-item"><a href="/n8n-api.html" class="nav-link">API n8n</a></li>
<li class="nav-item"><a href="/workflow-manager.html" class="nav-link">Gestionnaire de Workflows</a></li>
<li class="nav-item"><a href="/validator.html" class="nav-link active">Validateur</a></li>
<li class="nav-item"><a href="/templates.html" class="nav-link">Templates</a></li>
<li class="nav-item"><a href="/docs.html" class="nav-link">Documentation</a></li>
</ul>
</nav>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card workflow-card">
<div class="card-header">
<h5>Sélection du Workflow</h5>
</div>
<div class="card-body">
<form id="validation-form">
<div class="mb-3">
<label for="workflow-select" class="form-label">Sélectionnez un workflow</label>
<select class="form-select" id="workflow-select">
<option value="" selected>Chargement des workflows...</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">Validateurs à appliquer</label>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="naming" id="naming-check" checked>
<label class="form-check-label" for="naming-check">
Conventions de nommage
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="errorHandling" id="error-check" checked>
<label class="form-check-label" for="error-check">
Gestion des erreurs
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="security" id="security-check" checked>
<label class="form-check-label" for="security-check">
Sécurité
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="performance" id="performance-check" checked>
<label class="form-check-label" for="performance-check">
Performance
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="documentation" id="documentation-check" checked>
<label class="form-check-label" for="documentation-check">
Documentation
</label>
</div>
</div>
<div class="mb-3">
<label for="strictness-select" class="form-label">Niveau de rigueur</label>
<select class="form-select" id="strictness-select">
<option value="low">Faible</option>
<option value="medium" selected>Moyen</option>
<option value="high">Élevé</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Valider le workflow</button>
</form>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card workflow-card">
<div class="card-header">
<h5>Résultats de la validation</h5>
</div>
<div class="card-body">
<div id="validation-results">
<p class="text-muted">Les résultats de validation s'afficheront ici après analyse.</p>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Charger la liste des workflows
fetchWorkflows();
// Gérer la soumission du formulaire
document.getElementById('validation-form').addEventListener('submit', function(e) {
e.preventDefault();
validateWorkflow();
});
});
async function fetchWorkflows() {
try {
const response = await fetch('/api/workflow-manager', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
action: 'list'
})
});
const data = await response.json();
if (data.success) {
const select = document.getElementById('workflow-select');
select.innerHTML = '';
if (data.workflows.length === 0) {
const option = document.createElement('option');
option.value = '';
option.textContent = 'Aucun workflow disponible';
select.appendChild(option);
} else {
data.workflows.forEach(workflow => {
const option = document.createElement('option');
option.value = workflow.id;
option.textContent = workflow.name;
select.appendChild(option);
});
}
} else {
showError('Erreur lors du chargement des workflows: ' + data.error);
}
} catch (error) {
showError('Erreur de connexion: ' + error.message);
}
}
async function validateWorkflow() {
const workflowId = document.getElementById('workflow-select').value;
if (!workflowId) {
showError('Veuillez sélectionner un workflow à valider.');
return;
}
const validators = [];
document.querySelectorAll('input[type="checkbox"]:checked').forEach(checkbox => {
validators.push(checkbox.value);
});
if (validators.length === 0) {
showError('Veuillez sélectionner au moins un validateur.');
return;
}
const strictness = document.getElementById('strictness-select').value;
try {
const resultsContainer = document.getElementById('validation-results');
resultsContainer.innerHTML = '<p class="text-info">Validation en cours...</p>';
// Simuler une validation (à remplacer par l'appel API réel)
setTimeout(() => {
// Exemple de résultats (à remplacer par les résultats réels)
const results = {
naming: {
status: 'success',
messages: ['Conventions de nommage respectées']
},
errorHandling: {
status: 'warning',
messages: ['Certains nœuds n\'ont pas de gestion d\'erreur']
},
security: {
status: 'error',
messages: ['Informations sensibles non chiffrées', 'Authentification faible']
},
performance: {
status: 'success',
messages: ['Performance optimale']
},
documentation: {
status: 'warning',
messages: ['Documentation incomplète']
}
};
displayResults(results, validators);
}, 1500);
} catch (error) {
showError('Erreur lors de la validation: ' + error.message);
}
}
function displayResults(results, validators) {
const resultsContainer = document.getElementById('validation-results');
resultsContainer.innerHTML = '';
let hasErrors = false;
let hasWarnings = false;
validators.forEach(validator => {
if (results[validator]) {
const result = results[validator];
const resultDiv = document.createElement('div');
resultDiv.className = `validation-result validation-${result.status}`;
const title = document.createElement('h5');
title.textContent = getValidatorName(validator);
resultDiv.appendChild(title);
const list = document.createElement('ul');
result.messages.forEach(message => {
const item = document.createElement('li');
item.textContent = message;
list.appendChild(item);
});
resultDiv.appendChild(list);
resultsContainer.appendChild(resultDiv);
if (result.status === 'error') hasErrors = true;
if (result.status === 'warning') hasWarnings = true;
}
});
// Ajouter un résumé
const summaryDiv = document.createElement('div');
summaryDiv.className = 'mt-4';
const summaryTitle = document.createElement('h5');
summaryTitle.textContent = 'Résumé';
summaryDiv.appendChild(summaryTitle);
const summaryText = document.createElement('p');
if (hasErrors) {
summaryText.className = 'text-danger';
summaryText.textContent = 'Le workflow présente des problèmes critiques qui doivent être corrigés.';
} else if (hasWarnings) {
summaryText.className = 'text-warning';
summaryText.textContent = 'Le workflow présente des avertissements qui pourraient être améliorés.';
} else {
summaryText.className = 'text-success';
summaryText.textContent = 'Le workflow est conforme à toutes les bonnes pratiques !';
}
summaryDiv.appendChild(summaryText);
resultsContainer.appendChild(summaryDiv);
}
function getValidatorName(validator) {
const names = {
naming: 'Conventions de nommage',
errorHandling: 'Gestion des erreurs',
security: 'Sécurité',
performance: 'Performance',
documentation: 'Documentation'
};
return names[validator] || validator;
}
function showError(message) {
const resultsContainer = document.getElementById('validation-results');
resultsContainer.innerHTML = `<div class="alert alert-danger">${message}</div>`;
}
</script>
</body>
</html>