(function() { const loggedErrors = []; const loggedWarnings = []; const originalError = console.error; const originalWarn = console.warn; /** * Busca nodos estructurados que describen directorios ausentes y los prepara para mostrarlos. */ function collectStructuredDirectoryIssues() { if (!document.body) { return []; } return Array.from(document.querySelectorAll('[data-error-kind="missing-directory"]')).map(node => { const dataset = node.dataset || {}; let payload = {}; const rawPayload = node.getAttribute('data-error-payload'); if (rawPayload) { try { payload = JSON.parse(rawPayload); } catch (error) { console.warn('No se pudo analizar el payload del directorio ausente', error); } } const info = Object.assign( { path: '', owner: '', test: '', mediaFile: '', mediaUrl: '', ownerPath: '', ownerPathExists: null, reason: '', nextSteps: '', consequence: '', context: [], source: '' }, payload ); if (!info.path && dataset.directoryPath) { info.path = dataset.directoryPath; } if (!info.owner && dataset.owner) { info.owner = dataset.owner; } if (!info.test && dataset.test) { info.test = dataset.test; } if (!info.mediaFile && dataset.mediaFile) { info.mediaFile = dataset.mediaFile; } if (!info.mediaUrl && dataset.mediaUrl) { info.mediaUrl = dataset.mediaUrl; } if (!info.ownerPath && dataset.ownerPath) { info.ownerPath = dataset.ownerPath; } if (info.ownerPathExists === null && typeof dataset.ownerPathExists !== 'undefined') { info.ownerPathExists = dataset.ownerPathExists === 'true'; } if (!info.reason && dataset.reason) { info.reason = dataset.reason; } if (!info.nextSteps && dataset.nextSteps) { info.nextSteps = dataset.nextSteps; } if (!info.consequence && dataset.consequence) { info.consequence = dataset.consequence; } if (!info.source && dataset.source) { info.source = dataset.source; } const context = []; if (Array.isArray(payload.context) && payload.context.length) { context.push(...payload.context); } else if (dataset.context) { dataset.context .split('|') .map(value => value.trim()) .filter(Boolean) .forEach(value => context.push(value)); } info.context = context; return { node, data: info }; }); } /** * Analiza el texto plano para localizar mensajes heredados del tipo "El directorio no existe". */ function collectLegacyDirectoryIssues(bodyText) { if (!bodyText) { return []; } const lines = bodyText.split(/\r?\n/); const issues = []; for (let i = 0; i < lines.length; i++) { const match = lines[i].match(/El directorio no existe:?\s*(.*)/i); if (!match) { continue; } const path = match[1].trim(); const context = []; const nextLine = lines[i + 1] ? lines[i + 1].trim() : ''; const prevLine = lines[i - 1] ? lines[i - 1].trim() : ''; if (prevLine && !/El directorio no existe/i.test(prevLine)) { context.push(prevLine); } if (nextLine && !/^(Fatal error|Warning|Notice)/i.test(nextLine)) { context.push(nextLine); } issues.push({ path, owner: '', test: '', mediaFile: '', mediaUrl: '', ownerPath: '', ownerPathExists: null, reason: '', nextSteps: '', consequence: '', context, source: 'legacy-text-detection' }); } const seen = new Set(); return issues.filter(issue => { const key = `${issue.path}|${issue.context.join(' ')}`; if (seen.has(key)) { return false; } seen.add(key); return true; }); } /** * Oculta los nodos estructurados que contienen la información del directorio ausente. */ function hideStructuredDirectoryMessages(nodes) { nodes.forEach(node => { if (!node) { return; } node.style.display = 'none'; node.setAttribute('aria-hidden', 'true'); }); } /** * Oculta el texto original del error heredado para que el usuario solo vea la ventana flotante. */ function hideLegacyDirectoryMessages() { if (!document.body) { return; } const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT); const replacements = []; while (walker.nextNode()) { const node = walker.currentNode; if (node && node.nodeValue && /El directorio no existe:/i.test(node.nodeValue)) { replacements.push(node); } } replacements.forEach(node => { const wrapper = document.createElement('span'); wrapper.style.display = 'none'; wrapper.textContent = node.nodeValue; if (node.parentNode) { node.parentNode.replaceChild(wrapper, node); } }); } function createButton(label, variant = 'primary') { const btn = document.createElement('button'); btn.type = 'button'; btn.textContent = label; btn.style.padding = '10px 18px'; btn.style.borderRadius = '8px'; btn.style.border = 'none'; btn.style.cursor = 'pointer'; btn.style.fontWeight = '600'; btn.style.fontSize = '15px'; btn.style.transition = 'opacity 0.2s ease'; btn.onmouseenter = () => { btn.style.opacity = '0.9'; }; btn.onmouseleave = () => { btn.style.opacity = '1'; }; if (variant === 'primary') { btn.style.background = '#2563eb'; btn.style.color = '#f8fafc'; } else { btn.style.background = 'rgba(148, 163, 184, 0.15)'; btn.style.color = '#e2e8f0'; btn.style.border = '1px solid rgba(148, 163, 184, 0.4)'; } return btn; } function buildDirectorySection(issues) { const section = document.createElement('section'); section.style.marginTop = '12px'; const heading = document.createElement('h2'); heading.textContent = issues.length > 1 ? 'Directorios ausentes detectados' : 'Directorio ausente detectado'; heading.style.fontSize = '20px'; heading.style.marginBottom = '8px'; const intro = document.createElement('p'); intro.textContent = 'El servidor avisó de que falta una carpeta necesaria para completar la carga de los datos del estudio. ' + 'Esto suele ocurrir cuando la captura de resultados no ha generado todavía los archivos o cuando la ruta carece de permisos.'; intro.style.marginBottom = '12px'; intro.style.lineHeight = '1.6'; const list = document.createElement('ul'); list.style.listStyle = 'disc'; list.style.paddingLeft = '18px'; list.style.display = 'flex'; list.style.flexDirection = 'column'; list.style.gap = '6px'; issues.forEach(issue => { const item = document.createElement('li'); const fragments = []; fragments.push(`Ruta buscada: ${issue.path || 'no especificada'}.`); if (issue.owner) { fragments.push(`Owner: ${issue.owner}.`); } if (issue.test) { fragments.push(`Test: ${issue.test}.`); } if (issue.mediaFile) { fragments.push(`Archivo relacionado: ${issue.mediaFile}.`); } if (issue.ownerPath && issue.ownerPathExists === false) { fragments.push(`Carpeta padre ausente: ${issue.ownerPath}.`); } if (issue.reason) { fragments.push(`Motivo detectado: ${issue.reason}`); } if (issue.nextSteps) { fragments.push(`Siguiente paso sugerido: ${issue.nextSteps}`); } if (issue.consequence) { fragments.push(`Impacto previsto: ${issue.consequence}`); } if (issue.context && issue.context.length) { fragments.push(`Contexto adicional: ${issue.context.join(' / ')}`); } item.textContent = fragments.join(' '); list.appendChild(item); }); const consequences = document.createElement('p'); consequences.textContent = 'Puedes ignorar el aviso para continuar, pero las visualizaciones o descargas que dependan de archivos dentro de esa carpeta podrían fallar o mostrar datos incompletos hasta que la carpeta exista.'; consequences.style.marginTop = '12px'; consequences.style.lineHeight = '1.6'; section.appendChild(heading); section.appendChild(intro); section.appendChild(list); section.appendChild(consequences); return section; } function buildDiagnosticsSection({ errors, warnings, phpMessage }) { const parts = []; const section = document.createElement('section'); section.style.marginTop = '16px'; if (errors.length) { parts.push('Errores JS:\n' + errors.join('\n')); } if (warnings.length) { parts.push('Warnings JS:\n' + warnings.join('\n')); } if (phpMessage) { parts.push('Errores PHP:\n' + phpMessage); } if (!parts.length) { return null; } const heading = document.createElement('h2'); heading.textContent = 'Diagnóstico técnico'; heading.style.fontSize = '20px'; heading.style.marginBottom = '8px'; const pre = document.createElement('pre'); pre.textContent = parts.join('\n\n'); pre.style.whiteSpace = 'pre-wrap'; pre.style.background = 'rgba(15, 23, 42, 0.55)'; pre.style.padding = '12px'; pre.style.borderRadius = '8px'; pre.style.fontFamily = 'monospace'; pre.style.fontSize = '14px'; pre.style.lineHeight = '1.5'; pre.style.maxHeight = '240px'; pre.style.overflow = 'auto'; section.appendChild(heading); section.appendChild(pre); return { section, clipboardText: parts.join('\n\n') }; } console.error = function(...args) { loggedErrors.push(args.join(' ')); if (originalError) { originalError.apply(console, args); } }; console.warn = function(...args) { loggedWarnings.push(args.join(' ')); if (originalWarn) { originalWarn.apply(console, args); } }; window.addEventListener('error', function(event) { if (event.message) { loggedErrors.push(event.message); } }); window.addEventListener('load', function() { const bodyText = document.body ? document.body.innerText : ''; const phpMatch = bodyText.match(/(Fatal error.*|Warning.*|Notice.*)/i); const phpMessage = phpMatch ? phpMatch[0] : ''; const sections = []; const clipboardChunks = []; const structuredEntries = collectStructuredDirectoryIssues(); let directoryIssues = structuredEntries.map(entry => entry.data); if (structuredEntries.length) { hideStructuredDirectoryMessages(structuredEntries.map(entry => entry.node)); } else { directoryIssues = collectLegacyDirectoryIssues(bodyText); if (directoryIssues.length) { hideLegacyDirectoryMessages(); } } if (directoryIssues.length) { const directorySection = buildDirectorySection(directoryIssues); sections.push(directorySection); const formatted = directoryIssues .map(issue => { const lines = [ `El directorio no existe: ${issue.path || 'sin ruta'}`, issue.owner ? `Owner: ${issue.owner}` : '', issue.test ? `Test: ${issue.test}` : '', issue.mediaFile ? `Archivo relacionado: ${issue.mediaFile}` : '', issue.mediaUrl ? `Media URL: ${issue.mediaUrl}` : '', issue.ownerPath && issue.ownerPathExists === false ? `Carpeta padre ausente: ${issue.ownerPath}` : '', issue.reason ? `Motivo: ${issue.reason}` : '', issue.nextSteps ? `Siguiente paso: ${issue.nextSteps}` : '', issue.consequence ? `Impacto: ${issue.consequence}` : '', issue.context && issue.context.length ? `Contexto adicional: ${issue.context.join(' / ')}` : '', issue.source ? `Origen: ${issue.source}` : '' ].filter(Boolean); if (!lines.length) { return ''; } return lines.join('\n'); }) .filter(Boolean) .join('\n\n'); if (formatted) { clipboardChunks.push(formatted); } } const diagnosticsSection = buildDiagnosticsSection({ errors: loggedErrors, warnings: loggedWarnings, phpMessage }); if (diagnosticsSection) { sections.push(diagnosticsSection.section); clipboardChunks.push(diagnosticsSection.clipboardText); } if (!sections.length) { return; } const overlay = document.createElement('div'); overlay.style.position = 'fixed'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.width = '100vw'; overlay.style.height = '100vh'; overlay.style.background = 'rgba(15, 23, 42, 0.92)'; overlay.style.color = '#f8fafc'; overlay.style.zIndex = '100000'; overlay.style.display = 'flex'; overlay.style.justifyContent = 'center'; overlay.style.alignItems = 'center'; overlay.style.padding = '24px'; const dialog = document.createElement('div'); dialog.style.background = 'rgba(2, 6, 23, 0.9)'; dialog.style.borderRadius = '16px'; dialog.style.padding = '28px 32px'; dialog.style.maxWidth = '720px'; dialog.style.width = '100%'; dialog.style.boxShadow = '0 25px 50px -12px rgba(15, 23, 42, 0.8)'; dialog.style.maxHeight = '80vh'; dialog.style.overflowY = 'auto'; dialog.style.outline = 'none'; dialog.setAttribute('role', 'alertdialog'); dialog.setAttribute('aria-modal', 'true'); dialog.setAttribute('aria-label', 'Aviso del dashboard'); dialog.tabIndex = -1; const title = document.createElement('h1'); title.textContent = 'Se detectaron incidencias en el dashboard'; title.style.fontSize = '24px'; title.style.marginBottom = '12px'; dialog.appendChild(title); sections.forEach(section => dialog.appendChild(section)); const buttonRow = document.createElement('div'); buttonRow.style.display = 'flex'; buttonRow.style.gap = '12px'; buttonRow.style.justifyContent = 'flex-end'; buttonRow.style.marginTop = '24px'; const ignoreBtn = createButton('Ignorar y continuar'); ignoreBtn.addEventListener('click', function() { overlay.remove(); }); const copyBtn = createButton('Copiar detalle', 'secondary'); copyBtn.addEventListener('click', function() { const text = clipboardChunks.filter(Boolean).join('\n\n').trim(); if (!text) { return; } if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(text).catch(function(err) { console.warn('No se pudo copiar el aviso al portapapeles', err); }); } else { console.warn('API Clipboard no disponible para copiar detalles del error.'); } }); buttonRow.appendChild(copyBtn); buttonRow.appendChild(ignoreBtn); dialog.appendChild(buttonRow); overlay.appendChild(dialog); document.body.appendChild(overlay); setTimeout(() => { dialog.focus({ preventScroll: true }); }, 0); overlay.addEventListener('keydown', function(event) { if (event.key === 'Escape') { overlay.remove(); } }); }); })();