@djangocfg/ext-knowbase 1.0.21 → 1.0.22
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/dist/config.cjs +8 -1
- package/dist/config.js +8 -1
- package/dist/hooks.cjs +196 -35
- package/dist/hooks.js +197 -36
- package/dist/i18n.cjs +144 -0
- package/dist/i18n.d.cts +59 -0
- package/dist/i18n.d.ts +59 -0
- package/dist/i18n.js +118 -0
- package/dist/index.cjs +8 -1
- package/dist/index.js +8 -1
- package/package.json +16 -9
- package/src/components/Chat/ChatWidget.tsx +33 -16
- package/src/components/Chat/components/MessageInput.tsx +18 -8
- package/src/components/Chat/components/MessageList.tsx +19 -7
- package/src/components/Chat/components/SessionList.tsx +32 -14
- package/src/i18n/index.ts +23 -0
- package/src/i18n/locales/en.ts +36 -0
- package/src/i18n/locales/ko.ts +36 -0
- package/src/i18n/locales/ru.ts +36 -0
- package/src/i18n/types.ts +53 -0
|
@@ -7,8 +7,11 @@
|
|
|
7
7
|
|
|
8
8
|
import { Archive, Clock, Loader2, MessageSquare, Trash2 } from 'lucide-react';
|
|
9
9
|
import moment from 'moment';
|
|
10
|
-
import React, { useCallback, useEffect, useRef } from 'react';
|
|
10
|
+
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
11
11
|
|
|
12
|
+
import { createTypedExtensionT } from '@djangocfg/ext-base/i18n';
|
|
13
|
+
import { useT } from '@djangocfg/i18n';
|
|
14
|
+
import { KNOWBASE_NAMESPACE, type KnowbaseTranslations } from '../../../i18n';
|
|
12
15
|
import {
|
|
13
16
|
Badge, Button, ScrollArea, Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle
|
|
14
17
|
} from '@djangocfg/ui-nextjs';
|
|
@@ -28,6 +31,8 @@ export const SessionList: React.FC<SessionListProps> = ({
|
|
|
28
31
|
onSelectSession,
|
|
29
32
|
className = '',
|
|
30
33
|
}) => {
|
|
34
|
+
const baseT = useT();
|
|
35
|
+
const kt = createTypedExtensionT<typeof KNOWBASE_NAMESPACE, KnowbaseTranslations>(baseT, KNOWBASE_NAMESPACE);
|
|
31
36
|
const { deleteSession, archiveSession } = useKnowbaseSessionsContext();
|
|
32
37
|
const {
|
|
33
38
|
sessions,
|
|
@@ -36,7 +41,20 @@ export const SessionList: React.FC<SessionListProps> = ({
|
|
|
36
41
|
hasMore,
|
|
37
42
|
loadMore,
|
|
38
43
|
} = useInfiniteSessions();
|
|
39
|
-
|
|
44
|
+
|
|
45
|
+
const labels = useMemo(() => ({
|
|
46
|
+
title: kt('sessions.title'),
|
|
47
|
+
description: kt('sessions.description'),
|
|
48
|
+
noSessions: kt('sessions.noSessions'),
|
|
49
|
+
noSessionsDescription: kt('sessions.noSessionsDescription'),
|
|
50
|
+
untitled: kt('sessions.untitled'),
|
|
51
|
+
active: kt('sessions.active'),
|
|
52
|
+
archive: kt('sessions.archive'),
|
|
53
|
+
delete: kt('sessions.delete'),
|
|
54
|
+
loadingMore: kt('sessions.loadingMore'),
|
|
55
|
+
noMore: kt('sessions.noMore'),
|
|
56
|
+
}), [kt]);
|
|
57
|
+
|
|
40
58
|
const scrollRef = useRef<HTMLDivElement>(null);
|
|
41
59
|
|
|
42
60
|
// Handle scroll to load more
|
|
@@ -72,9 +90,9 @@ export const SessionList: React.FC<SessionListProps> = ({
|
|
|
72
90
|
<Sheet open={isOpen} onOpenChange={onClose}>
|
|
73
91
|
<SheetContent side="left" className={`w-[400px] sm:w-[540px] ${className}`}>
|
|
74
92
|
<SheetHeader>
|
|
75
|
-
<SheetTitle>
|
|
93
|
+
<SheetTitle>{labels.title}</SheetTitle>
|
|
76
94
|
<SheetDescription>
|
|
77
|
-
|
|
95
|
+
{labels.description}
|
|
78
96
|
</SheetDescription>
|
|
79
97
|
</SheetHeader>
|
|
80
98
|
|
|
@@ -87,10 +105,10 @@ export const SessionList: React.FC<SessionListProps> = ({
|
|
|
87
105
|
<div className="flex flex-col items-center justify-center py-12 text-center">
|
|
88
106
|
<MessageSquare className="h-12 w-12 text-muted-foreground mb-4" />
|
|
89
107
|
<h3 className="text-lg font-semibold text-foreground mb-2">
|
|
90
|
-
|
|
108
|
+
{labels.noSessions}
|
|
91
109
|
</h3>
|
|
92
110
|
<p className="text-sm text-muted-foreground max-w-md">
|
|
93
|
-
|
|
111
|
+
{labels.noSessionsDescription}
|
|
94
112
|
</p>
|
|
95
113
|
</div>
|
|
96
114
|
) : (
|
|
@@ -117,11 +135,11 @@ export const SessionList: React.FC<SessionListProps> = ({
|
|
|
117
135
|
<div className="flex-1 min-w-0">
|
|
118
136
|
<div className="flex items-start justify-between gap-2 mb-1">
|
|
119
137
|
<h4 className="font-medium text-sm truncate">
|
|
120
|
-
{session.title ||
|
|
138
|
+
{session.title || labels.untitled}
|
|
121
139
|
</h4>
|
|
122
140
|
{session.is_active && (
|
|
123
141
|
<Badge variant="default" className="shrink-0 text-xs">
|
|
124
|
-
|
|
142
|
+
{labels.active}
|
|
125
143
|
</Badge>
|
|
126
144
|
)}
|
|
127
145
|
</div>
|
|
@@ -143,20 +161,20 @@ export const SessionList: React.FC<SessionListProps> = ({
|
|
|
143
161
|
e.stopPropagation();
|
|
144
162
|
archiveSession(session.id, {});
|
|
145
163
|
}}
|
|
146
|
-
title=
|
|
164
|
+
title={labels.archive}
|
|
147
165
|
>
|
|
148
166
|
<Archive className="h-4 w-4" />
|
|
149
167
|
</Button>
|
|
150
168
|
<Button
|
|
151
169
|
variant="ghost"
|
|
152
170
|
size="sm"
|
|
153
|
-
className="h-8 w-8 p-0 text-destructive hover:text-destructive
|
|
171
|
+
className="h-8 w-8 p-0 text-destructive hover:text-destructive
|
|
154
172
|
hover:scale-110 active:scale-95 transition-transform duration-200"
|
|
155
173
|
onClick={(e) => {
|
|
156
174
|
e.stopPropagation();
|
|
157
175
|
deleteSession(session.id);
|
|
158
176
|
}}
|
|
159
|
-
title=
|
|
177
|
+
title={labels.delete}
|
|
160
178
|
>
|
|
161
179
|
<Trash2 className="h-4 w-4" />
|
|
162
180
|
</Button>
|
|
@@ -168,14 +186,14 @@ export const SessionList: React.FC<SessionListProps> = ({
|
|
|
168
186
|
{isLoadingMore && (
|
|
169
187
|
<div className="flex items-center justify-center py-6">
|
|
170
188
|
<Loader2 className="h-5 w-5 animate-spin text-muted-foreground mr-2" />
|
|
171
|
-
<span className="text-sm text-muted-foreground">
|
|
189
|
+
<span className="text-sm text-muted-foreground">{labels.loadingMore}</span>
|
|
172
190
|
</div>
|
|
173
191
|
)}
|
|
174
|
-
|
|
192
|
+
|
|
175
193
|
{/* No more sessions indicator */}
|
|
176
194
|
{!hasMore && sessions.length > 0 && (
|
|
177
195
|
<div className="text-center py-4">
|
|
178
|
-
<span className="text-xs text-muted-foreground">
|
|
196
|
+
<span className="text-xs text-muted-foreground">{labels.noMore}</span>
|
|
179
197
|
</div>
|
|
180
198
|
)}
|
|
181
199
|
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Knowbase Extension I18n
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createExtensionI18n } from '@djangocfg/ext-base/i18n';
|
|
6
|
+
import type { KnowbaseTranslations } from './types';
|
|
7
|
+
import { en } from './locales/en';
|
|
8
|
+
import { ru } from './locales/ru';
|
|
9
|
+
import { ko } from './locales/ko';
|
|
10
|
+
|
|
11
|
+
/** Knowbase extension namespace */
|
|
12
|
+
export const KNOWBASE_NAMESPACE = 'knowbase' as const;
|
|
13
|
+
|
|
14
|
+
export const knowbaseI18n = createExtensionI18n<KnowbaseTranslations>({
|
|
15
|
+
namespace: KNOWBASE_NAMESPACE,
|
|
16
|
+
defaultLocale: 'en',
|
|
17
|
+
locales: { en, ru, ko },
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const knowbaseTranslations = knowbaseI18n.getAllTranslations();
|
|
21
|
+
|
|
22
|
+
// Types
|
|
23
|
+
export type { KnowbaseTranslations, KnowbaseKeys, KnowbaseLocalKeys } from './types';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { KnowbaseTranslations } from '../types';
|
|
2
|
+
|
|
3
|
+
export const en: KnowbaseTranslations = {
|
|
4
|
+
chat: {
|
|
5
|
+
title: 'Knowledge Assistant',
|
|
6
|
+
titleShort: 'Support',
|
|
7
|
+
placeholder: 'Ask me anything...',
|
|
8
|
+
enterToSend: 'Press Enter to send, Shift+Enter for new line',
|
|
9
|
+
thinking: 'Thinking...',
|
|
10
|
+
source: 'Source {index}',
|
|
11
|
+
startConversation: 'Start a Conversation',
|
|
12
|
+
startConversationDescription: 'Ask me anything about the documentation, features, or get help with your project.',
|
|
13
|
+
openChat: 'Open Support Chat',
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
sessions: {
|
|
17
|
+
title: 'Chat Sessions',
|
|
18
|
+
description: 'View and manage your chat history',
|
|
19
|
+
noSessions: 'No Sessions Yet',
|
|
20
|
+
noSessionsDescription: 'Start a new conversation to create your first session.',
|
|
21
|
+
untitled: 'Untitled Session',
|
|
22
|
+
active: 'Active',
|
|
23
|
+
archive: 'Archive',
|
|
24
|
+
delete: 'Delete',
|
|
25
|
+
loadingMore: 'Loading more...',
|
|
26
|
+
noMore: 'No more sessions',
|
|
27
|
+
newChat: 'New Chat',
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
actions: {
|
|
31
|
+
sessions: 'Sessions',
|
|
32
|
+
collapse: 'Collapse',
|
|
33
|
+
expand: 'Expand',
|
|
34
|
+
close: 'Close',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { KnowbaseTranslations } from '../types';
|
|
2
|
+
|
|
3
|
+
export const ko: KnowbaseTranslations = {
|
|
4
|
+
chat: {
|
|
5
|
+
title: '지식 도우미',
|
|
6
|
+
titleShort: '지원',
|
|
7
|
+
placeholder: '무엇이든 물어보세요...',
|
|
8
|
+
enterToSend: 'Enter로 전송, Shift+Enter로 줄바꿈',
|
|
9
|
+
thinking: '생각 중...',
|
|
10
|
+
source: '출처 {index}',
|
|
11
|
+
startConversation: '대화 시작하기',
|
|
12
|
+
startConversationDescription: '문서, 기능에 대해 질문하거나 프로젝트 도움을 받으세요.',
|
|
13
|
+
openChat: '지원 채팅 열기',
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
sessions: {
|
|
17
|
+
title: '채팅 세션',
|
|
18
|
+
description: '채팅 기록 보기 및 관리',
|
|
19
|
+
noSessions: '세션 없음',
|
|
20
|
+
noSessionsDescription: '새 대화를 시작하여 첫 번째 세션을 만드세요.',
|
|
21
|
+
untitled: '제목 없음',
|
|
22
|
+
active: '활성',
|
|
23
|
+
archive: '보관',
|
|
24
|
+
delete: '삭제',
|
|
25
|
+
loadingMore: '불러오는 중...',
|
|
26
|
+
noMore: '더 이상 세션 없음',
|
|
27
|
+
newChat: '새 채팅',
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
actions: {
|
|
31
|
+
sessions: '세션',
|
|
32
|
+
collapse: '축소',
|
|
33
|
+
expand: '확장',
|
|
34
|
+
close: '닫기',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { KnowbaseTranslations } from '../types';
|
|
2
|
+
|
|
3
|
+
export const ru: KnowbaseTranslations = {
|
|
4
|
+
chat: {
|
|
5
|
+
title: 'База знаний',
|
|
6
|
+
titleShort: 'Поддержка',
|
|
7
|
+
placeholder: 'Задайте вопрос...',
|
|
8
|
+
enterToSend: 'Enter для отправки, Shift+Enter для новой строки',
|
|
9
|
+
thinking: 'Думаю...',
|
|
10
|
+
source: 'Источник {index}',
|
|
11
|
+
startConversation: 'Начать разговор',
|
|
12
|
+
startConversationDescription: 'Задайте любой вопрос о документации, функциях или получите помощь с проектом.',
|
|
13
|
+
openChat: 'Открыть чат поддержки',
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
sessions: {
|
|
17
|
+
title: 'Сессии чата',
|
|
18
|
+
description: 'Просмотр и управление историей чата',
|
|
19
|
+
noSessions: 'Нет сессий',
|
|
20
|
+
noSessionsDescription: 'Начните новый разговор, чтобы создать первую сессию.',
|
|
21
|
+
untitled: 'Без названия',
|
|
22
|
+
active: 'Активная',
|
|
23
|
+
archive: 'Архивировать',
|
|
24
|
+
delete: 'Удалить',
|
|
25
|
+
loadingMore: 'Загрузка...',
|
|
26
|
+
noMore: 'Больше нет сессий',
|
|
27
|
+
newChat: 'Новый чат',
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
actions: {
|
|
31
|
+
sessions: 'Сессии',
|
|
32
|
+
collapse: 'Свернуть',
|
|
33
|
+
expand: 'Развернуть',
|
|
34
|
+
close: 'Закрыть',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Knowbase Extension I18n Types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ExtensionKeys, PathKeys } from '@djangocfg/ext-base/i18n';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* All valid keys for knowbase translations (with namespace)
|
|
9
|
+
*/
|
|
10
|
+
export type KnowbaseKeys = ExtensionKeys<'knowbase', KnowbaseTranslations>;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Keys without namespace prefix (for createTypedExtensionT)
|
|
14
|
+
*/
|
|
15
|
+
export type KnowbaseLocalKeys = PathKeys<KnowbaseTranslations>;
|
|
16
|
+
|
|
17
|
+
export interface KnowbaseTranslations {
|
|
18
|
+
/** Chat widget */
|
|
19
|
+
chat: {
|
|
20
|
+
title: string;
|
|
21
|
+
titleShort: string;
|
|
22
|
+
placeholder: string;
|
|
23
|
+
enterToSend: string;
|
|
24
|
+
thinking: string;
|
|
25
|
+
source: string;
|
|
26
|
+
startConversation: string;
|
|
27
|
+
startConversationDescription: string;
|
|
28
|
+
openChat: string;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/** Sessions */
|
|
32
|
+
sessions: {
|
|
33
|
+
title: string;
|
|
34
|
+
description: string;
|
|
35
|
+
noSessions: string;
|
|
36
|
+
noSessionsDescription: string;
|
|
37
|
+
untitled: string;
|
|
38
|
+
active: string;
|
|
39
|
+
archive: string;
|
|
40
|
+
delete: string;
|
|
41
|
+
loadingMore: string;
|
|
42
|
+
noMore: string;
|
|
43
|
+
newChat: string;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/** Actions */
|
|
47
|
+
actions: {
|
|
48
|
+
sessions: string;
|
|
49
|
+
collapse: string;
|
|
50
|
+
expand: string;
|
|
51
|
+
close: string;
|
|
52
|
+
};
|
|
53
|
+
}
|