@cmnd-ai/chatbot-react 1.7.1 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +239 -15
- package/dist/ChatProvider/index.d.ts +1 -1
- package/dist/ChatProvider/index.js +54 -55
- package/dist/ChatProvider/useChatContext.d.ts +2 -2
- package/dist/ChatProvider/useChatContext.js +2 -2
- package/dist/CmndChatBot/index.d.ts +15 -4
- package/dist/CmndChatBot/index.js +4 -4
- package/dist/components/ChatInputBox.d.ts +2 -1
- package/dist/components/ChatInputBox.js +3 -3
- package/dist/components/Chatbubble.d.ts +13 -3
- package/dist/components/Chatbubble.js +18 -17
- package/dist/components/Conversation.d.ts +8 -3
- package/dist/components/Conversation.js +3 -2
- package/dist/components/ConversationCard.d.ts +18 -0
- package/dist/components/ConversationCard.js +83 -0
- package/dist/components/ConversationsPanel/index.d.ts +46 -0
- package/dist/components/ConversationsPanel/index.js +355 -0
- package/dist/components/LoadingBubble.d.ts +14 -2
- package/dist/components/LoadingBubble.js +8 -7
- package/dist/components/ScrollToBottomButton.d.ts +10 -0
- package/dist/components/ScrollToBottomButton.js +57 -0
- package/dist/constants/endpoints.d.ts +5 -0
- package/dist/constants/endpoints.js +6 -0
- package/dist/hooks/use-fetch-data.d.ts +8 -0
- package/dist/hooks/use-fetch-data.js +32 -0
- package/dist/hooks/use-messages-scroll.d.ts +15 -0
- package/dist/hooks/use-messages-scroll.js +80 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/services/getChatBotConversationsList/index.d.ts +7 -0
- package/dist/services/getChatBotConversationsList/index.js +12 -0
- package/dist/styles/index.css +110 -0
- package/dist/type.d.ts +57 -0
- package/dist/utils/format_date/index.d.ts +2 -0
- package/dist/utils/format_date/index.js +32 -0
- package/dist/utils/getConversationLocalStorageKey/index.d.ts +5 -0
- package/dist/utils/getConversationLocalStorageKey/index.js +2 -0
- package/dist/utils/getUTCDateTime/index.d.ts +2 -0
- package/dist/utils/getUTCDateTime/index.js +11 -0
- package/dist/utils/saveConversationIdToLocalStorage/index.d.ts +6 -0
- package/dist/utils/saveConversationIdToLocalStorage/index.js +19 -0
- package/package.json +1 -1
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { FiChevronDown } from "react-icons/fi";
|
|
3
|
+
const ScrollToBottomButton = ({ onClick, isVisible, theme = "light", customStyles, }) => {
|
|
4
|
+
const themeColors = {
|
|
5
|
+
light: {
|
|
6
|
+
background: "#1a1d24",
|
|
7
|
+
hover: "#2a2f3a",
|
|
8
|
+
icon: "#ffffff",
|
|
9
|
+
shadow: "rgba(0, 0, 0, 0.2)",
|
|
10
|
+
},
|
|
11
|
+
dark: {
|
|
12
|
+
background: "#1a1d24",
|
|
13
|
+
hover: "#2a2f3a",
|
|
14
|
+
icon: "#ffffff",
|
|
15
|
+
shadow: "rgba(0, 0, 0, 0.4)",
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
const colors = themeColors[theme];
|
|
19
|
+
const baseStyle = {
|
|
20
|
+
position: "fixed",
|
|
21
|
+
bottom: "100px",
|
|
22
|
+
right: "20px",
|
|
23
|
+
width: "48px",
|
|
24
|
+
height: "48px",
|
|
25
|
+
borderRadius: "50%",
|
|
26
|
+
backgroundColor: colors.background,
|
|
27
|
+
color: colors.icon,
|
|
28
|
+
border: "none",
|
|
29
|
+
cursor: "pointer",
|
|
30
|
+
display: "flex",
|
|
31
|
+
alignItems: "center",
|
|
32
|
+
justifyContent: "center",
|
|
33
|
+
boxShadow: `0 4px 12px ${colors.shadow}`,
|
|
34
|
+
transition: "all 0.2s ease-in-out",
|
|
35
|
+
opacity: isVisible ? 1 : 0,
|
|
36
|
+
visibility: isVisible ? "visible" : "hidden",
|
|
37
|
+
transform: isVisible ? "translateY(0)" : "translateY(10px)",
|
|
38
|
+
zIndex: 1000,
|
|
39
|
+
};
|
|
40
|
+
const hoverStyle = {
|
|
41
|
+
backgroundColor: colors.hover,
|
|
42
|
+
transform: "translateY(-2px)",
|
|
43
|
+
boxShadow: `0 6px 16px ${colors.shadow}`,
|
|
44
|
+
};
|
|
45
|
+
return (_jsx("button", { onClick: onClick, style: {
|
|
46
|
+
...baseStyle,
|
|
47
|
+
...customStyles?.scrollButtonStyle,
|
|
48
|
+
}, onMouseEnter: (e) => {
|
|
49
|
+
Object.assign(e.currentTarget.style, hoverStyle);
|
|
50
|
+
}, onMouseLeave: (e) => {
|
|
51
|
+
Object.assign(e.currentTarget.style, {
|
|
52
|
+
...baseStyle,
|
|
53
|
+
...customStyles?.scrollButtonStyle,
|
|
54
|
+
});
|
|
55
|
+
}, title: "Scroll to bottom", "aria-label": "Scroll to bottom", children: _jsx(FiChevronDown, { size: 20 }) }));
|
|
56
|
+
};
|
|
57
|
+
export default ScrollToBottomButton;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
declare const chatbot: {
|
|
2
2
|
patchChatbotConversationMemory: (organizationId: number, chatbotId: number, chatbotConversationId: number) => string;
|
|
3
3
|
deleteChatbotConversationMemory: (organizationId: number, chatbotId: number, chatbotConversationId: number, memoryKeyToDelete: string) => string;
|
|
4
|
+
getChatBotConversationsList: ({ organizationId, chatbotId, conversationIds, }: {
|
|
5
|
+
organizationId: number;
|
|
6
|
+
chatbotId: number;
|
|
7
|
+
conversationIds: number[];
|
|
8
|
+
}) => string;
|
|
4
9
|
};
|
|
5
10
|
export { chatbot };
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
const chatbot = {
|
|
2
2
|
patchChatbotConversationMemory: (organizationId, chatbotId, chatbotConversationId) => `/organizations/${organizationId}/chatbots/${chatbotId}/conversations/${chatbotConversationId}/memory`,
|
|
3
3
|
deleteChatbotConversationMemory: (organizationId, chatbotId, chatbotConversationId, memoryKeyToDelete) => `/organizations/${organizationId}/chatbots/${chatbotId}/conversations/${chatbotConversationId}/memory/${memoryKeyToDelete}`,
|
|
4
|
+
getChatBotConversationsList: ({ organizationId, chatbotId, conversationIds, }) => {
|
|
5
|
+
const ids = Array.isArray(conversationIds)
|
|
6
|
+
? conversationIds.join(",")
|
|
7
|
+
: conversationIds;
|
|
8
|
+
return `/organizations/${organizationId}/chatbots/${chatbotId}/conversations-list/${ids}`;
|
|
9
|
+
},
|
|
4
10
|
};
|
|
5
11
|
export { chatbot };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
const useFetchData = (apiCallFn, deps = []) => {
|
|
5
|
+
const [loading, setLoading] = useState(true);
|
|
6
|
+
const [error, setError] = useState(false);
|
|
7
|
+
const [data, setData] = useState({});
|
|
8
|
+
const fetchData = async () => {
|
|
9
|
+
setLoading(true);
|
|
10
|
+
setError(false);
|
|
11
|
+
try {
|
|
12
|
+
const response = await apiCallFn();
|
|
13
|
+
setData(response);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
setError(true);
|
|
17
|
+
}
|
|
18
|
+
finally {
|
|
19
|
+
setLoading(false);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
fetchData();
|
|
24
|
+
}, deps);
|
|
25
|
+
return {
|
|
26
|
+
loading,
|
|
27
|
+
error,
|
|
28
|
+
data,
|
|
29
|
+
refetch: fetchData,
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
export default useFetchData;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { Message } from "../type.js";
|
|
3
|
+
/**
|
|
4
|
+
* A custom hook to manage auto-scrolling of a message container.
|
|
5
|
+
* Automatically scrolls to the bottom when messages change, unless the user has scrolled up.
|
|
6
|
+
*
|
|
7
|
+
* @param messages - The list of messages.
|
|
8
|
+
* @returns An object containing the `messagesRef` for the chat timeline container and a `resetMessageScroll` function.
|
|
9
|
+
*/
|
|
10
|
+
declare const useMessagesScroll: (messages: Message[]) => {
|
|
11
|
+
messagesRef: import("react").MutableRefObject<HTMLDivElement | null>;
|
|
12
|
+
resetMessagesScroll: () => void;
|
|
13
|
+
isMessagesScrolledToBottom: boolean;
|
|
14
|
+
};
|
|
15
|
+
export default useMessagesScroll;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { useRef, useEffect, useState, useCallback } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* A custom hook to manage auto-scrolling of a message container.
|
|
4
|
+
* Automatically scrolls to the bottom when messages change, unless the user has scrolled up.
|
|
5
|
+
*
|
|
6
|
+
* @param messages - The list of messages.
|
|
7
|
+
* @returns An object containing the `messagesRef` for the chat timeline container and a `resetMessageScroll` function.
|
|
8
|
+
*/
|
|
9
|
+
const useMessagesScroll = (messages) => {
|
|
10
|
+
const messagesRef = useRef(null);
|
|
11
|
+
const [userScrolled, setUserScrolled] = useState(false);
|
|
12
|
+
const [isMessagesScrolledToBottom, setIsMessagesScrolledToBottom] = useState(true);
|
|
13
|
+
const [refAvailable, setRefAvailable] = useState(false);
|
|
14
|
+
// Reset userScrolled when new messages arrive (so auto-scroll resumes)
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (messages.length > 0 && userScrolled) {
|
|
17
|
+
setUserScrolled(false);
|
|
18
|
+
}
|
|
19
|
+
}, [messages.length]);
|
|
20
|
+
// Check if ref is available
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (messagesRef.current && !refAvailable) {
|
|
23
|
+
setRefAvailable(true);
|
|
24
|
+
}
|
|
25
|
+
else if (!messagesRef.current && refAvailable) {
|
|
26
|
+
setRefAvailable(false);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
const handleMessagesScroll = useCallback(() => {
|
|
30
|
+
const messagesElement = messagesRef.current;
|
|
31
|
+
if (!messagesElement)
|
|
32
|
+
return;
|
|
33
|
+
const { scrollTop, clientHeight, scrollHeight } = messagesElement;
|
|
34
|
+
const isScrolledToBottom = Math.abs(scrollTop + clientHeight - scrollHeight) <= 100;
|
|
35
|
+
setIsMessagesScrolledToBottom(isScrolledToBottom);
|
|
36
|
+
}, []);
|
|
37
|
+
// Set up event listeners when ref becomes available
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const ref = messagesRef.current;
|
|
40
|
+
if (!ref || !refAvailable) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const onScrollUp = (e) => {
|
|
44
|
+
if (e.deltaY < 0 && !userScrolled) {
|
|
45
|
+
setUserScrolled(true);
|
|
46
|
+
if (ref) {
|
|
47
|
+
ref.removeEventListener("wheel", onScrollUp);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
// Initial scroll position check
|
|
52
|
+
handleMessagesScroll();
|
|
53
|
+
ref.addEventListener("scroll", handleMessagesScroll);
|
|
54
|
+
if (!userScrolled) {
|
|
55
|
+
ref.addEventListener("wheel", onScrollUp);
|
|
56
|
+
}
|
|
57
|
+
return () => {
|
|
58
|
+
ref.removeEventListener("wheel", onScrollUp);
|
|
59
|
+
ref.removeEventListener("scroll", handleMessagesScroll);
|
|
60
|
+
};
|
|
61
|
+
}, [refAvailable, userScrolled, handleMessagesScroll]); // Run when ref becomes available or userScrolled changes
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (messagesRef.current && !userScrolled) {
|
|
64
|
+
// Use setTimeout to ensure DOM has updated
|
|
65
|
+
setTimeout(() => {
|
|
66
|
+
if (messagesRef.current) {
|
|
67
|
+
messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
|
|
68
|
+
}
|
|
69
|
+
}, 0);
|
|
70
|
+
}
|
|
71
|
+
}, [messages, userScrolled]);
|
|
72
|
+
const resetMessagesScroll = () => {
|
|
73
|
+
if (messagesRef.current) {
|
|
74
|
+
messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
|
|
75
|
+
}
|
|
76
|
+
setUserScrolled(false);
|
|
77
|
+
};
|
|
78
|
+
return { messagesRef, resetMessagesScroll, isMessagesScrolledToBottom };
|
|
79
|
+
};
|
|
80
|
+
export default useMessagesScroll;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { default as ChatProvider } from "./ChatProvider/index.js";
|
|
2
|
-
export {
|
|
2
|
+
export { ConversationsPanel } from "./components/ConversationsPanel/index.js";
|
|
3
|
+
export { CmndChatContext, InputFieldProps, SendButtonProps, CustomStyles, CMNDChatMemory, ChatbotConversation, ChatbotConversationsResponse, } from "./type.js";
|
|
3
4
|
export { setCurrentConversationMemory, deleteCurrentConversationMemory, } from "./ChatProvider/index.js";
|
|
5
|
+
export { useCMNDChatContext } from "./ChatProvider/useChatContext.js";
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
export { default as ChatProvider } from "./ChatProvider/index.js";
|
|
2
|
+
export { ConversationsPanel } from "./components/ConversationsPanel/index.js";
|
|
2
3
|
export { setCurrentConversationMemory, deleteCurrentConversationMemory, } from "./ChatProvider/index.js";
|
|
4
|
+
export { useCMNDChatContext } from "./ChatProvider/useChatContext.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { chatbot } from "../../constants/endpoints.js";
|
|
3
|
+
const getChatBotConversationsList = async ({ organizationId, chatbotId, conversationIds, baseUrl, }) => {
|
|
4
|
+
const endpoint = chatbot.getChatBotConversationsList({
|
|
5
|
+
organizationId,
|
|
6
|
+
chatbotId,
|
|
7
|
+
conversationIds,
|
|
8
|
+
});
|
|
9
|
+
const response = await axios.get(`${baseUrl}${endpoint}`);
|
|
10
|
+
return response.data;
|
|
11
|
+
};
|
|
12
|
+
export default getChatBotConversationsList;
|
package/dist/styles/index.css
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
justify-content: center;
|
|
13
13
|
align-items: center;
|
|
14
14
|
}
|
|
15
|
+
|
|
15
16
|
.cmnd-conversations-messages {
|
|
16
17
|
display: flex;
|
|
17
18
|
flex-direction: column;
|
|
@@ -202,3 +203,112 @@
|
|
|
202
203
|
font-size: 14px;
|
|
203
204
|
}
|
|
204
205
|
}
|
|
206
|
+
|
|
207
|
+
/* Conversation Panel Styles */
|
|
208
|
+
.cmnd-conversations-panel {
|
|
209
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
|
210
|
+
"Ubuntu", "Cantarell", sans-serif;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.cmnd-conversations-sidebar {
|
|
214
|
+
scrollbar-width: thin;
|
|
215
|
+
scrollbar-color: #3d4354 #20232c;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.cmnd-conversations-sidebar::-webkit-scrollbar {
|
|
219
|
+
width: 6px;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.cmnd-conversations-sidebar::-webkit-scrollbar-track {
|
|
223
|
+
background: #20232c;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.cmnd-conversations-sidebar::-webkit-scrollbar-thumb {
|
|
227
|
+
background: #3d4354;
|
|
228
|
+
border-radius: 3px;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.cmnd-conversations-sidebar::-webkit-scrollbar-thumb:hover {
|
|
232
|
+
background: #4a5568;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.cmnd-conversation-card {
|
|
236
|
+
transition: all 0.2s ease;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.cmnd-conversation-card:hover {
|
|
240
|
+
background-color: #2d3748 !important;
|
|
241
|
+
border-color: #4a5568 !important;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.cmnd-conversation-card-active {
|
|
245
|
+
background-color: #3d4354 !important;
|
|
246
|
+
border-color: #5a67d8 !important;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.cmnd-conversation-delete {
|
|
250
|
+
opacity: 0;
|
|
251
|
+
transition: opacity 0.2s ease;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.cmnd-conversation-card:hover .cmnd-conversation-delete {
|
|
255
|
+
opacity: 1;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* Responsive design for mobile */
|
|
259
|
+
@media screen and (max-width: 768px) {
|
|
260
|
+
.cmnd-conversations-sidebar {
|
|
261
|
+
width: 100% !important;
|
|
262
|
+
border-right: none !important;
|
|
263
|
+
border-bottom: 1px solid #3d4354;
|
|
264
|
+
max-height: 200px;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.cmnd-conversations-panel {
|
|
268
|
+
flex-direction: column;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.cmnd-conversation-card {
|
|
272
|
+
padding: 8px 12px !important;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.cmnd-conversation-title {
|
|
276
|
+
font-size: 13px !important;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.cmnd-conversation-date {
|
|
280
|
+
font-size: 11px !important;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* Scroll to bottom button */
|
|
285
|
+
.cmnd-scroll-to-bottom-button {
|
|
286
|
+
position: fixed;
|
|
287
|
+
bottom: 100px;
|
|
288
|
+
right: 20px;
|
|
289
|
+
width: 48px;
|
|
290
|
+
height: 48px;
|
|
291
|
+
border-radius: 50%;
|
|
292
|
+
border: none;
|
|
293
|
+
cursor: pointer;
|
|
294
|
+
display: flex;
|
|
295
|
+
align-items: center;
|
|
296
|
+
justify-content: center;
|
|
297
|
+
transition: all 0.2s ease-in-out;
|
|
298
|
+
z-index: 1000;
|
|
299
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.cmnd-scroll-to-bottom-button:hover {
|
|
303
|
+
transform: translateY(-2px);
|
|
304
|
+
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
@media screen and (max-width: 768px) {
|
|
308
|
+
.cmnd-scroll-to-bottom-button {
|
|
309
|
+
bottom: 80px;
|
|
310
|
+
right: 15px;
|
|
311
|
+
width: 44px;
|
|
312
|
+
height: 44px;
|
|
313
|
+
}
|
|
314
|
+
}
|
package/dist/type.d.ts
CHANGED
|
@@ -2,12 +2,37 @@ import { CSSProperties } from "react";
|
|
|
2
2
|
import { ConversationProps } from "./components/Conversation.js";
|
|
3
3
|
export interface CmndChatContext {
|
|
4
4
|
props: Partial<ConversationProps>;
|
|
5
|
+
/**
|
|
6
|
+
* Create a new conversation (resets state, starts a new chat thread)
|
|
7
|
+
*/
|
|
8
|
+
createNewConversation: () => void;
|
|
9
|
+
/**
|
|
10
|
+
* Toggle the sidebar open/collapsed state
|
|
11
|
+
*/
|
|
12
|
+
toggleSidebar: () => void;
|
|
13
|
+
/**
|
|
14
|
+
* Open the sidebar (set collapsed to false)
|
|
15
|
+
*/
|
|
16
|
+
openSidePanel: () => void;
|
|
17
|
+
/**
|
|
18
|
+
* Close the sidebar (set collapsed to true)
|
|
19
|
+
*/
|
|
20
|
+
closeSidePanel: () => void;
|
|
21
|
+
/**
|
|
22
|
+
* Set the message text in the input box
|
|
23
|
+
*/
|
|
24
|
+
setMessageText: (text: string) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Send the current message, or set and send if text is provided
|
|
27
|
+
*/
|
|
28
|
+
sendMessage: (text?: string) => void;
|
|
5
29
|
}
|
|
6
30
|
export interface InputFieldProps {
|
|
7
31
|
input: string;
|
|
8
32
|
setInput: (input: string) => void;
|
|
9
33
|
canSendMessage: boolean;
|
|
10
34
|
handleSendClick: () => void;
|
|
35
|
+
inputRef?: React.RefObject<HTMLInputElement> | React.RefObject<HTMLTextAreaElement> | React.RefObject<HTMLTextAreaElement>;
|
|
11
36
|
}
|
|
12
37
|
export interface SendButtonProps {
|
|
13
38
|
handleSendClick: () => void;
|
|
@@ -126,8 +151,40 @@ export interface CustomStyles {
|
|
|
126
151
|
chatbubbleStyle?: CSSProperties;
|
|
127
152
|
botChatbubbleStyle?: CSSProperties;
|
|
128
153
|
userChatbubbleStyle?: CSSProperties;
|
|
154
|
+
scrollButtonStyle?: CSSProperties;
|
|
155
|
+
panelStyle?: CSSProperties;
|
|
156
|
+
sidebarStyle?: CSSProperties;
|
|
157
|
+
conversationListStyle?: CSSProperties;
|
|
158
|
+
headerStyle?: CSSProperties;
|
|
159
|
+
newChatButtonStyle?: CSSProperties;
|
|
160
|
+
refreshButtonStyle?: CSSProperties;
|
|
161
|
+
conversationCardStyle?: CSSProperties;
|
|
162
|
+
activeConversationCardStyle?: CSSProperties;
|
|
163
|
+
titleStyle?: CSSProperties;
|
|
164
|
+
dateStyle?: CSSProperties;
|
|
165
|
+
deleteButtonStyle?: CSSProperties;
|
|
129
166
|
}
|
|
130
167
|
export interface CMNDChatMemory {
|
|
131
168
|
[key: string]: any;
|
|
132
169
|
}
|
|
170
|
+
export interface ChatbotConversationMessage {
|
|
171
|
+
id?: string;
|
|
172
|
+
role: "user" | "assistant";
|
|
173
|
+
message: string;
|
|
174
|
+
unuseful: boolean;
|
|
175
|
+
hiddenFromUser: boolean;
|
|
176
|
+
}
|
|
177
|
+
export interface ChatbotConversation {
|
|
178
|
+
chatbotConversationId: number;
|
|
179
|
+
messages: ChatbotConversationMessage[];
|
|
180
|
+
chatbotId: number;
|
|
181
|
+
chatbotConversationTitle: string;
|
|
182
|
+
createdAt: string;
|
|
183
|
+
updatedAt: string;
|
|
184
|
+
totalCostSoFar: number;
|
|
185
|
+
totalTokensSoFar: number;
|
|
186
|
+
}
|
|
187
|
+
export interface ChatbotConversationsResponse {
|
|
188
|
+
chatbotConversations: ChatbotConversation[];
|
|
189
|
+
}
|
|
133
190
|
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const formatDate = (date) => {
|
|
2
|
+
// Parse the input date string as UTC
|
|
3
|
+
const timestamp = new Date(date + " UTC");
|
|
4
|
+
const now = new Date();
|
|
5
|
+
const localTimestampYear = timestamp.getFullYear();
|
|
6
|
+
const localTimestampMonth = timestamp.getMonth();
|
|
7
|
+
const localTimestampDate = timestamp.getDate();
|
|
8
|
+
const nowYear = now.getFullYear();
|
|
9
|
+
const nowMonth = now.getMonth();
|
|
10
|
+
const nowDate = now.getDate();
|
|
11
|
+
const hours = timestamp.getHours();
|
|
12
|
+
const minutes = timestamp.getMinutes();
|
|
13
|
+
if (nowYear === localTimestampYear &&
|
|
14
|
+
nowMonth === localTimestampMonth &&
|
|
15
|
+
nowDate === localTimestampDate) {
|
|
16
|
+
return `Today at ${hours}:${minutes < 10 ? "0" + minutes : minutes}`;
|
|
17
|
+
}
|
|
18
|
+
else if (nowYear === localTimestampYear &&
|
|
19
|
+
nowMonth === localTimestampMonth &&
|
|
20
|
+
nowDate - localTimestampDate === 1) {
|
|
21
|
+
return `Yesterday at ${hours}:${minutes < 10 ? "0" + minutes : minutes}`;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
// Use toLocaleDateString to format in local time zone
|
|
25
|
+
return timestamp.toLocaleDateString("en-GB", {
|
|
26
|
+
month: "long",
|
|
27
|
+
day: "numeric",
|
|
28
|
+
year: "numeric",
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
export default formatDate;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const getUTCDateTime = () => {
|
|
2
|
+
const now = new Date();
|
|
3
|
+
const year = now.getUTCFullYear();
|
|
4
|
+
const month = String(now.getUTCMonth() + 1).padStart(2, "0");
|
|
5
|
+
const day = String(now.getUTCDate()).padStart(2, "0");
|
|
6
|
+
const hours = String(now.getUTCHours()).padStart(2, "0");
|
|
7
|
+
const minutes = String(now.getUTCMinutes()).padStart(2, "0");
|
|
8
|
+
const seconds = String(now.getUTCSeconds()).padStart(2, "0");
|
|
9
|
+
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
10
|
+
};
|
|
11
|
+
export default getUTCDateTime;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import getConversationLocalStorageKey from "../getConversationLocalStorageKey/index.js";
|
|
2
|
+
const saveConversationIdToLocalStorage = async ({ chatbotConversationId, chatbotId, organizationId, }) => {
|
|
3
|
+
try {
|
|
4
|
+
const key = getConversationLocalStorageKey({
|
|
5
|
+
organizationId,
|
|
6
|
+
chatbotId: Number(chatbotId),
|
|
7
|
+
});
|
|
8
|
+
//get the conversation ids from local storage
|
|
9
|
+
const conversations = JSON.parse(localStorage.getItem(key) || "[]") ?? [];
|
|
10
|
+
if (!conversations.includes(chatbotConversationId)) {
|
|
11
|
+
conversations.push(chatbotConversationId);
|
|
12
|
+
localStorage.setItem(key, JSON.stringify(conversations));
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
console.error("error saving conversation id to local storage", error);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
export default saveConversationIdToLocalStorage;
|