/* ======================================================== EcoleDirecte - 👋 Salut https://github.com/NotANumber-dev/ecoledirecte- Apache 2.0 License - (c) NotANumber-dev, noodlelover1 ======================================================== */ (async () => { try { document.documentElement.innerHTML = ''; document.body.style.backgroundColor = '#000000'; var credentials = JSON.parse(sessionStorage.getItem("credentials")); var token = credentials.payload.authToken; var accounts = JSON.parse(sessionStorage.getItem("accounts")); var id = accounts.payload.accounts[0].id; var apiLogs = []; var debugEnabled = false; var isUpdating = false; function logApiCall(url, responseCode, duration) { if (!debugEnabled) return; apiLogs.unshift({ timestamp: new Date().toLocaleString('fr-FR'), url: url, responseCode: responseCode, duration: duration + "ms" }); if (apiLogs.length > 100) apiLogs.pop(); } async function fetchWithLog(url, options, logUrl) { var startTime = Date.now(); try { var res = await fetch(url, options); var duration = Date.now() - startTime; logApiCall(logUrl || url, res.status, duration); return res; } catch(e) { var duration = Date.now() - startTime; logApiCall(logUrl || url, "ERROR", duration); throw e; } } function fetchWithTimeout(url, options, timeout = 5000) { return Promise.race([ fetch(url, options), new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), timeout) ) ]); } var placeholderWidget = document.createElement('div'); placeholderWidget.id = 'ed-widget-placeholder'; placeholderWidget.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:#0B0B1A;z-index:999998;overflow:auto;color:#FFFFFF;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;'; placeholderWidget.innerHTML = '
Chargement...
'; document.body.appendChild(placeholderWidget); var notesPromise = fetchWithTimeout(`https://api.ecoledirecte.com/v3/eleves/${id}/notes.awp?verbe=get&v=6.17.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({ anneeScolaire: "" })) }, 5000).then(function(res) { return res.ok ? res.json() : { data: { notes: [] } }; }).catch(function() { return { data: { notes: [] } }; }); var devoirsPromise = fetchWithTimeout(`https://api.ecoledirecte.com/v3/Eleves/${id}/cahierdetexte.awp?verbe=get&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }, 5000).then(function(res) { return res.ok ? res.json() : { data: {} }; }).catch(function() { return { data: {} }; }); var espacePromise = fetchWithTimeout(`https://api.ecoledirecte.com/v3/E/${id}/espacestravail.awp?verbe=get&typeModule=espaceTravail&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }, 5000).then(function(res) { return res.ok ? res.json() : { data: [] }; }).catch(function() { return { data: [] }; }); var carnetPromise = fetchWithTimeout(`https://api.ecoledirecte.com/v3/eleves/${id}/eleveCarnetCorrespondance.awp?verbe=get&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }, 5000).then(function(res) { return res.ok ? res.json() : { data: { correspondances: [] } }; }).catch(function() { return { data: { correspondances: [] } }; }); var vieScolairePromise = fetchWithTimeout(`https://api.ecoledirecte.com/v3/eleves/${id}/viescolaire.awp?verbe=get&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }, 5000).then(function(res) { return res.ok ? res.json() : { data: { absencesRetards: [], sanctionsEncouragements: [] } }; }).catch(function() { return { data: { absencesRetards: [], sanctionsEncouragements: [] } }; }); var messagesPromise = fetchWithTimeout(`https://api.ecoledirecte.com/v3/eleves/${id}/messages.awp?verbe=get&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }, 5000).then(function(res) { return res.ok ? res.json() : { data: { messages: { received: [], sent: [], draft: [], archived: [] } } }; }).catch(function() { return { data: { messages: { received: [], sent: [], draft: [], archived: [] } } }; }); var timelinePromise = fetchWithTimeout(`https://api.ecoledirecte.com/v3/eleves/${id}/timeline.awp?verbe=get&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }, 5000).then(function(res) { return res.ok ? res.json() : { data: [] }; }).catch(function() { return { data: [] }; }); var results = await Promise.all([notesPromise, devoirsPromise, espacePromise, carnetPromise, vieScolairePromise, messagesPromise, timelinePromise]); var notesJson = results[0]; var devoirsJson = results[1]; var espaceJson = results[2]; var carnetJson = results[3]; var vieScolaireJson = results[4]; var messagesJson = results[5]; var timelineJson = results[6]; var data = notesJson.data || {}; var originalNotes = data.notes || []; var cahierData = devoirsJson.data || {}; var espaceData = espaceJson.data || []; var carnetData = carnetJson.data || { correspondances: [] }; var vieScolaireData = vieScolaireJson.data || { absencesRetards: [], sanctionsEncouragements: [] }; var messagesData = messagesJson.data || { messages: { received: [], sent: [], draft: [], archived: [] } }; var timelineData = Array.isArray(timelineJson.data) ? timelineJson.data : (Array.isArray(timelineJson) ? timelineJson : []); var loadingWidget = document.createElement('div'); loadingWidget.id = 'ed-loading'; loadingWidget.style.cssText = 'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#1C1C2E;color:#FFFFFF;padding:20px;border-radius:12px;z-index:1000000;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;'; loadingWidget.innerHTML = '
Chargement...
'; document.body.appendChild(loadingWidget); var placeholderElement = document.getElementById('ed-widget-placeholder'); if (placeholderElement) placeholderElement.remove(); var trimesters = { "A001": { name: "1er Trimestre", subjects: {} }, "A002": { name: "2eme Trimestre", subjects: {} }, "A003": { name: "3eme Trimestre", subjects: {} } }; if (data.notes && Array.isArray(data.notes)) { var notesToProcess = data.notes.slice(0, 500); notesToProcess.forEach(function(note) { var valeur = note.valeur; var codePeriode = note.codePeriode; if (valeur && valeur !== "" && valeur !== "NE" && valeur !== "Abs" && trimesters[codePeriode]) { var numericValue = parseFloat(valeur.replace(',', '.')); if (!isNaN(numericValue)) { var noteSur = parseFloat(note.noteSur) || 20; var valueOn20 = (numericValue / noteSur) * 20; var subject = note.libelleMatiere; var coefficient = parseFloat(note.coef) || 1; if (!trimesters[codePeriode].subjects[subject]) { trimesters[codePeriode].subjects[subject] = { sum: 0, coefSum: 0, count: 0 }; } trimesters[codePeriode].subjects[subject].sum += valueOn20 * coefficient; trimesters[codePeriode].subjects[subject].coefSum += coefficient; trimesters[codePeriode].subjects[subject].count++; } } }); } Object.keys(trimesters).forEach(function(tri) { Object.keys(trimesters[tri].subjects).forEach(function(subject) { var subj = trimesters[tri].subjects[subject]; subj.average = subj.sum / subj.coefSum; }); }); var loadingElement = document.getElementById('ed-loading'); if (loadingElement) loadingElement.remove(); var existingWidget = document.getElementById('ed-widget'); if (existingWidget) existingWidget.remove(); var widget = document.createElement('div'); widget.id = 'ed-widget'; widget.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:#0B0B1A;z-index:999999;overflow:auto;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;'; var currentTab = "home"; var currentTrimester = "A001"; var dayDetailsCache = {}; var previousView = null; var currentSpaceId = null; var currentPath = []; document.body.appendChild(widget); setTimeout(function() { function chooseDefaultTrimester() { var available = Object.keys(trimesters).filter(function(tri) { return Object.keys(trimesters[tri].subjects).length > 0; }); return available.length > 0 ? available[available.length - 1] : "A001"; } currentTrimester = chooseDefaultTrimester(); function getEncouragementMessage(average) { if (average === null || isNaN(average)) return "Pret a commencer l'annee !"; var messages = []; if (average >= 0 && average < 5) messages = ["Là, va falloir bosser", "Le bon coté des choses, c'est que tu peux difficilement faire pire", "Attention a ne pas faire tomber ta moyenne en negatif"]; else if (average >= 5 && average < 10) messages = ["Euuuuuuuuuuuuuh", "Bah fais tes devoirs aussi", "Pense a ton futur"]; else if (average >= 10 && average < 13) messages = ["Au moins tu as une moyenne à 2 chiffre", "Arrête de jouer à Valo", "Dis toi que c'est 10/10 et pas 10/20"]; else if (average >= 13 && average < 15) messages = ["Bon bah c ok", "Lache pas trop quand meme", "Dis toi que l'art et la musique ne comptent pas au exams"]; else if (average >= 15 && average < 17) messages = ["Bon travail ! Tu peux geekhumtravailler !", "Vzy t chill", "async function etreAuTop()"]; else if (average >= 17 && average < 18.5) messages = ["Cool cool cool", "T bien soigné", "Bravo, tu es au top !"]; else if (average >= 18.5 && average < 20) messages = ["Faut pas copier sur tes voisins tu sais ?", "Bon amuse toi un peu", "L3G3ND3"]; else if (average === 20) messages = ["Tu as cheat comment ?"]; if (messages.length > 0) return messages[Math.floor(Math.random() * messages.length)]; return "Continue tes efforts !"; } function getGradeColor(avg) { if (avg === null || isNaN(avg)) return '#8E8E93'; if (avg < 10) return '#FF6B6B'; if (avg < 12) return '#FFB340'; if (avg < 14) return '#5E5EFF'; return '#40D9A4'; } function getTimelineCount() { var width = window.innerWidth; if (width < 600) return 1; if (width < 900) return 2; if (width < 1200) return 3; return 4; } function formatDate(dateStr) { var date = new Date(dateStr); var days = ["DIMANCHE", "LUNDI", "MARDI", "MERCREDI", "JEUDI", "VENDREDI", "SAMEDI"]; var months = ["JANVIER", "FEVRIER", "MARS", "AVRIL", "MAI", "JUIN", "JUILLET", "AOUT", "SEPTEMBRE", "OCTOBRE", "NOVEMBRE", "DECEMBRE"]; var dayName = days[date.getDay()]; var dayNum = date.getDate(); var month = months[date.getMonth()]; return { dayName: dayName, date: dayNum + " " + month, fullDate: dateStr }; } function decodeUtf8(str) { if (!str) return ""; try { var bytes = []; for (var i = 0; i < str.length; i++) { bytes.push(str.charCodeAt(i) & 0xFF); } var decoder = new TextDecoder('utf-8'); var decoded = decoder.decode(new Uint8Array(bytes)); var txt = document.createElement('textarea'); txt.innerHTML = decoded; decoded = txt.value; decoded = decoded.replace(/\s+/g, ' ').trim(); return decoded; } catch(e) { return str; } } function decodeContent(str) { if (!str) return ""; try { if (/^[A-Za-z0-9+\/=]+$/.test(str) && str.length % 4 === 0) { try { var base64Decoded = atob(str); var bytes = []; for (var i = 0; i < base64Decoded.length; i++) { bytes.push(base64Decoded.charCodeAt(i) & 0xFF); } var decoder = new TextDecoder('utf-8'); return decoder.decode(new Uint8Array(bytes)); } catch(e) {} } var fixed = str; var fixes = { 'é': 'é', 'è': 'è', 'ê': 'ê', 'ë': 'ë', 'ä': 'ä', 'â': 'â', 'î': 'î', 'ï': 'ï', 'ö': 'ö', 'ù': 'ù', 'û': 'û', 'ü': 'ü', 'ç': 'ç', 'Ø': 'Ø', 'æ': 'æ', 'Ã¥': 'å', 'ã': 'ã', 'ñ': 'ñ', 'à ': 'à', 'á': 'á', 'â': 'â', 'ã': 'ã', '€': '€', '’': "'", '“': '"', '”': '"', '•': '•', '–': '-', '—': '-', '‚': ',', '„': '"', '‹': '<', '›': '>', '‘': "'", '°': '°', '±': '±', '²': '²', '³': '³', 'µ': 'µ', '·': '·', '¹': '¹', 'º': 'º', '¼': '¼', '½': '½', '¾': '¾', '€': '€', '£': '£', 'Â¥': '¥', '§': '§', '©': '©', '®': '®', '™': '™', 'd': "d'", 'l': "l'", 'n': "n'", 's': "s'", 'm': "m'", 't': "t'", 'c': "c'", 'j': "j'", 'qu': "qu'", '': "'" }; for (var wrong in fixes) { while (fixed.indexOf(wrong) !== -1) { fixed = fixed.split(wrong).join(fixes[wrong]); } } return fixed; } catch(e) { return str; } } window.markHomework = function(devoirId, isDone, btn) { if (isUpdating) { alert("Veuillez patienter..."); return; } isUpdating = true; var originalText = btn.textContent; var taskDiv = btn.closest('.task-block') || btn.closest('.task-card'); var statusSpan = taskDiv ? taskDiv.querySelector('.task-status') : null; btn.textContent = "..."; btn.disabled = true; var bodyObj = isDone ? { idDevoirsEffectues: [devoirId], idDevoirsNonEffectues: [] } : { idDevoirsEffectues: [], idDevoirsNonEffectues: [devoirId] }; var formData = new URLSearchParams(); formData.append("data", JSON.stringify(bodyObj)); fetch(`https://api.ecoledirecte.com/v3/Eleves/${id}/cahierdetexte.awp?verbe=put&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: formData.toString() }) .then(res => res.json()) .then(json => { isUpdating = false; if (json.code === 200) { btn.setAttribute('data-done', isDone ? 'true' : 'false'); if (statusSpan) { statusSpan.textContent = isDone ? "FAIT" : "A FAIRE"; statusSpan.style.color = isDone ? "#5E5EFF" : "#FFB340"; } btn.textContent = isDone ? "Non fait" : "Fait"; btn.disabled = false; if (taskDiv) { taskDiv.style.borderLeftColor = isDone ? '#5E5EFF' : '#FFB340'; } for (var dateKey in cahierData) { var tasks = cahierData[dateKey]; for (var i = 0; i < tasks.length; i++) { var task = tasks[i]; var taskId = task.idDevoir || task.id; if (taskId === devoirId) { task.effectue = isDone; if (dayDetailsCache[dateKey]) { for (var j = 0; j < dayDetailsCache[dateKey].length; j++) { var cachedTask = dayDetailsCache[dateKey][j]; var cachedId = cachedTask.idDevoir || cachedTask.id; if (cachedId === devoirId) { cachedTask.effectue = isDone; break; } } } break; } } } var currentDatePill = document.querySelector('#ed-content .date-pill'); if (currentDatePill) { var viewDate = currentDatePill.getAttribute('data-date'); if (viewDate && dayDetailsCache[viewDate]) { for (var i = 0; i < dayDetailsCache[viewDate].length; i++) { var cachedTask = dayDetailsCache[viewDate][i]; var cachedId = cachedTask.idDevoir || cachedTask.id; if (cachedId === devoirId) { cachedTask.effectue = isDone; break; } } } } if (currentTab === 'devoirs') { var visibleTasks = document.querySelectorAll('.task-card'); for (var i = 0; i < visibleTasks.length; i++) { var card = visibleTasks[i]; var cardBtn = card.querySelector('.mark-homework-btn'); if (cardBtn) { var btnId = parseInt(cardBtn.getAttribute('data-id')); if (btnId === devoirId) { var cardStatus = card.querySelector('.task-status'); if (cardStatus) { cardStatus.textContent = isDone ? "FAIT" : "A FAIRE"; cardStatus.style.color = isDone ? "#5E5EFF" : "#FFB340"; } card.style.borderLeftColor = isDone ? '#5E5EFF' : '#FFB340'; cardBtn.setAttribute('data-done', isDone ? 'true' : 'false'); cardBtn.textContent = isDone ? 'Non fait' : 'Fait'; break; } } } } if (currentTab === 'home') { renderHome(); } } else { btn.textContent = originalText; btn.disabled = false; alert("Erreur: " + json.message); } }) .catch(err => { isUpdating = false; btn.textContent = originalText; btn.disabled = false; alert("Erreur: " + err.message); }); }; async function showDayDetails(dateKey) { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; previousView = currentTab; var cachedTasks = dayDetailsCache[dateKey]; if (cachedTasks) { for (var i = 0; i < cachedTasks.length; i++) { var cachedTask = cachedTasks[i]; var taskId = cachedTask.idDevoir || cachedTask.id; if (cahierData[dateKey]) { for (var j = 0; j < cahierData[dateKey].length; j++) { var sourceTask = cahierData[dateKey][j]; var sourceId = sourceTask.idDevoir || sourceTask.id; if (sourceId === taskId) { cachedTask.effectue = sourceTask.effectue; break; } } } } renderDayDetailsView(dateKey, cachedTasks); return; } contentDiv.innerHTML = '

Chargement...

'; try { var startTime = Date.now(); var res = await fetch(`https://api.ecoledirecte.com/v3/Eleves/${id}/cahierdetexte/${dateKey}.awp?verbe=get&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }); var duration = Date.now() - startTime; logApiCall(`Cahier texte ${dateKey}`, res.status, duration); var json = await res.json(); var matieres = json.data.matieres || []; var tasks = []; for (var i = 0; i < matieres.length; i++) { if (matieres[i].aFaire) { var task = matieres[i].aFaire; task.matiere = matieres[i].matiere; task.codeMatiere = matieres[i].codeMatiere; task.interrogation = matieres[i].interrogation || false; if (cahierData[dateKey]) { for (var j = 0; j < cahierData[dateKey].length; j++) { var sourceTask = cahierData[dateKey][j]; var sourceId = sourceTask.idDevoir || sourceTask.id; var taskId = task.idDevoir || task.id; if (sourceId === taskId) { task.effectue = sourceTask.effectue; break; } } } tasks.push(task); } } dayDetailsCache[dateKey] = tasks; renderDayDetailsView(dateKey, tasks); } catch(e) { contentDiv.innerHTML = '

Erreur: ' + e.message + '

'; } } function renderDevoirs() { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; contentDiv.innerHTML = ''; var dates = Object.keys(cahierData).sort(); var hasTasks = false; var html = '
'; for (var d = 0; d < dates.length; d++) { var dateKey = dates[d]; var devoirs = cahierData[dateKey]; var formatted = formatDate(dateKey); var notDoneTasks = []; var doneTasks = []; for (var i = 0; i < devoirs.length; i++) { if (devoirs[i].effectue === false) { notDoneTasks.push(devoirs[i]); } else { doneTasks.push(devoirs[i]); } } var allTasks = notDoneTasks.concat(doneTasks); if (allTasks.length > 0) { hasTasks = true; html += '
'; html += '
'; html += '
' + formatted.dayName + '' + formatted.date + '
'; html += '
' + allTasks.length + ' devoir(s)
'; html += '
'; html += '
'; for (var i = 0; i < allTasks.length; i++) { var task = allTasks[i]; var isDone = (task.effectue === true); var taskType = task.interrogation ? "Interrogation" : "Devoir"; var hasDocs = (task.documentsAFaire === true); var rawContent = ''; if (typeof task.contenu === 'string') { rawContent = task.contenu; } else if (typeof task.aFaire === 'string') { rawContent = task.aFaire; } var taskContent = decodeContent(rawContent); var taskDate = task.donneLe ? new Date(task.donneLe).toLocaleDateString('fr-FR') : formatted.date; var taskId = task.idDevoir || task.id; html += '
'; html += '
'; html += '
' + task.matiere + ' ' + taskType + '
'; html += '
'; html += '' + taskDate + ''; html += '' + (isDone ? 'FAIT' : 'A FAIRE') + ''; html += ''; html += '
'; html += '
'; if (taskContent) { html += '
' + taskContent + '
'; } if (hasDocs) { html += '
'; html += '📎 Pieces jointes disponibles'; html += '
'; } html += '
'; } html += '
'; html += '
'; } } if (!hasTasks) { html += '

Aucun devoir a venir

'; } html += '
'; contentDiv.innerHTML = html; var datePills = document.querySelectorAll('#ed-content .date-pill'); for (var i = 0; i < datePills.length; i++) { datePills[i].addEventListener('click', function(e) { e.stopPropagation(); var dateKey = this.getAttribute('data-date'); showDayDetails(dateKey); }); } var markBtns = document.querySelectorAll('.mark-homework-btn'); for (var i = 0; i < markBtns.length; i++) { markBtns[i].addEventListener('click', function(e) { e.stopPropagation(); var btn = this; var taskId = parseInt(btn.getAttribute('data-id')); var isCurrentlyDone = btn.getAttribute('data-done') === 'true'; window.markHomework(taskId, !isCurrentlyDone, btn); }); } } async function showAttachmentModal(fileId, fileName) { var modal = document.createElement('div'); modal.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.9);z-index:10000000;display:flex;align-items:center;justify-content:center;'; var content = document.createElement('div'); content.style.cssText = 'background:#1C1C2E;border-radius:16px;padding:20px;width:90vw;height:90vh;display:flex;flex-direction:column;'; var header = document.createElement('div'); header.style.cssText = 'display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;'; header.innerHTML = `${fileName}`; var btnGroup = document.createElement('div'); btnGroup.style.cssText = 'display:flex;gap:12px;'; var downloadBtn = document.createElement('a'); downloadBtn.textContent = 'Télécharger'; downloadBtn.style.cssText = 'background:#5E5EFF;color:white;padding:8px 16px;border-radius:8px;text-decoration:none;font-size:14px;opacity:0.4;pointer-events:none;'; var closeBtn = document.createElement('button'); closeBtn.textContent = '✕'; closeBtn.style.cssText = 'background:#2C2C44;border:none;color:white;padding:8px 16px;border-radius:8px;cursor:pointer;'; closeBtn.onclick = function() { modal.remove(); }; btnGroup.appendChild(downloadBtn); btnGroup.appendChild(closeBtn); header.appendChild(btnGroup); var body = document.createElement('div'); body.style.cssText = 'flex:1;display:flex;align-items:center;justify-content:center;background:#0B0B1A;border-radius:12px;overflow:auto;'; body.innerHTML = '
Chargement...
'; content.appendChild(header); content.appendChild(body); modal.appendChild(content); document.body.appendChild(modal); modal.onclick = function(e) { if (e.target === modal) modal.remove(); }; try { var formData = new URLSearchParams(); formData.append("data", JSON.stringify({ forceDownload: 0, anneeMessages: "2025-2026" })); var res = await fetch(`https://api.ecoledirecte.com/v3/telechargement.awp?verbe=get&fichierId=${fileId}&leTypeDeFichier=PIECE_JOINTE&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: formData.toString() }); if (!res.ok) throw new Error('HTTP ' + res.status); var blob = await res.blob(); var blobUrl = URL.createObjectURL(blob); downloadBtn.href = blobUrl; downloadBtn.download = fileName; downloadBtn.style.opacity = '1'; downloadBtn.style.pointerEvents = 'auto'; if (blob.type.startsWith('image/')) { body.innerHTML = ``; } else if (blob.type === 'application/pdf') { body.innerHTML = ``; } else if (blob.type.startsWith('text/')) { var text = await blob.text(); body.innerHTML = `
${text}
`; } else if (blob.type.startsWith('video/')) { body.innerHTML = ``; } else if (blob.type.startsWith('audio/')) { body.innerHTML = ``; } else { body.innerHTML = `
impossible de charger le fichier: non supporté
`; } } catch(err) { body.innerHTML = `
Impossible de charger
`; } } window.showAttachmentModal = showAttachmentModal; function renderDayDetailsView(dateKey, tasks) { var formatted = formatDate(dateKey); var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; var html = '
'; html += ''; html += '
'; html += '

' + formatted.dayName + '

'; html += '

' + formatted.date + '

'; html += '
'; for (var i = 0; i < tasks.length; i++) { var task = tasks[i]; var isDone = (task.effectue === true); var taskType = task.interrogation ? "Interrogation" : "Devoir"; var hasDocs = (task.documents && task.documents.length > 0); var rawContent = typeof task.contenu === 'string' ? task.contenu : ''; var cleanContent = decodeContent(rawContent); var taskId = task.idDevoir || task.id; html += '
'; html += '
'; html += '
' + task.matiere + ' ' + taskType + '
'; html += '
' + (isDone ? 'FAIT' : 'A FAIRE') + ''; html += ''; html += '
'; if (cleanContent) { html += '
' + cleanContent + '
'; } if (task.donneLe) { var givenDate = new Date(task.donneLe); html += '
Donne le: ' + givenDate.toLocaleDateString('fr-FR') + '
'; } if (hasDocs) { html += '
'; html += 'Pièces jointes:'; for (var d = 0; d < task.documents.length; d++) { html += '
📄 ' + task.documents[d].libelle + '
'; } html += '
'; } html += '
'; } html += '
'; contentDiv.innerHTML = html; var btns = document.querySelectorAll('.mark-homework-btn'); for (var i = 0; i < btns.length; i++) { btns[i].addEventListener('click', function(e) { e.stopPropagation(); var btn = this; var taskId = parseInt(btn.getAttribute('data-id')); var isCurrentlyDone = btn.getAttribute('data-done') === 'true'; window.markHomework(taskId, !isCurrentlyDone, btn); }); } } window.goBack = function() { if (previousView === 'devoirs') { renderDevoirs(); } else if (previousView === 'moyennes') { renderMoyennes(); } else { renderDevoirs(); } }; window.goBack = function() { if (previousView === 'devoirs') { renderDevoirs(); } else if (previousView === 'moyennes') { renderMoyennes(); } else { renderDevoirs(); } }; async function showDayDetails(dateKey) { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; previousView = currentTab; if (dayDetailsCache[dateKey]) { renderDayDetailsView(dateKey, dayDetailsCache[dateKey]); return; } contentDiv.innerHTML = '

Chargement...

'; try { var startTime = Date.now(); var res = await fetch(`https://api.ecoledirecte.com/v3/Eleves/${id}/cahierdetexte/${dateKey}.awp?verbe=get&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }); var duration = Date.now() - startTime; logApiCall(`Cahier texte ${dateKey}`, res.status, duration); var json = await res.json(); var matieres = json.data.matieres || []; var tasks = []; for (var i = 0; i < matieres.length; i++) { if (matieres[i].aFaire) { var task = matieres[i].aFaire; task.matiere = matieres[i].matiere; task.codeMatiere = matieres[i].codeMatiere; task.interrogation = matieres[i].interrogation || false; tasks.push(task); } } dayDetailsCache[dateKey] = tasks; renderDayDetailsView(dateKey, tasks); } catch(e) { contentDiv.innerHTML = '

Erreur: ' + e.message + '

'; } } function renderDayDetailsView(dateKey, tasks) { var formatted = formatDate(dateKey); var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; var html = '
'; html += ''; html += '
'; html += '

' + formatted.dayName + '

'; html += '

' + formatted.date + '

'; html += '
'; for (var i = 0; i < tasks.length; i++) { var task = tasks[i]; var isDone = (task.effectue === true); var taskType = task.interrogation ? "Interrogation" : "Devoir"; var hasDocs = (task.documents && task.documents.length > 0); var rawContent = typeof task.contenu === 'string' ? task.contenu : ''; var cleanContent = decodeContent(rawContent); var taskId = task.idDevoir || task.id; html += '
'; html += '
'; html += '
' + task.matiere + ' ' + taskType + '
'; html += '
' + (isDone ? 'FAIT' : 'A FAIRE') + ''; html += ''; html += '
'; if (cleanContent) { html += '
' + cleanContent + '
'; } if (task.donneLe) { var givenDate = new Date(task.donneLe); html += '
Donne le: ' + givenDate.toLocaleDateString('fr-FR') + '
'; } if (hasDocs) { html += '
'; html += 'Pieces jointes:'; for (var d = 0; d < task.documents.length; d++) { html += '
📄 ' + task.documents[d].libelle + '
'; } html += '
'; } html += '
'; } html += '
'; contentDiv.innerHTML = html; var btns = document.querySelectorAll('.mark-homework-btn'); for (var i = 0; i < btns.length; i++) { btns[i].addEventListener('click', function(e) { e.stopPropagation(); var btn = this; var taskId = parseInt(btn.getAttribute('data-id')); var isCurrentlyDone = btn.getAttribute('data-done') === 'true'; window.markHomework(taskId, !isCurrentlyDone, btn); }); } } function renderHome() { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; contentDiv.innerHTML = ''; var currentTrim = trimesters[currentTrimester]; var subjects = Object.keys(currentTrim.subjects).map(function(subject) { var subj = currentTrim.subjects[subject]; return { name: subject, average: subj.average, count: subj.count }; }).sort(function(a, b) { return b.average - a.average; }).slice(0, 4); var previousAvg = null; var avgDiff = null; var diffColor = '#8E8E93'; var diffText = ''; var homeworkCount = 0; var dates = Object.keys(cahierData || {}); for (var i = 0; i < dates.length; i++) { var tasks = cahierData[dates[i]] || []; for (var j = 0; j < tasks.length; j++) { if (tasks[j].effectue === false) homeworkCount++; } } var currentTrimAvg = null; var totalWeighted = 0; var totalCoef = 0; for (var subject in currentTrim.subjects) { var subj = currentTrim.subjects[subject]; totalWeighted += subj.sum; totalCoef += subj.coefSum; } if (totalCoef > 0) { currentTrimAvg = totalWeighted / totalCoef; } var html = ''; html += '
'; html += '
'; html += '
Accueil
'; html += '
'; html += '

EcoleDirecte

'; html += ''; html += '
'; html += '

' + getEncouragementMessage(currentTrimAvg) + '

'; html += '
'; html += '
'; html += '
Devoirs à faire' + homeworkCount + '
'; html += '
Moyenne générale' + (currentTrimAvg !== null ? currentTrimAvg.toFixed(2) : '—') + '
'; html += '
'; html += '' + (currentTrimAvg !== null ? currentTrimAvg.toFixed(2) : '—') + ''; if (diffText) { html += '' + diffText + ''; } html += '
'; html += '
'; html += '
'; if (subjects.length > 0) { html += '
Top matières
'; for (var k = 0; k < subjects.length; k++) { var item = subjects[k]; html += '
' + item.name + '' + item.average.toFixed(2) + '
'; } html += '
'; } html += '
'; // if (timelineData && timelineData.length > 0) { var timelineCount = getTimelineCount(); var displayedTimeline = timelineData.slice(0, timelineCount); html += '
'; html += '
Timeline récente
'; html += '
'; for (var t = 0; t < displayedTimeline.length; t++) { var event = displayedTimeline[t]; var eventDate = event.date ? new Date(event.date).toLocaleDateString('fr-FR') : 'Date inconnue'; var subtitle = event.soustitre || ''; var content = event.contenu || ''; html += '
'; html += '
' + (event.titre || 'Événement') + '
'; if (subtitle) html += '
' + subtitle + '
'; html += '
' + (event.typeElement || '') + '
'; html += '
' + eventDate + '
'; if (content) html += '
' + content + '
'; html += '
'; } html += '
'; html += '
'; // } contentDiv.innerHTML = html; } function renderMoyennes() { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; contentDiv.innerHTML = ''; var triData = trimesters[currentTrimester]; var subjectsList = []; var totalWeighted = 0; var totalCoef = 0; var totalGrades = 0; for (var subject in triData.subjects) { var subj = triData.subjects[subject]; subjectsList.push({ name: subject, average: subj.average, count: subj.count, coefSum: subj.coefSum }); totalWeighted += subj.sum; totalCoef += subj.coefSum; totalGrades += subj.count; } subjectsList.sort(function(a, b) { return b.average - a.average; }); var trimesterAverage = totalCoef > 0 ? (totalWeighted / totalCoef) : null; var allTotalWeighted = 0; var allTotalCoef = 0; var allTotalGrades = 0; for (var tri in trimesters) { for (var sub in trimesters[tri].subjects) { var s = trimesters[tri].subjects[sub]; allTotalWeighted += s.sum; allTotalCoef += s.coefSum; allTotalGrades += s.count; } } var annualAverage = allTotalCoef > 0 ? (allTotalWeighted / allTotalCoef) : null; var html = ''; if (subjectsList.length === 0) { html += '

Aucune note pour ce trimestre

'; } else { html += '
'; html += '
MOYENNE GENERALE
' + trimesterAverage.toFixed(2) + '
Coefficientee
'; html += '
NOMBRE DE NOTES
' + totalGrades + '
Ce trimestre
'; html += '
'; html += '
'; for (var i = 0; i < subjectsList.length; i++) { var sub = subjectsList[i]; var gradeColor = getGradeColor(sub.average); var diff = sub.average - trimesterAverage; var diffColor = getDifferenceColor(diff); var diffText = formatDifference(diff); html += '
'; html += '
'; html += '' + sub.name + ''; html += '' + sub.average.toFixed(2) + ''; html += '
'; html += '
'; html += '' + sub.count + ' note(s)'; html += 'Coeff. ' + sub.coefSum.toFixed(1) + ''; html += '
' + diffText + '
'; html += '
'; html += '
'; } html += '
'; } if (annualAverage !== null) { html += '
'; html += '
MOYENNE ANNUELLE PONDEREE
'; html += '
' + annualAverage.toFixed(2) + '
'; html += '
' + allTotalGrades + ' notes sur toute l annee
'; html += '
'; } contentDiv.innerHTML = html; var subjectCards = contentDiv.querySelectorAll('.subject-card[data-subject]'); for (var i = 0; i < subjectCards.length; i++) { subjectCards[i].addEventListener('click', function() { var subjectName = this.getAttribute('data-subject'); showSubjectGrades(subjectName); }); } } function showSubjectGrades(subjectName) { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; previousView = 'moyennes'; var subjectGrades = originalNotes.filter(function(note) { return note.libelleMatiere === subjectName && note.codePeriode === currentTrimester; }); if (subjectGrades.length === 0) { subjectGrades = originalNotes.filter(function(note) { return note.libelleMatiere === subjectName; }); var trimesterDisplay = 'Toutes les periodes'; } else { var trimesterDisplay = trimesters[currentTrimester].name; } var html = '
'; html += ''; html += '
'; html += '

' + subjectName + '

'; html += '

' + trimesterDisplay + '

'; html += '
'; if (subjectGrades.length === 0) { html += '

Aucune note trouvee pour cette matiere

'; } else { html += '
'; for (var i = 0; i < subjectGrades.length; i++) { var grade = subjectGrades[i]; var gradeValue = grade.valeur; var noteSur = grade.noteSur || 20; var gradeColor = getGradeColor(parseFloat(gradeValue.replace(',', '.')) / noteSur * 20); var dateStr = grade.date || grade.dateSaisie; var formattedDate = dateStr ? new Date(dateStr).toLocaleDateString('fr-FR') : 'Date inconnue'; var commentaire = grade.commentaire || ''; var decodedComment = decodeContent(commentaire); html += '
'; html += '
'; html += '
' + gradeValue + '/' + noteSur + '
'; html += '
' + formattedDate + '
'; if (decodedComment) { html += '
' + decodedComment + '
'; } html += '
'; html += '
'; html += '
' + gradeValue + '
'; html += '
Coeff. ' + (grade.coef || 1) + '
'; html += '
'; html += '
'; } html += '
'; } html += '
'; contentDiv.innerHTML = html; var backButton = document.getElementById('back-to-moyennes'); if (backButton) { backButton.addEventListener('click', function() { renderMoyennes(); }); } } function getDifferenceColor(diff) { if (diff > 0) return '#40D9A4'; if (diff < 0) return '#FF6B6B'; return '#8E8E93'; } function formatDifference(diff) { if (diff > 0) return '+' + diff.toFixed(2); if (diff < 0) return diff.toFixed(2); return '0.00'; } function renderDevoirs() { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; contentDiv.innerHTML = ''; var dates = Object.keys(cahierData).sort(); var hasTasks = false; var html = '
'; for (var d = 0; d < dates.length; d++) { var dateKey = dates[d]; var devoirs = cahierData[dateKey]; var formatted = formatDate(dateKey); var notDoneTasks = []; var doneTasks = []; for (var i = 0; i < devoirs.length; i++) { if (devoirs[i].effectue === false) { notDoneTasks.push(devoirs[i]); } else { doneTasks.push(devoirs[i]); } } var allTasks = notDoneTasks.concat(doneTasks); if (allTasks.length > 0) { hasTasks = true; html += '
'; html += '
'; html += '
' + formatted.dayName + '' + formatted.date + '
'; html += '
' + allTasks.length + ' devoir(s)
'; html += '
'; html += '
'; for (var i = 0; i < allTasks.length; i++) { var task = allTasks[i]; var isDone = (task.effectue === true); var taskType = task.interrogation ? "Interrogation" : "Devoir"; var hasDocs = (task.documentsAFaire === true); var rawContent = ''; if (typeof task.contenu === 'string') { rawContent = task.contenu; } else if (typeof task.aFaire === 'string') { rawContent = task.aFaire; } var taskContent = decodeContent(rawContent); var taskDate = task.donneLe ? new Date(task.donneLe).toLocaleDateString('fr-FR') : formatted.date; html += '
'; html += '
'; html += '
' + task.matiere + ' ' + taskType + '
'; html += '
' + taskDate + '' + (isDone ? 'FAIT' : 'A FAIRE') + '
'; html += '
'; if (taskContent) { html += '
' + taskContent + '
'; } if (hasDocs) { html += '
'; html += '📎 Pieces jointes disponibles'; html += '
'; } html += '
'; } html += '
'; html += '
'; } } if (!hasTasks) { html += '

Aucun devoir a venir

'; } html += '
'; contentDiv.innerHTML = html; var datePills = document.querySelectorAll('#ed-content .date-pill'); for (var i = 0; i < datePills.length; i++) { datePills[i].addEventListener('click', function(e) { e.stopPropagation(); var dateKey = this.getAttribute('data-date'); showDayDetails(dateKey); }); } } function isActuallySigned(msg) { if (!msg.signature) return false; if (Array.isArray(msg.signature)) { if (msg.signature.length === 0) return false; for (var i = 0; i < msg.signature.length; i++) { var sig = msg.signature[i]; if (sig.dateValidation && sig.dateValidation !== "") return true; if (sig.datevalidation && sig.datevalidation !== "") return true; } return false; } if (typeof msg.signature === 'object') { if (msg.signature.dateValidation && msg.signature.dateValidation !== "") return true; if (msg.signature.datevalidation && msg.signature.datevalidation !== "") return true; } return false; } function hasSignatureOption(msg) { return msg.isSignatureDemandee === true; } function getSignature(msg) { if (!msg.signature) return null; if (Array.isArray(msg.signature) && msg.signature.length > 0) { return msg.signature[0]; } if (typeof msg.signature === 'object') { return msg.signature; } return null; } function renderCarnet() { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; contentDiv.innerHTML = ''; var correspondances = carnetData.correspondances || []; function highlightText(text, searchTerm) { if (!searchTerm || searchTerm.trim() === "") return text; var regex = new RegExp('(' + searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + ')', 'gi'); return text.replace(regex, '$1'); } var html = '
'; html += ''; html += '
'; html += '
'; contentDiv.innerHTML = html; function renderMessages(filterText, filterType) { var messagesDiv = document.getElementById('carnetMessages'); if (!messagesDiv) return; var filtered = correspondances.filter(function(msg) { var auteur = msg.auteur || {}; var auteurName = ((auteur.nom || "") + " " + (auteur.prenom || "")).toLowerCase(); var content = (msg.contenu || "").toLowerCase(); var date = (msg.dateCreation || "").toLowerCase(); var searchLower = filterText.toLowerCase(); var matchesSearch = filterText === "" || auteurName.indexOf(searchLower) !== -1 || content.indexOf(searchLower) !== -1 || date.indexOf(searchLower) !== -1; var isSigned = isActuallySigned(msg); var matchesFilter = true; if (filterType === "signed") matchesFilter = isSigned; if (filterType === "unsigned") matchesFilter = hasSignatureOption(msg) && !isSigned; return matchesSearch && matchesFilter; }); if (filtered.length === 0) { messagesDiv.innerHTML = '

Aucun message trouve

'; return; } var html = ''; for (var i = 0; i < filtered.length; i++) { var msg = filtered[i]; var date = msg.dateCreation || ""; var formattedDate = date.replace(/-/g, '/').substring(0, 16); var isSigned = isActuallySigned(msg); var hasOption = hasSignatureOption(msg); var sig = getSignature(msg); var auteur = msg.auteur || {}; var auteurName = (auteur.nom || "") + " " + (auteur.prenom || ""); var cleanContent = decodeContent(msg.contenu || ""); var hasAttachment = msg.urlFichier && msg.urlFichier !== ""; var highlightedName = filterText ? highlightText(auteurName, filterText) : auteurName; var highlightedContent = filterText ? highlightText(cleanContent, filterText) : cleanContent; var highlightedDate = filterText ? highlightText(formattedDate, filterText) : formattedDate; var borderColor = '#2C2C44'; if (isSigned) borderColor = '#5E5EFF'; else if (hasOption) borderColor = '#FFB340'; html += '
'; html += '
'; html += '
' + highlightedName + ' (' + (msg.type || "") + ')
'; html += '
' + highlightedDate + '
'; html += '
'; html += '
' + highlightedContent + '
'; html += '
'; if (isSigned && sig) { var sigDate = sig.dateValidation || sig.datevalidation || ""; sigDate = sigDate.replace(/-/g, '/').substring(0, 16); var sigName = (sig.nom || "") + " " + (sig.prenom || ""); var highlightedSigName = filterText ? highlightText(sigName, filterText) : sigName; var highlightedSigDate = filterText ? highlightText(sigDate, filterText) : sigDate; html += '✓ Signe par ' + highlightedSigName + ' le ' + highlightedSigDate + ''; } else if (hasOption) { html += '○ En attente de signature'; } if (hasAttachment) { html += ''; } html += '
'; } messagesDiv.innerHTML = html; var attachBtns = document.querySelectorAll('.attachment-btn'); for (var i = 0; i < attachBtns.length; i++) { attachBtns[i].addEventListener('click', function(e) { e.stopPropagation(); alert("Piece jointe disponible. Veuillez utiliser l'application Ecole Directe ou le site web pour y acceder."); }); } } var searchInput = document.getElementById('carnetSearch'); var clearBtn = document.getElementById('clearSearch'); var currentFilter = "all"; function updateMessages() { var searchText = searchInput ? searchInput.value : ""; renderMessages(searchText, currentFilter); } if (searchInput) { searchInput.addEventListener('input', updateMessages); } if (clearBtn) { clearBtn.addEventListener('click', function() { if (searchInput) searchInput.value = ""; updateMessages(); }); } var filterBtns = document.querySelectorAll('.filter-btn'); for (var i = 0; i < filterBtns.length; i++) { filterBtns[i].addEventListener('click', function() { currentFilter = this.getAttribute('data-filter'); for (var j = 0; j < filterBtns.length; j++) { filterBtns[j].style.opacity = "0.6"; } this.style.opacity = "1"; updateMessages(); }); filterBtns[i].style.opacity = i === 0 ? "1" : "0.6"; } renderMessages("", "all"); } function renderVieScolaire() { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; contentDiv.innerHTML = ''; var absencesRetards = vieScolaireData.absencesRetards || []; var sanctionsEncouragements = vieScolaireData.sanctionsEncouragements || []; var absences = absencesRetards.filter(function(item) { return item.typeElement === "Absence"; }); var retards = absencesRetards.filter(function(item) { return item.typeElement === "Retard"; }); var repas = absencesRetards.filter(function(item) { return item.typeElement === "Repas"; }); var punitions = sanctionsEncouragements.filter(function(item) { return item.typeElement === "Punition"; }); var encouragements = sanctionsEncouragements.filter(function(item) { return item.typeElement === "Encouragement"; }); var html = '
'; if (absences.length > 0) { html += '
'; html += '

Absences

'; for (var i = 0; i < absences.length; i++) { var a = absences[i]; html += '
'; html += '
' + a.displayDate + '
'; html += '
' + a.libelle + '
'; html += '
' + (a.justifie ? '✓ Justifiee' : '○ Non justifiee') + '
'; if (a.motif && a.motif !== "En attente de motif") { html += '
Motif: ' + a.motif + '
'; } if (a.commentaire && a.commentaire !== "") { html += '
' + a.commentaire.substring(0, 100) + (a.commentaire.length > 100 ? '...' : '') + '
'; } html += '
'; } html += '
'; } if (retards.length > 0) { html += '
'; html += '

Retards

'; for (var i = 0; i < retards.length; i++) { var r = retards[i]; var isJustified = r.justifie === true; html += '
'; html += '
'; html += '' + r.displayDate + ''; if (!isJustified) { html += '⚠️'; } html += '
'; html += '
Duree: ' + r.libelle + '
'; html += '
' + (isJustified ? '✓ Justifie' : '⚠️ Non justifie') + '
'; if (r.motif && r.motif !== "En attente de motif") { html += '
Motif: ' + r.motif + '
'; } html += '
'; } html += '
'; } if (repas.length > 0) { html += '
'; html += '

Absences cantine

'; for (var i = 0; i < repas.length; i++) { var rp = repas[i]; html += '
'; html += '
' + rp.displayDate + '
'; html += '
' + rp.libelle + '
'; html += '
○ Absent
'; if (rp.commentaire && rp.commentaire !== "") { html += '
' + rp.commentaire.substring(0, 100) + (rp.commentaire.length > 100 ? '...' : '') + '
'; } html += '
'; } html += '
'; } if (punitions.length > 0) { html += '
'; html += '

⚠️ Punitions

'; for (var i = 0; i < punitions.length; i++) { var p = punitions[i]; html += '
'; html += '
' + p.libelle + ' - ' + p.date + '
'; html += '
Par: ' + p.par + '
'; if (p.motif) html += '
Motif: ' + p.motif + '
'; if (p.commentaire) html += '
' + p.commentaire + '
'; if (p.dateDeroulement) html += '
' + p.dateDeroulement + '
'; html += '
'; } html += '
'; } if (encouragements.length > 0) { html += '
'; html += '

Encouragements

'; for (var i = 0; i < encouragements.length; i++) { var e = encouragements[i]; html += '
'; html += '
' + e.libelle + ' - ' + e.date + '
'; if (e.motif) html += '
' + e.motif + '
'; if (e.commentaire) html += '
' + e.commentaire + '
'; html += '
'; } html += '
'; } if (absences.length === 0 && retards.length === 0 && repas.length === 0 && punitions.length === 0 && encouragements.length === 0) { html += '

Aucune information de vie scolaire

'; } html += '
'; contentDiv.innerHTML = html; } function renderMessagerie() { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; contentDiv.innerHTML = ''; var received = []; var sent = []; var draft = []; var archived = []; var currentFolder = "received"; var searchTerm = ""; var currentPage = 1; var messagesPerPage = 20; var foldersLoaded = false; function loadAllMessages() { contentDiv.innerHTML = '
Chargement des messages...
'; Promise.all([ fetch(`https://api.ecoledirecte.com/v3/eleves/${id}/messages.awp?force=false&typeRecuperation=received&idClasseur=0&orderBy=date&order=desc&query=&onlyRead=&page=0&itemsPerPage=1000&getAll=0&verbe=get&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }).then(res => res.json()), fetch(`https://api.ecoledirecte.com/v3/eleves/${id}/messages.awp?force=false&typeRecuperation=sent&idClasseur=0&orderBy=date&order=desc&query=&onlyRead=&page=0&itemsPerPage=1000&getAll=0&verbe=get&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }).then(res => res.json()), fetch(`https://api.ecoledirecte.com/v3/eleves/${id}/messages.awp?force=false&typeRecuperation=draft&idClasseur=0&orderBy=date&order=desc&query=&onlyRead=&page=0&itemsPerPage=1000&getAll=0&verbe=get&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }).then(res => res.json()), fetch(`https://api.ecoledirecte.com/v3/eleves/${id}/messages.awp?force=false&typeRecuperation=archived&idClasseur=0&orderBy=date&order=desc&query=&onlyRead=&page=0&itemsPerPage=1000&getAll=0&verbe=get&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }).then(res => res.json()) ]).then(function(results) { if (results[0].code === 200) received = results[0].data.messages.received || []; if (results[1].code === 200) sent = results[1].data.messages.sent || []; if (results[2].code === 200) draft = results[2].data.messages.draft || []; if (results[3].code === 200) archived = results[3].data.messages.archived || []; foldersLoaded = true; buildMessagerieUI(); }).catch(function() { buildMessagerieUI(); }); } function decodeBase64Content(str) { if (!str) return ""; try { var base64Decoded = atob(str); var bytes = []; for (var i = 0; i < base64Decoded.length; i++) bytes.push(base64Decoded.charCodeAt(i) & 0xFF); var decoder = new TextDecoder('utf-8'); return decoder.decode(new Uint8Array(bytes)); } catch(e) { return str; } } function getMessagesByFolder() { var messages = []; if (currentFolder === "received") messages = received.slice(); if (currentFolder === "sent") messages = sent.slice(); if (currentFolder === "draft") messages = draft.slice(); if (currentFolder === "archived") messages = archived.slice(); messages.sort(function(a, b) { return new Date(b.date || 0) - new Date(a.date || 0); }); return messages; } function showMessageDetail(messageId) { var detailDiv = document.getElementById('messageDetail'); if (!detailDiv) return; detailDiv.innerHTML = '
Chargement...
'; var mode = "destinataire"; if (currentFolder === "sent") mode = "expediteur"; else if (currentFolder === "draft") mode = "brouillon"; fetch(`https://api.ecoledirecte.com/v3/eleves/${id}/messages/${messageId}.awp?verbe=get&mode=${mode}&v=4.98.0`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }) .then(res => res.json()) .then(function(json) { var msg = json.data; if (!msg) { detailDiv.innerHTML = '
Message non trouvé
'; return; } var contactName = ""; if (currentFolder === "received" && msg.from) contactName = msg.from.prenom + " " + msg.from.nom; else if (currentFolder === "sent" && msg.to && msg.to[0]) contactName = msg.to[0].prenom + " " + msg.to[0].nom; else if (currentFolder === "archived" && msg.from) contactName = msg.from.prenom + " " + msg.from.nom; var date = (msg.date || "").replace(/-/g, '/').substring(0, 16); var cleanContent = decodeBase64Content(msg.content || ""); var subject = msg.subject || "(Sans objet)"; var hasAttachment = msg.files && msg.files.length > 0; var html = '
'; html += '
' + contactName + '
' + date + '
'; html += '
' + subject + '
'; html += '
' + cleanContent + '
'; html += '
'; detailDiv.innerHTML = html; if (hasAttachment) { var attachSection = document.createElement('div'); attachSection.style.cssText = 'margin-top:20px;padding-top:16px;border-top:1px solid #2C2C44;'; var label = document.createElement('span'); label.textContent = 'Pièces jointes:'; label.style.cssText = 'color:#8E8E93;display:block;margin-bottom:8px;'; attachSection.appendChild(label); for (var i = 0; i < msg.files.length; i++) { (function(file) { var btn = document.createElement('button'); btn.textContent = '📎 ' + file.libelle; btn.style.cssText = 'background:#2C2C44;border:none;color:#5E5EFF;padding:10px 16px;border-radius:12px;cursor:pointer;margin-right:8px;margin-bottom:8px;font-size:14px;font-weight:500;display:block;width:100%;text-align:left;'; btn.onclick = function(e) { e.preventDefault(); e.stopPropagation(); window.showAttachmentModal(file.id, file.libelle); }; attachSection.appendChild(btn); })(msg.files[i]); } detailDiv.appendChild(attachSection); } }) .catch(function(err) { detailDiv.innerHTML = '
Erreur: ' + err.message + '
'; }); } function renderMessages() { var allMessages = getMessagesByFolder(); var filtered = allMessages.filter(function(msg) { if (!searchTerm) return true; var contact = ""; if (currentFolder === "received" && msg.from) contact = msg.from.prenom + " " + msg.from.nom; else if (currentFolder === "sent" && msg.to && msg.to[0]) contact = msg.to[0].prenom + " " + msg.to[0].nom; else if (currentFolder === "archived" && msg.from) contact = msg.from.prenom + " " + msg.from.nom; return contact.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1 || (msg.subject || "").toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1; }); var totalPages = Math.ceil(filtered.length / messagesPerPage); var start = (currentPage - 1) * messagesPerPage; var pageMessages = filtered.slice(start, start + messagesPerPage); var listDiv = document.getElementById('messageList'); if (!listDiv) return; if (filtered.length === 0) { listDiv.innerHTML = '
Aucun message
'; return; } var html = '
' + filtered.length + ' message(s)
'; for (var i = 0; i < pageMessages.length; i++) { var msg = pageMessages[i]; var contactName = ""; if (currentFolder === "received" && msg.from) contactName = msg.from.prenom + " " + msg.from.nom; else if (currentFolder === "sent" && msg.to && msg.to[0]) contactName = msg.to[0].prenom + " " + msg.to[0].nom; else if (currentFolder === "archived" && msg.from) contactName = msg.from.prenom + " " + msg.from.nom; var date = (msg.date || "").replace(/-/g, '/').substring(0, 16); var subject = msg.subject || "(Sans objet)"; var isRead = msg.read !== false; var hasAttachment = msg.files && msg.files.length > 0; html += '
'; html += '
' + contactName + '
' + date + '
'; html += '
' + subject + '
'; if (hasAttachment) html += '
📎 ' + msg.files.length + ' piece(s)
'; html += '
'; } if (totalPages > 1) { html += '
'; if (currentPage > 1) { html += ''; html += ''; } for (var p = Math.max(1, currentPage - 2); p <= Math.min(totalPages, currentPage + 2); p++) { if (p === currentPage) html += '' + p + ''; else html += ''; } if (currentPage < totalPages) { html += ''; html += ''; } html += '
'; } listDiv.innerHTML = html; document.querySelectorAll('.message-item').forEach(el => el.addEventListener('click', e => showMessageDetail(el.dataset.id))); document.querySelectorAll('.page-btn').forEach(el => el.addEventListener('click', e => { currentPage = parseInt(el.dataset.page); renderMessages(); document.getElementById('messageList').scrollTop = 0; })); } function refreshUI() { currentPage = 1; renderMessages(); document.querySelectorAll('.folder-btn').forEach(btn => { btn.style.background = btn.dataset.folder === currentFolder ? '#5E5EFF' : '#2C2C44'; btn.style.color = 'white'; }); } function buildMessagerieUI() { var html = '
'; html += '
'; html += '
'; html += ''; html += ''; html += ''; html += ''; html += '
'; html += '
'; html += '🔍'; html += ''; html += ''; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; contentDiv.innerHTML = html; document.querySelectorAll('.folder-btn').forEach(btn => btn.addEventListener('click', function() { currentFolder = this.dataset.folder; document.getElementById('searchInput').value = ''; searchTerm = ''; refreshUI(); })); document.getElementById('searchInput').addEventListener('input', e => { searchTerm = e.target.value; currentPage = 1; renderMessages(); }); document.getElementById('clearSearch').addEventListener('click', () => { document.getElementById('searchInput').value = ''; searchTerm = ''; currentPage = 1; renderMessages(); }); refreshUI(); } if (!foldersLoaded) loadAllMessages(); else buildMessagerieUI(); } function renderApiLog() { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; if (apiLogs.length === 0) { contentDiv.innerHTML = '

Aucun log API. Activez le debug dans les parametres.

'; return; } var html = '
'; html += '

📋 API Logs

'; html += '
'; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; for (var i = 0; i < apiLogs.length; i++) { var log = apiLogs[i]; var statusColor = log.responseCode === 200 ? '#5E5EFF' : '#FF5E5E'; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; } html += '
DateAPIStatusDuree
' + log.timestamp + '' + (log.url.substring(0, 50) + (log.url.length > 50 ? '...' : '')) + '' + log.responseCode + '' + log.duration + '
'; contentDiv.innerHTML = html; } function renderSettings() { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; var html = '
'; html += '
'; html += '

Parametres

'; html += '
'; html += '
Mode Debug

Activer les logs API

'; html += '
'; html += ''; html += '
'; html += '
'; contentDiv.innerHTML = html; var debugToggle = document.getElementById('debugToggle'); if (debugToggle) { debugToggle.addEventListener('change', function(e) { debugEnabled = e.target.checked; if (!debugEnabled) { apiLogs.length = 0; } }); } var viewLogsBtn = document.getElementById('viewApiLogsBtn'); if (viewLogsBtn) { viewLogsBtn.addEventListener('click', function() { if (debugEnabled) { renderApiLog(); var tabBtns = document.querySelectorAll('#ed-widget .tab-btn'); for (var i = 0; i < tabBtns.length; i++) { tabBtns[i].classList.remove('active'); } currentTab = "apilog"; } else { alert("Activez le mode Debug d'abord dans les parametres"); } }); } } function renderEspaceTravail() { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; contentDiv.innerHTML = ''; if (!espaceData || espaceData.length === 0) { contentDiv.innerHTML = '

Aucun espace de travail disponible

'; return; } var mySpaces = []; var otherSpaces = []; for (var i = 0; i < espaceData.length; i++) { var space = espaceData[i]; if (space.estMembre === true) { mySpaces.push(space); } else { otherSpaces.push(space); } } var html = ''; if (mySpaces.length > 0) { html += '

Mes espaces

'; html += '
'; for (var i = 0; i < mySpaces.length; i++) { var space = mySpaces[i]; var resumeText = decodeContent(space.resume || ""); html += '
'; html += '

' + space.titre + '

'; if (resumeText) { html += '

' + resumeText + '

'; } html += '
'; if (space.cloud) html += 'Cloud'; if (space.discussion) html += 'Discussion'; if (space.agenda) html += 'Agenda'; html += '
'; html += '
Cree par: ' + (space.creePar || "Inconnu") + '
'; html += '
'; } html += '
'; } if (otherSpaces.length > 0) { html += '

Autres espaces disponibles

'; html += '
'; for (var i = 0; i < otherSpaces.length; i++) { var space = otherSpaces[i]; var resumeText = decodeContent(space.resume || ""); html += '
'; html += '

' + space.titre + '

'; if (resumeText) { html += '

' + resumeText + '

'; } html += '
'; if (space.cloud) html += 'Cloud'; if (space.discussion) html += 'Discussion'; if (space.agenda) html += 'Agenda'; html += '
'; html += '
'; } html += '
'; } contentDiv.innerHTML = html; var spaceCards = document.querySelectorAll('.espace-card[data-space-id]'); for (var i = 0; i < spaceCards.length; i++) { spaceCards[i].addEventListener('click', function(e) { var spaceId = this.getAttribute('data-space-id'); var spaceTitle = this.getAttribute('data-space-title'); showCloudExplorer(spaceId, spaceTitle); }); } } function showCloudExplorer(spaceId, spaceTitle) { currentSpaceId = spaceId; currentPath = []; loadFolder(spaceId, null); } function loadFolder(spaceId, folderId) { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; contentDiv.innerHTML = '

Chargement...

'; var url = `https://api.ecoledirecte.com/v3/cloud/W/${spaceId}.awp?verbe=get&v=4.98.0`; if (folderId && folderId !== '/') { url = `https://api.ecoledirecte.com/v3/cloud/W/${spaceId}/${encodeURIComponent(folderId)}.awp?verbe=get&v=4.98.0`; } fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Token": token }, body: "data=" + encodeURIComponent(JSON.stringify({})) }) .then(function(res) { return res.json(); }) .then(function(json) { var data = json.data; var items = []; if (data && data.length > 0) { if (folderId && folderId !== '/') { items = data; } else { for (var i = 0; i < data.length; i++) { if (data[i].libelle === '/' && data[i].type === 'folder') { items = data[i].children || []; break; } } } } renderCloudExplorer(spaceId, items, folderId); }) .catch(function(e) { contentDiv.innerHTML = '

Erreur: ' + e.message + '

'; document.getElementById('cloudBackBtn').addEventListener('click', function() { renderEspaceTravail(); }); }); } function renderCloudExplorer(spaceId, items, currentFolderId) { var contentDiv = document.getElementById('ed-content'); if (!contentDiv) return; var html = '
'; if (currentPath.length > 0) { html += ''; } html += ''; html += '
'; if (items && items.length > 0) { html += '
'; for (var i = 0; i < items.length; i++) { var item = items[i]; var isFolder = item.type === 'folder'; var icon = isFolder ? '📁' : '📄'; html += '
'; html += '' + item.libelle + ''; html += '
'; if (!isFolder) { var size = item.taille || 0; html += '' + formatFileSize(size) + ''; } else { html += 'Dossier'; } html += '
'; } html += '
'; } else { html += '

Dossier vide

'; } contentDiv.innerHTML = html; if (currentPath.length > 0) { var backBtn = document.getElementById('backBtn'); if (backBtn) { backBtn.addEventListener('click', function() { currentPath.pop(); var parentId = currentPath.length > 0 ? currentPath[currentPath.length - 1] : null; loadFolder(currentSpaceId, parentId); }); } } var backToSpacesBtn = document.getElementById('cloudBackToSpacesBtn'); if (backToSpacesBtn) { backToSpacesBtn.addEventListener('click', function() { currentPath = []; renderEspaceTravail(); }); } } window.navigateToFolder = function(folderId) { currentPath.push(folderId); loadFolder(currentSpaceId, folderId); }; function formatFileSize(bytes) { if (!bytes) return ''; if (bytes < 1024) return bytes + ' o'; if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' Ko'; return (bytes / 1048576).toFixed(1) + ' Mo'; } function renderContent() { if (currentTab === "home") { renderHome(); } else if (currentTab === "moyennes") { renderMoyennes(); } else if (currentTab === "devoirs") { renderDevoirs(); } else if (currentTab === "espacetravail") { renderEspaceTravail(); } else if (currentTab === "carnet") { renderCarnet(); } else if (currentTab === "viescolaire") { renderVieScolaire(); } else if (currentTab === "messagerie") { renderMessagerie(); } else if (currentTab === "apilog") { renderApiLog(); } else if (currentTab === "settings") { renderSettings(); } } widget.innerHTML = `
`; document.body.appendChild(widget); window.goBack = goBack; window.navigateToFolder = navigateToFolder; var tabBtns = document.querySelectorAll('#ed-widget .tab-btn'); function setTab(tab) { currentTab = tab; for (var j = 0; j < tabBtns.length; j++) { tabBtns[j].classList.remove('active'); } var button = document.querySelector('#ed-widget .tab-btn[data-tab="' + tab + '"]'); if (button) button.classList.add('active'); var trimesterSelector = document.querySelector('#ed-widget .selector-container'); if (trimesterSelector) { if (tab === "moyennes") { trimesterSelector.style.display = 'block'; } else { trimesterSelector.style.display = 'none'; } } renderContent(); } for (var i = 0; i < tabBtns.length; i++) { tabBtns[i].addEventListener('click', function(e) { setTab(this.getAttribute('data-tab')); }); } window.setTab = setTab; var activeTab = document.querySelector('#ed-widget .tab-btn[data-tab="home"]'); if (activeTab) activeTab.classList.add('active'); var trimesterSelectorHtml = document.createElement('div'); trimesterSelectorHtml.className = 'selector-container'; trimesterSelectorHtml.innerHTML = `
`; var contentDiv = document.getElementById('ed-content'); var parentDiv = contentDiv.parentNode; parentDiv.insertBefore(trimesterSelectorHtml, contentDiv); trimesterSelectorHtml.style.display = 'none'; renderContent(); var triButtons = document.querySelectorAll('#ed-widget .trimester-option'); for (var i = 0; i < triButtons.length; i++) { triButtons[i].addEventListener('click', function(e) { var tri = this.getAttribute('data-tri'); currentTrimester = tri; for (var j = 0; j < triButtons.length; j++) { triButtons[j].classList.remove('active'); } this.classList.add('active'); if (currentTab === "moyennes") { renderMoyennes(); } }); } var activeTri = document.querySelector('#ed-widget .trimester-option[data-tri="' + currentTrimester + '"]'); if (activeTri) activeTri.classList.add('active'); renderContent(); }, 50); completion("Charge"); } catch (error) { console.error('Erreur dans le script EcoleDirecte:', error); var loadingElement = document.getElementById('ed-loading'); if (loadingElement) loadingElement.remove(); var placeholderElement = document.getElementById('ed-widget-placeholder'); if (placeholderElement) placeholderElement.remove(); completion("Erreur: " + (error.message || "Erreur inconnue")); } })(); /* =================== Script End ✨ =================== */