@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
package/dist/i18n.d.cts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as _djangocfg_ext_base_i18n from '@djangocfg/ext-base/i18n';
|
|
2
|
+
import { ExtensionKeys, PathKeys } from '@djangocfg/ext-base/i18n';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Knowbase Extension I18n Types
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* All valid keys for knowbase translations (with namespace)
|
|
10
|
+
*/
|
|
11
|
+
type KnowbaseKeys = ExtensionKeys<'knowbase', KnowbaseTranslations>;
|
|
12
|
+
/**
|
|
13
|
+
* Keys without namespace prefix (for createTypedExtensionT)
|
|
14
|
+
*/
|
|
15
|
+
type KnowbaseLocalKeys = PathKeys<KnowbaseTranslations>;
|
|
16
|
+
interface KnowbaseTranslations {
|
|
17
|
+
/** Chat widget */
|
|
18
|
+
chat: {
|
|
19
|
+
title: string;
|
|
20
|
+
titleShort: string;
|
|
21
|
+
placeholder: string;
|
|
22
|
+
enterToSend: string;
|
|
23
|
+
thinking: string;
|
|
24
|
+
source: string;
|
|
25
|
+
startConversation: string;
|
|
26
|
+
startConversationDescription: string;
|
|
27
|
+
openChat: string;
|
|
28
|
+
};
|
|
29
|
+
/** Sessions */
|
|
30
|
+
sessions: {
|
|
31
|
+
title: string;
|
|
32
|
+
description: string;
|
|
33
|
+
noSessions: string;
|
|
34
|
+
noSessionsDescription: string;
|
|
35
|
+
untitled: string;
|
|
36
|
+
active: string;
|
|
37
|
+
archive: string;
|
|
38
|
+
delete: string;
|
|
39
|
+
loadingMore: string;
|
|
40
|
+
noMore: string;
|
|
41
|
+
newChat: string;
|
|
42
|
+
};
|
|
43
|
+
/** Actions */
|
|
44
|
+
actions: {
|
|
45
|
+
sessions: string;
|
|
46
|
+
collapse: string;
|
|
47
|
+
expand: string;
|
|
48
|
+
close: string;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Knowbase extension namespace */
|
|
53
|
+
declare const KNOWBASE_NAMESPACE: "knowbase";
|
|
54
|
+
declare const knowbaseI18n: _djangocfg_ext_base_i18n.ExtensionI18n<KnowbaseTranslations>;
|
|
55
|
+
declare const knowbaseTranslations: Record<string, {
|
|
56
|
+
[namespace: string]: KnowbaseTranslations;
|
|
57
|
+
}>;
|
|
58
|
+
|
|
59
|
+
export { KNOWBASE_NAMESPACE, type KnowbaseKeys, type KnowbaseLocalKeys, type KnowbaseTranslations, knowbaseI18n, knowbaseTranslations };
|
package/dist/i18n.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as _djangocfg_ext_base_i18n from '@djangocfg/ext-base/i18n';
|
|
2
|
+
import { ExtensionKeys, PathKeys } from '@djangocfg/ext-base/i18n';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Knowbase Extension I18n Types
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* All valid keys for knowbase translations (with namespace)
|
|
10
|
+
*/
|
|
11
|
+
type KnowbaseKeys = ExtensionKeys<'knowbase', KnowbaseTranslations>;
|
|
12
|
+
/**
|
|
13
|
+
* Keys without namespace prefix (for createTypedExtensionT)
|
|
14
|
+
*/
|
|
15
|
+
type KnowbaseLocalKeys = PathKeys<KnowbaseTranslations>;
|
|
16
|
+
interface KnowbaseTranslations {
|
|
17
|
+
/** Chat widget */
|
|
18
|
+
chat: {
|
|
19
|
+
title: string;
|
|
20
|
+
titleShort: string;
|
|
21
|
+
placeholder: string;
|
|
22
|
+
enterToSend: string;
|
|
23
|
+
thinking: string;
|
|
24
|
+
source: string;
|
|
25
|
+
startConversation: string;
|
|
26
|
+
startConversationDescription: string;
|
|
27
|
+
openChat: string;
|
|
28
|
+
};
|
|
29
|
+
/** Sessions */
|
|
30
|
+
sessions: {
|
|
31
|
+
title: string;
|
|
32
|
+
description: string;
|
|
33
|
+
noSessions: string;
|
|
34
|
+
noSessionsDescription: string;
|
|
35
|
+
untitled: string;
|
|
36
|
+
active: string;
|
|
37
|
+
archive: string;
|
|
38
|
+
delete: string;
|
|
39
|
+
loadingMore: string;
|
|
40
|
+
noMore: string;
|
|
41
|
+
newChat: string;
|
|
42
|
+
};
|
|
43
|
+
/** Actions */
|
|
44
|
+
actions: {
|
|
45
|
+
sessions: string;
|
|
46
|
+
collapse: string;
|
|
47
|
+
expand: string;
|
|
48
|
+
close: string;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Knowbase extension namespace */
|
|
53
|
+
declare const KNOWBASE_NAMESPACE: "knowbase";
|
|
54
|
+
declare const knowbaseI18n: _djangocfg_ext_base_i18n.ExtensionI18n<KnowbaseTranslations>;
|
|
55
|
+
declare const knowbaseTranslations: Record<string, {
|
|
56
|
+
[namespace: string]: KnowbaseTranslations;
|
|
57
|
+
}>;
|
|
58
|
+
|
|
59
|
+
export { KNOWBASE_NAMESPACE, type KnowbaseKeys, type KnowbaseLocalKeys, type KnowbaseTranslations, knowbaseI18n, knowbaseTranslations };
|
package/dist/i18n.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// src/i18n/index.ts
|
|
2
|
+
import { createExtensionI18n } from "@djangocfg/ext-base/i18n";
|
|
3
|
+
|
|
4
|
+
// src/i18n/locales/en.ts
|
|
5
|
+
var en = {
|
|
6
|
+
chat: {
|
|
7
|
+
title: "Knowledge Assistant",
|
|
8
|
+
titleShort: "Support",
|
|
9
|
+
placeholder: "Ask me anything...",
|
|
10
|
+
enterToSend: "Press Enter to send, Shift+Enter for new line",
|
|
11
|
+
thinking: "Thinking...",
|
|
12
|
+
source: "Source {index}",
|
|
13
|
+
startConversation: "Start a Conversation",
|
|
14
|
+
startConversationDescription: "Ask me anything about the documentation, features, or get help with your project.",
|
|
15
|
+
openChat: "Open Support Chat"
|
|
16
|
+
},
|
|
17
|
+
sessions: {
|
|
18
|
+
title: "Chat Sessions",
|
|
19
|
+
description: "View and manage your chat history",
|
|
20
|
+
noSessions: "No Sessions Yet",
|
|
21
|
+
noSessionsDescription: "Start a new conversation to create your first session.",
|
|
22
|
+
untitled: "Untitled Session",
|
|
23
|
+
active: "Active",
|
|
24
|
+
archive: "Archive",
|
|
25
|
+
delete: "Delete",
|
|
26
|
+
loadingMore: "Loading more...",
|
|
27
|
+
noMore: "No more sessions",
|
|
28
|
+
newChat: "New Chat"
|
|
29
|
+
},
|
|
30
|
+
actions: {
|
|
31
|
+
sessions: "Sessions",
|
|
32
|
+
collapse: "Collapse",
|
|
33
|
+
expand: "Expand",
|
|
34
|
+
close: "Close"
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// src/i18n/locales/ru.ts
|
|
39
|
+
var ru = {
|
|
40
|
+
chat: {
|
|
41
|
+
title: "\u0411\u0430\u0437\u0430 \u0437\u043D\u0430\u043D\u0438\u0439",
|
|
42
|
+
titleShort: "\u041F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0430",
|
|
43
|
+
placeholder: "\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u0432\u043E\u043F\u0440\u043E\u0441...",
|
|
44
|
+
enterToSend: "Enter \u0434\u043B\u044F \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0438, Shift+Enter \u0434\u043B\u044F \u043D\u043E\u0432\u043E\u0439 \u0441\u0442\u0440\u043E\u043A\u0438",
|
|
45
|
+
thinking: "\u0414\u0443\u043C\u0430\u044E...",
|
|
46
|
+
source: "\u0418\u0441\u0442\u043E\u0447\u043D\u0438\u043A {index}",
|
|
47
|
+
startConversation: "\u041D\u0430\u0447\u0430\u0442\u044C \u0440\u0430\u0437\u0433\u043E\u0432\u043E\u0440",
|
|
48
|
+
startConversationDescription: "\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043B\u044E\u0431\u043E\u0439 \u0432\u043E\u043F\u0440\u043E\u0441 \u043E \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u0438, \u0444\u0443\u043D\u043A\u0446\u0438\u044F\u0445 \u0438\u043B\u0438 \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u0435 \u043F\u043E\u043C\u043E\u0449\u044C \u0441 \u043F\u0440\u043E\u0435\u043A\u0442\u043E\u043C.",
|
|
49
|
+
openChat: "\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0447\u0430\u0442 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0438"
|
|
50
|
+
},
|
|
51
|
+
sessions: {
|
|
52
|
+
title: "\u0421\u0435\u0441\u0441\u0438\u0438 \u0447\u0430\u0442\u0430",
|
|
53
|
+
description: "\u041F\u0440\u043E\u0441\u043C\u043E\u0442\u0440 \u0438 \u0443\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435 \u0438\u0441\u0442\u043E\u0440\u0438\u0435\u0439 \u0447\u0430\u0442\u0430",
|
|
54
|
+
noSessions: "\u041D\u0435\u0442 \u0441\u0435\u0441\u0441\u0438\u0439",
|
|
55
|
+
noSessionsDescription: "\u041D\u0430\u0447\u043D\u0438\u0442\u0435 \u043D\u043E\u0432\u044B\u0439 \u0440\u0430\u0437\u0433\u043E\u0432\u043E\u0440, \u0447\u0442\u043E\u0431\u044B \u0441\u043E\u0437\u0434\u0430\u0442\u044C \u043F\u0435\u0440\u0432\u0443\u044E \u0441\u0435\u0441\u0441\u0438\u044E.",
|
|
56
|
+
untitled: "\u0411\u0435\u0437 \u043D\u0430\u0437\u0432\u0430\u043D\u0438\u044F",
|
|
57
|
+
active: "\u0410\u043A\u0442\u0438\u0432\u043D\u0430\u044F",
|
|
58
|
+
archive: "\u0410\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
59
|
+
delete: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C",
|
|
60
|
+
loadingMore: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430...",
|
|
61
|
+
noMore: "\u0411\u043E\u043B\u044C\u0448\u0435 \u043D\u0435\u0442 \u0441\u0435\u0441\u0441\u0438\u0439",
|
|
62
|
+
newChat: "\u041D\u043E\u0432\u044B\u0439 \u0447\u0430\u0442"
|
|
63
|
+
},
|
|
64
|
+
actions: {
|
|
65
|
+
sessions: "\u0421\u0435\u0441\u0441\u0438\u0438",
|
|
66
|
+
collapse: "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C",
|
|
67
|
+
expand: "\u0420\u0430\u0437\u0432\u0435\u0440\u043D\u0443\u0442\u044C",
|
|
68
|
+
close: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C"
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// src/i18n/locales/ko.ts
|
|
73
|
+
var ko = {
|
|
74
|
+
chat: {
|
|
75
|
+
title: "\uC9C0\uC2DD \uB3C4\uC6B0\uBBF8",
|
|
76
|
+
titleShort: "\uC9C0\uC6D0",
|
|
77
|
+
placeholder: "\uBB34\uC5C7\uC774\uB4E0 \uBB3C\uC5B4\uBCF4\uC138\uC694...",
|
|
78
|
+
enterToSend: "Enter\uB85C \uC804\uC1A1, Shift+Enter\uB85C \uC904\uBC14\uAFC8",
|
|
79
|
+
thinking: "\uC0DD\uAC01 \uC911...",
|
|
80
|
+
source: "\uCD9C\uCC98 {index}",
|
|
81
|
+
startConversation: "\uB300\uD654 \uC2DC\uC791\uD558\uAE30",
|
|
82
|
+
startConversationDescription: "\uBB38\uC11C, \uAE30\uB2A5\uC5D0 \uB300\uD574 \uC9C8\uBB38\uD558\uAC70\uB098 \uD504\uB85C\uC81D\uD2B8 \uB3C4\uC6C0\uC744 \uBC1B\uC73C\uC138\uC694.",
|
|
83
|
+
openChat: "\uC9C0\uC6D0 \uCC44\uD305 \uC5F4\uAE30"
|
|
84
|
+
},
|
|
85
|
+
sessions: {
|
|
86
|
+
title: "\uCC44\uD305 \uC138\uC158",
|
|
87
|
+
description: "\uCC44\uD305 \uAE30\uB85D \uBCF4\uAE30 \uBC0F \uAD00\uB9AC",
|
|
88
|
+
noSessions: "\uC138\uC158 \uC5C6\uC74C",
|
|
89
|
+
noSessionsDescription: "\uC0C8 \uB300\uD654\uB97C \uC2DC\uC791\uD558\uC5EC \uCCAB \uBC88\uC9F8 \uC138\uC158\uC744 \uB9CC\uB4DC\uC138\uC694.",
|
|
90
|
+
untitled: "\uC81C\uBAA9 \uC5C6\uC74C",
|
|
91
|
+
active: "\uD65C\uC131",
|
|
92
|
+
archive: "\uBCF4\uAD00",
|
|
93
|
+
delete: "\uC0AD\uC81C",
|
|
94
|
+
loadingMore: "\uBD88\uB7EC\uC624\uB294 \uC911...",
|
|
95
|
+
noMore: "\uB354 \uC774\uC0C1 \uC138\uC158 \uC5C6\uC74C",
|
|
96
|
+
newChat: "\uC0C8 \uCC44\uD305"
|
|
97
|
+
},
|
|
98
|
+
actions: {
|
|
99
|
+
sessions: "\uC138\uC158",
|
|
100
|
+
collapse: "\uCD95\uC18C",
|
|
101
|
+
expand: "\uD655\uC7A5",
|
|
102
|
+
close: "\uB2EB\uAE30"
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// src/i18n/index.ts
|
|
107
|
+
var KNOWBASE_NAMESPACE = "knowbase";
|
|
108
|
+
var knowbaseI18n = createExtensionI18n({
|
|
109
|
+
namespace: KNOWBASE_NAMESPACE,
|
|
110
|
+
defaultLocale: "en",
|
|
111
|
+
locales: { en, ru, ko }
|
|
112
|
+
});
|
|
113
|
+
var knowbaseTranslations = knowbaseI18n.getAllTranslations();
|
|
114
|
+
export {
|
|
115
|
+
KNOWBASE_NAMESPACE,
|
|
116
|
+
knowbaseI18n,
|
|
117
|
+
knowbaseTranslations
|
|
118
|
+
};
|
package/dist/index.cjs
CHANGED
|
@@ -4369,7 +4369,7 @@ var apiKnowbase = api.createExtensionAPI(API);
|
|
|
4369
4369
|
// package.json
|
|
4370
4370
|
var package_default = {
|
|
4371
4371
|
name: "@djangocfg/ext-knowbase",
|
|
4372
|
-
version: "1.0.
|
|
4372
|
+
version: "1.0.22",
|
|
4373
4373
|
description: "Knowledge base and chat extension for DjangoCFG",
|
|
4374
4374
|
keywords: [
|
|
4375
4375
|
"django",
|
|
@@ -4415,6 +4415,11 @@ var package_default = {
|
|
|
4415
4415
|
types: "./dist/config.d.ts",
|
|
4416
4416
|
import: "./dist/config.js",
|
|
4417
4417
|
require: "./dist/config.cjs"
|
|
4418
|
+
},
|
|
4419
|
+
"./i18n": {
|
|
4420
|
+
types: "./dist/i18n.d.ts",
|
|
4421
|
+
import: "./dist/i18n.js",
|
|
4422
|
+
require: "./dist/i18n.cjs"
|
|
4418
4423
|
}
|
|
4419
4424
|
},
|
|
4420
4425
|
files: [
|
|
@@ -4430,6 +4435,7 @@ var package_default = {
|
|
|
4430
4435
|
peerDependencies: {
|
|
4431
4436
|
"@djangocfg/api": "workspace:*",
|
|
4432
4437
|
"@djangocfg/ext-base": "workspace:*",
|
|
4438
|
+
"@djangocfg/i18n": "workspace:*",
|
|
4433
4439
|
"@djangocfg/ui-core": "workspace:*",
|
|
4434
4440
|
"@djangocfg/ui-nextjs": "workspace:*",
|
|
4435
4441
|
consola: "^3.4.2",
|
|
@@ -4446,6 +4452,7 @@ var package_default = {
|
|
|
4446
4452
|
devDependencies: {
|
|
4447
4453
|
"@djangocfg/api": "workspace:*",
|
|
4448
4454
|
"@djangocfg/ext-base": "workspace:*",
|
|
4455
|
+
"@djangocfg/i18n": "workspace:*",
|
|
4449
4456
|
"@djangocfg/ui-core": "workspace:*",
|
|
4450
4457
|
"@djangocfg/typescript-config": "workspace:*",
|
|
4451
4458
|
"@types/node": "^24.7.2",
|
package/dist/index.js
CHANGED
|
@@ -4363,7 +4363,7 @@ var apiKnowbase = createExtensionAPI(API);
|
|
|
4363
4363
|
// package.json
|
|
4364
4364
|
var package_default = {
|
|
4365
4365
|
name: "@djangocfg/ext-knowbase",
|
|
4366
|
-
version: "1.0.
|
|
4366
|
+
version: "1.0.22",
|
|
4367
4367
|
description: "Knowledge base and chat extension for DjangoCFG",
|
|
4368
4368
|
keywords: [
|
|
4369
4369
|
"django",
|
|
@@ -4409,6 +4409,11 @@ var package_default = {
|
|
|
4409
4409
|
types: "./dist/config.d.ts",
|
|
4410
4410
|
import: "./dist/config.js",
|
|
4411
4411
|
require: "./dist/config.cjs"
|
|
4412
|
+
},
|
|
4413
|
+
"./i18n": {
|
|
4414
|
+
types: "./dist/i18n.d.ts",
|
|
4415
|
+
import: "./dist/i18n.js",
|
|
4416
|
+
require: "./dist/i18n.cjs"
|
|
4412
4417
|
}
|
|
4413
4418
|
},
|
|
4414
4419
|
files: [
|
|
@@ -4424,6 +4429,7 @@ var package_default = {
|
|
|
4424
4429
|
peerDependencies: {
|
|
4425
4430
|
"@djangocfg/api": "workspace:*",
|
|
4426
4431
|
"@djangocfg/ext-base": "workspace:*",
|
|
4432
|
+
"@djangocfg/i18n": "workspace:*",
|
|
4427
4433
|
"@djangocfg/ui-core": "workspace:*",
|
|
4428
4434
|
"@djangocfg/ui-nextjs": "workspace:*",
|
|
4429
4435
|
consola: "^3.4.2",
|
|
@@ -4440,6 +4446,7 @@ var package_default = {
|
|
|
4440
4446
|
devDependencies: {
|
|
4441
4447
|
"@djangocfg/api": "workspace:*",
|
|
4442
4448
|
"@djangocfg/ext-base": "workspace:*",
|
|
4449
|
+
"@djangocfg/i18n": "workspace:*",
|
|
4443
4450
|
"@djangocfg/ui-core": "workspace:*",
|
|
4444
4451
|
"@djangocfg/typescript-config": "workspace:*",
|
|
4445
4452
|
"@types/node": "^24.7.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/ext-knowbase",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.22",
|
|
4
4
|
"description": "Knowledge base and chat extension for DjangoCFG",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"django",
|
|
@@ -46,6 +46,11 @@
|
|
|
46
46
|
"types": "./dist/config.d.ts",
|
|
47
47
|
"import": "./dist/config.js",
|
|
48
48
|
"require": "./dist/config.cjs"
|
|
49
|
+
},
|
|
50
|
+
"./i18n": {
|
|
51
|
+
"types": "./dist/i18n.d.ts",
|
|
52
|
+
"import": "./dist/i18n.js",
|
|
53
|
+
"require": "./dist/i18n.cjs"
|
|
49
54
|
}
|
|
50
55
|
},
|
|
51
56
|
"files": [
|
|
@@ -59,10 +64,11 @@
|
|
|
59
64
|
"check": "tsc --noEmit"
|
|
60
65
|
},
|
|
61
66
|
"peerDependencies": {
|
|
62
|
-
"@djangocfg/api": "^2.1.
|
|
63
|
-
"@djangocfg/ext-base": "^1.0.
|
|
64
|
-
"@djangocfg/
|
|
65
|
-
"@djangocfg/ui-
|
|
67
|
+
"@djangocfg/api": "^2.1.111",
|
|
68
|
+
"@djangocfg/ext-base": "^1.0.17",
|
|
69
|
+
"@djangocfg/i18n": "^2.1.111",
|
|
70
|
+
"@djangocfg/ui-core": "^2.1.111",
|
|
71
|
+
"@djangocfg/ui-nextjs": "^2.1.111",
|
|
66
72
|
"consola": "^3.4.2",
|
|
67
73
|
"lucide-react": "^0.545.0",
|
|
68
74
|
"next": "^16",
|
|
@@ -75,10 +81,11 @@
|
|
|
75
81
|
"moment": "^2.30.1"
|
|
76
82
|
},
|
|
77
83
|
"devDependencies": {
|
|
78
|
-
"@djangocfg/api": "^2.1.
|
|
79
|
-
"@djangocfg/ext-base": "^1.0.
|
|
80
|
-
"@djangocfg/
|
|
81
|
-
"@djangocfg/
|
|
84
|
+
"@djangocfg/api": "^2.1.111",
|
|
85
|
+
"@djangocfg/ext-base": "^1.0.17",
|
|
86
|
+
"@djangocfg/i18n": "^2.1.111",
|
|
87
|
+
"@djangocfg/ui-core": "^2.1.111",
|
|
88
|
+
"@djangocfg/typescript-config": "^2.1.111",
|
|
82
89
|
"@types/node": "^24.7.2",
|
|
83
90
|
"@types/react": "^19.0.0",
|
|
84
91
|
"consola": "^3.4.2",
|
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
import { List, Maximize2, MessageSquare, Minimize2, Plus, X } from 'lucide-react';
|
|
9
9
|
import { usePathname } from 'next/navigation';
|
|
10
|
-
import React, { useCallback, useEffect, useState } from 'react';
|
|
10
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
11
11
|
import { createPortal } from 'react-dom';
|
|
12
12
|
|
|
13
|
+
import { createTypedExtensionT } from '@djangocfg/ext-base/i18n';
|
|
14
|
+
import { useT } from '@djangocfg/i18n';
|
|
15
|
+
import { KNOWBASE_NAMESPACE, type KnowbaseTranslations } from '../../i18n';
|
|
13
16
|
import {
|
|
14
17
|
Button, Card, CardContent, CardHeader,
|
|
15
18
|
} from '@djangocfg/ui-nextjs';
|
|
@@ -37,6 +40,8 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
37
40
|
onToggle,
|
|
38
41
|
onMessage,
|
|
39
42
|
}) => {
|
|
43
|
+
const baseT = useT();
|
|
44
|
+
const kt = createTypedExtensionT<typeof KNOWBASE_NAMESPACE, KnowbaseTranslations>(baseT, KNOWBASE_NAMESPACE);
|
|
40
45
|
const { sendQuery, getChatHistory } = useKnowbaseChatContext();
|
|
41
46
|
const { createSession, getSession } = useKnowbaseSessionsContext();
|
|
42
47
|
const {
|
|
@@ -48,9 +53,21 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
48
53
|
toggleTimestamps,
|
|
49
54
|
} = useChatUI();
|
|
50
55
|
|
|
56
|
+
const labels = useMemo(() => ({
|
|
57
|
+
title: kt('chat.title'),
|
|
58
|
+
titleShort: kt('chat.titleShort'),
|
|
59
|
+
placeholder: kt('chat.placeholder'),
|
|
60
|
+
openChat: kt('chat.openChat'),
|
|
61
|
+
sessions: kt('actions.sessions'),
|
|
62
|
+
newChat: kt('sessions.newChat'),
|
|
63
|
+
collapse: kt('actions.collapse'),
|
|
64
|
+
expand: kt('actions.expand'),
|
|
65
|
+
close: kt('actions.close'),
|
|
66
|
+
}), [kt]);
|
|
67
|
+
|
|
51
68
|
const pathname = usePathname();
|
|
52
69
|
const isMobile = useIsMobile();
|
|
53
|
-
|
|
70
|
+
|
|
54
71
|
const [isLoading, setIsLoading] = useState(false);
|
|
55
72
|
const [showSessions, setShowSessions] = useState(false);
|
|
56
73
|
const [mounted, setMounted] = useState(false);
|
|
@@ -233,7 +250,7 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
233
250
|
<div className="flex items-center justify-between p-4 border-b bg-background shadow-sm">
|
|
234
251
|
<div className="flex items-center gap-2">
|
|
235
252
|
<MessageSquare className="h-5 w-5 text-primary" />
|
|
236
|
-
<h2 className="font-semibold text-foreground">
|
|
253
|
+
<h2 className="font-semibold text-foreground">{labels.title}</h2>
|
|
237
254
|
</div>
|
|
238
255
|
|
|
239
256
|
<div className="flex items-center gap-2">
|
|
@@ -242,7 +259,7 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
242
259
|
size="sm"
|
|
243
260
|
onClick={() => setShowSessions(true)}
|
|
244
261
|
className="text-muted-foreground hover:text-foreground"
|
|
245
|
-
title=
|
|
262
|
+
title={labels.sessions}
|
|
246
263
|
>
|
|
247
264
|
<List className="h-5 w-5" />
|
|
248
265
|
</Button>
|
|
@@ -252,7 +269,7 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
252
269
|
size="sm"
|
|
253
270
|
onClick={handleNewChat}
|
|
254
271
|
className="text-muted-foreground hover:text-foreground"
|
|
255
|
-
title=
|
|
272
|
+
title={labels.newChat}
|
|
256
273
|
>
|
|
257
274
|
<Plus className="h-5 w-5" />
|
|
258
275
|
</Button>
|
|
@@ -282,7 +299,7 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
282
299
|
<MessageInput
|
|
283
300
|
onSend={handleSendMessage}
|
|
284
301
|
isLoading={isLoading}
|
|
285
|
-
placeholder=
|
|
302
|
+
placeholder={labels.placeholder}
|
|
286
303
|
/>
|
|
287
304
|
</div>
|
|
288
305
|
</div>
|
|
@@ -342,7 +359,7 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
342
359
|
<CardHeader className="flex-row items-center justify-between space-y-0 pb-3 border-b">
|
|
343
360
|
<div className="flex items-center gap-2">
|
|
344
361
|
<MessageSquare className="h-5 w-5 text-primary" />
|
|
345
|
-
<h3 className="font-semibold text-foreground">
|
|
362
|
+
<h3 className="font-semibold text-foreground">{labels.titleShort}</h3>
|
|
346
363
|
</div>
|
|
347
364
|
|
|
348
365
|
<div className="flex items-center gap-1">
|
|
@@ -351,7 +368,7 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
351
368
|
size="sm"
|
|
352
369
|
onClick={() => setShowSessions(true)}
|
|
353
370
|
className="h-8 w-8 p-0"
|
|
354
|
-
title=
|
|
371
|
+
title={labels.sessions}
|
|
355
372
|
>
|
|
356
373
|
<List className="h-4 w-4" />
|
|
357
374
|
</Button>
|
|
@@ -361,7 +378,7 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
361
378
|
size="sm"
|
|
362
379
|
onClick={handleNewChat}
|
|
363
380
|
className="h-8 w-8 p-0"
|
|
364
|
-
title=
|
|
381
|
+
title={labels.newChat}
|
|
365
382
|
>
|
|
366
383
|
<Plus className="h-4 w-4" />
|
|
367
384
|
</Button>
|
|
@@ -371,7 +388,7 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
371
388
|
size="sm"
|
|
372
389
|
onClick={uiState.isExpanded ? collapseChat : expandChat}
|
|
373
390
|
className="h-8 w-8 p-0"
|
|
374
|
-
title={uiState.isExpanded ?
|
|
391
|
+
title={uiState.isExpanded ? labels.collapse : labels.expand}
|
|
375
392
|
>
|
|
376
393
|
{uiState.isExpanded ? (
|
|
377
394
|
<Minimize2 className="h-4 w-4" />
|
|
@@ -385,7 +402,7 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
385
402
|
size="sm"
|
|
386
403
|
onClick={toggleChat}
|
|
387
404
|
className="h-8 w-8 p-0"
|
|
388
|
-
title=
|
|
405
|
+
title={labels.close}
|
|
389
406
|
>
|
|
390
407
|
<X className="h-4 w-4" />
|
|
391
408
|
</Button>
|
|
@@ -406,7 +423,7 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
406
423
|
<MessageInput
|
|
407
424
|
onSend={handleSendMessage}
|
|
408
425
|
isLoading={isLoading}
|
|
409
|
-
placeholder=
|
|
426
|
+
placeholder={labels.placeholder}
|
|
410
427
|
/>
|
|
411
428
|
</CardContent>
|
|
412
429
|
</Card>
|
|
@@ -439,8 +456,8 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
439
456
|
`}</style>
|
|
440
457
|
<Button
|
|
441
458
|
onClick={toggleChat}
|
|
442
|
-
className="w-full h-full rounded-full shadow-2xl
|
|
443
|
-
hover:scale-110 hover:rotate-12 active:scale-95
|
|
459
|
+
className="w-full h-full rounded-full shadow-2xl
|
|
460
|
+
hover:scale-110 hover:rotate-12 active:scale-95
|
|
444
461
|
transition-all duration-300 ease-out
|
|
445
462
|
flex items-center justify-center
|
|
446
463
|
group"
|
|
@@ -449,8 +466,8 @@ export const ChatWidget: React.FC<ChatWidgetProps> = ({
|
|
|
449
466
|
borderRadius: '50%',
|
|
450
467
|
padding: 0,
|
|
451
468
|
}}
|
|
452
|
-
title=
|
|
453
|
-
aria-label=
|
|
469
|
+
title={labels.openChat}
|
|
470
|
+
aria-label={labels.openChat}
|
|
454
471
|
>
|
|
455
472
|
<MessageSquare
|
|
456
473
|
className="h-7 w-7 text-primary-foreground group-hover:scale-110 transition-transform duration-300"
|
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
'use client';
|
|
7
7
|
|
|
8
8
|
import { Loader2, Send } from 'lucide-react';
|
|
9
|
-
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
9
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
10
10
|
|
|
11
|
+
import { createTypedExtensionT } from '@djangocfg/ext-base/i18n';
|
|
12
|
+
import { useT } from '@djangocfg/i18n';
|
|
13
|
+
import { KNOWBASE_NAMESPACE, type KnowbaseTranslations } from '../../../i18n';
|
|
11
14
|
import { Button, Textarea } from '@djangocfg/ui-nextjs';
|
|
12
15
|
|
|
13
16
|
import { chatLogger } from '../../../utils/logger';
|
|
@@ -22,13 +25,20 @@ export const MessageInput: React.FC<MessageInputProps> = ({
|
|
|
22
25
|
onSend,
|
|
23
26
|
isLoading = false,
|
|
24
27
|
disabled = false,
|
|
25
|
-
placeholder
|
|
28
|
+
placeholder,
|
|
26
29
|
className = '',
|
|
27
30
|
}) => {
|
|
31
|
+
const baseT = useT();
|
|
32
|
+
const kt = createTypedExtensionT<typeof KNOWBASE_NAMESPACE, KnowbaseTranslations>(baseT, KNOWBASE_NAMESPACE);
|
|
28
33
|
const [message, setMessage] = useState('');
|
|
29
34
|
const [rows, setRows] = useState(1);
|
|
30
35
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
|
31
36
|
|
|
37
|
+
const labels = useMemo(() => ({
|
|
38
|
+
placeholder: placeholder || kt('chat.placeholder'),
|
|
39
|
+
enterToSend: kt('chat.enterToSend'),
|
|
40
|
+
}), [kt, placeholder]);
|
|
41
|
+
|
|
32
42
|
// Auto-resize textarea based on content
|
|
33
43
|
useEffect(() => {
|
|
34
44
|
if (textareaRef.current) {
|
|
@@ -95,19 +105,19 @@ export const MessageInput: React.FC<MessageInputProps> = ({
|
|
|
95
105
|
value={message}
|
|
96
106
|
onChange={(e) => setMessage(e.target.value)}
|
|
97
107
|
onKeyDown={handleKeyDown}
|
|
98
|
-
placeholder={placeholder}
|
|
108
|
+
placeholder={labels.placeholder}
|
|
99
109
|
disabled={isDisabled}
|
|
100
110
|
rows={rows}
|
|
101
|
-
className="resize-none min-h-[40px] max-h-[120px] transition-all duration-200
|
|
111
|
+
className="resize-none min-h-[40px] max-h-[120px] transition-all duration-200
|
|
102
112
|
focus:ring-2 focus:ring-primary/20"
|
|
103
113
|
style={{ resize: 'none' }}
|
|
104
114
|
/>
|
|
105
|
-
|
|
115
|
+
|
|
106
116
|
<Button
|
|
107
117
|
type="submit"
|
|
108
118
|
size="icon"
|
|
109
119
|
disabled={!canSend}
|
|
110
|
-
className="shrink-0 h-10 w-10 transition-all duration-200
|
|
120
|
+
className="shrink-0 h-10 w-10 transition-all duration-200
|
|
111
121
|
hover:scale-110 active:scale-95 disabled:scale-100"
|
|
112
122
|
>
|
|
113
123
|
{isLoading ? (
|
|
@@ -117,9 +127,9 @@ export const MessageInput: React.FC<MessageInputProps> = ({
|
|
|
117
127
|
)}
|
|
118
128
|
</Button>
|
|
119
129
|
</div>
|
|
120
|
-
|
|
130
|
+
|
|
121
131
|
<p className="text-xs text-muted-foreground mt-2">
|
|
122
|
-
|
|
132
|
+
{labels.enterToSend}
|
|
123
133
|
</p>
|
|
124
134
|
</form>
|
|
125
135
|
);
|
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
import { Bot, ExternalLink, Loader2, User } from 'lucide-react';
|
|
9
9
|
import moment from 'moment';
|
|
10
|
-
import React, { useEffect, useRef } from 'react';
|
|
10
|
+
import React, { useEffect, useMemo, useRef } from 'react';
|
|
11
11
|
|
|
12
12
|
import { useAuth } from '@djangocfg/api/auth';
|
|
13
|
+
import { createTypedExtensionT } from '@djangocfg/ext-base/i18n';
|
|
14
|
+
import { useT } from '@djangocfg/i18n';
|
|
15
|
+
import { KNOWBASE_NAMESPACE, type KnowbaseTranslations } from '../../../i18n';
|
|
13
16
|
import {
|
|
14
17
|
Avatar, AvatarFallback, AvatarImage, Badge, Card, CardContent, ScrollArea
|
|
15
18
|
} from '@djangocfg/ui-nextjs';
|
|
@@ -29,9 +32,18 @@ export const MessageList: React.FC<MessageListProps> = ({
|
|
|
29
32
|
autoScroll = true,
|
|
30
33
|
className = '',
|
|
31
34
|
}) => {
|
|
35
|
+
const baseT = useT();
|
|
36
|
+
const kt = createTypedExtensionT<typeof KNOWBASE_NAMESPACE, KnowbaseTranslations>(baseT, KNOWBASE_NAMESPACE);
|
|
32
37
|
const scrollRef = useRef<HTMLDivElement>(null);
|
|
33
38
|
const { user } = useAuth();
|
|
34
39
|
|
|
40
|
+
const labels = useMemo(() => ({
|
|
41
|
+
startConversation: kt('chat.startConversation'),
|
|
42
|
+
startConversationDescription: kt('chat.startConversationDescription'),
|
|
43
|
+
source: kt('chat.source'),
|
|
44
|
+
thinking: kt('chat.thinking'),
|
|
45
|
+
}), [kt]);
|
|
46
|
+
|
|
35
47
|
// Auto-scroll to bottom on new messages
|
|
36
48
|
useEffect(() => {
|
|
37
49
|
if (autoScroll && scrollRef.current) {
|
|
@@ -58,10 +70,10 @@ export const MessageList: React.FC<MessageListProps> = ({
|
|
|
58
70
|
<div className="flex flex-col items-center justify-center h-full text-center py-12">
|
|
59
71
|
<Bot className="h-12 w-12 text-muted-foreground mb-4" />
|
|
60
72
|
<h3 className="text-lg font-semibold text-foreground mb-2">
|
|
61
|
-
|
|
73
|
+
{labels.startConversation}
|
|
62
74
|
</h3>
|
|
63
75
|
<p className="text-sm text-muted-foreground max-w-md">
|
|
64
|
-
|
|
76
|
+
{labels.startConversationDescription}
|
|
65
77
|
</p>
|
|
66
78
|
</div>
|
|
67
79
|
) : (
|
|
@@ -123,12 +135,12 @@ export const MessageList: React.FC<MessageListProps> = ({
|
|
|
123
135
|
<div key={idx}>
|
|
124
136
|
<Badge
|
|
125
137
|
variant="secondary"
|
|
126
|
-
className="text-xs flex items-center gap-1 cursor-pointer
|
|
127
|
-
hover:bg-secondary/80 hover:scale-105 active:scale-95
|
|
138
|
+
className="text-xs flex items-center gap-1 cursor-pointer
|
|
139
|
+
hover:bg-secondary/80 hover:scale-105 active:scale-95
|
|
128
140
|
transition-all duration-200 animate-in fade-in zoom-in-95"
|
|
129
141
|
style={{ animationDelay: `${(idx + 1) * 100}ms` }}
|
|
130
142
|
>
|
|
131
|
-
{source.document_title ||
|
|
143
|
+
{source.document_title || labels.source.replace('{index}', String(idx + 1))}
|
|
132
144
|
<ExternalLink className="h-3 w-3" />
|
|
133
145
|
</Badge>
|
|
134
146
|
</div>
|
|
@@ -163,7 +175,7 @@ export const MessageList: React.FC<MessageListProps> = ({
|
|
|
163
175
|
<CardContent className="p-3">
|
|
164
176
|
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
|
165
177
|
<Loader2 className="h-4 w-4 animate-spin" />
|
|
166
|
-
<span className="animate-pulse">
|
|
178
|
+
<span className="animate-pulse">{labels.thinking}</span>
|
|
167
179
|
</div>
|
|
168
180
|
</CardContent>
|
|
169
181
|
</Card>
|