splitscreen more_horiz
PROBLEMAS
SALIDA
TERMINAL
more_horiz expand_less close
warning 0 error 0
Lín. 1, col. 1 UTF-8 PHP notifications
⚠️ Warning: Variable no definida: 'proyecto'
Call Stack
#
Function
File
Class
0
handleError
/home/u266581275/domains/ikode.live/public_html/src/mopla/src/Parser.php::464
ErrorHandler
1
mensaje
/home/u266581275/domains/ikode.live/public_html/src/mopla/src/Parser.php::74
Parser
2
parse
/home/u266581275/domains/ikode.live/public_html/src/mopla/src/Mopla.php::58
Parser
3
render
/home/u266581275/domains/ikode.live/public_html/index.php::80
Mopla
res.json()) .then(json => { if (json.error) { const errorBox = document.getElementById('mensajeError'); if (errorBox) { errorBox.textContent = json.error; errorBox.style.display = 'block'; } else { alert(json.error); } return; } fileTreeData = [json]; renderAll(fileTreeData); }); } function renderAll(data) { const container = document.getElementById("fileTree"); container.innerHTML = ''; renderTree(data, container, "", 0); } function renderTree(tree, container, basePath, depth) { tree.forEach(item => { const itemEl = document.createElement('div'); itemEl.classList.add('folder-item'); const depthClasses = ['sub-item', 'sub-sub-item', 'sub-sub-sub-item', 'sub-sub-sub-sub-item', 'sub-sub-sub-sub-sub-item', 'sub-sub-sub-sub-sub-sub-item', 'sub-sub-sub-sub-sub-sub-sub-item','sub-sub-sub-sub-sub-sub-sub-sub-item']; if (depth > 0 && depth <= 7) { itemEl.classList.add(depthClasses[depth - 1]); } itemEl.dataset.name = item.name; itemEl.dataset.type = item.type; const fullPath = basePath ? `${basePath}/${item.name}` : item.name; itemEl.title = fullPath; const icon = document.createElement('span'); icon.className = `${item.type === 'file' ? obtenerClaseIcono(item.name) : 'ifr if-folder-closed'}`;//if-folder-open const nameSpan = document.createElement('span'); nameSpan.classList.add('span-titulo'); nameSpan.textContent = item.name; // CLICK: Abrir carpeta o imprimir archivo itemEl.addEventListener('click', e => { e.stopPropagation(); document.querySelectorAll('.folder-item.active').forEach(el => el.classList.remove('active')); itemEl.classList.add('active'); if (item.type === 'folder') { item.open = !item.open; renderAll(fileTreeData); } else { if (item.type === 'file') { console.log("Abrir archivo:", '/ronald/'+fullPath); fetch('/src/api/files/open.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ruta: '/ronald/'+fullPath // ← asegúrate que el JSON de archivos incluya el ID }) }) .then(res => res.json()) .then(json => { if (json.error) { alert("Error al abrir archivo: " + json.error); } else { abrirArchivoEnEditor(item.name, fullPath ,json.contenido, item); } }); }else{console.log('no es un archivo');} } }); // DRAG & DROP itemEl.setAttribute('draggable', true); itemEl.addEventListener('dragstart', (e) => { draggedItem = { item, from: tree }; const d = document.createElement('div'); d.className = 'drag-preview'; d.textContent = item.name; // Insertar el div y posicionarlo fuera de la vista document.body.appendChild(d); // Ahora sí usarlo como imagen de drag e.dataTransfer.setDragImage(d, -25,-7); // No lo eliminamos de inmediato (para que no se corte), sino después setTimeout(() => { if (d.parentNode) d.remove(); }, 100); }); itemEl.addEventListener('dragover', e => { e.preventDefault(); itemEl.classList.add('drag-over'); }); itemEl.addEventListener('dragleave', () => { itemEl.classList.remove('drag-over'); }); itemEl.addEventListener('drop', e => { e.preventDefault(); itemEl.classList.remove('drag-over'); if (item.type === 'folder' && draggedItem.item !== item) { if (!item.children) item.children = []; item.open = true; const idx = draggedItem.from.indexOf(draggedItem.item); if (idx >= 0) draggedItem.from.splice(idx, 1); item.children.push(draggedItem.item); //lamar a mover.php para cambiar los archivos reales fetch('/src/api/files/move.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ origen: draggedItem.item.path, destino: item.path + '/' + draggedItem.item.name }) }) .then(res => res.json()) .then(json => { if (json.error) { alert("Error al mover: " + json.error); } else { console.log("Movimiento confirmado"); } }); renderAll(fileTreeData); } }); itemEl.appendChild(icon); itemEl.appendChild(nameSpan); container.appendChild(itemEl); if (item.type === 'folder' && item.open && item.children) { renderTree(item.children, container, fullPath, depth + 1); } }); } function obtenerClaseIcono(nombre) { const ext = nombre.split('.').pop().toLowerCase(); const iconos = { js: 'ifb if-square-js', php: 'ifb if-php', html: 'ifb if-html5', css: 'ifb if-css3-alt', json: 'ifr if-file-code', png: 'ifr if-file-png', jpg: 'ifr if-file-jpg', jpeg: 'ifr if-file-jpg', gif: 'ifr if-gift', mp4: 'ifr if-file-video', mp3: 'ifr if-file-mp3', txt: 'ifr if-file-text', md: 'ifr if-file-circle-question', pdf: 'ifr if-file-pdf', zip: 'ifr if-file-zip', rar: 'ifr if-file-zipper', // Agrega más según tu librería de íconos }; return iconos[ext] || 'ifr if-file'; // por defecto } fetchFileTree(); let contadorArchivos = 0; const editores = {}; let archivoActivo = null; require.config({ paths: { 'vs': 'assets/js/vs' }}); function abrirArchivoEnEditor(nombre, ruta, contenidoBase64) { const id = 'archivo-' + (++contadorArchivos); // ID incremental // Crear pestaña const tab = document.createElement('div'); tab.className = 'tab'; tab.id = 'tab-' + id; tab.innerHTML = ` ${obtenerLenguajeDesdeExtension(nombre)} ${nombre} close `; document.getElementById('tabs-content').appendChild(tab); // Crear breadcrumb const breadcrumb = document.createElement('div'); breadcrumb.className = 'breadcrumb-line'; breadcrumb.id = 'breadcrumb-' + id; breadcrumb.innerHTML = ` ${ruta.split('/')[0]} chevron_right ${ruta} `; document.getElementById('breadcrumb-content').appendChild(breadcrumb); // Crear contenedor de editor const contenedorEditor = document.createElement('div'); contenedorEditor.className = 'editor-instance'; contenedorEditor.id = 'editor-' + id; contenedorEditor.style.width = '100%'; contenedorEditor.style.height = '100%'; document.getElementById('editor').appendChild(contenedorEditor); // Inicializar Monaco require(['vs/editor/editor.main'], function () { editores[id] = monaco.editor.create(contenedorEditor, { value: decodeBase64UTF8(contenidoBase64), language: obtenerLenguajeDesdeExtension(nombre), theme: 'vs', automaticLayout: true }); activarArchivo(id); // Activar después de crear }); } function decodeBase64UTF8(base64) { const binary = atob(base64); const bytes = Uint8Array.from(binary, c => c.charCodeAt(0)); return new TextDecoder('utf-8').decode(bytes); } function activarArchivo(id) { archivoActivo = id; document.querySelectorAll('#tabs-content .tab').forEach(t => t.classList.remove('active')); document.getElementById('tab-' + id).classList.add('active'); document.querySelectorAll('#breadcrumb-content .breadcrumb-line').forEach(b => b.classList.remove('active')); document.getElementById('breadcrumb-' + id).classList.add('active'); document.querySelectorAll('#editor .editor-instance').forEach(e => e.style.display = 'none'); document.getElementById('editor-' + id).style.display = 'block'; } // Cerrar pestaña document.addEventListener('click', (e) => { if (e.target.classList.contains('cerrar-tab')) { const id = e.target.dataset.id; document.getElementById('tab-' + id)?.remove(); document.getElementById('breadcrumb-' + id)?.remove(); document.getElementById('editor-' + id)?.remove(); editores[id]?.dispose(); delete editores[id]; if (archivoActivo === id) { const restantes = Object.keys(editores); if (restantes.length > 0) activarArchivo(restantes[0]); else archivoActivo = null; } } }); // Detectar clic en pestaña para activar document.addEventListener('click', e => { if (e.target.closest('.tab') && e.target.closest('.tab').id?.startsWith('tab-')) { const id = e.target.closest('.tab').id.replace('tab-', ''); activarArchivo(id); } }); function obtenerLenguajeDesdeExtension(nombre) { const ext = nombre.split('.').pop().toLowerCase(); return { js: 'javascript', php: 'php', html: 'html', css: 'css', json: 'json', md: 'markdown', txt: 'plaintext' }[ext] || 'plaintext'; }