Skip to content

Commit 50a76b5

Browse files
author
Jicheng Lu
committed
Merge branch 'main' of https://github.com/SciSharp/BotSharp-UI into features/refine-chat-window
2 parents c73b117 + d0cfdb6 commit 50a76b5

File tree

7 files changed

+274
-3
lines changed

7 files changed

+274
-3
lines changed

src/lib/helpers/types/userTypes.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,15 @@
4949
* @property {string[]} [external_ids] - The external ids.
5050
*/
5151

52+
/**
53+
* @typedef {Object} DashboardModel
54+
* @property {DashboardConversation[]} [conversation_list] - conversation components
55+
*/
56+
57+
/**
58+
* @typedef {Object} DashboardConversation
59+
* @property {string} [name] - The conversation name.
60+
* @property {string} [conversation_id] - The conversation id.
61+
* @property {string} [instruction] - The user input instruction.
62+
*/
5263
export default {};

src/lib/services/api-endpoints.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export const endpoints = {
6060
conversationMessageUpdateUrl: `${host}/conversation/{conversationId}/update-message`,
6161
conversationTagsUpdateUrl: `${host}/conversation/{conversationId}/update-tags`,
6262
fileUploadUrl: `${host}/agent/{agentId}/conversation/{conversationId}/upload`,
63+
pinConversationUrl: `${host}/agent/{agentId}/conversation/{conversationId}/dashboard`,
6364

6465
// LLM provider
6566
llmProvidersUrl: `${host}/llm-providers`,
@@ -93,6 +94,10 @@ export const endpoints = {
9394
// chathub
9495
chatHubUrl: `${host}/chatHub`,
9596

97+
// dashboard
98+
dashboardSettingUrl: `${host}/dashboard/components`,
99+
dashConversationInstructionUrl: `${host}/dashboard/component/conversation?userId={userId}`,
100+
96101
// Google geocode api
97102
addressUrl: `${host}/address/options`
98103
}

src/lib/services/conversation-service.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,47 @@ export async function sendMessageToHub(agentId, conversationId, text, data = nul
105105
return response.data;
106106
}
107107

108+
/**
109+
* pin a conversation to dashboard
110+
* @param {string} agentId - The agent id
111+
* @param {string} conversationId - The conversation id
112+
*/
113+
export async function pinConversationToDashboard(agentId, conversationId) {
114+
let url = replaceUrl(endpoints.pinConversationUrl, {
115+
agentId: agentId,
116+
conversationId: conversationId
117+
});
118+
const response = await axios.put(url);
119+
return response.data;
120+
}
121+
122+
/**
123+
* unpin a conversation from dashboard
124+
* @param {string} agentId - The agent id
125+
* @param {string} conversationId - The conversation id
126+
*/
127+
export async function unpinConversationFromDashboard(agentId, conversationId) {
128+
let url = replaceUrl(endpoints.pinConversationUrl, {
129+
agentId: agentId,
130+
conversationId: conversationId
131+
});
132+
const response = await axios.delete(url);
133+
return response.data;
134+
}
135+
136+
/**
137+
* update a dashboard conversation instuction
138+
* @param {string} userId - The conversation id
139+
* @param {import('$userTypes').DashboardConversation} dashConv - The instruction
140+
*/
141+
export async function updateDashboardConversation(userId, dashConv) {
142+
let url = replaceUrl(endpoints.dashConversationInstructionUrl, {
143+
userId: userId
144+
});
145+
const response = await axios.post(url, dashConv);
146+
return response.data;
147+
}
148+
108149

109150
/**
110151
* send a notification to conversation
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { endpoints } from '$lib/services/api-endpoints.js';
2+
import axios from 'axios';
3+
4+
/**
5+
* Get dashboard settings
6+
* @param {string} userId - The user id
7+
* @returns {Promise<import('$userTypes').DashboardModel>}
8+
*/
9+
export async function getDashboardSettings(userId) {
10+
let userIdParam = userId;
11+
let url = endpoints.dashboardSettingUrl;
12+
console.log(url);
13+
const response = await axios.get(url, {
14+
params: {
15+
"userId" : userId
16+
}
17+
});
18+
return response.data;
19+
}

src/routes/chat/[agentId]/[conversationId]/chat-box.svelte

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
getConversationUser,
3535
uploadConversationFiles,
3636
getAddressOptions,
37+
pinConversationToDashboard,
3738
} from '$lib/services/conversation-service.js';
3839
import {
3940
PUBLIC_LIVECHAT_ENTRY_ICON,
@@ -553,6 +554,12 @@
553554
window.location.href = url.toString();
554555
}
555556
557+
function pinDashboard() {
558+
const agentId = params.agentId;
559+
const convId = params.conversationId;
560+
pinConversationToDashboard(agentId, convId).then().finally();
561+
}
562+
556563
function handleSaveKnowledge() {
557564
sendChatMessage("Save knowledge");
558565
}
@@ -1520,7 +1527,10 @@
15201527
{/if}
15211528
{#if agent?.id === LEARNER_ID && mode === TRAINING_MODE}
15221529
<DropdownItem on:click={() => handleSaveKnowledge()}>Save Knowledge</DropdownItem>
1523-
{/if}
1530+
{/if}
1531+
<DropdownItem on:click={() => pinDashboard()}>
1532+
Pin to Dashboard
1533+
</DropdownItem>
15241534
</DropdownMenu>
15251535
</Dropdown>
15261536
{:else}

src/routes/page/dashboard/+page.svelte

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,44 @@
2828
} from '$env/static/public';
2929
import { onMount } from 'svelte';
3030
import { getUserStore, userStore } from '$lib/helpers/store';
31+
import Conversation from './Conversation.svelte';
32+
import { getDashboardSettings } from '$lib/services/dashboard-service';
3133
3234
let subscribemodal = false;
33-
let user = {full_name: ""};
35+
let user = {full_name: "", id: ""};
36+
37+
/**
38+
* @type {import("../../../lib/helpers/types/userTypes").DashboardModel}
39+
*/
40+
let dashboard_model ;
3441
const togglesubscribemodal = (() => {
3542
subscribemodal = !subscribemodal;
3643
})
3744
3845
onMount(() => {
39-
const userModelSubscribe = userStore.subscribe((/** @type {{ full_name: string; }} */ value) => {
46+
const userModelSubscribe = userStore.subscribe((/** @type {{ full_name: string; id: string }} */ value) => {
4047
user = value;
4148
})
4249
user = getUserStore();
50+
loadDashboardComponents(user.id);
4351
setTimeout(() => {
4452
subscribemodal = true;
4553
}, 1000);
4654
})
55+
56+
/**
57+
* delete a message in conversation
58+
* @param {string} userId The user input
59+
*/
60+
async function loadDashboardComponents(userId) {
61+
getDashboardSettings(userId)
62+
.then(
63+
response => {
64+
dashboard_model = response
65+
}
66+
)
67+
.catch();
68+
}
4769
</script>
4870

4971
<HeadTitle title={$_('Dashboard')} />
@@ -207,6 +229,14 @@
207229
</Col>
208230
</Row>
209231

232+
<Row>
233+
{#each dashboard_model?.conversation_list || [] as conv, index (conv.conversation_id)}
234+
{#if conv?.conversation_id}
235+
<Conversation conversationId={conv.conversation_id} instruction={conv.instruction} userId={user.id}/>
236+
{/if}
237+
{/each}
238+
</Row>
239+
210240
<Row>
211241
<SocialSource />
212242
<Activity />
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
<script>
2+
import { Card, CardBody, CardTitle, Col, Row } from '@sveltestrap/sveltestrap';
3+
import { _ } from 'svelte-i18n';
4+
import { onMount } from 'svelte';
5+
import ChatTextArea from '../../chat/[agentId]/[conversationId]/chat-util/chat-text-area.svelte';
6+
import { getConversation, updateDashboardConversation, unpinConversationFromDashboard } from '$lib/services/conversation-service';
7+
8+
/** @type {string}*/
9+
export let conversationId;
10+
/** @type {string}*/
11+
export let instruction;
12+
/** @type {string}*/
13+
export let userId;
14+
15+
/** @type {import('$conversationTypes').ConversationModel}*/
16+
let conversationModel;
17+
18+
let agent = {
19+
name: "Loading",
20+
icon_url: "https://botsharp.azurewebsites.net/images/users/bot.png"
21+
};
22+
23+
let isLoading = true;
24+
25+
/** @type {string} */
26+
let hide = '';
27+
28+
/** @type {string} */
29+
let text;
30+
/** @type {boolean} */
31+
let loadUtils;
32+
33+
/** @type {number} */
34+
let messageInputTimeout;
35+
36+
/** @type {string[]} */
37+
let chatUtilOptions = [];
38+
39+
onMount(() => {
40+
if (conversationId) {
41+
loadDashboardComponents(conversationId);
42+
}
43+
if (instruction) {
44+
text = instruction;
45+
}
46+
}
47+
);
48+
49+
/**
50+
* delete a message in conversation
51+
* @param {string} id The user input
52+
*/
53+
async function loadDashboardComponents(id) {
54+
getConversation(id)
55+
.then(
56+
response => {
57+
conversationModel = response;
58+
isLoading = false;
59+
}
60+
)
61+
.catch();
62+
}
63+
64+
/** @param {any} e */
65+
function handleMessageInput(e) {
66+
const value = e.target.value;
67+
68+
clearTimeout(messageInputTimeout);
69+
chatUtilOptions = [];
70+
}
71+
</script>
72+
73+
<Col xl={4}>
74+
<Card bind:class={hide}>
75+
<CardBody>
76+
{#if isLoading}
77+
<CardTitle class="mb-0">{"Loading..."} </CardTitle>
78+
<p> Loading ... </p>
79+
{:else}
80+
<div class="row">
81+
<div class="col-10">
82+
<CardTitle class="mb-0">{conversationModel.title} </CardTitle>
83+
</div>
84+
<div class="col-2 ">
85+
<button
86+
class={`btn btn-rounded btn-sm btn-light`}
87+
on:click={() => {
88+
hide = 'hide';
89+
unpinConversationFromDashboard(conversationModel.agent_id, conversationId);
90+
}}
91+
>
92+
<i
93+
class="mdi mdi-pin-off"
94+
style="font-size: 12px;"
95+
data-bs-toggle="tooltip"
96+
data-bs-placement="top"
97+
title="Unpin"
98+
/>
99+
</button>
100+
</div>
101+
</div>
102+
<div class="card mb-2">
103+
<div class="chat-head">
104+
<div class="row chat-row">
105+
<div class="col-md-0 col-7 chat-head-info">
106+
<div class="chat-head-agent">
107+
{#if agent?.icon_url}
108+
<div class="line-align-center">
109+
<img class="chat-head-agent-icon" src={agent.icon_url} alt="">
110+
</div>
111+
{/if}
112+
<div class="chat-head-agent-name line-align-center ellipsis">{conversationModel.agent_id}</div>
113+
</div>
114+
</div>
115+
</div>
116+
</div>
117+
118+
<div class={`chat-input-section css-animation fade-in-from-none mb-2`}>
119+
<div class="row">
120+
<div class="col-10">
121+
<div class="position-relative">
122+
<ChatTextArea
123+
className={`chat-input`}
124+
maxLength={1024}
125+
disabled={false}
126+
bind:text={text}
127+
bind:loadUtils={loadUtils}
128+
bind:options={chatUtilOptions}
129+
onFocus={e => chatUtilOptions = []}
130+
>
131+
</ChatTextArea>
132+
</div>
133+
</div>
134+
<div class="col-auto">
135+
<button
136+
type="submit"
137+
class={`btn btn-rounded chat-send waves-effect waves-light btn-primary`}
138+
disabled={!!!(text)}
139+
on:click={() => updateDashboardConversation(userId, {
140+
conversation_id: conversationId,
141+
name: '',
142+
instruction: text
143+
})}
144+
>
145+
<i class="mdi mdi-send" />
146+
</button>
147+
</div>
148+
</div>
149+
</div>
150+
</div>
151+
{/if}
152+
153+
</CardBody>
154+
</Card>
155+
</Col>

0 commit comments

Comments
 (0)