diff --git a/src/lib/common/LiveChatEntry.svelte b/src/lib/common/LiveChatEntry.svelte index 6c55fad2..3f63249c 100644 --- a/src/lib/common/LiveChatEntry.svelte +++ b/src/lib/common/LiveChatEntry.svelte @@ -10,22 +10,20 @@ onMount(async () => { const agentSettings = await getSettingDetail("Agent"); - chatUrl = `${PUBLIC_LIVECHAT_HOST}chat/${agentSettings.hostAgentId}?isFrame=true`; + chatUrl = `${PUBLIC_LIVECHAT_HOST}chat/${agentSettings.hostAgentId}`; }); // Handle event from iframe window.onmessage = async function(e) { if (e.data.action == 'close') { - chatBotStore.set({ - showChatBox: false - }); + chatBotStore.set({ showChatBox: false }); + } else if (e.data.action == 'open') { + chatBotStore.set({ showChatBox: true }); } }; function openChatBox() { - chatBotStore.set({ - showChatBox: true - }); + chatBotStore.set({ showChatBox: true }); } @@ -51,7 +49,6 @@ src={chatUrl} width="0px" height="0px" - class={`border border-2 rounded-3 m-3 float-end chat-iframe`} title="live chat" id={CHAT_FRAME_ID} /> diff --git a/src/lib/common/ProfileDropdown.svelte b/src/lib/common/ProfileDropdown.svelte index 943250a9..15200391 100644 --- a/src/lib/common/ProfileDropdown.svelte +++ b/src/lib/common/ProfileDropdown.svelte @@ -7,6 +7,7 @@ import { PUBLIC_SERVICE_URL } from '$env/static/public'; import { _ } from 'svelte-i18n'; import { buildUrl } from '$lib/helpers/utils/common'; + import { ChatAction } from '$lib/helpers/enums'; /** @type {any} */ export let user; @@ -19,7 +20,7 @@ const chatFrame = document.getElementById('chat-frame'); if (chatFrame) { // @ts-ignore - chatFrame.contentWindow.postMessage({ action: "logout" }, "*"); + chatFrame.contentWindow.postMessage({ action: ChatAction.Logout }, "*"); } goto('login'); diff --git a/src/lib/common/audio-player/AudioSpeaker.svelte b/src/lib/common/audio-player/AudioSpeaker.svelte index 5b735a50..217b436e 100644 --- a/src/lib/common/audio-player/AudioSpeaker.svelte +++ b/src/lib/common/audio-player/AudioSpeaker.svelte @@ -84,14 +84,14 @@
- speak()}> +
speak()}> {#if !speaking} - + {:else} {/if} - +
\ No newline at end of file diff --git a/src/lib/helpers/enums.js b/src/lib/helpers/enums.js index ed622d67..7db32d1a 100644 --- a/src/lib/helpers/enums.js +++ b/src/lib/helpers/enums.js @@ -98,4 +98,11 @@ const knowledgeDocSource = { User: 'user', Web: 'web' }; -export const KnowledgeDocSource = Object.freeze(knowledgeDocSource); \ No newline at end of file +export const KnowledgeDocSource = Object.freeze(knowledgeDocSource); + +const chatAction = { + Logout: 'logout', + Chat: 'chat', + NewChat: 'new-chat' +}; +export const ChatAction = Object.freeze(chatAction); \ No newline at end of file diff --git a/src/lib/helpers/utils/chat.js b/src/lib/helpers/utils/chat.js index 4dc3eb3a..434fe190 100644 --- a/src/lib/helpers/utils/chat.js +++ b/src/lib/helpers/utils/chat.js @@ -1,11 +1,12 @@ /** + * @param {string} action * @param {string} chatFrameId - * @param {string} text + * @param {string | null} text * @param {import('$conversationTypes').MessageData | null} data */ -export function sendToChatBot(chatFrameId, text, data = null) { +export function sendToChatBot(action, chatFrameId, text = null, data = null) { const chatFrame = document.getElementById(chatFrameId); - const content = { action: "chat", text: text, data: data }; + const content = { action: action, text: text, data: data }; if (chatFrame) { // @ts-ignore diff --git a/src/routes/chat/[agentId]/+page.svelte b/src/routes/chat/[agentId]/+page.svelte index 15edda43..3c557a70 100644 --- a/src/routes/chat/[agentId]/+page.svelte +++ b/src/routes/chat/[agentId]/+page.svelte @@ -40,23 +40,15 @@ } conversationId = conversation.id; - let chatUrl = `chat/${agentId}/${conversationId}`; - let query = ""; - + const chatUrl = new URL(`chat/${agentId}/${conversationId}`, window.location.origin); + + const searchParams = new URLSearchParams(); if (agentId === LERNER_ID) { - query += `mode=${TRAINING_MODE}`; - } - - const isFrame = $page.url.searchParams.get('isFrame'); - if (isFrame === 'true') { - query += "isFrame=true"; - } - - if (!!query) { - chatUrl = `${chatUrl}?${query}`; + searchParams.append('mode', TRAINING_MODE); } - window.location.href = chatUrl; + chatUrl.search = searchParams?.toString(); + window.location.href = chatUrl.toString(); }); diff --git a/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte b/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte index 04aa3a36..db1f3bfc 100644 --- a/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte +++ b/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte @@ -44,7 +44,7 @@ import { utcToLocal } from '$lib/helpers/datetime'; import { replaceNewLine } from '$lib/helpers/http'; import { isAudio, isExcel, isPdf } from '$lib/helpers/utils/file'; - import { EditorType, FileSourceType, SenderAction, UserRole } from '$lib/helpers/enums'; + import { ChatAction, EditorType, FileSourceType, SenderAction, UserRole } from '$lib/helpers/enums'; import RichContent from './rich-content/rich-content.svelte'; import RcMessage from "./rich-content/rc-message.svelte"; import RcDisclaimer from './rich-content/rc-disclaimer.svelte'; @@ -55,6 +55,7 @@ import ChatBigMessage from './chat-util/chat-big-message.svelte'; import PersistLog from './persist-log/persist-log.svelte'; import InstantLog from './instant-log/instant-log.svelte'; + import Loader from '$lib/common/Loader.svelte'; const options = { @@ -151,6 +152,7 @@ let disableAction = false; let loadChatUtils = false; let disableSpeech = false; + let isLoading = false; $: { @@ -192,19 +194,38 @@ refresh(); autoScrollLog = false; - window.addEventListener('message', e => { - if (e.data.action === 'logout') { + window.addEventListener('message', async e => { + if (e.data.action === ChatAction.Logout) { resetLocalStorage(true); + return; } - if (e.data.action === 'chat' && !isThinking && !isSendingMsg) { - sendChatMessage(e.data.text, e.data.data || null); + if (e.data.action === ChatAction.NewChat) { + const conv = await createNewConversation(); + if (!!e.data.text && !isThinking && !isSendingMsg) { + isLoading = true; + sendChatMessage(e.data.text, e.data.data || null, conv.id).then(() => { + redirectToNewConversation(conv); + isLoading = false; + openFrame(); + }); + } + return; + } + + if (e.data.action === ChatAction.Chat && !!e.data.text && !isThinking && !isSendingMsg) { + sendChatMessage(e.data.text, e.data.data || null).then(() => { + openFrame(); + }); + return; } }); - - // window.parent.postMessage({ event: "chat-box-mounted" }, "*"); }); + function openFrame() { + window.parent.postMessage({ action: "open" }, "*"); + } + function resizeChatWindow() { isLite = Viewport.Width <= screenWidthThreshold; if (!isLite) { @@ -219,7 +240,7 @@ } function initChatView() { - isFrame = $page.url.searchParams.get('isFrame') === 'true'; + isFrame = window.location != window.parent.location; mode = $page.url.searchParams.get('mode') || ''; // initial condition isPersistLogClosed = false; @@ -430,10 +451,22 @@ } async function handleNewConversation() { + const conv = await createNewConversation(); + redirectToNewConversation(conv); + } + + async function createNewConversation() { const conversation = await newConversation(params.agentId); conversationStore.set(conversation); - const url = `chat/${params.agentId}/${conversation.id}`; - window.location.href = url; + return conversation; + } + + /** @param {import('$conversationTypes').ConversationModel} conversation */ + function redirectToNewConversation(conversation) { + const url = new URL(`chat/${params.agentId}/${conversation.id}`, window.location.origin); + const searchParams = $page.url.searchParams; + url.search = searchParams?.toString(); + window.location.href = url.toString(); } function handleSaveKnowledge() { @@ -443,8 +476,9 @@ /** * @param {string} msgText * @param {import('$conversationTypes').MessageData?} data + * @param {string?} conversationId */ - function sendChatMessage(msgText, data = null) { + function sendChatMessage(msgText, data = null, conversationId = null) { isSendingMsg = true; autoScrollLog = true; clearInstantLogs(); @@ -471,7 +505,7 @@ if (files?.length > 0 && !!!messageData.inputMessageId) { const filePayload = buildFilePayload(files); return new Promise((resolve, reject) => { - uploadConversationFiles(params.agentId, params.conversationId, files).then(resMessageId => { + uploadConversationFiles(params.agentId, conversationId || params.conversationId, files).then(resMessageId => { messageData = { ...messageData, inputMessageId: resMessageId }; if (!!filePayload) { messageData = { @@ -484,7 +518,7 @@ }; } - sendMessageToHub(params.agentId, params.conversationId, msgText, messageData).then(res => { + sendMessageToHub(params.agentId, conversationId || params.conversationId, msgText, messageData).then(res => { resolve(res); }).catch(err => { reject(err); @@ -510,7 +544,7 @@ }; } - sendMessageToHub(params.agentId, params.conversationId, msgText, messageData).then(res => { + sendMessageToHub(params.agentId, conversationId || params.conversationId, msgText, messageData).then(res => { resolve(res); }).catch(err => { reject(err); @@ -520,7 +554,7 @@ }); }); } else { - sendMessageToHub(params.agentId, params.conversationId, msgText, messageData).then(res => { + sendMessageToHub(params.agentId, conversationId || params.conversationId, msgText, messageData).then(res => { resolve(res); }).catch(err => { reject(err); @@ -1003,11 +1037,34 @@ bigText = ''; sendChatMessage(text); } + + /** + * @param {any} e + * @param {any} message + */ + function likeMessage(e, message) { + e.preventDefault(); + + const text = 'I like this message.'; + const data = { + postback: { + functionName: 'like_response', + payload: 'I really like this message!', + parentId: message?.id + }, + states: [] + }; + sendChatMessage(text, data); + } resizeChatWindow()}/> +{#if isLoading} + +{/if} + {#if message?.message_id === lastBotMsg?.message_id} - +
+ +
+ + +
likeMessage(e, message)} + > + +
+
+
{/if} {#if !!message.is_chat_message || !!message.has_message_files}