Skip to content

Commit 22f14ec

Browse files
authored
Merge pull request #45 from iceljc/features/refine-conversation-list-loader
Features/refine conversation list loader
2 parents 55c9fe3 + 40e7d9f commit 22f14ec

File tree

12 files changed

+92
-37
lines changed

12 files changed

+92
-37
lines changed

src/lib/common/LoadingToComplete.svelte

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,24 @@
55
export let isLoading = false;
66
export let isComplete = false;
77
export let isError = false;
8+
9+
export let successText = 'Update completed!';
10+
export let errorText = 'Error!';
11+
export let spinnerSize = 50;
812
</script>
913

1014
{#if isLoading}
11-
<Loader />
15+
<Loader size={spinnerSize} />
1216
{/if}
1317

1418
{#if isComplete}
1519
<Alert color="success">
16-
<div>Update completed!</div>
20+
<div>{successText}</div>
1721
</Alert>
1822
{/if}
1923

2024
{#if isError}
2125
<Alert color="danger">
22-
<div>Error!</div>
26+
<div>{errorText}</div>
2327
</Alert>
2428
{/if}

src/lib/helpers/datetime.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function format(datetime, type = 'date') {
2828
* @param {Date} datetime
2929
* @param {string} format - date or time
3030
*/
31-
export function utcToLocal(datetime, format = 'MMM DD YYYY, hh:mm A') {
31+
export function utcToLocal(datetime, format = 'MMM D YYYY, hh:mm A') {
3232
return moment.utc(datetime).local().format(format);
3333
}
3434

src/lib/helpers/enums.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const userRole = {
22
System: "system",
33
User: "user",
4+
Client: "client",
45
Function: "function",
56
Assistant: "assistant"
67
};

src/lib/helpers/http.js

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
import axios from 'axios';
2-
import { getUserStore, setGlobalLoad } from '$lib/helpers/store.js';
2+
import { getUserStore, loaderStore } from '$lib/helpers/store.js';
33

44
// Add a request interceptor to attach authentication tokens or headers
55
axios.interceptors.request.use(
66
(config) => {
77
// Add your authentication logic here
88
let user = getUserStore();
9-
setGlobalLoad(true);
9+
if (!skipLoader(config)) {
10+
loaderStore.set(true);
11+
}
1012
// For example, attach an authentication token to the request headers
1113
if (user.token)
1214
config.headers.Authorization = `Bearer ${user.token}`;
1315
return config;
1416
},
1517
(error) => {
16-
setGlobalLoad(false);
18+
loaderStore.set(false);
1719
return Promise.reject(error);
1820
}
1921
);
@@ -22,12 +24,11 @@ axios.interceptors.request.use(
2224
axios.interceptors.response.use(
2325
(response) => {
2426
// If the request was successful, return the response
25-
setGlobalLoad(false);
27+
loaderStore.set(false);
2628
return response;
2729
},
2830
(error) => {
29-
setGlobalLoad(false);
30-
31+
loaderStore.set(false);
3132
let user = getUserStore();
3233

3334
if (Date.now() / 1000 > user.expires) {
@@ -46,6 +47,15 @@ axios.interceptors.response.use(
4647
}
4748
);
4849

50+
/** @param {import('axios').InternalAxiosRequestConfig<any>} config */
51+
function skipLoader(config) {
52+
const regex = new RegExp('http(s*)://(.*?)/conversation/(.*?)/(.*?)', 'g');
53+
if (config.method === 'post' && !!config.data && regex.test(config.url || '')) {
54+
return true;
55+
}
56+
return false;
57+
}
58+
4959
/**
5060
* @param {String} url
5161
* @param {Object} args

src/lib/helpers/store.js

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const userStore = writable({ id: "", full_name: "", expires: 0, token: nu
1111
/**
1212
* @returns {Writable<import('$types').UserModel>}
1313
*/
14-
export function getUserStore () {
14+
export function getUserStore() {
1515
if (browser) {
1616
// Access localStorage only if in the browser context
1717
let json = localStorage.getItem('user');
@@ -31,14 +31,6 @@ userStore.subscribe(value => {
3131
}
3232
});
3333

34-
export const globalLoaderStore = writable(false);
35-
36-
/**
37-
* @param {boolean} value
38-
*/
39-
export function setGlobalLoad(value){
40-
globalLoaderStore.set(value);
41-
}
4234

4335
/** @type {Writable<import('$types').ConversationModel>}*/
4436
export const conversationStore = writable({});
@@ -72,6 +64,18 @@ conversationStore.subscribe(value => {
7264
});
7365

7466

67+
68+
const createLoaderStore = () => {
69+
const { subscribe, set } = writable(false);
70+
return {
71+
subscribe,
72+
set
73+
};
74+
}
75+
76+
export const loaderStore = createLoaderStore();
77+
78+
7579
const createConversationUserStateStore = () => {
7680
return {
7781
reset: () => {

src/lib/helpers/types.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ IRichContent.prototype.text;
263263
* @typedef {Object} ContentLogModel
264264
* @property {string} conversation_id - The conversation id.
265265
* @property {string} name - The sender name.
266+
* @property {string} role - The sender role.
266267
* @property {string} content - The log content.
267268
* @property {Date} created_at - The log sent time.
268269
* @property {boolean} is_collapsed - For UI display.

src/lib/scss/custom/pages/_conversation.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,8 @@
33
outline: none !important;
44
box-shadow: none !important;
55
}
6+
}
7+
8+
.list-title {
9+
width: 40%;
610
}

src/routes/+layout.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import en from '$lib/langs/en.json';
44
import '$lib/helpers/http';
55
import { onMount } from 'svelte';
6-
import { globalLoaderStore } from '$lib/helpers/store';
6+
import { loaderStore } from '$lib/helpers/store';
77
import Loader from '$lib/common/Loader.svelte';
88
99
addMessages('en', en);
@@ -17,7 +17,7 @@
1717
*/
1818
let isLoading;
1919
onMount(() => {
20-
const subscribe = globalLoaderStore.subscribe((value) => {
20+
const subscribe = loaderStore.subscribe(value => {
2121
isLoading = value;
2222
});
2323
})

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

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
let isLoadStateLog = false;
8181
let isOpenEditMsgModal = false;
8282
let isOpenStateModal = false;
83+
let isSendingMsg = false;
8384
8485
onMount(async () => {
8586
dialogs = await GetDialogs(params.conversationId);
@@ -157,16 +158,30 @@
157158
window.location.href = `chat/${params.agentId}/${conversation.id}`;
158159
}
159160
160-
async function sendTextMessage() {
161-
await sendMessageToHub(params.agentId, params.conversationId, text);
161+
function sendTextMessage() {
162+
isSendingMsg = true;
163+
return new Promise((resolve, reject) => {
164+
sendMessageToHub(params.agentId, params.conversationId, text).then(res => {
165+
isSendingMsg = false;
166+
resolve(res);
167+
}).catch(err => {
168+
isSendingMsg = false;
169+
reject(err);
170+
});
171+
});
172+
162173
}
163174
164175
async function startListen() {
165176
microphoneIcon = "microphone";
166-
webSpeech.onSpeechToTextDetected = async (transcript) => {
177+
webSpeech.onSpeechToTextDetected = (transcript) => {
167178
text = transcript;
168-
await sendTextMessage();
169-
microphoneIcon = "microphone-off";
179+
if (!!!_.trim(text) || isSendingMsg) return;
180+
sendTextMessage().then(() => {
181+
microphoneIcon = "microphone-off";
182+
}).catch(() => {
183+
microphoneIcon = "microphone-off";
184+
});
170185
}
171186
webSpeech.start();
172187
}
@@ -186,12 +201,13 @@
186201
/** @param {import('$types').ChatResponseModel[]} dialogs */
187202
function groupDialogs(dialogs) {
188203
if (!!!dialogs) return [];
204+
const format = 'MMM D, YYYY';
189205
// @ts-ignore
190206
return _.groupBy(dialogs, (x) => {
191-
const createDate = moment.utc(x.created_at).local().format('MMM DD YYYY');
192-
if (createDate == moment.utc().local().format('MMM DD YYYY')) {
207+
const createDate = moment.utc(x.created_at).local().format(format);
208+
if (createDate == moment.utc().local().format(format)) {
193209
return 'Today';
194-
} else if (createDate == moment.utc().local().subtract(1, 'days').format('MMM DD YYYY')) {
210+
} else if (createDate == moment.utc().local().subtract(1, 'days').format(format)) {
195211
return 'Yesterday';
196212
}
197213
return createDate;
@@ -228,12 +244,17 @@
228244
return;
229245
}
230246
231-
if ((e.key === 'Enter' && (!!e.shiftKey || !!e.ctrlKey)) || e.key !== 'Enter' || !!!_.trim(text)) {
247+
if ((e.key === 'Enter' && (!!e.shiftKey || !!e.ctrlKey)) || e.key !== 'Enter' || !!!_.trim(text) || isSendingMsg) {
232248
return;
233249
}
234250
235251
prevSentMsgs = [...prevSentMsgs, text];
236-
await sendMessageToHub(params.agentId, params.conversationId, text);
252+
isSendingMsg = true;
253+
sendMessageToHub(params.agentId, params.conversationId, text).then(() => {
254+
isSendingMsg = false;
255+
}).catch(() => {
256+
isSendingMsg = false;
257+
});
237258
}
238259
239260
function endChat() {
@@ -482,7 +503,7 @@
482503
</Dropdown>
483504
{:else}
484505
<div class="cicon-wrap float-start">
485-
{#if message.sender.role == "client"}
506+
{#if message.sender.role == UserRole.Client}
486507
<img src="images/users/user-dummy.jpg" class="rounded-circle avatar-xs" alt="avatar">
487508
{:else}
488509
<img src={PUBLIC_LIVECHAT_ENTRY_ICON} class="rounded-circle avatar-xs" alt="avatar">
@@ -557,7 +578,7 @@
557578
<button
558579
type="submit"
559580
class="btn btn-primary btn-rounded chat-send waves-effect waves-light"
560-
disabled={!!!_.trim(text)}
581+
disabled={!!!_.trim(text) || isSendingMsg}
561582
on:click={sendTextMessage}
562583
><span class="d-none d-sm-inline-block me-2">Send</span>
563584
<i class="mdi mdi-send" />

src/routes/chat/[agentId]/[conversationId]/content-log-element.svelte

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { Button } from '@sveltestrap/sveltestrap';
33
import moment from 'moment';
44
import { replaceNewLine } from '$lib/helpers/http';
5+
import { UserRole } from '$lib/helpers/enums';
56
67
/** @type {import('$types').ContentLogModel} */
78
export let data;
@@ -21,7 +22,9 @@
2122
<div class="log-content" class:log-collapse={!!data?.is_collapsed}>
2223
{@html replaceNewLine(data?.content)}
2324
</div>
25+
{#if data.role != UserRole.User}
2426
<Button class='toggle-btn' color="link" on:click={(e) => toggleText(e)}>
2527
{`${!!data?.is_collapsed ? 'More +' : 'Less -'}`}
2628
</Button>
29+
{/if}
2730
</div>

0 commit comments

Comments
 (0)