diff --git a/IVR/tab_5_conditions.json b/IVR/tab_5_conditions.json new file mode 100644 index 00000000..cbbd56fb --- /dev/null +++ b/IVR/tab_5_conditions.json @@ -0,0 +1,11 @@ +{ + "tabId": "5", + "tabName": "IVR_Principal", + "node3_conditions": [ + { + "nodeId": "node1733230736190", + "title": "Prompt y Condiciones", + "conditions": [] + } + ] +} \ No newline at end of file diff --git a/IVR/tab_6_conditions.json b/IVR/tab_6_conditions.json new file mode 100644 index 00000000..03b7e115 --- /dev/null +++ b/IVR/tab_6_conditions.json @@ -0,0 +1,27 @@ +{ + "tabId": "6", + "tabName": "Prueba", + "node3_conditions": [ + { + "nodeId": "node1733232084628", + "title": "Prompt y Condiciones", + "conditions": [ + { + "condition_string": "*", + "target_node_id": "node1733232156012", + "extensionNumber": "1000" + }, + { + "condition_string": "**", + "target_node_id": "node1733232177548", + "extensionNumber": "2000" + }, + { + "condition_string": "***", + "target_node_id": "node1733232195165", + "extensionNumber": "3000" + } + ] + } + ] +} \ No newline at end of file diff --git a/IVR/tab_7_conditions.json b/IVR/tab_7_conditions.json new file mode 100644 index 00000000..19daaa51 --- /dev/null +++ b/IVR/tab_7_conditions.json @@ -0,0 +1,27 @@ +{ + "tabId": "7", + "tabName": "Prueba2", + "node3_conditions": [ + { + "nodeId": "node1733433983845", + "title": "Prompt y Condiciones", + "conditions": [ + { + "condition_string": "*", + "target_node_id": "node1733434056630", + "extensionNumber": "1000" + }, + { + "condition_string": "**", + "target_node_id": "node1733434058542", + "extensionNumber": "2000" + }, + { + "condition_string": "***", + "target_node_id": "node1733434061078", + "extensionNumber": "3000" + } + ] + } + ] +} \ No newline at end of file diff --git a/IVR/tab_8_conditions.json b/IVR/tab_8_conditions.json new file mode 100644 index 00000000..1b86b3f4 --- /dev/null +++ b/IVR/tab_8_conditions.json @@ -0,0 +1,11 @@ +{ + "tabId": "8", + "tabName": "Prueba3", + "node3_conditions": [ + { + "nodeId": "node1733754870530", + "title": "Prompt y Condiciones", + "conditions": [] + } + ] +} \ No newline at end of file diff --git a/flow/__pycache__/urls.cpython-311.pyc b/flow/__pycache__/urls.cpython-311.pyc index e29edebd..09b660fe 100644 Binary files a/flow/__pycache__/urls.cpython-311.pyc and b/flow/__pycache__/urls.cpython-311.pyc differ diff --git a/flow/__pycache__/views.cpython-311.pyc b/flow/__pycache__/views.cpython-311.pyc index fcb41c43..be458f46 100644 Binary files a/flow/__pycache__/views.cpython-311.pyc and b/flow/__pycache__/views.cpython-311.pyc differ diff --git a/flow/data/tab_1_IVR_1.json b/flow/data/tab_1_IVR_1.json deleted file mode 100644 index 83662986..00000000 --- a/flow/data/tab_1_IVR_1.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "tabName": "IVR_1", - "nodes": [ - { - "id": "node1732650780573", - "title": "DID", - "extensionNumber": "1234", - "position": { - "top": "100px", - "left": "100px" - }, - "nodeType": "node1" - }, - { - "id": "node1732655323939", - "title": "Bienvenida", - "audioFile": "/media/tabs/tab_1/audio_files/Bienvenida_node2_node1732655323939.wav", - "position": { - "top": "101px", - "left": "373px" - }, - "nodeType": "node2" - }, - { - "id": "node1732657836004", - "title": "Prompt y Condiciones", - "content": "Chao", - "position": { - "top": "100px", - "left": "681px" - }, - "nodeType": "node3", - "textFile": "", - "conditions": [] - } - ], - "connections": [ - { - "startNodeId": "node1732650780573", - "startPortClass": "out", - "endNodeId": "node1732655323939", - "endPortClass": "in", - "isActive": false - }, - { - "startNodeId": "node1732655323939", - "startPortClass": "out", - "endNodeId": "node1732657836004", - "endPortClass": "in", - "isActive": false - } - ] -} \ No newline at end of file diff --git a/flow/data/tab_5_IVR_Principal.json b/flow/data/tab_5_IVR_Principal.json new file mode 100644 index 00000000..ad10cdc1 --- /dev/null +++ b/flow/data/tab_5_IVR_Principal.json @@ -0,0 +1,121 @@ +{ + "tabName": "IVR_Principal", + "nodes": [ + { + "id": "node1733230735070", + "title": "Extension", + "extensionNumber": "1000", + "position": { + "top": "149px", + "left": "79px" + }, + "nodeType": "node1" + }, + { + "id": "node1733230735781", + "title": "IVR", + "audioFile": "", + "position": { + "top": "149px", + "left": "325px" + }, + "nodeType": "node2" + }, + { + "id": "node1733230736190", + "title": "Prompt y Condiciones", + "content": "", + "position": { + "top": "149px", + "left": "567px" + }, + "nodeType": "node3", + "textFile": "", + "conditions": [] + }, + { + "id": "node1733230736965", + "title": "Administración", + "position": { + "top": "149px", + "left": "865px" + }, + "nodeType": "node4", + "extensionNumber": "2000" + }, + { + "id": "node1733230754214", + "title": "Tecnología", + "position": { + "top": "57px", + "left": "865px" + }, + "nodeType": "node4", + "extensionNumber": "1000" + }, + { + "id": "node1733230754725", + "title": "Comercial", + "position": { + "top": "243px", + "left": "864px" + }, + "nodeType": "node4", + "extensionNumber": "3000" + }, + { + "id": "node1733408772925", + "title": "Asesor", + "position": { + "top": "345px", + "left": "868px" + }, + "nodeType": "node4", + "extensionNumber": "4000" + } + ], + "connections": [ + { + "startNodeId": "node1733230735070", + "startPortClass": "out", + "endNodeId": "node1733230735781", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733230735781", + "startPortClass": "out", + "endNodeId": "node1733230736190", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733230736190", + "startPortClass": "out", + "endNodeId": "node1733230754214", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733230736190", + "startPortClass": "out", + "endNodeId": "node1733230754725", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733230736190", + "startPortClass": "out", + "endNodeId": "node1733230736965", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733230736190", + "startPortClass": "out", + "endNodeId": "node1733408772925", + "endPortClass": "in", + "isActive": false + } + ] +} \ No newline at end of file diff --git a/flow/data/tab_6_Prueba.json b/flow/data/tab_6_Prueba.json new file mode 100644 index 00000000..54388b90 --- /dev/null +++ b/flow/data/tab_6_Prueba.json @@ -0,0 +1,117 @@ +{ + "tabName": "Prueba", + "nodes": [ + { + "id": "node1733232048812", + "title": "DID o Extensión", + "extensionNumber": "7890", + "position": { + "top": "157px", + "left": "106px" + }, + "nodeType": "node1" + }, + { + "id": "node1733232060675", + "title": "IVR", + "audioFile": "/media/tabs/tab_6/audio_files/IVR_node2_node1733232060675.wav", + "position": { + "top": "156px", + "left": "379px" + }, + "nodeType": "node2" + }, + { + "id": "node1733232084628", + "title": "Prompt y Condiciones", + "content": "Eres un agente de servicio al cliente de telefonía y debes identificar si la persona quiere ser transferida al área de tecnología, administración o comercial. \nEn caso de tecnología devuelve 1 *.\nEn caso de Administración devuelve **.\nEn caso de Comercial devuelve ***.\n\nEs de suma importacia que los asteriscos deben ir al inicio de tú respuesta y siempre debes indicar a cuál área será transferido el cliente e indicar que fue un gusto atenderlo. Nunca puedes enviar los asteriscos solos, tienes que decir que fue un placer atenderte.", + "position": { + "top": "155px", + "left": "654px" + }, + "nodeType": "node3", + "textFile": "", + "conditions": [ + { + "condition_string": "*", + "target_node_id": "node1733232156012" + }, + { + "condition_string": "**", + "target_node_id": "node1733232177548" + }, + { + "condition_string": "***", + "target_node_id": "node1733232195165" + } + ] + }, + { + "id": "node1733232156012", + "title": "Tecnología", + "position": { + "top": "62px", + "left": "1010px" + }, + "nodeType": "node4", + "extensionNumber": "1000" + }, + { + "id": "node1733232177548", + "title": "Administración", + "position": { + "top": "181px", + "left": "1013px" + }, + "nodeType": "node4", + "extensionNumber": "2000" + }, + { + "id": "node1733232195165", + "title": "Comercial", + "position": { + "top": "290px", + "left": "1015px" + }, + "nodeType": "node4", + "extensionNumber": "3000" + } + ], + "connections": [ + { + "startNodeId": "node1733232048812", + "startPortClass": "out", + "endNodeId": "node1733232060675", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733232060675", + "startPortClass": "out", + "endNodeId": "node1733232084628", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733232084628", + "startPortClass": "out", + "endNodeId": "node1733232156012", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733232084628", + "startPortClass": "out", + "endNodeId": "node1733232177548", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733232084628", + "startPortClass": "out", + "endNodeId": "node1733232195165", + "endPortClass": "in", + "isActive": false + } + ] +} \ No newline at end of file diff --git a/flow/data/tab_7_Prueba2.json b/flow/data/tab_7_Prueba2.json new file mode 100644 index 00000000..b171909e --- /dev/null +++ b/flow/data/tab_7_Prueba2.json @@ -0,0 +1,117 @@ +{ + "tabName": "Prueba2", + "nodes": [ + { + "id": "node1733433839548", + "title": "Número extensión", + "extensionNumber": "4562", + "position": { + "top": "147px", + "left": "111px" + }, + "nodeType": "node1" + }, + { + "id": "node1733433894348", + "title": "Cupula", + "audioFile": "/media/tabs/tab_7/audio_files/Cupula_node2_node1733433894348.wav", + "position": { + "top": "147px", + "left": "378px" + }, + "nodeType": "node2" + }, + { + "id": "node1733433983845", + "title": "Prompt y Condiciones", + "content": "Eres un agente de servicio al cliente de telefonía y debes identificar si la persona quiere ser transferida al área de tecnología, administración o comercial. \nEn caso de tecnología devuelve 1 *.\nEn caso de Administración devuelve **.\nEn caso de Comercial devuelve ***.\n\nEs de suma importacia que los asteriscos deben ir al inicio de tú respuesta y siempre debes indicar a cuál área será transferido el cliente e indicar que fue un gusto atenderlo. Nunca puedes enviar los asteriscos solos, tienes que decir que fue un placer atenderte.", + "position": { + "top": "147px", + "left": "629px" + }, + "nodeType": "node3", + "textFile": "", + "conditions": [ + { + "condition_string": "*", + "target_node_id": "node1733434056630" + }, + { + "condition_string": "**", + "target_node_id": "node1733434058542" + }, + { + "condition_string": "***", + "target_node_id": "node1733434061078" + } + ] + }, + { + "id": "node1733434056630", + "title": "Tecnología", + "position": { + "top": "55px", + "left": "947px" + }, + "nodeType": "node4", + "extensionNumber": "1000" + }, + { + "id": "node1733434058542", + "title": "Administración", + "position": { + "top": "157px", + "left": "947px" + }, + "nodeType": "node4", + "extensionNumber": "2000" + }, + { + "id": "node1733434061078", + "title": "Comercial", + "position": { + "top": "253px", + "left": "947px" + }, + "nodeType": "node4", + "extensionNumber": "3000" + } + ], + "connections": [ + { + "startNodeId": "node1733433839548", + "startPortClass": "out", + "endNodeId": "node1733433894348", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733433894348", + "startPortClass": "out", + "endNodeId": "node1733433983845", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733433983845", + "startPortClass": "out", + "endNodeId": "node1733434056630", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733433983845", + "startPortClass": "out", + "endNodeId": "node1733434058542", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733433983845", + "startPortClass": "out", + "endNodeId": "node1733434061078", + "endPortClass": "in", + "isActive": false + } + ] +} \ No newline at end of file diff --git a/flow/data/tab_8_Prueba3.json b/flow/data/tab_8_Prueba3.json new file mode 100644 index 00000000..81abaa03 --- /dev/null +++ b/flow/data/tab_8_Prueba3.json @@ -0,0 +1,70 @@ +{ + "tabName": "Prueba3", + "nodes": [ + { + "id": "node1733497381839", + "title": "Extensión", + "extensionNumber": "9999", + "position": { + "top": "100px", + "left": "100px" + }, + "nodeType": "node1" + }, + { + "id": "node1733497412734", + "title": "IVR", + "audioFile": "/media/tabs/tab_8/audio_files/IVR_node2_node1733497412734.wav", + "position": { + "top": "98px", + "left": "378px" + }, + "nodeType": "node2" + }, + { + "id": "node1733754870530", + "title": "Prompt y Condiciones", + "content": "", + "position": { + "top": "95px", + "left": "690px" + }, + "nodeType": "node3", + "textFile": "", + "conditions": [] + }, + { + "id": "node1733754876681", + "title": "Pruebita 1", + "position": { + "top": "94px", + "left": "983px" + }, + "nodeType": "node4", + "extensionNumber": "1000" + } + ], + "connections": [ + { + "startNodeId": "node1733497381839", + "startPortClass": "out", + "endNodeId": "node1733497412734", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733497412734", + "startPortClass": "out", + "endNodeId": "node1733754870530", + "endPortClass": "in", + "isActive": false + }, + { + "startNodeId": "node1733754870530", + "startPortClass": "out", + "endNodeId": "node1733754876681", + "endPortClass": "in", + "isActive": false + } + ] +} \ No newline at end of file diff --git a/flow/static/css/flow.css b/flow/static/css/flow.css index c54444be..1dccc71b 100644 --- a/flow/static/css/flow.css +++ b/flow/static/css/flow.css @@ -1,20 +1,30 @@ /* flow.css */ body { - background-color: black; + --grid-size: 50px; + + background-color: white; + + background-image: + linear-gradient(to right, rgba(0,0,0,0.2) 1px, transparent 1px), + linear-gradient(to bottom, rgba(0,0,0,0.2) 1px, transparent 1px); + + background-size: var(--grid-size) var(--grid-size); + + min-height: 100vh; + margin: 0; } .right_sidebar{ - height: 99.9%; + height: 100%; width: 180px; - background: black; + background: rgba(255,255,255,0.5); position: absolute; top: 0px; right: 0; padding: 0 10px; z-index: 2; - border-left: 1px solid white; - border-bottom: 1px solid white; + border-left: 1px solid black; } .node { @@ -30,16 +40,20 @@ body { z-index: 1; } -#node1, [data-node-id="node1"] { - background-color: lightblue; +#node1, [data-node-type="node1"] { + background-color: #004D40; } -#node2, [data-node-id="node2"] { - background-color: lightgreen; +#node2, [data-node-type="node2"] { + background-color: #00BFA5; } -#node3, [data-node-id="node3"] { - background-color: lightsalmon; +#node3, [data-node-type="node3"] { + background-color: #DDDDDD; +} + +#node4, [data-node-type="node4"] { + background: #1DE9B6; } .slice_node { @@ -59,7 +73,7 @@ body { .port { width: 10px; height: 10px; - background-color: white; + background-color: black; border-radius: 50%; position: absolute; user-select: none; diff --git a/flow/static/css/tabs.css b/flow/static/css/tabs.css index 533b41db..182aea87 100644 --- a/flow/static/css/tabs.css +++ b/flow/static/css/tabs.css @@ -1,11 +1,14 @@ /* tabs.css */ body { - font-family: Arial, sans-serif; + font-family: "Markazi Text", serif; + font-size: 20px; } .container_create { + margin: 5px 3px 0 5px; display: flex; - max-height: 55px; + max-height: 45px; + position: absolute; } #tabsContainer { @@ -16,10 +19,11 @@ body { list-style-type: none; display: flex; padding: 0; + margin: 0; } #tabsList li { - margin: 0 5px; + margin: 0 2px; padding: 10px; background-color: #f0f0f0; cursor: pointer; @@ -44,17 +48,18 @@ body { #createTabButton { padding: 10px 20px; - background-color: #4CAF50; + background-color: #00796B; color: white; border: none; border-radius: 5px; cursor: pointer; height: auto; z-index: 1; + transition: all 0.5s ease; } #createTabButton:hover { - background-color: #45a049; + background-color: #004139; } button { @@ -74,6 +79,7 @@ button { } .modal { + z-index: 1; display: flex; flex-wrap: wrap; width: 300px; @@ -110,6 +116,7 @@ button { } .background { + z-index: 2; position: fixed; top: 0; left: 0; @@ -131,36 +138,39 @@ button { } .btnGuardar { - width: 100px; - height: 30px; + font-size: 18px; + width: 110px; + height: 50px; + color: white; border: none; border-radius: 10px; cursor: pointer; position: fixed; bottom: 30px; - right: 50px; + right: 45px; + background: #155b40; transition: all 1s ease; } .btnGuardar:hover { - background: radial-gradient(white, lightgoldenrodyellow); - filter: drop-shadow(lightgoldenrodyellow 10px 10px 10px); + background: radial-gradient(#10a169, #155b40); + filter: drop-shadow(#10a169 10px 10px 10px); } [data-node-type="node1"] { - background: lightblue; + background-color: #004D40; } [data-node-type="node2"] { - background: lightgreen; + background-color: #00BFA5; } [data-node-type="node3"] { - background: lightsalmon; + background-color: #DDDDDD; } [data-node-type="node4"] { - background: lightseagreen; + background: #1DE9B6; } .conditions-container { diff --git a/flow/static/js/connections.js b/flow/static/js/connections.js index da5fa6bf..7e0a54e0 100644 --- a/flow/static/js/connections.js +++ b/flow/static/js/connections.js @@ -168,7 +168,7 @@ function drawLine(x1, y1, x2, y2, tabId) { ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); - ctx.strokeStyle = '#FFFFFF'; + ctx.strokeStyle = '#000000'; ctx.lineWidth = 2; ctx.stroke(); ctx.closePath(); diff --git a/flow/static/js/flow_doc.js b/flow/static/js/flow_doc.js index d6d20c38..8740d870 100644 --- a/flow/static/js/flow_doc.js +++ b/flow/static/js/flow_doc.js @@ -118,13 +118,13 @@ function createNode(e, tabId) { // Asignar puertos en base al tipo de nodo if (node_type === "node1") { - element.style.background = "lightblue"; + element.style.background = "#004D40"; 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 = "lightgreen"; + element.style.background = "#00BFA5"; element.setAttribute('data-node-type', 'node2'); const portIn = document.createElement('div'); portIn.className = 'port port-in'; @@ -133,7 +133,7 @@ function createNode(e, tabId) { portOut.className = 'port port-out'; element.appendChild(portOut); } else if (node_type === "node3") { - element.style.background = "lightsalmon"; + element.style.background = "#DDDDDD"; element.setAttribute('data-node-type', 'node3'); const portIn = document.createElement("div"); portIn.className = "port port-in"; @@ -142,7 +142,7 @@ function createNode(e, tabId) { portOut.className = "port port-out"; element.appendChild(portOut); // Añadimos un puerto de salida } else if (node_type === "node4") { - element.style.background = "lightseagreen"; // Cambiar color a lightseagreen + element.style.background = "#1DE9B6"; // Cambiar color a lightseagreen element.setAttribute('data-node-type', 'node4'); const displayElement = document.createElement('div'); displayElement.className = 'display-extension'; @@ -834,9 +834,14 @@ function openModal(e, node) { // 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 @@ -847,6 +852,7 @@ function openModal(e, node) { }, body: JSON.stringify({ tabId: tabId, + tabName: tabName, nodeId: node.id, // Incluir nodeId nodeType: nodeType, // Incluir nodeType extensionNumber: newExtensionNumber @@ -865,16 +871,6 @@ function openModal(e, node) { alert('Ocurrió un error al actualizar node4.'); } - // Actualizar el título en el backend si cambió - if (newAreaName !== oldTitle) { - // Enviar solicitud para actualizar el título del nodo4 - // Esto podría hacerse a través de otra vista si es necesario - // Por ahora, asumimos que el título ya se actualizó en el frontend - } - - // 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"); diff --git a/flow/static/js/tabs.js b/flow/static/js/tabs.js index 3e631511..759a8c4b 100644 --- a/flow/static/js/tabs.js +++ b/flow/static/js/tabs.js @@ -73,9 +73,12 @@ async function loadExistingTabs() { const response = await fetch('/list-tabs/'); if (response.ok) { const data = await response.json(); + let maxTabId = 0; for (const tab of data.tabs) { await createNewTab(tab.name, tab.id); + maxTabId = Math.max(maxTabId, parseInt(tab.id)); } + tabCount = maxTabId; // Establecer tabCount al ID máximo existente } else { console.error('Error al cargar las pestañas existentes'); } @@ -85,8 +88,15 @@ async function loadExistingTabs() { } async function createNewTab(tabName, existingTabId = null) { - tabCount++; - const tabId = existingTabId || tabCount; + let tabId; + if (existingTabId) { + // Usar el ID existente sin incrementar tabCount + tabId = existingTabId; + } else { + // Incrementar tabCount y asignarlo como nuevo ID + tabCount++; + tabId = tabCount; + } const tabList = document.getElementById("tabsList"); const tabContent = document.getElementById("tabContent"); @@ -126,7 +136,7 @@ async function createNewTab(tabName, existingTabId = null) {