Spaces:
Runtime error
Runtime error
| class WindowHandler{ | |
| /* Eventos generados | |
| - chat:enviar | |
| - chat:eliminar | |
| **********************/ | |
| /* Eventos escuchados | |
| **********************/ | |
| conversacion = [] | |
| constructor(conversacion, index, chatHndl){ | |
| // El indice de este chat | |
| this.index = index | |
| this.conversacion = conversacion | |
| this.chatHandler = chatHndl || 0 | |
| // Template de mensajes | |
| this.templateMsg = $("#template-message").contents("div.message").clone() | |
| this.tabs = $(".tabs") | |
| this.templateLabel = $("#template-label").contents("label").clone() | |
| this.templateTab = $("#template-tab").contents("div.tab").clone() | |
| this.chatbox = this.templateTab.find(".chat") | |
| // Parametros base | |
| this.active = false; | |
| // ha tenido su primera interacci贸n | |
| this.interacted = false | |
| this.crearVentanaChat(index, "Tab "+ index) | |
| this.cargarEventos(); | |
| $(document).trigger("ventana:cambiada") | |
| this.cargarChat(conversacion) | |
| } | |
| crearVentanaChat(index, nombre){ | |
| // coloca el valor al input y lo selecciona | |
| let newLabel = this.templateLabel.clone() | |
| newLabel.find("input").val(index).prop("checked", true); | |
| newLabel.find("> div").text(nombre) | |
| this.tabs.append(newLabel) | |
| this.label = newLabel | |
| // Crea la ventana de chat | |
| let tempTab = this.templateTab.clone(); | |
| tempTab.attr("id", index) | |
| $(".chats").append(tempTab) | |
| // establece los contextos de ventana | |
| this.ctx = tempTab | |
| this.chatbox = this.ctx.find(".chat"); | |
| this.ventanaSeleccionada() | |
| } | |
| ventanaSeleccionada(){ | |
| // cuando la ventana es seleccionada, cambia | |
| $(".tab").removeClass("active") | |
| this.label.find("input")[0].checked=true; | |
| this.ctx.addClass("active"); | |
| } | |
| cargarEventos(){ | |
| this.label.click(()=> this.ventanaSeleccionada()) | |
| this.ctx.find(".input-text").keypress((event) => { | |
| if (!event.shiftKey && event.keyCode === 13) { | |
| this.manejadorEnviar(); | |
| } | |
| this.recalcularTextarea() | |
| }); | |
| this.ctx.find(".input-send").click(() => this.manejadorEnviar()); | |
| this.ctx.find(".input-text").on("keyup,keydown", () => this.recalcularTextarea()); | |
| this.ctx.find(".input-delete").click(() => this.eliminarChat() ) | |
| this.ctx.find(".input-menu").click(() => $(document).trigger("mostrar:opciones")) | |
| } | |
| crearMensaje(texto, user){ | |
| this.active = this.templateMsg.clone(); | |
| switch(user){ | |
| case "system": | |
| return; | |
| case "user": | |
| this.active.addClass("me"); | |
| this.active.find("div p").text(texto); | |
| break; | |
| case "assistant": | |
| texto = this.procesarTexto(texto); | |
| this.active.find("div p").html(texto); | |
| Prism.highlightAllUnder(this.active[0]) | |
| break; | |
| case "loading": | |
| this.active.find("div p").html('<div class="loader-wrap"><span class="loader"></span></div>'); | |
| break; | |
| } | |
| this.chatbox.append(this.active); | |
| this.chatbox.scrollTop(this.chatbox[0].scrollHeight); | |
| this.interacted=true | |
| return this.active | |
| } | |
| manejadorEnviar(){ | |
| let mensaje = this.ctx.find(".input-text").val(); | |
| this.ctx.find("button").prop("disabled", true); | |
| this.ctx.find("textarea").prop("disabled", true); | |
| if(mensaje==""){ | |
| return false; | |
| } | |
| if(this.conversacion.length==0){ | |
| this.conversacion.push({role:"system", content: this.chatHandler.config.assistantPrompt}) | |
| } | |
| this.conversacion.push({role: "user", content: mensaje}) | |
| self = this | |
| this.crearMensaje(mensaje, "user"); | |
| $(document).trigger("chat:enviar", {ctx: self, conversacion:this.conversacion}) | |
| } | |
| respuestaInicio(){ | |
| this.crearMensaje("", "loading"); | |
| } | |
| respuestaStatus(mensaje, modo=false){ | |
| let temp = $("<div></div>") | |
| temp.text(mensaje) | |
| if(!this.active.find(".loader").hasClass("firststage")){ | |
| this.active.find(".loader").addClass("firststage") | |
| } | |
| switch(modo){ | |
| case "enlinea": | |
| this.active.find("div p div:last-child").text(this.active.find("div p div:last-child").text() + mensaje); | |
| break; | |
| case "reemplazar": | |
| this.active.find("div p div:not(.loader-wrap)").remove(); | |
| this.active.find("div p").append(temp) | |
| break; | |
| default: | |
| this.active.find("div p").append(temp) | |
| } | |
| this.chatbox.scrollTop(this.chatbox[0].scrollHeight); | |
| } | |
| respuestaMensaje(data){ | |
| let mensaje = data.content | |
| this.active.find("div p").html(""); | |
| mensaje = this.procesarTexto(mensaje); | |
| this.active.find("div p").html(mensaje); | |
| Prism.highlightAllUnder(this.active[0]); | |
| this.chatbox.scrollTop(this.chatbox[0].scrollHeight); | |
| this.conversacion.push(data) | |
| this.active = false; | |
| this.interacted = true; | |
| this.ctx.find("button").prop("disabled", false); | |
| this.ctx.find("textarea").prop("disabled", false); | |
| this.ctx.find("textarea").val("") | |
| this.ctx.find("textarea").focus(); | |
| $(document).trigger("chat:salvar", {index: this.index, conversacion: this.conversacion}) | |
| } | |
| respuestaError(error){ | |
| this.ctx.find("button").prop("disabled", false); | |
| this.ctx.find("textarea").prop("disabled", false); | |
| this.ctx.find("textarea").val("") | |
| this.ctx.find("textarea").focus(); | |
| if(error.hasOwnProperty("responseJSON")){ | |
| this.active.find("div p").html(error.responseJSON.detail) | |
| }else{ | |
| this.active.find("div p").html("El API no responde, la conexi贸n pudo haberse caido") | |
| } | |
| switch(error.status | 0){ | |
| case 404: | |
| this.active.addClass("error") | |
| break; | |
| case 408: | |
| this.active.addClass("warning") | |
| break; | |
| default: | |
| this.active.addClass("error") | |
| } | |
| this.active = false; | |
| this.chatbox.scrollTop(this.chatbox[0].scrollHeight) | |
| } | |
| cargarChat(conversacion){ | |
| for(let mensaje of this.conversacion){ | |
| this.crearMensaje(mensaje.content, mensaje.role) | |
| } | |
| } | |
| eliminarChat(){ | |
| if(confirm("驴Est谩s seguro que quieres eliminar esta conversaci贸n?")){ | |
| this.label.remove() | |
| this.ctx.remove() | |
| $(document).trigger("chat:eliminar", {ctx:this.ctx, index:this.index}) | |
| } | |
| } | |
| recalcularTextarea(){ | |
| this.ctx.find(".input-box").css("height", "30px"); | |
| let height = parseInt((this.ctx.find(".input-text").prop('scrollHeight')+15)/15)*15; | |
| this.ctx.find(".input-box").css("height", height+"px"); | |
| height -= 30; | |
| this.ctx.find(".chat").css("--textarea", height+"px"); | |
| } | |
| procesarTexto(texto){ | |
| let resultado = ""; | |
| let codigo = false; | |
| for(let actual of texto.split("```")){ | |
| if(codigo){ | |
| let temp = actual.split("\n",1); | |
| resultado += "<pre><code class='language-"; | |
| resultado += temp[0].length>1?temp[0]:"none"; | |
| temp = $("<div></div>").text(actual.substr(temp[0].length+1)).html() | |
| resultado += "'>"+temp+"</code></pre>"; | |
| }else{ | |
| resultado += $("<div></div>").text(actual).html().replace(/`([^`]+?)`/gm, "<b>$1</b>").replace(/\n/g, "<br>"); | |
| resultado = resultado.replace(/\[(.*?)\]\((.*?)\)/gm, "[<a href='$2' target='_blank'>$1</a>]") | |
| } | |
| codigo = !codigo; | |
| } | |
| return resultado | |
| } | |
| } |