From c6862dd1cac83d2c9102451736ed0fb2e050237e Mon Sep 17 00:00:00 2001 From: "roary.yao" Date: Fri, 7 Feb 2025 14:04:54 +0800 Subject: [PATCH 1/2] AII-449 --- src/lib/common/RemoteSearchInput.svelte | 84 +++++++++++++++ src/lib/helpers/http.js | 1 + src/lib/scss/custom/common/_common.scss | 12 +++ src/lib/services/api-endpoints.js | 2 + src/lib/services/conversation-service.js | 34 ++++++ src/routes/page/conversation/+page.svelte | 124 +++++++++++++++------- 6 files changed, 220 insertions(+), 37 deletions(-) create mode 100644 src/lib/common/RemoteSearchInput.svelte diff --git a/src/lib/common/RemoteSearchInput.svelte b/src/lib/common/RemoteSearchInput.svelte new file mode 100644 index 00000000..b69f4635 --- /dev/null +++ b/src/lib/common/RemoteSearchInput.svelte @@ -0,0 +1,84 @@ + + +
+ 0 || loading)} toggle={() => isOpen = !isOpen}> + + + + + {#if loading} + + + + {:else} + {#each searchResults as result, index} + selectResult(result)} + title={result.name} + > + {result.name} + + {/each} + {/if} + + +
\ No newline at end of file diff --git a/src/lib/helpers/http.js b/src/lib/helpers/http.js index 06f52516..4a113b32 100644 --- a/src/lib/helpers/http.js +++ b/src/lib/helpers/http.js @@ -90,6 +90,7 @@ function skipLoader(config) { new RegExp('http(s*)://(.*?)/role/(.*?)/details', 'g'), new RegExp('http(s*)://(.*?)/user/(.*?)/details', 'g'), new RegExp('http(s*)://(.*?)/agent/labels', 'g'), + new RegExp('http(s*)://(.*?)/conversation/state-search', 'g'), ]; if (config.method === 'post' && postRegexes.some(regex => regex.test(config.url || ''))) { diff --git a/src/lib/scss/custom/common/_common.scss b/src/lib/scss/custom/common/_common.scss index 211d44ca..69efba04 100644 --- a/src/lib/scss/custom/common/_common.scss +++ b/src/lib/scss/custom/common/_common.scss @@ -180,3 +180,15 @@ button:focus { .thin-scrollbar { scrollbar-width: thin; } + +.scrollable-dropdown { + .dropdown-menu { + max-height: 200px; + overflow-y: auto; + } + .dropdown-item { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } +} diff --git a/src/lib/services/api-endpoints.js b/src/lib/services/api-endpoints.js index df5758c8..b42c4cb3 100644 --- a/src/lib/services/api-endpoints.js +++ b/src/lib/services/api-endpoints.js @@ -67,6 +67,8 @@ export const endpoints = { conversationTagsUpdateUrl: `${host}/conversation/{conversationId}/update-tags`, fileUploadUrl: `${host}/agent/{agentId}/conversation/{conversationId}/upload`, pinConversationUrl: `${host}/agent/{agentId}/conversation/{conversationId}/dashboard`, + conversationStateValueUrl: `${host}/conversation/state-search`, + conversationStateKeyListUrl: `${host}/conversation/state-key`, // LLM provider llmProvidersUrl: `${host}/llm-providers`, diff --git a/src/lib/services/conversation-service.js b/src/lib/services/conversation-service.js index 91d8a261..16124019 100644 --- a/src/lib/services/conversation-service.js +++ b/src/lib/services/conversation-service.js @@ -288,4 +288,38 @@ export async function getAddressOptions(text) { } }); return response.data; +} + +/** + * get conversation state key list + * @returns {Promise<{id: string, name: string, description: string}[]>} + */ +export async function getConversationStateKey() { + let url = endpoints.conversationStateKeyListUrl; + const response = await axios.get(url); + return response.data; +} + +/** @type {import('axios').CancelTokenSource | null} */ +let getConversationStateValueCancelToken = null; +/** + * get conversation state value + * @param {string} key + * @param {string} query + * @returns {Promise<{id: string, name: string}[]>} + */ +export async function getConversationStateValue(key, query) { + let url = endpoints.conversationStateValueUrl; + if (getConversationStateValueCancelToken) { + getConversationStateValueCancelToken.cancel(); + } + getConversationStateValueCancelToken = axios.CancelToken.source(); + const response = await axios.get(url, { + params: { + conversatinFilterType: key, + searchKey: query + }, + cancelToken: getConversationStateValueCancelToken.token + }); + return response.data; } \ No newline at end of file diff --git a/src/routes/page/conversation/+page.svelte b/src/routes/page/conversation/+page.svelte index 3cc288a3..9f526da0 100644 --- a/src/routes/page/conversation/+page.svelte +++ b/src/routes/page/conversation/+page.svelte @@ -21,12 +21,13 @@ import StateModal from '$lib/common/StateModal.svelte'; import { onMount } from 'svelte'; import { getAgents } from '$lib/services/agent-service'; - import { getConversations, deleteConversation } from '$lib/services/conversation-service.js'; + import { getConversations, deleteConversation, getConversationStateKey, getConversationStateValue } from '$lib/services/conversation-service.js'; import { utcToLocal } from '$lib/helpers/datetime'; import Swal from 'sweetalert2'; import lodash from "lodash"; import MultiSelect from '$lib/common/MultiSelect.svelte'; import { ConversationChannel, ConversationTag } from '$lib/helpers/enums'; + import RemoteSearchInput from '$lib/common/RemoteSearchInput.svelte'; let isLoading = false; let isComplete = false; @@ -82,11 +83,29 @@ tags: [] }; + /** @type {any[]} */ + let stateOptions = []; + + /** @type {string | null} */ + let selectedState = null; + + /** @type {{id: string, name: string} | null} */ + let selectedValue; + + + let isValueEditable = false; + + /** + * @type {RemoteSearchInput} + */ + let remoteSearchInput; + onMount(async () => { isLoading = true; Promise.all([ loadAgentOptions(), loadSearchOption(), + loadStates(), loadConversations()]) .finally(() => { isLoading = false @@ -221,13 +240,23 @@ }; } - function toggleSearchStateModal() { - isOpenSearchStateModal = !isOpenSearchStateModal; - } - - function handleConfirmStateModal() { + /** + * @param {any} e + */ + function handleConfirmStateModal(e) { + if (selectedState && selectedValue?.id) { + searchOption.states = [ + { + key: { data: stateOptions.find(x => Number(x.id) === Number(selectedState))?.description, isValid: true }, + value: {data: selectedValue.id, isValid: true }, + active_rounds: {data: 0, isValid: true}, + } + ]; + } else { + searchOption.states = []; + } handleSearchStates(); - toggleSearchStateModal(); + searchConversations(e); } function loadSearchOption() { @@ -333,46 +362,72 @@ }; } } + + async function loadStates() { + const response = await getConversationStateKey(); + stateOptions = response; + } + + /** + * @param { any } e + */ + function handleStateChange(e) { + selectedState = e.target.value; + isValueEditable = !!selectedState; + selectedValue = null; + remoteSearchInput?.clearSearchResults(); + } + + /** + * @param {any} query + */ + async function handleValueSearch(query) { + if (!selectedState) return []; + const response = await getConversationStateValue(selectedState, query); + return response; + } - toggleSearchStateModal()} - confirm={() => handleConfirmStateModal()} - cancel={() => toggleSearchStateModal()} -/>
-
{$_('Conversation List')}
-
+
{$_('Conversation List')}
+
+ + + + + + + + + + + + - - - - - - toggleSearchStateModal()} - > - {$_('Search States')} - - -
@@ -416,8 +471,8 @@ /> + + -->