diff --git a/index.html b/index.html index 16b1c2d..465f56f 100755 --- a/index.html +++ b/index.html @@ -21,7 +21,8 @@
-
+
+ View our privacy policy here
@@ -38,6 +39,20 @@ Log Out + + + diff --git a/js/script.js b/js/script.js index 1d1c6bc..1a0ae90 100755 --- a/js/script.js +++ b/js/script.js @@ -607,6 +607,201 @@ const selectTOV = (new_tov_key) => { document.getElementById("tov-list").classList.add("tov-list-hidden"); }; +const onAuthenticated = () => { + goToCreateNewConversationsPage(); + getConversations(); + getAssistants(); + getTOVs(); + + // Ensure the send button is enabled by default + document.getElementById("message-input").value = ""; + + document.getElementById("assistant-name-container").classList.remove("assistant-name-container-active"); + document.getElementById("assistant-name").classList.remove("assistant-name-placeholder"); + document.getElementById("assistants-list").classList.add("assistants-list-hidden"); + + document.getElementById("tov-name-container").classList.remove("tov-name-container-active"); + document.getElementById("tov-name").classList.remove("tov-name-placeholder"); + document.getElementById("tov-list").classList.add("tov-list-hidden"); + + Array.from(document.getElementsByClassName("chat-message-appear"))?.map((el) => el.classList.remove("chat-message-appear")); + document.getElementById("chat").innerHTML += chat_message_user_new.replaceAll("{CONTENT}", md_converter?.makeHtml(message)); + + // Scroll to Last Message + document.getElementById("chat").scrollTop = document.getElementById("chat").scrollHeight; + + setTimeout(() => { + Array.from(document.getElementsByClassName("chat-message-appear"))?.map((el) => el.classList.remove("chat-message-appear")); + + document.getElementById("chat").innerHTML += chat_message_assistant_loading_dots; + + setTimeout(() => { + // Scroll to Last Message + document.getElementById("chat").scrollTop = document.getElementById("chat").scrollHeight; + }, 5); + }, 2000); + + //console.log("URI encoded message: " + encodeURI(message)); + + + const utf8Bytes = new TextEncoder().encode(message); + let binary = ''; + for (let i = 0; i < utf8Bytes.length; i++) { + binary += String.fromCharCode(utf8Bytes[i]); + } + const encodedMessage = btoa(binary); + + // Function to make the API call (so we can retry it) + const makeAPICall = (retryCount = 0) => { + return gcp_fetch( + make_url + + `?ConversationID=${encodeURI(conversation_id)}&AssistantKey=${encodeURI(new_assistant_key)}&TOV_Key=${encodeURI( + new_tov_key + )}&Message=${encodeURIComponent(encodedMessage)}` + ) + .then((res) => { + if (!res.ok) { + throw new Error(`Server responded with status: ${res.status} ${res.statusText}`); + } + return res.json(); + }) + .then((res) => { + if (sending_message && res?.conversation_id) { + conversation_id = res?.conversation_id; + + if (conversations.findIndex((e) => e.id === res?.conversation_id) === -1 && res?.conversation_title) { + conversations = [ + { id: res?.conversation_id, title: res?.conversation_title, assistant_key: new_assistant_key, tov_key: new_tov_key }, + ].concat(conversations); + + document.getElementById("conversations-list").innerHTML = conversations + ?.map((conversation) => { + if (conversation?.id === res?.conversation_id) + return conversations_list_item_active + ?.replaceAll("{CONVERSATION_ID}", conversation?.id) + ?.replaceAll("{CONVERSATION_TITLE}", processConversationTitle(conversation?.title)); + return conversations_list_item + ?.replaceAll("{CONVERSATION_ID}", conversation?.id) + ?.replaceAll("{CONVERSATION_TITLE}", processConversationTitle(conversation?.title)); + }) + ?.join(""); + } + } + + // Re-enable the send button + document.getElementById("send-button").disabled = false; + + sending_message = false; + Array.from(document.getElementsByClassName("chat-message-appear"))?.map((el) => el.classList.remove("chat-message-appear")); + Array.from(document.getElementsByClassName("chat-message-loading-dots"))?.map((el) => el.remove()); + + // Check if we have a message, otherwise show error + if (res?.message) { + document.getElementById("chat").innerHTML += chat_message_assistant_new.replaceAll("{CONTENT}", md_converter?.makeHtml(removeCitations(res.message))); + } else { + document.getElementById("chat").innerHTML += chat_message_assistant_new.replaceAll("{CONTENT}", "Sorry, there was an issue processing your request. The response was incomplete."); + } + + // Scroll to Last Message + document.getElementById("chat").scrollTop = document.getElementById("chat").scrollHeight; + }) + .catch((error) => { + console.error(`Error in API call (attempt ${retryCount + 1}):`, error); + + // If this is the first failure, retry once + if (retryCount === 0) { + console.log("Retrying request..."); + + // Keep loading indicator + // Don't remove the loading dots yet + + // Wait a moment before retrying (e.g., 1 second) + return new Promise(resolve => setTimeout(resolve, 1000)) + .then(() => makeAPICall(retryCount + 1)); + } + + // If we've already retried or max retries reached, show the error + // Re-enable the send button + document.getElementById("send-button").disabled = false; + + sending_message = false; + Array.from(document.getElementsByClassName("chat-message-appear"))?.map((el) => el.classList.remove("chat-message-appear")); + Array.from(document.getElementsByClassName("chat-message-loading-dots"))?.map((el) => el.remove()); + + // Show error message in chat + document.getElementById("chat").innerHTML += chat_message_assistant_new.replaceAll( + "{CONTENT}", + `
Sorry, an error occurred: ${error.message}
` + ); + + // Scroll to Last Message + document.getElementById("chat").scrollTop = document.getElementById("chat").scrollHeight; + }); + }; + + // Start the API call with retry functionality + makeAPICall(); +}; + +const toggleAssistantsDropdown = () => { + if (conversation_id !== false || sending_message) return false; + + if (Array.from(document.getElementById("assistants-list").classList).includes("assistants-list-hidden")) { + document.getElementById("assistant-name-container").classList.add("assistant-name-container-active"); + document.getElementById("assistants-list").classList.remove("assistants-list-hidden"); + } else { + document.getElementById("assistant-name-container").classList.remove("assistant-name-container-active"); + document.getElementById("assistants-list").classList.add("assistants-list-hidden"); + } +}; + +const selectAssistant = (new_assistant_key) => { + if (conversation_id !== false || sending_message) return false; + + const assistant = assistants?.find((e) => e.key === new_assistant_key); + if (!assistant) return false; + + assistant_key = new_assistant_key; + + document.getElementById("assistant-name").innerHTML = assistants.find((e) => e.key === new_assistant_key)?.name; + document.getElementById("assistant-name-container").classList.remove("assistant-name-container-active"); + document.getElementById("assistant-name").classList.remove("assistant-name-placeholder"); + document.getElementById("assistants-list").classList.add("assistants-list-hidden"); + + document.getElementById("chat").innerHTML = ``; + setTimeout(() => { + if (JSON.stringify(assistant_key) === JSON.stringify(new_assistant_key)) { + document.getElementById("chat").innerHTML = chat_message_assistant_new.replaceAll("{CONTENT}", assistant?.initial_message); + } + }, 500); +}; + +const toggleTOVsDropdown = () => { + if (conversation_id !== false || sending_message) return false; + + if (Array.from(document.getElementById("tov-list").classList).includes("tov-list-hidden")) { + document.getElementById("tov-name-container").classList.add("tov-name-container-active"); + document.getElementById("tov-list").classList.remove("tov-list-hidden"); + } else { + document.getElementById("tov-name-container").classList.remove("tov-name-container-active"); + document.getElementById("tov-list").classList.add("tov-list-hidden"); + } +}; + +const selectTOV = (new_tov_key) => { + if (conversation_id !== false || sending_message) return false; + + const tov = tone_of_voices?.find((e) => e.key === new_tov_key); + if (!tov) return false; + + tov_key = new_tov_key; + + document.getElementById("tov-name").innerHTML = tone_of_voices.find((e) => e.key === new_tov_key)?.name; + document.getElementById("tov-name-container").classList.remove("tov-name-container-active"); + document.getElementById("tov-name").classList.remove("tov-name-placeholder"); + document.getElementById("tov-list").classList.add("tov-list-hidden"); +}; + const onAuthenticated = () => { goToCreateNewConversationsPage(); getConversations(); @@ -620,4 +815,29 @@ const onAuthenticated = () => { sendButton.disabled = false; } }, 500); // Small delay to ensure DOM is ready -}; \ No newline at end of file +}; + +// Help Modal Functionality +document.addEventListener('DOMContentLoaded', () => { + const modal = document.getElementById("help-modal"); + const btn = document.getElementById("help-btn"); + const span = document.getElementsByClassName("close-btn")[0]; + + if (btn) { + btn.onclick = function() { + modal.style.display = "flex"; + } + } + + if (span) { + span.onclick = function() { + modal.style.display = "none"; + } + } + + window.onclick = function(event) { + if (event.target == modal) { + modal.style.display = "none"; + } + } +}); \ No newline at end of file diff --git a/style.css b/style.css index 274c5ec..209d54b 100644 --- a/style.css +++ b/style.css @@ -652,3 +652,99 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } + +/* Help Button */ +.help-btn { + position: absolute; + top: 15px; + left: 30px; + background-color: #0079E8; + color: white; + border: none; + padding: 8px 16px; + border-radius: 20px; + cursor: pointer; + font-size: 14px; + font-weight: 600; + transition: background-color 0.2s; +} + +.help-btn:hover { + background-color: #0056b3; +} + +/* Modal Styles */ +.modal { + display: none; + position: fixed; + z-index: 3000; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgba(0, 0, 0, 0.5); + align-items: center; + justify-content: center; +} + +.modal-content { + background-color: #fefefe; + margin: auto; + padding: 0; + border: 1px solid #888; + width: 80%; + max-width: 600px; + border-radius: 8px; + box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); + animation-name: animatetop; + animation-duration: 0.4s +} + +@keyframes animatetop { + from {top: -300px; opacity: 0} + to {top: 0; opacity: 1} +} + +.modal-header { + padding: 15px 20px; + border-bottom: 1px solid #eee; + display: flex; + justify-content: space-between; + align-items: center; +} + +.modal-header h2 { + margin: 0; + font-size: 24px; + font-weight: 600; +} + +.close-btn { + color: #aaa; + font-size: 28px; + font-weight: bold; + cursor: pointer; +} + +.close-btn:hover, +.close-btn:focus { + color: black; + text-decoration: none; + cursor: pointer; +} + +.modal-body { + padding: 20px; + font-size: 16px; + line-height: 1.5; +} + +.modal-body a { + color: #0079E8; + text-decoration: none; +} + +.modal-body a:hover { + text-decoration: underline; +}