From 441c702de9e0f4ddddc1ad2444c41a76fc2b08d4 Mon Sep 17 00:00:00 2001 From: gneb Date: Sun, 26 Mar 2023 18:57:55 +0400 Subject: [PATCH] topics --- src/scrpt.js | 91 ++++++++++++++++++++++++++++++++++++++++++------ src/scrpt.min.js | 2 +- 2 files changed, 81 insertions(+), 12 deletions(-) diff --git a/src/scrpt.js b/src/scrpt.js index 4f29356..fba4dd2 100644 --- a/src/scrpt.js +++ b/src/scrpt.js @@ -2,13 +2,14 @@ const xPositions = ['left', 'right']; const yPositions = ['top', 'bottom']; const nm = 'scrpt'; const chatWidth = '400px'; -const domain = 'http://164.90.239.9:8000'; +const domain = 'http://161.35.71.150'; class Scrpt { loadInterval; constructor({ position = 'bottom-right', appName = '' } = {}) { this.position = this.getPosition(position); this.open = false; this.inputText = ''; + this.topics = []; this.appName = appName; if (!position.includes('-')) { @@ -97,7 +98,9 @@ class Scrpt { const styleTag = this.dce('style'); document.head.appendChild(styleTag); styleTag.innerHTML = ` - .${nm}-clearfix::after {content: "";clear: both;display: table;}.${nm}-icon {cursor: pointer;width: 65%;position: absolute;top: 11px;left: 13px;transition: transform .3s ease;filter: invert(1);}.${nm}-hidden {transform: scale(0);}.${nm}-button-container {background: linear-gradient(to bottom right, #4294e3, #8f12fd);width: 70px;height: 70px;border-radius: 50%;}.${nm}-chat-container {box-shadow: 0 0 18px 8px rgba(0,0,0, 0.1);right: -25px;bottom: 75px;position: absolute;transition: max-height .2s ease;background-color: white;border-radius: 10px;}.${nm}-chat-container.hidden {max-height: 0px;}.${nm}-scrpt-header {display: inline-block;width: 100%;margin: 0;padding: 10px;color: white;background: linear-gradient(to bottom right, #4294e3, #8f12fd);border-top-left-radius: 10px;border-top-right-radius: 10px;}.${nm}-chat-container form input {padding: 20px;display: inline-block;width: calc(100% - 50px);border: 0px;background-color: #f7f7f7;}.${nm}-chat-container form input:focus {outline: none;}.${nm}-chat-send {cursor: pointer;display: inline-block;padding: 20px 14px;background-color: #f7f7f7;}.${nm}-scrpt-chat-bottom-menu {padding-top: 20px;list-style-type: none;text-align: center;padding-left: 0px;margin-left: 0px;}.${nm}-scrpt-chat-bottom-menu li {display: inline-block;padding-left: 30px;padding-right: 30px;cursor: pointer;}.${nm}-bottom-menu-icon {padding-bottom: 8px;display: inline-block; width: 20px;}.${nm}-chat-content {display: block;width: 100%;padding: 10px;overflow-y: scroll;position: relative;box-shadow: 0 4px 2px -2px rgba(0,0,0, 0.1);}.${nm}-close-button, .${nm}-fullscreen-button {border: 0px;background-color: white;border-radius: 100%;padding-bottom: 3px;float: right;margin-left: 4px;}.${nm}-msg-box {display: inline-block;width:80%;}.${nm}-msg-box p {padding: 7px;}.${nm}-income {float: left;}.${nm}-outcome {float: right;}.${nm}-bubble-outcome {background-color: gray;color: white;border-top-left-radius: 10px;border-top-right-radius: 10px;border-bottom-left-radius: 10px;}.${nm}-bubble-income {background-color: #f7f7f7;color: #424242;border-top-left-radius: 10px;border-top-right-radius: 10px;border-bottom-right-radius: 10px;} + .${nm}-clearfix::after {content: "";clear: both;display: table;}.${nm}-topics{position:absolute; right:0;bottom:0; padding:0 13px 10px 0; margin-bottom:150px; z-index:11} .${nm}-topics-tags{height:0px;padding-left: 5px; + list-style-type: none;display: block;overflow-y: scroll;position: absolute;bottom: 0; transition:transform .3s ease;margin-bottom: 180px; z-index:10}.${nm}-topics-tags li{ display:inline-block; float:left; margin-left: 5px;padding: 2px; background: linear-gradient(to bottom right, #4294e3, #8f12fd); +color: white;border-radius: 7px;font-size: 14px;margin-bottom: 3px;} .${nm}-icon {cursor: pointer;width: 65%;position: absolute;top: 11px;left: 13px;transition: transform .3s ease;filter: invert(1);}.${nm}-hidden {transform: scale(0);}.${nm}-button-container {background: linear-gradient(to bottom right, #4294e3, #8f12fd);width: 70px;height: 70px;border-radius: 50%;}.${nm}-chat-container {box-shadow: 0 0 18px 8px rgba(0,0,0, 0.1);right: -25px;bottom: 75px;position: absolute;transition: max-height .2s ease;background-color: white;border-radius: 10px;}.${nm}-chat-container.hidden {max-height: 0px;}.${nm}-scrpt-header {display: inline-block;width: 100%;margin: 0;padding: 10px;color: white;background: linear-gradient(to bottom right, #4294e3, #8f12fd);border-top-left-radius: 10px;border-top-right-radius: 10px;}.${nm}-chat-container form input {padding: 20px;display: inline-block;width: calc(100% - 50px);border: 0px;background-color: #f7f7f7;}.${nm}-chat-container form input:focus {outline: none;}.${nm}-chat-send {cursor: pointer;display: inline-block;padding: 20px 14px;background-color: #f7f7f7;}.${nm}-scrpt-chat-bottom-menu {padding-top: 20px;list-style-type: none;text-align: center;padding-left: 0px;margin-left: 0px;}.${nm}-scrpt-chat-bottom-menu li {display: inline-block;padding-left: 30px;padding-right: 30px;cursor: pointer;}.${nm}-bottom-menu-icon {padding-bottom: 8px;display: inline-block; width: 20px;}.${nm}-chat-content {display: block;width: 100%;padding: 10px;overflow-y: scroll;position: relative;box-shadow: 0 4px 2px -2px rgba(0,0,0, 0.1);}.${nm}-close-button, .${nm}-fullscreen-button {border: 0px;background-color: white;border-radius: 100%;padding-bottom: 3px;float: right;margin-left: 4px;}.${nm}-msg-box {display: inline-block;width:80%;}.${nm}-msg-box p {padding: 7px;}.${nm}-income {float: left;}.${nm}-outcome {float: right;}.${nm}-bubble-outcome { background: linear-gradient(to bottom right, #4294e3, #8f12fd);color: white;border-top-left-radius: 10px;border-top-right-radius: 10px;border-bottom-left-radius: 10px;}.${nm}-bubble-income {background-color: #f7f7f7;color: #424242;border-top-left-radius: 10px;border-top-right-radius: 10px;border-bottom-right-radius: 10px;} `; } @@ -136,6 +139,10 @@ class Scrpt { text.type = "text"; text.placeholder = this.inputText; + this.topicsTags = this.dce('ul'); + this.topicsTags.setAttribute('id', `${nm}-topics-tags`); + this.topicsTags.classList.add(`${nm}-topics-tags`); + let btnDiv = this.dce('div'); this.btn = this.dce('img'); this.btn.src = `https://icons.getbootstrap.com/assets/icons/send.svg`; @@ -145,13 +152,22 @@ class Scrpt { this.chatContent = this.dce('div'); this.chatContent.classList.add(`${nm}-chat-content`); + + this.topicBtn = this.dce('img'); + this.topicBtn.classList.add(`${nm}-topics`); + this.topicBtn.setAttribute('role', 'button'); + this.topicBtn.setAttribute('id', `${nm}-topics-img`); + this.topicBtn.src = 'https://icons.getbootstrap.com/assets/icons/book.svg'; + this.chatContainer.appendChild(this.topicBtn); + this.chatContainer.appendChild(this.topicsTags); form.appendChild(this.chatContent); form.appendChild(clrfx); - + this.listTopics(); form.appendChild(text); form.appendChild(btnDiv); form.addEventListener('submit', this.submit.bind(this)); + document.body.addEventListener('click', (event) => this.handleTopics(this, event)); const bottomMenuContainer = this.dce('ul'); bottomMenuContainer.classList.add(`${nm}-scrpt-chat-bottom-menu`); @@ -161,21 +177,28 @@ class Scrpt { icon: `https://icons.getbootstrap.com/assets/icons/house.svg`, text: 'Home', click: function () { - alert(this.text); + // alert(this.text); } }, + // { + // icon: `https://icons.getbootstrap.com/assets/icons/book.svg`, + // text: 'Topics', + // click: function () { + // alert(1); + // } + // }, { icon: this.chatIcon.src, text: 'Chat', click: function () { - alert(this.text); + // alert(this.text); } }, { icon: `https://icons.getbootstrap.com/assets/icons/question-circle.svg`, text: 'Help', click: function () { - alert(this.text); + // alert(this.text); } }, ]; @@ -185,6 +208,7 @@ class Scrpt { let span = this.dce('img'); span.classList.add(`${nm}-bottom-menu-icon`); span.src = item.icon; + span.onclick = item.click; li.appendChild(span); let br = this.dce('br'); li.appendChild(br); @@ -202,18 +226,24 @@ class Scrpt { async submit(e) { e.preventDefault(); - let id = this.generateUniqueId(); let inpt = document.getElementById(`${nm}-text`); let q = inpt.value; if (q.trim() === '') { return; } - this.chatContent.innerHTML += this.chatStripe(false, q, ''); inpt.disabled = true; inpt.value = ''; + + await this.sendQuestion(q); + + } + + async sendQuestion(q) { + let id = this.generateUniqueId(); + this.chatContent.innerHTML += this.chatStripe(false, q, ''); this.btn.disabled = true; this.blurAll(); - let result = await this.makeRequest("POST", `${domain}/api/answer/${this.appName}`, { + let result = await this.makeRequest("POST", `${domain}/api/projects/${this.appName}/answer`, { question: q }); result = JSON.parse(result); @@ -221,7 +251,6 @@ class Scrpt { const messageDiv = document.getElementById(id); this.typeText(messageDiv, result.answer); - } toggleOpen() { @@ -231,6 +260,45 @@ class Scrpt { } else { this.closeChat(); } + + } + + listTopics() { + this.topicsTags.innerHTML = ''; + this.topics.map((item) => { + const singleTopic = this.dce('li'); + singleTopic.setAttribute('role', 'button'); + singleTopic.innerText = item.title; + singleTopic.onclick = async (e) => { + if (this.topics.length > 0) { + let idx = this.topics.findIndex(item => { return item.title === e.target.innerText }); + this.topics.splice(idx, 1); + this.listTopics(); + this.toggleTopics(); + await this.sendQuestion(`Tell me more about ${item.title}`); + + } + + }; + this.topicsTags.appendChild(singleTopic); + }); + } + + handleTopics(obj, e) { + if (e.target.id == `${nm}-topics-img`) { + this.toggleTopics(); + }; + } + + toggleTopics() { + let tagsElement = document.getElementById(`${nm}-topics-tags`); + if (tagsElement.clientHeight === 0) { + tagsElement.style.height = '84px'; + this.topicBtn.src = `https://icons.getbootstrap.com/assets/icons/x.svg`; + } else { + tagsElement.style.height = '0px'; + this.topicBtn.src = `https://icons.getbootstrap.com/assets/icons/book.svg`; + } } fullscreenchat() { @@ -293,10 +361,11 @@ class Scrpt { async getChatInitialData(appName) { - let result = await this.makeRequest("GET", `${domain}/api/project/${appName}/init`); + let result = await this.makeRequest("GET", `${domain}/api/projects/${appName}/init`); let data = JSON.parse(result); this.welcomeMessage = data.data.welcome_message; this.inputText = data.data.input_text; + this.topics = data.topics; } dce(el) { diff --git a/src/scrpt.min.js b/src/scrpt.min.js index 4acb217..ea6f9d9 100644 --- a/src/scrpt.min.js +++ b/src/scrpt.min.js @@ -1 +1 @@ -const xPositions = ["left", "right"], yPositions = ["top", "bottom"], nm = "scrpt", chatWidth = "400px", domain = "http://164.90.239.9:8000"; class Scrpt { loadInterval; constructor({ position: t = "bottom-right", appName: e = "" } = {}) { if (this.position = this.getPosition(t), this.open = !1, this.inputText = "", this.appName = e, !t.includes("-")) throw new Error("position must include - symbol. for example bottom-right"); if (!yPositions.includes(t.split("-")[0])) throw new Error("y position must be top or bottom"); if (!xPositions.includes(t.split("-")[1])) throw new Error("x position must be left or right"); if ("" === e) throw new Error("invalid app name"); this.getChatInitialData(e).then((t => { this.initialize() })), this.createStyles() } detectMob() { return [/Android/i, /webOS/i, /iPhone/i, /iPad/i, /iPod/i, /BlackBerry/i, /Windows Phone/i].some((t => navigator.userAgent.match(t))) } getPosition(t) { const [e, i] = t.split("-"); return { [e]: "40px", [i]: "40px" } } initialize() { const t = this.dce("div"); t.style.position = "fixed", t.style.zIndex = "9999", Object.keys(this.position).forEach((e => t.style[e] = this.position[e])), document.body.appendChild(t); const e = this.dce("div"); e.classList.add(`${nm}-button-container`); const i = this.dce("img"); i.src = "https://icons.getbootstrap.com/assets/icons/chat-dots.svg", i.classList.add(`${nm}-icon`), this.chatIcon = i; const n = this.dce("img"); n.src = "https://icons.getbootstrap.com/assets/icons/x.svg", n.classList.add(`${nm}-icon`, `${nm}-hidden`), this.closeIcon = n, this.chatContainer = this.dce("div"), this.chatContainer.classList.add(`${nm}-hidden`, `${nm}-chat-container`), this.chatContainer.style.width = this.detectMob() ? window.innerWidth - 15 + "px" : "400px", this.chatContainer.style.bottom = this.detectMob() ? "-18px" : "75px", this.createChatContainerContent(), this.chatContent.style.height = this.detectMob() ? window.innerHeight - 230 + "px" : "500px", e.appendChild(this.chatIcon), e.appendChild(this.closeIcon), e.addEventListener("click", this.toggleOpen.bind(this)), t.appendChild(this.chatContainer), t.appendChild(e), this.chatContent.innerHTML += this.chatStripe(!0, this.welcomeMessage, "") } createStyles() { const t = this.dce("style"); document.head.appendChild(t), t.innerHTML = `\n .${nm}-clearfix::after {content: "";clear: both;display: table;}.${nm}-icon {cursor: pointer;width: 65%;position: absolute;top: 11px;left: 13px;transition: transform .3s ease;filter: invert(1);}.${nm}-hidden {transform: scale(0);}.${nm}-button-container {background: linear-gradient(to bottom right, #4294e3, #8f12fd);width: 70px;height: 70px;border-radius: 50%;}.${nm}-chat-container {box-shadow: 0 0 18px 8px rgba(0,0,0, 0.1);right: -25px;bottom: 75px;position: absolute;transition: max-height .2s ease;background-color: white;border-radius: 10px;}.${nm}-chat-container.hidden {max-height: 0px;}.${nm}-scrpt-header {display: inline-block;width: 100%;margin: 0;padding: 10px;color: white;background: linear-gradient(to bottom right, #4294e3, #8f12fd);border-top-left-radius: 10px;border-top-right-radius: 10px;}.${nm}-chat-container form input {padding: 20px;display: inline-block;width: calc(100% - 50px);border: 0px;background-color: #f7f7f7;}.${nm}-chat-container form input:focus {outline: none;}.${nm}-chat-send {cursor: pointer;display: inline-block;padding: 20px 14px;background-color: #f7f7f7;}.${nm}-scrpt-chat-bottom-menu {padding-top: 20px;list-style-type: none;text-align: center;padding-left: 0px;margin-left: 0px;}.${nm}-scrpt-chat-bottom-menu li {display: inline-block;padding-left: 30px;padding-right: 30px;cursor: pointer;}.${nm}-bottom-menu-icon {padding-bottom: 8px;display: inline-block; width: 20px;}.${nm}-chat-content {display: block;width: 100%;padding: 10px;overflow-y: scroll;position: relative;box-shadow: 0 4px 2px -2px rgba(0,0,0, 0.1);}.${nm}-close-button, .${nm}-fullscreen-button {border: 0px;background-color: white;border-radius: 100%;padding-bottom: 3px;float: right;margin-left: 4px;}.${nm}-msg-box {display: inline-block;width:80%;}.${nm}-msg-box p {padding: 7px;}.${nm}-income {float: left;}.${nm}-outcome {float: right;}.${nm}-bubble-outcome {background-color: gray;color: white;border-top-left-radius: 10px;border-top-right-radius: 10px;border-bottom-left-radius: 10px;}.${nm}-bubble-income {background-color: #f7f7f7;color: #424242;border-top-left-radius: 10px;border-top-right-radius: 10px;border-bottom-right-radius: 10px;}\n ` } createChatContainerContent() { const t = this.dce("span"); t.classList.add(`${nm}-clearfix`), this.chatContainer.innerHTML = ""; const e = this.dce("div"); e.classList.add(`${nm}-scrpt-header`); const i = this.dce("button"); let n = this.dce("img"); n.src = this.closeIcon.src, i.appendChild(n), i.classList.add(`${nm}-close-button`), i.addEventListener("click", (() => this.closeChat())), e.appendChild(i), this.fullScreenButton = this.dce("button"); let s = this.dce("img"); s.src = "https://icons.getbootstrap.com/assets/icons/arrows-angle-expand.svg", this.fullScreenButton.appendChild(s), this.fullScreenButton.classList.add(`${nm}-fullscreen-button`), this.fullScreenButton.addEventListener("click", (() => this.fullscreenchat())), e.appendChild(this.fullScreenButton); const o = this.dce("form"); o.classList.add(`${nm}-content`); const a = this.dce("input"); a.requered = !0, a.id = `${nm}-text`, a.type = "text", a.placeholder = this.inputText; let c = this.dce("div"); this.btn = this.dce("img"), this.btn.src = "https://icons.getbootstrap.com/assets/icons/send.svg", c.classList.add(`${nm}-chat-send`), this.btn.style.width = "20px", c.appendChild(this.btn), this.chatContent = this.dce("div"), this.chatContent.classList.add(`${nm}-chat-content`), o.appendChild(this.chatContent), o.appendChild(t), o.appendChild(a), o.appendChild(c), o.addEventListener("submit", this.submit.bind(this)); const d = this.dce("ul"); d.classList.add(`${nm}-scrpt-chat-bottom-menu`);[{ icon: "https://icons.getbootstrap.com/assets/icons/house.svg", text: "Home", click: function () { alert(this.text) } }, { icon: this.chatIcon.src, text: "Chat", click: function () { alert(this.text) } }, { icon: "https://icons.getbootstrap.com/assets/icons/question-circle.svg", text: "Help", click: function () { alert(this.text) } }].forEach((t => { let e = this.dce("li"), i = this.dce("img"); i.classList.add(`${nm}-bottom-menu-icon`), i.src = t.icon, e.appendChild(i); let n = this.dce("br"); e.appendChild(n); let s = this.dce("span"); s.innerHTML = t.text, e.appendChild(s), d.appendChild(e) })), this.chatContainer.appendChild(e), this.chatContainer.appendChild(o), this.chatContainer.appendChild(t), this.chatContainer.appendChild(d) } async submit(t) { t.preventDefault(); let e = this.generateUniqueId(), i = document.getElementById(`${nm}-text`), n = i.value; if ("" === n.trim()) return; this.chatContent.innerHTML += this.chatStripe(!1, n, ""), i.disabled = !0, i.value = "", this.btn.disabled = !0, this.blurAll(); let s = await this.makeRequest("POST", `${domain}/api/answer/${this.appName}`, { question: n }); s = JSON.parse(s), this.chatContent.innerHTML += this.chatStripe(!0, " ", e); const o = document.getElementById(e); this.typeText(o, s.answer) } toggleOpen() { this.open = !this.open, this.open ? this.openChat() : this.closeChat() } fullscreenchat() { "400px" === this.chatContainer.style.width ? (this.chatContainer.style.width = window.innerWidth - 30 + "px", this.chatContainer.style.height = window.innerHeight - 125 + "px") : (this.chatContainer.style.width = this.detectMob() ? window.innerWidth - 17 + "px" : "400px", this.chatContainer.style.bottom = this.detectMob() ? "-18px" : "75px", this.chatContainer.style.height = "auto") } closeChat() { this.open = !1, this.chatIcon.classList.remove(`${nm}-hidden`), this.closeIcon.classList.add(`${nm}-hidden`), this.chatContainer.classList.add(`${nm}-hidden`) } openChat() { this.chatIcon.classList.add(`${nm}-hidden`), this.closeIcon.classList.remove(`${nm}-hidden`), this.chatContainer.classList.remove(`${nm}-hidden`) } typeText(t, e) { let i = 0, n = setInterval((() => { if (i < e.length) t.innerHTML += e.charAt(i), i++, this.chatContent.scrollTop = this.chatContent.scrollHeight; else { clearInterval(n), document.getElementById(`${nm}-text`).disabled = !1, this.btn.disabled = !1 } }), 20) } uuidv4() { return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (t => (t ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> t / 4).toString(16))) } generateUniqueId() { return this.uuidv4() } chatStripe(t, e, i) { return `\n
\n

${e}

\n
\n ` } async getChatInitialData(t) { let e = await this.makeRequest("GET", `${domain}/api/project/${t}/init`), i = JSON.parse(e); this.welcomeMessage = i.data.welcome_message, this.inputText = i.data.input_text } dce(t) { return document.createElement([t]) } blurAll() { var t = document.createElement("input"); document.body.appendChild(t), t.focus(), document.body.removeChild(t) } makeRequest(t, e, i = {}) { return new Promise((function (n, s) { let o = new XMLHttpRequest; o.open(t, e), o.setRequestHeader("Content-type", "application/json"), o.onload = function () { this.status >= 200 && this.status < 300 ? n(o.response) : s({ status: this.status, statusText: o.statusText }) }, o.onerror = function () { s({ status: this.status, statusText: o.statusText }) }, 0 !== Object.keys(i).length ? o.send(JSON.stringify(i)) : o.send() })) } } \ No newline at end of file +const xPositions = ["left", "right"], yPositions = ["top", "bottom"], nm = "scrpt", chatWidth = "400px", domain = "http://161.35.71.150"; class Scrpt { loadInterval; constructor({ position: t = "bottom-right", appName: i = "" } = {}) { if (this.position = this.getPosition(t), this.open = !1, this.inputText = "", this.topics = [], this.appName = i, !t.includes("-")) throw new Error("position must include - symbol. for example bottom-right"); if (!yPositions.includes(t.split("-")[0])) throw new Error("y position must be top or bottom"); if (!xPositions.includes(t.split("-")[1])) throw new Error("x position must be left or right"); if ("" === i) throw new Error("invalid app name"); this.getChatInitialData(i).then((t => { this.initialize() })), this.createStyles() } detectMob() { return [/Android/i, /webOS/i, /iPhone/i, /iPad/i, /iPod/i, /BlackBerry/i, /Windows Phone/i].some((t => navigator.userAgent.match(t))) } getPosition(t) { const [i, e] = t.split("-"); return { [i]: "40px", [e]: "40px" } } initialize() { const t = this.dce("div"); t.style.position = "fixed", t.style.zIndex = "9999", Object.keys(this.position).forEach((i => t.style[i] = this.position[i])), document.body.appendChild(t); const i = this.dce("div"); i.classList.add(`${nm}-button-container`); const e = this.dce("img"); e.src = "https://icons.getbootstrap.com/assets/icons/chat-dots.svg", e.classList.add(`${nm}-icon`), this.chatIcon = e; const s = this.dce("img"); s.src = "https://icons.getbootstrap.com/assets/icons/x.svg", s.classList.add(`${nm}-icon`, `${nm}-hidden`), this.closeIcon = s, this.chatContainer = this.dce("div"), this.chatContainer.classList.add(`${nm}-hidden`, `${nm}-chat-container`), this.chatContainer.style.width = this.detectMob() ? window.innerWidth - 15 + "px" : "400px", this.chatContainer.style.bottom = this.detectMob() ? "-18px" : "75px", this.createChatContainerContent(), this.chatContent.style.height = this.detectMob() ? window.innerHeight - 230 + "px" : "500px", i.appendChild(this.chatIcon), i.appendChild(this.closeIcon), i.addEventListener("click", this.toggleOpen.bind(this)), t.appendChild(this.chatContainer), t.appendChild(i), this.chatContent.innerHTML += this.chatStripe(!0, this.welcomeMessage, "") } createStyles() { const t = this.dce("style"); document.head.appendChild(t), t.innerHTML = `\n .${nm}-clearfix::after {content: "";clear: both;display: table;}.${nm}-topics{position:absolute; right:0;bottom:0; padding:0 13px 10px 0; margin-bottom:150px; z-index:11} .${nm}-topics-tags{height:0px;padding-left: 5px;\n list-style-type: none;display: block;overflow-y: scroll;position: absolute;bottom: 0; transition:transform .3s ease;margin-bottom: 180px; z-index:10}.${nm}-topics-tags li{ display:inline-block; float:left; margin-left: 5px;padding: 2px; background: linear-gradient(to bottom right, #4294e3, #8f12fd);\ncolor: white;border-radius: 7px;font-size: 14px;margin-bottom: 3px;} .${nm}-icon {cursor: pointer;width: 65%;position: absolute;top: 11px;left: 13px;transition: transform .3s ease;filter: invert(1);}.${nm}-hidden {transform: scale(0);}.${nm}-button-container {background: linear-gradient(to bottom right, #4294e3, #8f12fd);width: 70px;height: 70px;border-radius: 50%;}.${nm}-chat-container {box-shadow: 0 0 18px 8px rgba(0,0,0, 0.1);right: -25px;bottom: 75px;position: absolute;transition: max-height .2s ease;background-color: white;border-radius: 10px;}.${nm}-chat-container.hidden {max-height: 0px;}.${nm}-scrpt-header {display: inline-block;width: 100%;margin: 0;padding: 10px;color: white;background: linear-gradient(to bottom right, #4294e3, #8f12fd);border-top-left-radius: 10px;border-top-right-radius: 10px;}.${nm}-chat-container form input {padding: 20px;display: inline-block;width: calc(100% - 50px);border: 0px;background-color: #f7f7f7;}.${nm}-chat-container form input:focus {outline: none;}.${nm}-chat-send {cursor: pointer;display: inline-block;padding: 20px 14px;background-color: #f7f7f7;}.${nm}-scrpt-chat-bottom-menu {padding-top: 20px;list-style-type: none;text-align: center;padding-left: 0px;margin-left: 0px;}.${nm}-scrpt-chat-bottom-menu li {display: inline-block;padding-left: 30px;padding-right: 30px;cursor: pointer;}.${nm}-bottom-menu-icon {padding-bottom: 8px;display: inline-block; width: 20px;}.${nm}-chat-content {display: block;width: 100%;padding: 10px;overflow-y: scroll;position: relative;box-shadow: 0 4px 2px -2px rgba(0,0,0, 0.1);}.${nm}-close-button, .${nm}-fullscreen-button {border: 0px;background-color: white;border-radius: 100%;padding-bottom: 3px;float: right;margin-left: 4px;}.${nm}-msg-box {display: inline-block;width:80%;}.${nm}-msg-box p {padding: 7px;}.${nm}-income {float: left;}.${nm}-outcome {float: right;}.${nm}-bubble-outcome { background: linear-gradient(to bottom right, #4294e3, #8f12fd);color: white;border-top-left-radius: 10px;border-top-right-radius: 10px;border-bottom-left-radius: 10px;}.${nm}-bubble-income {background-color: #f7f7f7;color: #424242;border-top-left-radius: 10px;border-top-right-radius: 10px;border-bottom-right-radius: 10px;}\n ` } createChatContainerContent() { const t = this.dce("span"); t.classList.add(`${nm}-clearfix`), this.chatContainer.innerHTML = ""; const i = this.dce("div"); i.classList.add(`${nm}-scrpt-header`); const e = this.dce("button"); let s = this.dce("img"); s.src = this.closeIcon.src, e.appendChild(s), e.classList.add(`${nm}-close-button`), e.addEventListener("click", (() => this.closeChat())), i.appendChild(e), this.fullScreenButton = this.dce("button"); let n = this.dce("img"); n.src = "https://icons.getbootstrap.com/assets/icons/arrows-angle-expand.svg", this.fullScreenButton.appendChild(n), this.fullScreenButton.classList.add(`${nm}-fullscreen-button`), this.fullScreenButton.addEventListener("click", (() => this.fullscreenchat())), i.appendChild(this.fullScreenButton); const o = this.dce("form"); o.classList.add(`${nm}-content`); const a = this.dce("input"); a.requered = !0, a.id = `${nm}-text`, a.type = "text", a.placeholder = this.inputText, this.topicsTags = this.dce("ul"), this.topicsTags.setAttribute("id", `${nm}-topics-tags`), this.topicsTags.classList.add(`${nm}-topics-tags`); let c = this.dce("div"); this.btn = this.dce("img"), this.btn.src = "https://icons.getbootstrap.com/assets/icons/send.svg", c.classList.add(`${nm}-chat-send`), this.btn.style.width = "20px", c.appendChild(this.btn), this.chatContent = this.dce("div"), this.chatContent.classList.add(`${nm}-chat-content`), this.topicBtn = this.dce("img"), this.topicBtn.classList.add(`${nm}-topics`), this.topicBtn.setAttribute("role", "button"), this.topicBtn.setAttribute("id", `${nm}-topics-img`), this.topicBtn.src = "https://icons.getbootstrap.com/assets/icons/book.svg", this.chatContainer.appendChild(this.topicBtn), this.chatContainer.appendChild(this.topicsTags), o.appendChild(this.chatContent), o.appendChild(t), this.listTopics(), o.appendChild(a), o.appendChild(c), o.addEventListener("submit", this.submit.bind(this)), document.body.addEventListener("click", (t => this.handleTopics(this, t))); const d = this.dce("ul"); d.classList.add(`${nm}-scrpt-chat-bottom-menu`);[{ icon: "https://icons.getbootstrap.com/assets/icons/house.svg", text: "Home", click: function () { } }, { icon: this.chatIcon.src, text: "Chat", click: function () { } }, { icon: "https://icons.getbootstrap.com/assets/icons/question-circle.svg", text: "Help", click: function () { } }].forEach((t => { let i = this.dce("li"), e = this.dce("img"); e.classList.add(`${nm}-bottom-menu-icon`), e.src = t.icon, e.onclick = t.click, i.appendChild(e); let s = this.dce("br"); i.appendChild(s); let n = this.dce("span"); n.innerHTML = t.text, i.appendChild(n), d.appendChild(i) })), this.chatContainer.appendChild(i), this.chatContainer.appendChild(o), this.chatContainer.appendChild(t), this.chatContainer.appendChild(d) } async submit(t) { t.preventDefault(); let i = document.getElementById(`${nm}-text`), e = i.value; "" !== e.trim() && (i.disabled = !0, i.value = "", await this.sendQuestion(e)) } async sendQuestion(t) { let i = this.generateUniqueId(); this.chatContent.innerHTML += this.chatStripe(!1, t, ""), this.btn.disabled = !0, this.blurAll(); let e = await this.makeRequest("POST", `${domain}/api/projects/${this.appName}/answer`, { question: t }); e = JSON.parse(e), this.chatContent.innerHTML += this.chatStripe(!0, " ", i); const s = document.getElementById(i); this.typeText(s, e.answer) } toggleOpen() { this.open = !this.open, this.open ? this.openChat() : this.closeChat() } listTopics() { this.topicsTags.innerHTML = "", this.topics.map((t => { const i = this.dce("li"); i.setAttribute("role", "button"), i.innerText = t.title, i.onclick = async i => { if (this.topics.length > 0) { let e = this.topics.findIndex((t => t.title === i.target.innerText)); this.topics.splice(e, 1), this.listTopics(), this.toggleTopics(), await this.sendQuestion(`Tell me more about ${t.title}`) } }, this.topicsTags.appendChild(i) })) } handleTopics(t, i) { i.target.id == `${nm}-topics-img` && this.toggleTopics() } toggleTopics() { let t = document.getElementById(`${nm}-topics-tags`); 0 === t.clientHeight ? (t.style.height = "84px", this.topicBtn.src = "https://icons.getbootstrap.com/assets/icons/x.svg") : (t.style.height = "0px", this.topicBtn.src = "https://icons.getbootstrap.com/assets/icons/book.svg") } fullscreenchat() { "400px" === this.chatContainer.style.width ? (this.chatContainer.style.width = window.innerWidth - 30 + "px", this.chatContainer.style.height = window.innerHeight - 125 + "px") : (this.chatContainer.style.width = this.detectMob() ? window.innerWidth - 17 + "px" : "400px", this.chatContainer.style.bottom = this.detectMob() ? "-18px" : "75px", this.chatContainer.style.height = "auto") } closeChat() { this.open = !1, this.chatIcon.classList.remove(`${nm}-hidden`), this.closeIcon.classList.add(`${nm}-hidden`), this.chatContainer.classList.add(`${nm}-hidden`) } openChat() { this.chatIcon.classList.add(`${nm}-hidden`), this.closeIcon.classList.remove(`${nm}-hidden`), this.chatContainer.classList.remove(`${nm}-hidden`) } typeText(t, i) { let e = 0, s = setInterval((() => { if (e < i.length) t.innerHTML += i.charAt(e), e++, this.chatContent.scrollTop = this.chatContent.scrollHeight; else { clearInterval(s), document.getElementById(`${nm}-text`).disabled = !1, this.btn.disabled = !1 } }), 20) } uuidv4() { return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (t => (t ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> t / 4).toString(16))) } generateUniqueId() { return this.uuidv4() } chatStripe(t, i, e) { return `\n
\n

${i}

\n
\n ` } async getChatInitialData(t) { let i = await this.makeRequest("GET", `${domain}/api/projects/${t}/init`), e = JSON.parse(i); this.welcomeMessage = e.data.welcome_message, this.inputText = e.data.input_text, this.topics = e.topics } dce(t) { return document.createElement([t]) } blurAll() { var t = document.createElement("input"); document.body.appendChild(t), t.focus(), document.body.removeChild(t) } makeRequest(t, i, e = {}) { return new Promise((function (s, n) { let o = new XMLHttpRequest; o.open(t, i), o.setRequestHeader("Content-type", "application/json"), o.onload = function () { this.status >= 200 && this.status < 300 ? s(o.response) : n({ status: this.status, statusText: o.statusText }) }, o.onerror = function () { n({ status: this.status, statusText: o.statusText }) }, 0 !== Object.keys(e).length ? o.send(JSON.stringify(e)) : o.send() })) } } \ No newline at end of file