Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features/refine chat window #83

Merged
merged 3 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions src/lib/common/Label.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<script>

/** @type {string} */
export let text = "";
export let className = "";
export let style = "";
/** @type {string | number} */
export let index;
/** @type {(args0: number | string) => void} */
export let onClose = () => {};

/**
* @param {any} e
* @param {string | number} index
*/
function handleClose(e, index) {
e.preventDefault();
onClose && onClose(index);
}
</script>

<div class={`label-container ${className}`} style={`${style}`}>
<button class="btn btn-primary btn-sm label-btn">
<div style="display: flex;">
<span class="d-none d-sm-inline-block me-2 label-text">
{text}
</span>
<i
class="mdi mdi-window-close label-close"
role="button"
tabindex="0"
on:keydown={() => {}}
on:click={(e) => handleClose(e, index)}
/>
</div>
</button>
</div>


<style>
.label-container {
display: inline-block;
margin-top: 10px;
margin-bottom: 10px;
margin-right: 5px;
}

.label-btn {
cursor: default;
font-size: 12px;
border-radius: 15px;
}

.label-text {
text-align: left;
}

.label-close {
cursor: pointer;
display: flex;
align-items: center;
}
</style>
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<script>
import { Button, Input, Modal, ModalBody, ModalFooter, ModalHeader, Row, Form, FormGroup } from "@sveltestrap/sveltestrap";
import _ from "lodash";
import { page } from '$app/stores';
import { conversationUserStateStore } from "$lib/helpers/store";

/** @type {boolean} */
export let isOpen;
Expand All @@ -23,22 +21,25 @@
export let cancel;

/** @type {number} */
const limit = 10;
const params = $page.params;
export let limit = 10;

/** @type {string} */
export let title = "Add states";

/** @type {boolean} */
export let validateKey = true;
export let validateValue = true;

/** @type {import('$types').UserStateDetailModel[]} */
let states = [];
export let states = [];

$: {
if (isOpen) {
const conversationUserStates = conversationUserStateStore.get();
if (!!conversationUserStates && conversationUserStates.conversationId == params.conversationId && !!conversationUserStates.states) {
states = [...conversationUserStates.states];
if (states?.length > 0) {
states = [...states];
} else {
states = [{ key: { data: '', isValid: true }, value: { data: '', isValid: true } }];
}
} else {
states = [];
}
}

Expand All @@ -52,29 +53,19 @@
states = states.map(state => {
const key = _.trim(state.key.data);
const value = _.trim(state.value.data);
if (!!!key) {
if (!!!key && validateKey) {
state.key.isValid = false;
isValidForm = isValidForm && state.key.isValid;
}

if (!!!value) {
if (!!!value && validateValue) {
state.value.isValid = false;
isValidForm = isValidForm && state.value.isValid;
}

isValidForm = isValidForm && state.key.isValid && state.value.isValid;
return state;
});

if (!isValidForm) return;

const cleanStates = states.map(state => {
state.key.data = _.trim(state.key.data);
state.value.data = _.trim(state.value.data);
return state;
});
conversationUserStateStore.put({
conversationId: params.conversationId,
states: cleanStates
});
confirm && confirm();
}

Expand All @@ -89,7 +80,7 @@
}

/** @param {number} index */
function removeState(index) {
function remove(index) {
states = states.filter((x, idx) => idx !== index);
}

Expand Down Expand Up @@ -123,7 +114,7 @@
</script>

<Modal class={className} fade size={size} isOpen={isOpen} toggle={() => toggleModal && toggleModal()}>
<ModalHeader>Add states</ModalHeader>
<ModalHeader>{title}</ModalHeader>
<ModalBody>
<Form class="state-form">
{#each states as state, idx (idx)}
Expand All @@ -149,7 +140,7 @@
<Button
class="btn btn-sm btn-rounded"
color="danger"
on:click={() => removeState(idx)}
on:click={() => remove(idx)}
>
<i class="mdi mdi-window-close"></i>
</Button>
Expand Down
18 changes: 18 additions & 0 deletions src/lib/helpers/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { browser } from '$app/environment';

const conversationKey = "conversation";
const conversationUserStatesKey = "conversation_user_states";
const conversationSearchStatesKey = "conversation_search_states";
const conversationUserMessageKey = "conversation_user_messages";

/** @type {Writable<import('$types').UserModel>} */
Expand Down Expand Up @@ -94,6 +95,23 @@ const createConversationUserStateStore = () => {

export const conversationUserStateStore = createConversationUserStateStore();

const createConversationSearchStateStore = () => {
return {
reset: () => {
localStorage.removeItem(conversationSearchStatesKey);
},
get: () => {
const json = localStorage.getItem(conversationSearchStatesKey);
return json ? JSON.parse(json) : [];
},
put: (value) => {
localStorage.setItem(conversationSearchStatesKey, JSON.stringify(value));
}
}
};

export const conversationSearchStateStore = createConversationSearchStateStore();


const createConversationUserMessageStore = () => {
return {
Expand Down
4 changes: 4 additions & 0 deletions src/lib/scss/custom/pages/_chat.scss
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,10 @@

.state-form {
padding-left: 25px;
overflow-y: auto;
overflow-x: hidden;
max-height: 800px;
scrollbar-width: thin;

.state-input {
flex: 0.45;
Expand Down
53 changes: 39 additions & 14 deletions src/routes/chat/[agentId]/[conversationId]/chat-box.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@
import _ from "lodash";
import { Pane, Splitpanes } from 'svelte-splitpanes';
import StateLog from './stateLogs/state-log.svelte';
import StateModal from './addStateModal/state-modal.svelte';
import ChatImage from './chatImage/chat-image.svelte';
import Swal from 'sweetalert2/dist/sweetalert2.js';
import "sweetalert2/src/sweetalert2.scss";
import moment from 'moment';
import StateModal from '$lib/common/StateModal.svelte';

const options = {
scrollbars: {
Expand Down Expand Up @@ -81,13 +81,16 @@
/** @type {import('$types').ConversationStateLogModel[]} */
let stateLogs = [];

/** @type {import('$types').UserStateDetailModel[]} */
let userAddStates = [];

/** @type {boolean} */
let isLoadContentLog = false;
let isLoadStateLog = false;
let isContentLogClosed = false; // initial condition
let isStateLogClosed = false; // initial condition
let isOpenEditMsgModal = false;
let isOpenAddStateModal = false;
let isOpenUserAddStateModal = false;
let isSendingMsg = false;
let isThinking = false;
let isLite = false;
Expand Down Expand Up @@ -120,7 +123,7 @@
isLoadContentLog = false;
isLoadStateLog = false;
isOpenEditMsgModal = false;
isOpenAddStateModal = false;
isOpenUserAddStateModal = false;
}
}

Expand Down Expand Up @@ -416,8 +419,31 @@
stateLogs = [];
}

function toggleAddStateModal() {
isOpenAddStateModal = !isOpenAddStateModal;
function toggleUserAddStateModal() {
isOpenUserAddStateModal = !isOpenUserAddStateModal;
if (isOpenUserAddStateModal) {
loadAddStates();
}
}

function loadAddStates() {
const conversationUserStates = conversationUserStateStore.get();
if (!!conversationUserStates && conversationUserStates.conversationId == params.conversationId && !!conversationUserStates.states) {
userAddStates = [...conversationUserStates.states];
}
}

function handleConfirmUserAddStates() {
const cleanStates = userAddStates.map(state => {
state.key.data = _.trim(state.key.data);
state.value.data = _.trim(state.value.data);
return state;
});
conversationUserStateStore.put({
conversationId: params.conversationId,
states: cleanStates
});
toggleUserAddStateModal();
}

function clearAddedStates() {
Expand Down Expand Up @@ -619,7 +645,6 @@
<svelte:window on:resize={() => resizeChatWindow()}/>

<DialogModal
className="custom-modal"
title={'Edit message'}
isOpen={isOpenEditMsgModal}
toggleModal={toggleEditMsgModal}
Expand All @@ -631,11 +656,11 @@
</DialogModal>

<StateModal
className="custom-modal"
isOpen={isOpenAddStateModal}
toggleModal={toggleAddStateModal}
confirm={toggleAddStateModal}
cancel={toggleAddStateModal}
isOpen={isOpenUserAddStateModal}
bind:states={userAddStates}
toggleModal={toggleUserAddStateModal}
confirm={handleConfirmUserAddStates}
cancel={toggleUserAddStateModal}
/>

<HeadTitle title="Chat" addOn='' />
Expand Down Expand Up @@ -683,7 +708,7 @@
{#if !isLite && !isLoadContentLog}
<DropdownItem on:click={() => toggleContentLog()}>View Log</DropdownItem>
{/if}
{#if !isLite && (!isLoadStateLog || !isOpenAddStateModal)}
{#if !isLite && (!isLoadStateLog || !isOpenUserAddStateModal)}
<li>
<Dropdown direction="right" class="state-menu">
<DropdownToggle caret class="dropdown-item">
Expand All @@ -693,8 +718,8 @@
{#if !isLoadStateLog}
<DropdownItem on:click={() => toggleStateLog()}>View States</DropdownItem>
{/if}
{#if !isOpenAddStateModal}
<DropdownItem on:click={() => toggleAddStateModal()}>Add States</DropdownItem>
{#if !isOpenUserAddStateModal}
<DropdownItem on:click={() => toggleUserAddStateModal()}>Add States</DropdownItem>
{/if}
<DropdownItem on:click={() => clearAddedStates()}>Clear States</DropdownItem>
</DropdownMenu>
Expand Down
27 changes: 24 additions & 3 deletions src/routes/page/agent/[agentId]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
} from '@sveltestrap/sveltestrap';
import Breadcrumb from '$lib/common/Breadcrumb.svelte';
import HeadTitle from '$lib/common/HeadTitle.svelte';

import LoadingToComplete from '$lib/common/LoadingToComplete.svelte';
import AgentPrompt from './agent-prompt.svelte';
import AgentOverview from './agent-overview.svelte';
import AgentFunction from './agent-function.svelte';
Expand All @@ -16,19 +16,39 @@
import { onMount } from 'svelte';
const params = $page.params;
import { _ } from 'svelte-i18n'

/** @type {import('$types').AgentModel} */
let agent;
/** @type {any} */
let agentFunctionCmp = null;

/** @type {boolean} */
let isLoading = false;
let isComplete = false;
let isError = false;
const duration = 3000;

onMount(async () => {
agent = await getAgent(params.agentId);
});

async function handleAgentUpdate() {
fetchJsonContent();
const result = await saveAgent(agent)
isLoading = true;
saveAgent(agent).then(res => {
isLoading = false;
isComplete = true;
setTimeout(() => {
isComplete = false;
}, duration);
}).catch(err => {
isLoading = false;
isComplete = false;
isError = true;
setTimeout(() => {
isError = false;
}, duration);
});
}

function fetchJsonContent() {
Expand All @@ -46,6 +66,7 @@

<HeadTitle title="{$_('Agent Overview')}" />
<Breadcrumb title="{$_('Agent')}" pagetitle="{$_('Agent Overview')}" />
<LoadingToComplete isLoading={isLoading} isComplete={isComplete} isError={isError} />

<Row>
{#if agent}
Expand Down
Loading
Loading