You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1475 lines
57 KiB
1475 lines
57 KiB
// flow_doc.js
|
|
let nodes = [];
|
|
let connections = [];
|
|
const body = document.querySelector("body");
|
|
|
|
// Función para obtener el CSRF token
|
|
function getCSRFToken() {
|
|
const name = 'csrftoken';
|
|
let cookieValue = null;
|
|
if (document.cookie && document.cookie !== '') {
|
|
const cookies = document.cookie.split(';');
|
|
for (let i = 0; i < cookies.length; i++) {
|
|
const cookie = cookies[i].trim();
|
|
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return cookieValue;
|
|
}
|
|
|
|
// Función para extraer el nombre del archivo desde la URL
|
|
function extractFileName(url) {
|
|
return url.split('/').pop();
|
|
}
|
|
|
|
// Función para crear el menú contextual
|
|
function createContextMenu(x, y, options) {
|
|
// Eliminar cualquier menú existente
|
|
removeContextMenu();
|
|
|
|
const menu = document.createElement('div');
|
|
menu.classList.add('context-menu');
|
|
menu.style.top = `${y}px`;
|
|
menu.style.left = `${x}px`;
|
|
|
|
options.forEach(option => {
|
|
const item = document.createElement('div');
|
|
item.classList.add('context-menu-item');
|
|
item.textContent = option.label;
|
|
item.addEventListener('click', option.action);
|
|
menu.appendChild(item);
|
|
});
|
|
|
|
document.body.appendChild(menu);
|
|
menu.classList.add('show');
|
|
|
|
// Cerrar el menú al hacer clic en cualquier parte
|
|
document.addEventListener('click', removeContextMenu);
|
|
}
|
|
|
|
// Función para eliminar el menú contextual
|
|
function removeContextMenu() {
|
|
const existingMenu = document.querySelector('.context-menu');
|
|
if (existingMenu) {
|
|
existingMenu.remove();
|
|
document.removeEventListener('click', removeContextMenu);
|
|
}
|
|
}
|
|
|
|
// Función para crear un nodo
|
|
function createNode(e, tabId) {
|
|
let container = document.getElementById(`nodeContainer${tabId}`);
|
|
let element = document.createElement('div');
|
|
element.className = "slice_node";
|
|
element.style.position = 'absolute';
|
|
element.style.top = '100px';
|
|
element.style.left = '100px';
|
|
element.id = `node${Date.now()}`; // Asignar un ID único al nodo
|
|
|
|
// Inicializar propiedades adicionales
|
|
element.audioFile = "";
|
|
element.textFile = "";
|
|
element.extensionNumber = ""; // Para Node1 y Node4
|
|
element.content = ""; // Almacenar internamente el contenido
|
|
element.conditions = []; // Para condiciones dinámicas en node3
|
|
|
|
let node_type = e.target.getAttribute('data-node-type');
|
|
let textContent = e.target.textContent;
|
|
|
|
// Crear elemento para el título
|
|
const titleElement = document.createElement('div');
|
|
titleElement.className = 'node-title';
|
|
titleElement.textContent = textContent; // Solo el nombre, sin ID
|
|
element.appendChild(titleElement);
|
|
|
|
if (node_type === "node7") {
|
|
element.style.background = "#A0D2EB"; // Color para node7
|
|
element.setAttribute('data-node-type', 'node7');
|
|
|
|
// Agregar puertos de entrada y salida
|
|
const portIn1 = document.createElement('div');
|
|
portIn1.className = 'port port-in';
|
|
element.appendChild(portIn1);
|
|
|
|
const portIn2 = document.createElement('div');
|
|
portIn2.className = 'port port-in';
|
|
element.appendChild(portIn2);
|
|
|
|
const portOut1 = document.createElement('div');
|
|
portOut1.className = 'port port-out';
|
|
element.appendChild(portOut1);
|
|
|
|
const portOut2 = document.createElement('div');
|
|
portOut2.className = 'port port-out';
|
|
element.appendChild(portOut2);
|
|
}
|
|
|
|
// Asignar propiedades y puertos según el tipo de nodo
|
|
if (node_type === "node5") {
|
|
element.style.background = "#CDDC39"; // Color para node5
|
|
element.setAttribute('data-node-type', 'node5');
|
|
|
|
// Agregar puertos de entrada y salida
|
|
const portIn1 = document.createElement('div');
|
|
portIn1.className = 'port port-in';
|
|
element.appendChild(portIn1);
|
|
|
|
const portIn2 = document.createElement('div');
|
|
portIn2.className = 'port port-in';
|
|
element.appendChild(portIn2);
|
|
|
|
const portOut1 = document.createElement('div');
|
|
portOut1.className = 'port port-out';
|
|
element.appendChild(portOut1);
|
|
|
|
const portOut2 = document.createElement('div');
|
|
portOut2.className = 'port port-out';
|
|
element.appendChild(portOut2);
|
|
}
|
|
|
|
if (node_type === "node6") {
|
|
element.style.background = "#BFD4BB"; // Color para node6
|
|
element.setAttribute('data-node-type', 'node6');
|
|
|
|
// Agregar puertos de entrada y salida
|
|
const portIn1 = document.createElement('div');
|
|
portIn1.className = 'port port-in';
|
|
element.appendChild(portIn1);
|
|
|
|
const portIn2 = document.createElement('div');
|
|
portIn2.className = 'port port-in';
|
|
element.appendChild(portIn2);
|
|
|
|
const portOut1 = document.createElement('div');
|
|
portOut1.className = 'port port-out';
|
|
element.appendChild(portOut1);
|
|
|
|
const portOut2 = document.createElement('div');
|
|
portOut2.className = 'port port-out';
|
|
element.appendChild(portOut2);
|
|
}
|
|
|
|
// Crear elemento para el nombre del archivo .txt (Node3)
|
|
if (node_type === "node3") {
|
|
const txtFileElement = document.createElement('div');
|
|
txtFileElement.className = 'txt-file';
|
|
txtFileElement.textContent = "No guardado"; // Inicialmente sin archivo
|
|
txtFileElement.style.display = 'none'; // Ocultar por defecto
|
|
element.appendChild(txtFileElement);
|
|
}
|
|
|
|
// Crear elemento para el ícono de reproducción (Node2 y Node3)
|
|
if (node_type === "node2" || node_type === "node6") { // Solo para node2
|
|
const playIcon = document.createElement('span');
|
|
playIcon.className = 'play-icon';
|
|
playIcon.innerHTML = '▶'; // Unicode para el triángulo de reproducción
|
|
playIcon.title = "Reproducir Audio";
|
|
playIcon.style.cursor = 'pointer';
|
|
playIcon.style.marginLeft = '10px';
|
|
playIcon.style.color = 'white';
|
|
playIcon.style.fontSize = '16px';
|
|
playIcon.style.verticalAlign = 'middle';
|
|
playIcon.onclick = function() {
|
|
if (element.audioFile) {
|
|
let audio = new Audio(element.audioFile);
|
|
audio.play();
|
|
} else {
|
|
alert("No hay audio asociado a este nodo.");
|
|
}
|
|
};
|
|
element.appendChild(playIcon);
|
|
}
|
|
|
|
// Asignar puertos en base al tipo de nodo
|
|
if (node_type === "node1") {
|
|
element.style.background = "#92a5b9";
|
|
element.setAttribute('data-node-type', 'node1');
|
|
const portOut = document.createElement('div');
|
|
portOut.className = 'port port-out';
|
|
element.appendChild(portOut);
|
|
} else if (node_type === "node2") {
|
|
element.style.background = "#00BFA5";
|
|
element.setAttribute('data-node-type', 'node2');
|
|
const portIn = document.createElement('div');
|
|
portIn.className = "port port-in";
|
|
element.appendChild(portIn);
|
|
const portOut = document.createElement('div');
|
|
portOut.className = "port port-out";
|
|
element.appendChild(portOut);
|
|
} else if (node_type === "node3") {
|
|
element.style.background = "#DDDDDD";
|
|
element.setAttribute('data-node-type', 'node3');
|
|
const portIn = document.createElement("div");
|
|
portIn.className = "port port-in";
|
|
element.appendChild(portIn);
|
|
const portOut = document.createElement("div");
|
|
portOut.className = "port port-out";
|
|
element.appendChild(portOut); // Añadimos un puerto de salida
|
|
} else if (node_type === "node4") {
|
|
element.style.background = "#1DE9B6"; // Cambiar color a lightseagreen
|
|
element.setAttribute('data-node-type', 'node4');
|
|
const displayElement = document.createElement('div');
|
|
displayElement.className = 'display-extension';
|
|
displayElement.textContent = "No recibido"; // Inicialmente sin string
|
|
displayElement.style = "display: none";
|
|
element.appendChild(displayElement);
|
|
const portIn = document.createElement("div");
|
|
portIn.className = "port port-in";
|
|
element.appendChild(portIn);
|
|
}
|
|
|
|
container.appendChild(element);
|
|
|
|
// Permitir mover el nodo
|
|
element.addEventListener('mousedown', (event) => {
|
|
if (!event.target.classList.contains('port') && !event.target.classList.contains('play-icon')) {
|
|
mouseDown(event, element, tabId);
|
|
}
|
|
});
|
|
|
|
// Agregar eventos a los puertos
|
|
const ports = element.querySelectorAll('.port');
|
|
ports.forEach(port => {
|
|
port.addEventListener('mousedown', (e) => {
|
|
startConnection(e, tabId);
|
|
});
|
|
});
|
|
|
|
// Agregar evento de doble clic para abrir el modal
|
|
element.addEventListener('dblclick', (e) => openModal(e, element));
|
|
|
|
// Añadir evento de clic derecho para mostrar el menú contextual
|
|
element.addEventListener('contextmenu', (e) => {
|
|
e.preventDefault();
|
|
createContextMenu(e.pageX, e.pageY, [
|
|
{
|
|
label: 'Eliminar Nodo',
|
|
action: () => deleteNode(element, tabId)
|
|
}
|
|
]);
|
|
});
|
|
|
|
nodes.push(element); // Agregar nodo al array global
|
|
saveTabData(tabId);
|
|
}
|
|
|
|
// Función para manejar el movimiento de los nodos
|
|
function mouseDown(e, nodeElement, tabId) {
|
|
let startX = e.clientX;
|
|
let startY = e.clientY;
|
|
let node_target = nodeElement;
|
|
|
|
let moveHandler = (e) => {
|
|
let newX = startX - e.clientX;
|
|
let newY = startY - e.clientY;
|
|
startX = e.clientX;
|
|
startY = e.clientY;
|
|
|
|
node_target.style.top = (node_target.offsetTop - newY) + 'px';
|
|
node_target.style.left = (node_target.offsetLeft - newX) + 'px';
|
|
updateConnectionPoints(tabId);
|
|
updateConnections(tabId); // Actualizar las conexiones cada vez que se mueva el nodo
|
|
};
|
|
|
|
document.addEventListener('mousemove', moveHandler);
|
|
|
|
document.addEventListener('mouseup', () => {
|
|
document.removeEventListener('mousemove', moveHandler);
|
|
}, { once: true });
|
|
}
|
|
|
|
// Función para abrir el modal de edición del nodo
|
|
function openModal(e, node) {
|
|
|
|
const nodeType2 = e.target.dataset.nodeType;
|
|
const parentElement = e.target.parentElement;
|
|
const nodeType = parentElement.getAttribute('data-node-type');
|
|
|
|
const fragment = document.createDocumentFragment();
|
|
|
|
const modal = document.createElement("div");
|
|
modal.classList.add("modal");
|
|
modal.id = "modal";
|
|
|
|
const background = document.createElement("div");
|
|
background.classList.add("background");
|
|
background.id = "modal-overlay";
|
|
|
|
if ((nodeType2 || nodeType) == "node3") {
|
|
|
|
// Crear campo de entrada para el título del nodo
|
|
const titleLabel = document.createElement('label');
|
|
titleLabel.textContent = 'Título del nodo:';
|
|
titleLabel.style.color = 'black';
|
|
fragment.appendChild(titleLabel);
|
|
|
|
const titleInput = document.createElement('input');
|
|
titleInput.type = 'text';
|
|
titleInput.id = 'nodeTitleInput';
|
|
titleInput.value = node.querySelector('.node-title').textContent || '';
|
|
titleInput.style = 'width: 250px; height: 30px; margin-bottom: 10px;';
|
|
fragment.appendChild(titleInput);
|
|
|
|
// Crear campo de entrada para el contenido del nodo
|
|
const contentLabel = document.createElement('label');
|
|
contentLabel.textContent = 'Contenido del nodo:';
|
|
contentLabel.style.color = 'black';
|
|
fragment.appendChild(contentLabel);
|
|
|
|
const contentInput = document.createElement('textarea');
|
|
contentInput.id = 'nodeContentInput';
|
|
contentInput.value = node.content || ""; // Mostrar contenido si existe
|
|
contentInput.style = 'width: 250px; height: 70px; margin-bottom: 10px;';
|
|
fragment.appendChild(contentInput);
|
|
|
|
// Sección para condiciones dinámicas
|
|
const conditionsContainer = document.createElement('div');
|
|
conditionsContainer.id = 'conditionsContainer';
|
|
conditionsContainer.style.marginBottom = '10px';
|
|
|
|
const conditionsLabel = document.createElement('label');
|
|
conditionsLabel.textContent = 'Condiciones Dinámicas:';
|
|
conditionsLabel.style.color = 'black';
|
|
conditionsContainer.appendChild(conditionsLabel);
|
|
|
|
const addConditionButton = document.createElement('button');
|
|
addConditionButton.textContent = 'Agregar Condición';
|
|
addConditionButton.type = 'button';
|
|
addConditionButton.style.marginLeft = '10px';
|
|
addConditionButton.onclick = addCondition;
|
|
conditionsContainer.appendChild(addConditionButton);
|
|
|
|
// Lista de condiciones
|
|
const conditionsList = document.createElement('ul');
|
|
conditionsList.id = 'conditionsList';
|
|
conditionsList.style.listStyleType = 'none';
|
|
conditionsList.style.padding = '0';
|
|
conditionsContainer.appendChild(conditionsList);
|
|
|
|
fragment.appendChild(conditionsContainer);
|
|
|
|
// Función para agregar una nueva condición
|
|
function addCondition(condition = { condition_string: '', target_node_id: '' }) {
|
|
const conditionItem = document.createElement('li');
|
|
conditionItem.style.marginBottom = '5px';
|
|
|
|
const conditionStringInput = document.createElement('input');
|
|
conditionStringInput.type = 'text';
|
|
conditionStringInput.placeholder = 'String de Condición';
|
|
conditionStringInput.value = condition.condition_string;
|
|
conditionStringInput.style.width = '150px';
|
|
conditionStringInput.style.marginRight = '10px';
|
|
conditionStringInput.style = 'border-radius: 5px; border: 1px solid gray;';
|
|
conditionItem.appendChild(conditionStringInput);
|
|
|
|
const targetNodeSelect = document.createElement('select');
|
|
targetNodeSelect.style.width = '150px';
|
|
targetNodeSelect.style.borderRadius = '5px';
|
|
targetNodeSelect.style.border = '1px solid gray';
|
|
targetNodeSelect.innerHTML = '<option value="">Seleccionar node4</option>';
|
|
|
|
// Obtener todos los node4 disponibles
|
|
const tabId = getTabIdFromNode(node);
|
|
const nodeContainer = document.getElementById(`nodeContainer${tabId}`);
|
|
const node4Elements = nodeContainer.querySelectorAll('[data-node-type="node4"]');
|
|
|
|
node4Elements.forEach(n4 => {
|
|
const option = document.createElement('option');
|
|
option.value = n4.id;
|
|
option.textContent = n4.querySelector('.node-title').textContent;
|
|
if (condition.target_node_id === n4.id) {
|
|
option.selected = true;
|
|
}
|
|
targetNodeSelect.appendChild(option);
|
|
});
|
|
|
|
conditionItem.appendChild(targetNodeSelect);
|
|
|
|
const removeConditionButton = document.createElement('button');
|
|
removeConditionButton.textContent = 'Eliminar';
|
|
removeConditionButton.type = 'button';
|
|
removeConditionButton.style.marginLeft = '10px';
|
|
removeConditionButton.style.borderRadius = '5px';
|
|
removeConditionButton.style.border = '1px solid gray';
|
|
removeConditionButton.onclick = () => {
|
|
conditionItem.remove();
|
|
};
|
|
conditionItem.appendChild(removeConditionButton);
|
|
|
|
conditionsList.appendChild(conditionItem);
|
|
}
|
|
|
|
// Cargar condiciones existentes si las hay
|
|
if (node.conditions && node.conditions.length > 0) {
|
|
node.conditions.forEach(cond => addCondition(cond));
|
|
}
|
|
|
|
const saveButton = document.createElement("button");
|
|
saveButton.classList.add("saveButton");
|
|
saveButton.innerText = "Guardar";
|
|
|
|
saveButton.onclick = async function() {
|
|
// Actualizar el título y contenido del nodo
|
|
const newTitle = titleInput.value.trim();
|
|
const newContent = contentInput.value.trim();
|
|
|
|
if (!newTitle || !newContent) {
|
|
alert("El título y el contenido no pueden estar vacíos.");
|
|
return;
|
|
}
|
|
|
|
const oldTitle = node.querySelector('.node-title').textContent;
|
|
node.querySelector('.node-title').textContent = newTitle;
|
|
|
|
// Obtener las condiciones
|
|
const conditions = [];
|
|
const conditionItems = conditionsList.querySelectorAll('li');
|
|
conditionItems.forEach(item => {
|
|
const conditionString = item.querySelector('input').value.trim();
|
|
const targetNodeId = item.querySelector('select').value;
|
|
if (conditionString && targetNodeId) {
|
|
conditions.push({
|
|
condition_string: conditionString,
|
|
target_node_id: targetNodeId
|
|
});
|
|
}
|
|
});
|
|
|
|
// Obtener el tabId del nodo
|
|
const tabId = getTabIdFromNode(node);
|
|
|
|
// Obtener nodeType desde el atributo data-node-type
|
|
const nodeType = node.getAttribute('data-node-type');
|
|
|
|
const tabName = getTabName();
|
|
|
|
// **Obtener el nombre del archivo de audio del node2 o node6 conectado**
|
|
let audioFileName = 'saludo_claude'; // Por defecto
|
|
const connections = window.tabConnections[tabId] || [];
|
|
let audioFound = false;
|
|
|
|
connections.forEach(connection => {
|
|
if (connection.endPoint.to.id === node.id) {
|
|
const fromNode = document.getElementById(connection.startPoint.from.id);
|
|
console.log(fromNode)
|
|
if (fromNode) {
|
|
const fromNodeType = fromNode.getAttribute('data-node-type');
|
|
if (fromNodeType === 'node2' && fromNode.audioFile) {
|
|
audioFileName = extractFileName(fromNode.audioFile).split('.').slice(0, -1).join('.');
|
|
audioFound = true;
|
|
} else if (fromNodeType === 'node6' && fromNode.audioFile && !audioFound) {
|
|
// Si no se encontró audio en node2, usar node6
|
|
audioFileName = extractFileName(fromNode.audioFile).split('.').slice(0, -1).join('.');
|
|
audioFound = true;
|
|
console.log(audioFileName)
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
audioFileName = `${audioFileName}`;
|
|
|
|
console.log(audioFileName)
|
|
// Enviar los datos a save_tts para generar los archivos
|
|
try {
|
|
const response = await fetch('/save_tts/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': getCSRFToken(),
|
|
},
|
|
body: JSON.stringify({
|
|
tabId: tabId,
|
|
tabName: tabName,
|
|
nodeId: node.id, // Incluir nodeId
|
|
nodeType: nodeType, // Incluir nodeType
|
|
title: newTitle,
|
|
content: newContent,
|
|
audioFile: audioFileName // Enviar el nombre del archivo de audio
|
|
})
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.status === 'success') {
|
|
// Si el título cambió, eliminar archivos antiguos
|
|
if (newTitle !== oldTitle) {
|
|
await fetch('/delete_files/', { // Vista ya creada en views.py
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': getCSRFToken(),
|
|
},
|
|
body: JSON.stringify({
|
|
tabId: tabId,
|
|
nodeId: node.id, // Incluir nodeId
|
|
nodeType: nodeType, // Incluir nodeType
|
|
oldTitle: oldTitle
|
|
})
|
|
});
|
|
}
|
|
|
|
// Actualizar el nodo con las URLs de los archivos
|
|
node.textFile = result.textFile;
|
|
node.content = newContent;
|
|
node.conditions = conditions; // Actualizar condiciones
|
|
|
|
// Actualizar el nombre del archivo .txt en el nodo
|
|
const txtFileElement = node.querySelector('.txt-file');
|
|
txtFileElement.style.display = 'none'; // Mantener oculto
|
|
|
|
alert("Archivo de texto guardado exitosamente.");
|
|
} else if (result.status === 'skipped') {
|
|
alert(result.message);
|
|
} else {
|
|
alert(`Error: ${result.message}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error al generar archivos:', error);
|
|
alert('Ocurrió un error al generar los archivos.');
|
|
}
|
|
|
|
// Guardar las condiciones en la pestaña
|
|
await saveTabData(tabId);
|
|
|
|
// Cerrar el modal
|
|
modal.classList.remove("show");
|
|
background.classList.remove("show");
|
|
|
|
setTimeout(() => {
|
|
document.body.removeChild(background);
|
|
}, 300);
|
|
};
|
|
|
|
modal.appendChild(fragment);
|
|
modal.appendChild(saveButton);
|
|
|
|
setTimeout(() => {
|
|
modal.classList.add("show");
|
|
background.classList.add("show");
|
|
}, 10);
|
|
} else if ((nodeType2 || nodeType) == "node2") {
|
|
|
|
const div_node2 = document.createElement('div');
|
|
div_node2.classList.add('div_node2');
|
|
div_node2.id = 'div_node2';
|
|
|
|
// Crear campo de entrada para el título del nodo
|
|
const titleLabel = document.createElement('label');
|
|
titleLabel.textContent = 'Título del nodo:';
|
|
titleLabel.style.color = 'black';
|
|
div_node2.appendChild(titleLabel);
|
|
|
|
const iname_node2 = document.createElement('input');
|
|
iname_node2.type = 'text';
|
|
iname_node2.id = 'iname_node2';
|
|
iname_node2.classList.add('iname_node2');
|
|
iname_node2.placeholder = 'Título del nodo';
|
|
iname_node2.value = node.querySelector('.node-title').textContent || '';
|
|
iname_node2.style = 'width: 250px; height: 30px; margin-bottom: 10px;';
|
|
div_node2.appendChild(iname_node2);
|
|
|
|
// Crear campo de entrada para el archivo de audio
|
|
const audioLabel = document.createElement('label');
|
|
audioLabel.textContent = 'Cargar Audio:';
|
|
audioLabel.style.color = 'black';
|
|
div_node2.appendChild(audioLabel);
|
|
|
|
const input_node2 = document.createElement('input');
|
|
input_node2.type = 'file';
|
|
input_node2.accept = 'audio/*';
|
|
input_node2.id = 'input_node2';
|
|
input_node2.classList.add('input_node2');
|
|
div_node2.appendChild(input_node2);
|
|
|
|
// Mostrar el audio actual si existe
|
|
const audioPlay = document.createElement('audio');
|
|
audioPlay.id = 'audioPlayer';
|
|
audioPlay.classList.add('audioPlayer');
|
|
audioPlay.controls = true;
|
|
if (node.audioFile) {
|
|
audioPlay.src = node.audioFile;
|
|
}
|
|
div_node2.appendChild(audioPlay);
|
|
|
|
fragment.appendChild(div_node2);
|
|
modal.appendChild(fragment);
|
|
|
|
// Evento para cargar y previsualizar el audio
|
|
input_node2.addEventListener('change', (event) => {
|
|
const file = event.target.files[0];
|
|
|
|
if (file) {
|
|
const urlAudio = URL.createObjectURL(file);
|
|
audioPlay.src = urlAudio;
|
|
audioPlay.play().catch(error => {
|
|
console.error('Error al reproducir el audio: ', error);
|
|
});
|
|
}
|
|
});
|
|
|
|
const saveButton = document.createElement("button");
|
|
saveButton.classList.add("saveButton");
|
|
saveButton.innerText = "Guardar";
|
|
|
|
saveButton.onclick = async function() {
|
|
const newTitle = iname_node2.value.trim();
|
|
|
|
if (!newTitle) {
|
|
alert("El título no puede estar vacío.");
|
|
return;
|
|
}
|
|
|
|
const oldTitle = node.querySelector('.node-title').textContent;
|
|
node.querySelector('.node-title').textContent = newTitle;
|
|
|
|
const tabId = getTabIdFromNode(node);
|
|
|
|
let newAudioFile = node.audioFile;
|
|
|
|
// Obtener nodeType desde el atributo data-node-type
|
|
const nodeType = node.getAttribute('data-node-type');
|
|
|
|
const tabName = getTabName();
|
|
|
|
// Si se ha seleccionado un nuevo archivo de audio
|
|
if (input_node2.files.length > 0) {
|
|
const file = input_node2.files[0];
|
|
const formData = new FormData();
|
|
formData.append('tabId', tabId);
|
|
formData.append('nodeId', node.id); // Incluir nodeId
|
|
formData.append('nodeType', nodeType); // Incluir nodeType
|
|
formData.append('title', newTitle);
|
|
formData.append('audioFile', file);
|
|
|
|
try {
|
|
const response = await fetch('/upload_audio/', { // Vista ya creada en views.py
|
|
method: 'POST',
|
|
headers: {
|
|
'X-CSRFToken': getCSRFToken(),
|
|
},
|
|
body: formData
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.status === 'success') {
|
|
// Si el título o el audio cambió, eliminar archivos antiguos
|
|
if (newTitle !== oldTitle || node.audioFile !== result.audioFile) {
|
|
await fetch('/delete_audio/', { // Vista ya creada en views.py
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': getCSRFToken(),
|
|
},
|
|
body: JSON.stringify({
|
|
tabId: tabId,
|
|
nodeId: node.id, // Incluir nodeId
|
|
nodeType: nodeType, // Incluir nodeType
|
|
oldAudioFile: node.audioFile
|
|
})
|
|
});
|
|
}
|
|
|
|
newAudioFile = result.audioFile;
|
|
node.audioFile = newAudioFile;
|
|
audioPlay.src = newAudioFile;
|
|
|
|
alert("Audio guardado exitosamente.");
|
|
} else {
|
|
alert(`Error: ${result.message}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error al subir el audio:', error);
|
|
alert('Ocurrió un error al subir el audio.');
|
|
}
|
|
}
|
|
|
|
// Si el título cambió y no se subió un nuevo audio
|
|
if (newTitle !== oldTitle && input_node2.files.length === 0) {
|
|
// Renombrar el archivo de audio existente
|
|
try {
|
|
const response = await fetch('/rename_audio/', { // Vista ya creada en views.py
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': getCSRFToken(),
|
|
},
|
|
body: JSON.stringify({
|
|
tabId: tabId,
|
|
nodeId: node.id, // Incluir nodeId
|
|
nodeType: nodeType, // Incluir nodeType
|
|
oldTitle: oldTitle,
|
|
newTitle: newTitle,
|
|
currentAudioFile: node.audioFile
|
|
})
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.status === 'success') {
|
|
node.audioFile = result.audioFile;
|
|
audioPlay.src = result.newAudioFile;
|
|
alert("Audio renombrado exitosamente.");
|
|
} else {
|
|
alert(`Error: ${result.message}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error al renombrar el audio:', error);
|
|
alert('Ocurrió un error al renombrar el audio.');
|
|
}
|
|
}
|
|
|
|
// Guardar los datos de la pestaña para incluir el título y la extensión
|
|
await saveTabData(tabId);
|
|
|
|
// Cerrar el modal
|
|
modal.classList.remove("show");
|
|
background.classList.remove("show");
|
|
|
|
setTimeout(() => {
|
|
document.body.removeChild(background);
|
|
}, 300);
|
|
};
|
|
|
|
modal.appendChild(saveButton);
|
|
|
|
setTimeout(() => {
|
|
modal.classList.add("show");
|
|
background.classList.add("show");
|
|
}, 10);
|
|
} else if ((nodeType2 || nodeType) == "node1") {
|
|
|
|
const div_a = document.createElement('div');
|
|
div_a.classList.add('div-a');
|
|
|
|
// Campo para el título del nodo
|
|
const titleLabel = document.createElement('label');
|
|
titleLabel.textContent = 'Título del nodo:';
|
|
titleLabel.style.color = 'black';
|
|
div_a.appendChild(titleLabel);
|
|
|
|
const title_node1 = document.createElement('input');
|
|
title_node1.type = 'text';
|
|
title_node1.id = 'title_node1';
|
|
title_node1.classList.add('title_node1');
|
|
title_node1.placeholder = 'Título del nodo';
|
|
title_node1.value = node.querySelector('.node-title').textContent || '';
|
|
title_node1.style = 'width: 250px; height: 30px; margin-bottom: 10px;';
|
|
div_a.appendChild(title_node1);
|
|
|
|
// Campo para el número de extensión
|
|
const extensionLabel = document.createElement('label');
|
|
extensionLabel.classList.add('label_node1');
|
|
extensionLabel.textContent = "Número de Extensión:";
|
|
extensionLabel.style.color = 'black';
|
|
div_a.appendChild(extensionLabel);
|
|
|
|
const input = document.createElement('input');
|
|
input.type = 'text';
|
|
input.classList = 'input_node1';
|
|
input.placeholder = 'Ingrese el número de extensión';
|
|
input.value = node.extensionNumber || '';
|
|
input.style = 'width: 250px; height: 30px; margin-bottom: 10px;';
|
|
div_a.appendChild(input);
|
|
|
|
const save = document.createElement('button');
|
|
save.textContent = "Guardar";
|
|
save.classList.add('save_node1');
|
|
|
|
div_a.appendChild(save);
|
|
modal.appendChild(div_a);
|
|
|
|
save.onclick = async function() {
|
|
const newTitle = title_node1.value.trim();
|
|
const newExtension = input.value.trim();
|
|
|
|
if (!newTitle || !newExtension) {
|
|
alert("El título y el número de extensión no pueden estar vacíos.");
|
|
return;
|
|
}
|
|
|
|
const oldTitle = node.querySelector('.node-title').textContent;
|
|
node.querySelector('.node-title').textContent = newTitle;
|
|
node.extensionNumber = newExtension; // Guardar internamente
|
|
|
|
// Obtener el tabId del nodo
|
|
const tabId = getTabIdFromNode(node);
|
|
|
|
// Obtener nodeType desde el atributo data-node-type
|
|
const nodeType = node.getAttribute('data-node-type');
|
|
|
|
const tabName = getTabName();
|
|
|
|
// Enviar los datos al servidor para actualizar Node1
|
|
try {
|
|
const response = await fetch('/update_node1/', { // Vista ya creada en views.py
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': getCSRFToken(),
|
|
},
|
|
body: JSON.stringify({
|
|
tabId: tabId,
|
|
tabName: tabName,
|
|
nodeId: node.id, // Incluir nodeId
|
|
nodeType: nodeType, // Incluir nodeType
|
|
newTitle: newTitle,
|
|
newExtension: newExtension,
|
|
oldTitle: oldTitle
|
|
})
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.status === 'success') {
|
|
alert("Nodo actualizado exitosamente.");
|
|
} else {
|
|
alert(`Error: ${result.message}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error al actualizar el nodo:', error);
|
|
alert('Ocurrió un error al actualizar el nodo.');
|
|
}
|
|
|
|
// Guardar los datos de la pestaña para incluir el número de extensión
|
|
await saveTabData(tabId);
|
|
|
|
// Cerrar el modal
|
|
modal.classList.remove("show");
|
|
background.classList.remove("show");
|
|
|
|
setTimeout(() => {
|
|
document.body.removeChild(background);
|
|
}, 300);
|
|
};
|
|
|
|
setTimeout(() => {
|
|
modal.classList.add("show");
|
|
background.classList.add("show");
|
|
}, 10);
|
|
} else if ((nodeType2 || nodeType) == "node4") {
|
|
// Modal para node4
|
|
const displayDiv = document.createElement('div');
|
|
displayDiv.classList.add('div_node4');
|
|
displayDiv.id = 'div_node4';
|
|
|
|
// Crear campo para el Nombre del Área (Título del Nodo)
|
|
const areaLabel = document.createElement('label');
|
|
areaLabel.textContent = 'Nombre del área:';
|
|
areaLabel.style.color = 'black';
|
|
displayDiv.appendChild(areaLabel);
|
|
|
|
const areaInput = document.createElement('input');
|
|
areaInput.type = 'text';
|
|
areaInput.id = 'areaInput';
|
|
areaInput.classList.add('areaInput');
|
|
areaInput.value = node.querySelector('.node-title').textContent || '';
|
|
areaInput.style = 'width: 250px; height: 30px; margin-bottom: 10px;';
|
|
displayDiv.appendChild(areaInput);
|
|
|
|
// Crear campo para el Número de Extensión
|
|
const extensionLabel = document.createElement('label');
|
|
extensionLabel.textContent = 'Número de Extensión:';
|
|
extensionLabel.style.color = 'black';
|
|
displayDiv.appendChild(extensionLabel);
|
|
|
|
const extensionInput = document.createElement('input');
|
|
extensionInput.type = 'text';
|
|
extensionInput.id = 'extensionInput';
|
|
extensionInput.classList.add('extensionInput');
|
|
extensionInput.value = node.extensionNumber || '';
|
|
extensionInput.style = 'width: 250px; height: 30px; margin-bottom: 10px;';
|
|
displayDiv.appendChild(extensionInput);
|
|
|
|
const saveButton = document.createElement("button");
|
|
saveButton.classList.add("saveButton");
|
|
saveButton.innerText = "Guardar";
|
|
|
|
saveButton.onclick = async function() {
|
|
const newAreaName = areaInput.value.trim();
|
|
const newExtensionNumber = extensionInput.value.trim();
|
|
|
|
if (!newAreaName || !newExtensionNumber) {
|
|
alert("El nombre del área y el número de extensión no pueden estar vacíos.");
|
|
return;
|
|
}
|
|
|
|
// Actualizar el título del nodo (Nombre del Área)
|
|
const oldTitle = node.querySelector('.node-title').textContent;
|
|
node.querySelector('.node-title').textContent = newAreaName;
|
|
|
|
// Actualizar el número de extensión
|
|
node.extensionNumber = newExtensionNumber;
|
|
const displayElement = node.querySelector('.display-extension');
|
|
if (displayElement) {
|
|
displayElement.textContent = newExtensionNumber;
|
|
}
|
|
|
|
// Obtener el tabId del nodo
|
|
const tabId = getTabIdFromNode(node);
|
|
|
|
const tabName = getTabName()
|
|
|
|
// Obtener nodeType desde el atributo data-node-type
|
|
const nodeType = node.getAttribute('data-node-type');
|
|
|
|
// Guardar los datos de la pestaña para incluir el título y la extensión
|
|
await saveTabData(tabId);
|
|
|
|
// Enviar los datos al servidor para actualizar node4
|
|
try {
|
|
const response = await fetch('/update_node4/', { // Vista ya creada en views.py
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': getCSRFToken(),
|
|
},
|
|
body: JSON.stringify({
|
|
tabId: tabId,
|
|
tabName: tabName,
|
|
nodeId: node.id, // Incluir nodeId
|
|
nodeType: nodeType, // Incluir nodeType
|
|
extensionNumber: newExtensionNumber
|
|
})
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.status === 'success') {
|
|
alert("node4 actualizado exitosamente.");
|
|
} else {
|
|
alert(`Error: ${result.message}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error al actualizar node4:', error);
|
|
alert('Ocurrió un error al actualizar node4.');
|
|
}
|
|
|
|
// Cerrar el modal
|
|
modal.classList.remove("show");
|
|
background.classList.remove("show");
|
|
|
|
setTimeout(() => {
|
|
document.body.removeChild(background);
|
|
}, 300);
|
|
};
|
|
|
|
displayDiv.appendChild(saveButton);
|
|
modal.appendChild(displayDiv);
|
|
|
|
setTimeout(() => {
|
|
modal.classList.add("show");
|
|
background.classList.add("show");
|
|
}, 10);
|
|
} else if ((nodeType2 || nodeType) == "node5") {
|
|
|
|
const div_all = document.createElement('div');
|
|
div_all.classList.add('div_node5');
|
|
div_all.id = 'div_node5';
|
|
|
|
const label_select_node5 = document.createElement('p');
|
|
label_select_node5.innerText = 'Base de datos a la que deseas conectarte';
|
|
label_select_node5.classList.add('label_select_node5');
|
|
label_select_node5.id = 'label_select_node5';
|
|
div_all.append(label_select_node5);
|
|
|
|
const select_db = document.createElement('select');
|
|
select_db.classList.add('select_db');
|
|
select_db.id = 'select_db';
|
|
const options_db = [
|
|
{'value' : '', 'text' : 'Elige una opción'},
|
|
{'value' : 'mysql', 'text' : 'MySQL'},
|
|
{'value' : 'mysql', 'text' : 'MariaDB'},
|
|
{'value' : 'mssql', 'text' : 'SQL Server'},
|
|
{'value' : 'oracle', 'text' : 'OracleDB'},
|
|
{'value' : 'postgresql', 'text' : 'PostgreSQL'},
|
|
];
|
|
options_db.forEach(option => {
|
|
const optionElementDb = document.createElement('option');
|
|
optionElementDb.classList.add('optionElementDb');
|
|
optionElementDb.id = 'optionElementDb';
|
|
optionElementDb.value = option.value;
|
|
optionElementDb.textContent = option.text;
|
|
select_db.append(optionElementDb);
|
|
})
|
|
div_all.append(select_db);
|
|
|
|
const text_node5 = document.createElement('p');
|
|
text_node5.innerText = 'Nombre de la base de datos';
|
|
text_node5.classList.add('text_node5');
|
|
text_node5.id = 'text_node5';
|
|
|
|
const input_node5 = document.createElement('input');
|
|
input_node5.type = 'text';
|
|
input_node5.classList.add('input_node5');
|
|
input_node5.id = 'input_node5';
|
|
|
|
const text_node5_2 = document.createElement('p');
|
|
text_node5_2.innerText = 'Usuario de la base de datos';
|
|
text_node5_2.classList.add('text_node5_2');
|
|
text_node5_2.id = 'text_node5_2';
|
|
|
|
const input_user_node5 = document.createElement('input');
|
|
input_user_node5.type = 'text';
|
|
input_user_node5.classList.add('input_user_node5');
|
|
input_user_node5.id = 'input_user_node5';
|
|
|
|
const label_password_node5 = document.createElement('p');
|
|
label_password_node5.classList.add('label_password_node5');
|
|
label_password_node5.id = 'label_password_node5';
|
|
label_password_node5.innerText = 'Contraseña de la base de datos';
|
|
|
|
const password_node5 = document.createElement('input');
|
|
password_node5.type = 'password';
|
|
password_node5.classList.add('password_node5');
|
|
password_node5.id = 'password_node5';
|
|
|
|
const label_host_node5 = document.createElement('p');
|
|
label_host_node5.classList.add('label_host_node5');
|
|
label_host_node5.id = 'label_host_node5';
|
|
label_host_node5.innerText = 'Host de la base de datos';
|
|
|
|
const host_node5 = document.createElement('input');
|
|
host_node5.type = 'text';
|
|
host_node5.classList.add('host_node5');
|
|
host_node5.id = 'host_node5';
|
|
|
|
const label_port_node5 = document.createElement('p');
|
|
label_port_node5.classList.add('label_port_node5');
|
|
label_port_node5.id = 'label_port_node5';
|
|
label_port_node5.innerText = 'Puerto de la base de datos';
|
|
|
|
const port_node5 = document.createElement('input');
|
|
port_node5.type = 'text';
|
|
port_node5.classList.add('port_node5');
|
|
port_node5.id = 'port_node5';
|
|
|
|
const btnGuardar = document.createElement('button');
|
|
btnGuardar.classList.add('save_node5');
|
|
btnGuardar.id = 'save_node5';
|
|
btnGuardar.textContent = 'Guardar';
|
|
|
|
btnGuardar.onclick = async function () {
|
|
|
|
try {
|
|
const response = await fetch('/connect_bd/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': getCSRFToken(),
|
|
},
|
|
body: JSON.stringify({
|
|
bd: document.getElementById('select_db').value,
|
|
name_bd: document.getElementById('input_node5').value,
|
|
user_bd: document.getElementById('input_user_node5').value,
|
|
password_bd: document.getElementById('password_node5').value,
|
|
host_bd: document.getElementById('host_node5').value,
|
|
port_bd: document.getElementById('port_node5').value
|
|
})
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`Error HTTP: ${response.status}`);
|
|
}
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.status === 'success') {
|
|
alert("Conexión a la base de datos exitosa.");
|
|
} else {
|
|
alert(`Error: ${result.message}\nDetalles: ${JSON.stringify(result.details || {}, null, 2)}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error completo:', error);
|
|
alert('Error al intentar conectar con la base de datos: ' + error.message);
|
|
}
|
|
};
|
|
|
|
const elements_mysql = [
|
|
text_node5,
|
|
input_node5,
|
|
text_node5_2,
|
|
input_user_node5,
|
|
label_password_node5,
|
|
password_node5,
|
|
label_host_node5,
|
|
host_node5,
|
|
label_port_node5,
|
|
port_node5,
|
|
btnGuardar,
|
|
];
|
|
|
|
const elements_oracle = [
|
|
label_port_node5,
|
|
port_node5
|
|
];
|
|
|
|
select_db.addEventListener('change', (event) => {
|
|
const selectValue = event.target.value;
|
|
|
|
if (selectValue == 'mysql' || selectValue == 'mssql' || selectValue == 'postgresql'){
|
|
elements_mysql.forEach(element => {
|
|
div_all.append(element);
|
|
});
|
|
} else if (selectValue == 'oracle') {
|
|
elements_oracle.forEach(element => {
|
|
if (element) {
|
|
element.remove();
|
|
}
|
|
})
|
|
} else {
|
|
elements_mysql.forEach(element => {
|
|
if(element){
|
|
element.remove();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
modal.append(div_all);
|
|
} else if ((nodeType2 || nodeType) == "node6") {
|
|
|
|
const div_node6 = document.createElement('div');
|
|
div_node6.classList.add('div_node6');
|
|
div_node6.id = 'div_node6';
|
|
|
|
// Crear campo de entrada para el título del nodo
|
|
const titleLabel = document.createElement('label');
|
|
titleLabel.textContent = 'Título del nodo:';
|
|
titleLabel.style.color = 'black';
|
|
div_node6.appendChild(titleLabel);
|
|
|
|
const title_node6 = document.createElement('input');
|
|
title_node6.type = 'text';
|
|
title_node6.classList.add('title_node6');
|
|
title_node6.id = 'title_node6';
|
|
title_node6.placeholder = 'Título del nodo';
|
|
title_node6.value = node.querySelector('.node-title').textContent || '';
|
|
div_node6.appendChild(title_node6);
|
|
|
|
// Crear campo de entrada para el texto a convertir
|
|
const textLabel = document.createElement('label');
|
|
textLabel.textContent = 'Texto a convertir:';
|
|
textLabel.style.color = 'black';
|
|
div_node6.appendChild(textLabel);
|
|
|
|
const text_node6 = document.createElement('textarea'); // Cambiado a textarea para permitir textos largos
|
|
text_node6.type = 'text';
|
|
text_node6.classList.add('text_node6');
|
|
text_node6.id = 'text_node6';
|
|
text_node6.placeholder = 'Ingrese el texto para generar el audio';
|
|
text_node6.value = node.content || '';
|
|
div_node6.appendChild(text_node6);
|
|
|
|
// Mostrar el audio actual si existe
|
|
const audioPlayNode6 = document.createElement('audio');
|
|
audioPlayNode6.id = 'audioPlayerNode6';
|
|
audioPlayNode6.classList.add('audioPlayerNode6');
|
|
audioPlayNode6.controls = true;
|
|
if (node.audioFile) {
|
|
audioPlayNode6.src = node.audioFile;
|
|
}
|
|
div_node6.appendChild(audioPlayNode6);
|
|
|
|
fragment.appendChild(div_node6);
|
|
modal.appendChild(fragment);
|
|
|
|
// Evento para generar y previsualizar el audio
|
|
text_node6.addEventListener('input', (event) => {
|
|
const text = event.target.value.trim();
|
|
if (text) {
|
|
// Opcional: Mostrar una vista previa o indicar que el audio está listo
|
|
}
|
|
});
|
|
|
|
const saveButtonNode6 = document.createElement("button");
|
|
saveButtonNode6.classList.add("saveButtonNode6");
|
|
saveButtonNode6.innerText = "Generar y Guardar Audio";
|
|
|
|
saveButtonNode6.onclick = async function() {
|
|
const newTitle = title_node6.value.trim();
|
|
const text = text_node6.value.trim();
|
|
|
|
if (!newTitle || !text) {
|
|
alert("El título y el texto no pueden estar vacíos.");
|
|
return;
|
|
}
|
|
|
|
const oldTitle = node.querySelector('.node-title').textContent;
|
|
node.querySelector('.node-title').textContent = newTitle;
|
|
node.content = text; // Guardar el contenido
|
|
|
|
const tabId = getTabIdFromNode(node);
|
|
const nodeId = node.id;
|
|
const nodeType = node.getAttribute('data-node-type');
|
|
const tabName = getTabName();
|
|
|
|
// Formatear el nombre del archivo como {node_id}_{node_title}.WAV
|
|
const audioFileName = `${nodeId}_${newTitle}.WAV`;
|
|
|
|
try {
|
|
const response = await fetch('/tts_module/', { // Vista ya creada en views.py
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': getCSRFToken(),
|
|
},
|
|
body: JSON.stringify({
|
|
tabId: tabId,
|
|
title: newTitle,
|
|
text: text,
|
|
nodeId: nodeId, // Incluir nodeId
|
|
nodeType: nodeType, // Incluir nodeType
|
|
})
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.status === 'success') {
|
|
// Actualizar el audioFile del nodo6
|
|
node.audioFile = result.audioFile; // Asegurarse de que el nombre siga la estructura
|
|
audioPlayNode6.src = result.audioFile;
|
|
|
|
alert("Audio generado y guardado exitosamente.");
|
|
|
|
// Guardar los datos de la pestaña
|
|
await saveTabData(tabId);
|
|
} else {
|
|
alert(`Error: ${result.message}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error al generar el audio:', error);
|
|
alert('Ocurrió un error al generar el audio.');
|
|
}
|
|
};
|
|
|
|
div_node6.appendChild(saveButtonNode6);
|
|
|
|
const playButtonNode6 = document.createElement('button');
|
|
playButtonNode6.classList.add("playButtonNode6");
|
|
playButtonNode6.innerText = "Reproducir Audio";
|
|
|
|
playButtonNode6.onclick = function() {
|
|
if (node.audioFile) {
|
|
let audio = new Audio(node.audioFile);
|
|
audio.play();
|
|
} else {
|
|
alert("No hay audio asociado a este nodo.");
|
|
}
|
|
};
|
|
|
|
div_node6.appendChild(playButtonNode6);
|
|
|
|
modal.appendChild(saveButtonNode6);
|
|
modal.appendChild(playButtonNode6);
|
|
|
|
setTimeout(() => {
|
|
modal.classList.add("show");
|
|
background.classList.add("show");
|
|
}, 10);
|
|
} else if ((nodeType2 || nodeType) == "node7") {
|
|
const div_node7 = document.createElement('div');
|
|
div_node7.classList.add('div_node7');
|
|
div_node7.id = 'div_node7';
|
|
|
|
const label_node7 = document.createElement('p');
|
|
label_node7.classList.add('label_node7');
|
|
label_node7.id = 'label_node7';
|
|
label_node7.innerText = 'Nombre del nodo';
|
|
div_node7.append(label_node7);
|
|
|
|
const name_node7 = document.createElement('input');
|
|
name_node7.type = 'text';
|
|
name_node7.classList.add('name_node7');
|
|
name_node7.id = 'name_node7';
|
|
div_node7.append(name_node7);
|
|
|
|
const label_query = document.createElement('p');
|
|
label_query.classList.add('label_query');
|
|
label_query.id = 'label_query';
|
|
label_query.innerText = 'Consulta a la Base de datos';
|
|
div_node7.append(label_query);
|
|
|
|
const input_query = document.createElement('input');
|
|
input_query.classList.add('input_query');
|
|
input_query.id = 'input_query';
|
|
div_node7.append(input_query);
|
|
|
|
const save_node7 = document.createElement('button');
|
|
save_node7.classList.add('save_node7');
|
|
save_node7.id = 'save_node7';
|
|
save_node7.innerText = 'Consultar';
|
|
div_node7.append(save_node7);
|
|
|
|
save_node7.onclick = async function() {
|
|
const name_value = document.getElementById('name_node7').value;
|
|
const query_value = document.getElementById('input_query').value;
|
|
|
|
console.log(name_value, query_value);
|
|
|
|
try {
|
|
const response = await fetch('/query/', { // Vista ya creada en views.py
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': getCSRFToken(),
|
|
},
|
|
body: JSON.stringify({
|
|
name : name_value,
|
|
query : query_value,
|
|
})
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.status === 'success') {
|
|
console.log("Datos recibidos:", result.data);
|
|
console.log("Columnas:", result.columns);
|
|
alert("Query realizado exitosamente");
|
|
} else {
|
|
alert(`Error: ${result.message}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error al generar la respuesta del query:', error);
|
|
alert('Ocurrió un error al retornar la respuesta.');
|
|
}
|
|
};
|
|
|
|
modal.append(div_node7);
|
|
}
|
|
|
|
background.appendChild(modal);
|
|
document.body.appendChild(background);
|
|
}
|
|
|
|
// Función para obtener el tabId desde el nodo
|
|
function getTabIdFromNode(node) {
|
|
// Asumiendo que el contenedor de nodos está dentro de un elemento con id "tabNodes<tabId>"
|
|
const parent = node.closest('.tabNodes');
|
|
if (parent) {
|
|
const id = parent.id.replace('tabNodes', '');
|
|
return id;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function getTabName() {
|
|
const activeTab = document.querySelector('#tabsList .tab.active');
|
|
return activeTab ? activeTab.getAttribute('data-tab-name') : null;
|
|
}
|
|
|
|
// Función para cerrar el modal al presionar la tecla Esc
|
|
function closeModal(e) {
|
|
if (e.key === "Escape" || e.target.id === "modal-overlay") {
|
|
let background = document.getElementById("modal-overlay");
|
|
try {
|
|
document.body.removeChild(background);
|
|
} catch {
|
|
console.log("No hay modal abierto");
|
|
}
|
|
}
|
|
}
|
|
|
|
document.addEventListener('keydown', closeModal);
|
|
document.addEventListener('click', closeModal);
|
|
|
|
// Función para eliminar un nodo
|
|
async function deleteNode(node, tabId) {
|
|
const confirmDelete = confirm("¿Estás seguro de que deseas eliminar este nodo y sus conexiones?");
|
|
if (!confirmDelete) return;
|
|
|
|
const nodeId = node.id;
|
|
const nodeType = node.getAttribute('data-node-type');
|
|
|
|
console.log("Datos enviados para eliminar nodo:", { tabId, nodeId, nodeType });
|
|
|
|
try {
|
|
const response = await fetch('/delete_node/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': getCSRFToken(),
|
|
},
|
|
body: JSON.stringify({
|
|
tabId: tabId,
|
|
nodeId: nodeId,
|
|
nodeType: nodeType
|
|
})
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.status === 'success') {
|
|
// Eliminar el nodo del DOM
|
|
node.remove();
|
|
|
|
// Eliminar las conexiones asociadas
|
|
window.tabConnections[tabId] = window.tabConnections[tabId].filter(conn => {
|
|
return conn.startPoint.from.id !== nodeId && conn.endPoint.to.id !== nodeId;
|
|
});
|
|
|
|
// Actualizar el canvas
|
|
updateConnections(tabId);
|
|
alert("Nodo y sus conexiones eliminados exitosamente.");
|
|
} else {
|
|
alert(`Error: ${result.message}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error al eliminar el nodo:', error);
|
|
alert('Ocurrió un error al eliminar el nodo.');
|
|
}
|
|
}
|
|
|
|
// Función para eliminar una pestaña
|
|
async function deleteTab(tabElement) {
|
|
const confirmDelete = confirm("¿Estás seguro de que deseas eliminar esta pestaña y todos sus contenidos?");
|
|
if (!confirmDelete) return;
|
|
|
|
const tabId = tabElement.id.slice(3); // Asumiendo que el ID es 'tab<id>'
|
|
const tabName = tabElement.getAttribute('data-tab-name');
|
|
|
|
try {
|
|
const response = await fetch('/delete_tab/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': getCSRFToken(),
|
|
},
|
|
body: JSON.stringify({
|
|
tabId: tabId,
|
|
tabName: tabName
|
|
})
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.status === 'success') {
|
|
// Eliminar la pestaña y su contenido del DOM
|
|
const contentElement = document.getElementById(`content${tabId}`);
|
|
tabElement.remove();
|
|
contentElement.remove();
|
|
|
|
// Eliminar datos de conexiones y nodos almacenados en JS
|
|
delete window.tabConnections[tabId];
|
|
delete tabNodes[tabId];
|
|
|
|
alert("Pestaña eliminada exitosamente.");
|
|
} else {
|
|
alert(`Error: ${result.message}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error al eliminar la pestaña:', error);
|
|
alert('Ocurrió un error al eliminar la pestaña.');
|
|
}
|
|
}
|
|
|
|
// Exportar funciones necesarias para conexiones.js
|
|
window.initializeCanvas = initializeCanvas;
|
|
window.updateConnectionPoints = updateConnectionPoints;
|
|
window.updateConnections = updateConnections;
|
|
window.startConnection = startConnection;
|
|
window.deleteTab = deleteTab; // Exportar deleteTab para que pueda ser llamado desde el menú contextual
|