From 74864b74afc4c8a0c0d49a13df33ac28c6383a04 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Fri, 18 Oct 2024 15:48:37 -0500 Subject: [PATCH] add chat tags --- src/lib/common/MultiSelect.svelte | 32 ++-- src/lib/helpers/enums.js | 8 +- src/lib/helpers/http.js | 1 + src/lib/helpers/store.js | 1 - src/lib/helpers/types/conversationTypes.js | 18 ++- .../scss/custom/components/_multiselect.scss | 2 +- src/lib/scss/custom/pages/_chat.scss | 40 +++++ src/lib/services/api-endpoints.js | 1 + src/lib/services/conversation-service.js | 26 +++- .../[conversationId]/chat-box.svelte | 140 ++++++++++++++++-- src/routes/page/conversation/+page.svelte | 86 +++++++---- .../[conversationId]/conv-dialogs.svelte | 4 +- .../[conversationId]/conv-overview.svelte | 15 ++ 13 files changed, 316 insertions(+), 58 deletions(-) diff --git a/src/lib/common/MultiSelect.svelte b/src/lib/common/MultiSelect.svelte index bdc227d..b2cb03b 100644 --- a/src/lib/common/MultiSelect.svelte +++ b/src/lib/common/MultiSelect.svelte @@ -17,6 +17,9 @@ /** @type {string} */ export let searchPlaceholder = ''; + /** @type {string} */ + export let placeholder = ''; + /** @type {string} */ export let containerClasses = ""; @@ -26,9 +29,13 @@ /** @type {boolean} */ export let disableDefaultStyles = false; + /** @type {boolean} */ + export let searchMode = false; + /** @type {null | undefined | (() => Promise)} */ export let onScrollMoreOptions = null; + /** @type {string} */ let searchValue = ''; @@ -179,7 +186,7 @@ function sendEvent() { svelteDispatch("select", { - selecteds: refOptions.filter(x => !!x.checked) + selecteds: refOptions.filter(x => !!x.checked).map(x => ({ key: x.key, value: x.value })) }); } @@ -261,6 +268,7 @@ type="text" class='clickable' value={displayText} + placeholder={placeholder} readonly />
@@ -269,17 +277,19 @@ {#if showOptionList} diff --git a/src/routes/page/conversation/+page.svelte b/src/routes/page/conversation/+page.svelte index 1fb4139..8933b30 100644 --- a/src/routes/page/conversation/+page.svelte +++ b/src/routes/page/conversation/+page.svelte @@ -19,13 +19,14 @@ import LoadingToComplete from '$lib/common/LoadingToComplete.svelte'; import Label from '$lib/common/Label.svelte'; import StateModal from '$lib/common/StateModal.svelte'; - import { conversationSearchOptionStore } from '$lib/helpers/store'; import { onMount } from 'svelte'; import { getAgents } from '$lib/services/agent-service'; import { getConversations, deleteConversation } 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 { ConversationTag } from '$lib/helpers/enums'; let isLoading = false; let isComplete = false; @@ -33,7 +34,7 @@ let isOpenSearchStateModal = false; const duration = 3000; const firstPage = 1; - const pageSize = 10; + const pageSize = 15; /** @type {import('$commonTypes').PagedItems} */ let conversations = { count: 0, items: [] }; @@ -55,15 +56,32 @@ /** @type {import('$commonTypes').IdName[]} */ let agentOptions = []; - /** - * @type {{agentId: string?, channel: string?, status: string?, taskId: string?, states: import('$conversationTypes').UserStateDetailModel[]}} - * */ + /** @type {import('$commonTypes').IdName[]} */ + let statusOptions = [ + { id: 'open', name: 'Active' }, + { id: 'closed', name: 'Completed' } + ]; + + /** @type {import('$commonTypes').IdName[]} */ + let channelOptions = [ + { id: 'webchat', name: 'Live Chat' }, + { id: 'phone', name: 'Phone' }, + { id: 'email', name: 'Email' } + ]; + + /** @type {import('$commonTypes').KeyValuePair[]} */ + let tagOptions = Object.entries(ConversationTag).map(([k, v]) => ( + { key: k, value: v } + )); + + /** @type {import('$conversationTypes').ConversationSearchOption} */ let searchOption = { agentId: null, channel: null, status: null, taskId: null, states: [], + tags: [] }; onMount(async () => { @@ -147,8 +165,7 @@ async function reloadConversations() { - filter = { ...initFilter }; - conversations = await getConversations(filter); + conversations = await getConversations({ ...filter }); refreshPager(conversations.count); } @@ -197,7 +214,6 @@ refreshFilter(); initFilterPager(); getPagedConversations(); - saveSearchOption(); } function initFilterPager() { @@ -218,11 +234,6 @@ function loadSearchOption() { return new Promise((resolve, reject) => { - const savedOption = conversationSearchOptionStore.get(); - searchOption = { - ...searchOption, - ...savedOption - }; refreshFilter(); handleSearchStates(); resolve(searchOption); @@ -237,7 +248,8 @@ channel: searchOption.channel, status: searchOption.status, taskId: searchOption.taskId, - states: searchStates + states: searchStates, + tags: searchOption.tags }; } @@ -285,10 +297,6 @@ }); } - function saveSearchOption() { - conversationSearchOptionStore.put(searchOption); - } - /** @param {string | number} index */ function handleCloseLabel(index) { searchOption.states = searchOption.states.filter((x, idx) => idx != index); @@ -320,6 +328,12 @@ ...searchOption, status: e.target.value || null }; + } else if (type === 'tags') { + searchOption = { + ...searchOption, + // @ts-ignore + tags: e.detail.selecteds?.map(x => x.value) || [] + }; } } @@ -368,36 +382,45 @@ - changeOption(e, 'agent')}> {#each agentOptions as op} - + {/each} - changeOption(e, 'task')}> - changeOption(e, 'status')}> - - + {#each statusOptions as op} + + {/each} - changeOption(e, 'channel')}> - - - + {#each channelOptions as op} + + {/each} - + changeOption(e, "tags")} + /> + {#if searchStateStrs?.length > 0} {#each searchStateStrs as str, idx (idx)} - diff --git a/src/routes/page/conversation/[conversationId]/conv-dialogs.svelte b/src/routes/page/conversation/[conversationId]/conv-dialogs.svelte index a5dddc9..abc6eba 100644 --- a/src/routes/page/conversation/[conversationId]/conv-dialogs.svelte +++ b/src/routes/page/conversation/[conversationId]/conv-dialogs.svelte @@ -3,7 +3,7 @@ import { _ } from 'svelte-i18n' import util from "lodash"; import { Card, CardBody, CardTitle, Col, Row } from '@sveltestrap/sveltestrap'; - import { GetDialogs, getConversationFiles, sendNotification } from '$lib/services/conversation-service.js'; + import { getDialogs, getConversationFiles, sendNotification } from '$lib/services/conversation-service.js'; import { utcToLocal } from '$lib/helpers/datetime'; import { USER_SENDERS } from '$lib/helpers/constants'; import MessageFileGallery from '$lib/common/MessageFileGallery.svelte'; @@ -30,7 +30,7 @@ export let conversation; onMount(async () => { - dialogs = await GetDialogs(conversation.id); + dialogs = await getDialogs(conversation.id); }); /** diff --git a/src/routes/page/conversation/[conversationId]/conv-overview.svelte b/src/routes/page/conversation/[conversationId]/conv-overview.svelte index 98b96da..7e0e5d2 100644 --- a/src/routes/page/conversation/[conversationId]/conv-overview.svelte +++ b/src/routes/page/conversation/[conversationId]/conv-overview.svelte @@ -52,6 +52,21 @@
+ {#if conversation.tags?.length > 0} +
  • +
    + +
    +
    {$_('Tags')}
    +
      + {#each conversation.tags as tag} +
    • {tag}
    • + {/each} +
    +
    +
    +
  • + {/if} \ No newline at end of file