`);
// Ajouter les event listeners pour les boutons
document.getElementById('validate-rephrase')?.addEventListener('click', () => this.validateRephrase());
document.getElementById('cancel-rephrase')?.addEventListener('click', () => this.clearFeedback());
break;
case 'inconsistencies':
result = await this.callAI('/api/ai/check-inconsistencies', { content: contentToUse });
this.showAIFeedback(`Analyse des incohérences
${this.formatAIResponse(result.analysis)}`);
break;
case 'duplications':
result = await this.callAI('/api/ai/check-duplications', { content: contentToUse });
this.showAIFeedback(`Vérification des doublons
${this.formatAIResponse(result.analysis)}`);
break;
case 'advice':
result = await this.callAI('/api/ai/give-advice', { content: contentToUse, domain: 'conception' });
this.showAIFeedback(`Conseils d'amélioration
${this.formatAIResponse(result.advice)}`);
break;
case 'liberty':
// Sauvegarder l'état avant les modifications de l'IA
this.saveState(true);
const count = document.getElementById('liberty-repeat-count')?.value || 3;
const precision = document.getElementById('liberty-precision')?.value || 70;
// Initialiser l'affichage de progression
this.showAIFeedback(`
`;
iterationsDiv.innerHTML += errorHTML;
return;
}
if (data.iteration) {
// Mettre à jour la barre de progression
const totalIterations = parseInt(document.getElementById('liberty-repeat-count')?.value || 3);
const progressPercent = (data.iteration / totalIterations) * 100;
if (progressFill) {
progressFill.style.width = `${progressPercent}%`;
}
// Afficher l'explication de cette itération
const iterationHTML = `
🔄 Itération ${data.iteration}
${this.formatAIResponse(data.explanation)}
`;
iterationsDiv.innerHTML += iterationHTML;
// Mettre à jour l'éditeur avec le nouveau markdown si disponible
if (data.markdown && data.markdown !== this.editor.innerText) {
this.editor.innerText = data.markdown;
this.generateTOC();
}
// Scroller vers le bas du feedback pour voir la nouvelle itération
const feedback = document.getElementById('ai-assistant-feedback');
feedback.scrollTop = feedback.scrollHeight;
}
if (data.completed) {
// Finaliser l'affichage
if (progressFill) {
progressFill.style.width = '100%';
}
if (data.finalMarkdown) {
// S'assurer que le contenu final est bien dans l'éditeur
this.editor.innerText = data.finalMarkdown;
this.generateTOC();
// Sauvegarder l'état final
this.saveState(true);
}
// Message de fin
const completedHTML = `
`;
// Scroll vers le haut du feedback pour voir le résultat
feedback.scrollTop = 0;
}
validateRephrase() {
if (!this.lastRephraseData) return;
try {
// Sauvegarder l'état avant la reformulation pour permettre l'undo
this.saveState(true);
// Remplacer le texte dans l'éditeur
const range = this.lastRephraseData.selection.getRangeAt(0);
range.deleteContents();
range.insertNode(document.createTextNode(this.lastRephraseData.rephrased));
// Nettoyer la sélection et régénérer la TOC
window.getSelection().removeAllRanges();
this.generateTOC();
// Sauvegarder l'état après la reformulation
this.saveState(true);
// Afficher un message de succès
this.showNotification('Reformulation appliquée avec succès', 'success');
this.clearFeedback();
// Nettoyer les données
this.lastRephraseData = null;
} catch (error) {
console.error('Erreur application reformulation:', error);
this.showNotification('Erreur lors de l\'application de la reformulation', 'error');
}
}
clearFeedback() {
const feedback = document.getElementById('ai-assistant-feedback');
feedback.innerHTML = `
Assistant IA prêt
Sélectionnez du texte dans l'éditeur et cliquez sur une action pour commencer.
`;
}
ensureEditMode() {
// Si on est en mode preview, forcer le retour en mode édition
if (this.isPreviewMode) {
const previewBtn = document.getElementById('preview-toggle');
// Revenir en mode édition sans utiliser originalContent car on veut le nouveau contenu
this.editor.contentEditable = true;
this.editor.style.background = '';
this.editor.style.border = '';
this.editor.style.borderRadius = '';
// Changer le bouton
if (previewBtn) {
previewBtn.innerHTML = 'Visualiser';
previewBtn.classList.remove('secondary');
previewBtn.classList.add('primary');
}
this.isPreviewMode = false;
}
// S'assurer que l'éditeur est toujours éditable
this.editor.contentEditable = true;
}
showNotification(message, type = 'success') {
const notification = document.createElement('div');
notification.className = `notification ${type}`;
notification.textContent = message;
document.body.appendChild(notification);
setTimeout(() => notification.classList.add('show'), 100);
setTimeout(() => {
notification.classList.remove('show');
setTimeout(() => document.body.removeChild(notification), 300);
}, 3000);
}
async togglePreview() {
const previewBtn = document.getElementById('preview-toggle');
if (!this.isPreviewMode) {
// Passer en mode prévisualisation
this.originalContent = this.editor.innerHTML;
const markdownContent = this.editor.innerText;
// Configurer Marked pour un rendu compatible GitHub
if (typeof marked !== 'undefined') {
marked.setOptions({
breaks: true,
gfm: true,
headerIds: true,
sanitize: false,
smartypants: false
});
}
// Convertir le Markdown en HTML avec Marked (compatible GitHub)
let previewHTML = '';
if (typeof marked !== 'undefined') {
previewHTML = marked.parse(markdownContent);
} else {
// Fallback vers notre parseur maison si Marked n'est pas chargé
previewHTML = this.parseMarkdown(markdownContent);
}
// Désactiver l'édition et appliquer le style preview GitHub
this.editor.contentEditable = false;
this.editor.innerHTML = `
${previewHTML}
`;
this.editor.style.background = '';
this.editor.style.border = '';
this.editor.style.borderRadius = '';
// Traiter les diagrammes Mermaid après le rendu
if (typeof mermaid !== 'undefined') {
try {
mermaid.initialize({
startOnLoad: false,
theme: document.body.classList.contains('dark-theme') ? 'dark' : 'default',
securityLevel: 'loose',
fontFamily: 'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif'
});
// Attendre que le DOM soit prêt pour traiter les diagrammes Mermaid
setTimeout(() => {
const preview = this.editor.querySelector('.markdown-preview');
if (preview) {
// Chercher tous les blocs de code avec la langue 'mermaid'
const mermaidBlocks = preview.querySelectorAll('code.language-mermaid, pre code.language-mermaid');
mermaidBlocks.forEach((block, index) => {
try {
const mermaidCode = block.textContent;
const uniqueId = `mermaid-${Date.now()}-${index}`;
// Créer un div avec l'ID unique pour Mermaid
const mermaidDiv = document.createElement('div');
mermaidDiv.id = uniqueId;
mermaidDiv.className = 'mermaid';
mermaidDiv.textContent = mermaidCode;
// Remplacer le bloc de code par le div Mermaid
const pre = block.closest('pre') || block;
pre.parentNode.replaceChild(mermaidDiv, pre);
// Render le diagramme
mermaid.render(uniqueId + '-svg', mermaidCode).then(({ svg }) => {
mermaidDiv.innerHTML = svg;
}).catch(err => {
console.warn('Erreur rendu Mermaid:', err);
mermaidDiv.innerHTML = `
Erreur de rendu Mermaid: ${err.message}
`;
});
} catch (error) {
console.warn('Erreur traitement Mermaid:', error);
}
});
}
}, 200);
} catch (error) {
console.warn('Erreur initialisation Mermaid:', error);
}
}
// Changer le bouton
previewBtn.innerHTML = 'Éditer';
previewBtn.classList.remove('primary');
previewBtn.classList.add('secondary');
this.isPreviewMode = true;
this.showNotification('Mode prévisualisation activé', 'success');
} else {
// Revenir en mode édition
this.editor.contentEditable = true;
this.editor.innerHTML = this.originalContent;
this.editor.style.background = '';
this.editor.style.border = '';
this.editor.style.borderRadius = '';
// Changer le bouton
previewBtn.innerHTML = 'Visualiser';
previewBtn.classList.remove('secondary');
previewBtn.classList.add('primary');
this.isPreviewMode = false;
this.showNotification('Mode édition activé', 'success');
}
}
}
// Gestion des panneaux latéraux
function togglePanel(side) {
const panel = document.getElementById(`${side}-panel`);
const overlay = document.getElementById('panel-overlay');
const otherPanel = document.getElementById(side === 'left' ? 'right-panel' : 'left-panel');
// Fermer l'autre panneau s'il est ouvert
if (otherPanel && otherPanel.classList.contains('open')) {
otherPanel.classList.remove('open');
}
// Toggle le panneau actuel
if (panel.classList.contains('open')) {
panel.classList.remove('open');
overlay.classList.remove('active');
} else {
panel.classList.add('open');
overlay.classList.add('active');
}
}
function closeAllPanels() {
const leftPanel = document.getElementById('left-panel');
const rightPanel = document.getElementById('right-panel');
const overlay = document.getElementById('panel-overlay');
if (leftPanel) leftPanel.classList.remove('open');
if (rightPanel) rightPanel.classList.remove('open');
if (overlay) overlay.classList.remove('active');
}
// Fermer les panneaux avec Escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
closeAllPanels();
}
});
// Initialisation de l'application
let app;
document.addEventListener('DOMContentLoaded', () => {
app = new ConceptionAssistant();
// Charger le thème sauvegardé
const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'dark') {
document.body.classList.add('dark-theme');
}
// Initialiser les panneaux
initializePanels();
});
function initializePanels() {
// Initialiser la gestion des templates
initializeTemplateForm();
}
function initializeTemplateForm() {
const domainSelect = document.getElementById('domain-select');
const levelSelect = document.getElementById('level-select');
const loadTemplateBtn = document.getElementById('load-template');
// Gestion du changement de domaine
if (domainSelect) {
domainSelect.addEventListener('change', async () => {
const domain = domainSelect.value;
if (!domain) {
levelSelect.disabled = true;
levelSelect.innerHTML = '';
loadTemplateBtn.disabled = true;
return;
}
// Activer le select de niveau
levelSelect.disabled = false;
levelSelect.innerHTML = `
`;
loadTemplateBtn.disabled = true;
});
}
// Gestion du changement de niveau
if (levelSelect) {
levelSelect.addEventListener('change', async () => {
const domain = domainSelect.value;
const level = levelSelect.value;
if (!domain || !level) {
loadTemplateBtn.disabled = true;
return;
}
// Activer le bouton de chargement directement
loadTemplateBtn.disabled = false;
});
}
// Gestion du chargement du template
if (loadTemplateBtn) {
loadTemplateBtn.addEventListener('click', async () => {
const domain = domainSelect.value;
const level = levelSelect.value;
if (!domain || !level) {
app.showNotification('Veuillez sélectionner un domaine et un niveau', 'warning');
return;
}
try {
loadTemplateBtn.classList.add('loading');
const response = await fetch(`/api/templates/${domain}/${level}`);
const result = await response.json();
if (result.success) {
// Charger le template dans l'éditeur
app.editor.innerText = result.data.content;
app.generateTOC();
app.currentJournalId = null; // Nouveau journal
// Réinitialiser l'historique pour le nouveau template
app.undoStack = [result.data.content];
app.redoStack = [];
// S'assurer que l'éditeur est en mode édition
app.ensureEditMode();
app.showNotification(`Template ${domain}/${level} chargé avec succès`, 'success');
closeAllPanels();
} else {
app.showNotification('Erreur lors du chargement du template', 'error');
}
} catch (error) {
console.error('Erreur:', error);
app.showNotification('Erreur lors du chargement du template', 'error');
} finally {
loadTemplateBtn.classList.remove('loading');
}
});
}
}
// S'assurer que togglePanel est accessible globalement
window.togglePanel = togglePanel;