@eeacms/volto-eea-chatbot 2.0.5 → 3.0.1
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/.github/workflows/betterleaks.yml +133 -0
- package/.gitleaks.toml +89 -0
- package/AGENTS.md +230 -0
- package/CHANGELOG.md +40 -0
- package/README.md +59 -0
- package/RELEASE.md +1 -1
- package/locales/de/LC_MESSAGES/volto.po +44 -0
- package/locales/en/LC_MESSAGES/volto.po +44 -0
- package/locales/it/LC_MESSAGES/volto.po +44 -0
- package/locales/ro/LC_MESSAGES/volto.po +44 -0
- package/locales/volto.pot +46 -2
- package/package.json +2 -1
- package/src/AISearchInput/AISearchInputEdit.jsx +37 -0
- package/src/AISearchInput/AISearchInputView.jsx +130 -0
- package/src/AISearchInput/components/DeepResearchToggle.jsx +35 -0
- package/src/AISearchInput/components/DisclaimerText.jsx +10 -0
- package/src/AISearchInput/components/IntroHeader.jsx +24 -0
- package/src/AISearchInput/components/PromptChips.jsx +22 -0
- package/src/AISearchInput/components/SearchInput.jsx +53 -0
- package/src/AISearchInput/index.js +32 -0
- package/src/AISearchInput/messages.js +38 -0
- package/src/AISearchInput/schema.jsx +215 -0
- package/src/AISearchInput/styles.less +320 -0
- package/src/ChatBlock/ChatBlockView.jsx +4 -0
- package/src/ChatBlock/chat/ChatWindow.tsx +23 -0
- package/src/ChatBlock/packets/MultiToolRenderer.tsx +20 -11
- package/src/ChatBlock/services/messageProcessor.ts +32 -14
- package/src/ChatBlock/style.less +41 -51
- package/src/halloumi/filtering.js +2 -2
- package/src/halloumi/generative.test.js +1 -1
- package/src/halloumi/middleware.js +2 -2
- package/src/halloumi/middleware.test.js +5 -5
- package/src/icons/sparkle.svg +3 -0
- package/src/index.js +2 -0
- package/src/middleware.js +2 -2
- package/src/middleware.test.js +11 -11
|
@@ -11,4 +11,48 @@ msgstr ""
|
|
|
11
11
|
"Content-Transfer-Encoding: \n"
|
|
12
12
|
"Plural-Forms: \n"
|
|
13
13
|
|
|
14
|
+
#. Default: "AI Search Input"
|
|
15
|
+
#: AISearchInput/messages
|
|
16
|
+
msgid "AI Search Input"
|
|
17
|
+
msgstr ""
|
|
18
|
+
|
|
19
|
+
#. Default: "Ask your question..."
|
|
20
|
+
#: AISearchInput/components/SearchInput
|
|
21
|
+
#: AISearchInput/messages
|
|
22
|
+
msgid "Ask your question..."
|
|
23
|
+
msgstr ""
|
|
24
|
+
|
|
25
|
+
#. Default: "Assistant page is not configured. Please contact the site administrator."
|
|
26
|
+
#: AISearchInput/AISearchInputView
|
|
27
|
+
#: AISearchInput/messages
|
|
28
|
+
msgid "Assistant page is not configured. Please contact the site administrator."
|
|
29
|
+
msgstr ""
|
|
30
|
+
|
|
31
|
+
#. Default: "Deep research"
|
|
32
|
+
#: AISearchInput/components/DeepResearchToggle
|
|
33
|
+
#: AISearchInput/messages
|
|
34
|
+
msgid "Deep research"
|
|
35
|
+
msgstr ""
|
|
14
36
|
|
|
37
|
+
#. Default: "Deep research on"
|
|
38
|
+
#: AISearchInput/components/DeepResearchToggle
|
|
39
|
+
#: AISearchInput/messages
|
|
40
|
+
msgid "Deep research on"
|
|
41
|
+
msgstr ""
|
|
42
|
+
|
|
43
|
+
#. Default: "Invalid assistant page URL."
|
|
44
|
+
#: AISearchInput/AISearchInputView
|
|
45
|
+
#: AISearchInput/messages
|
|
46
|
+
msgid "Invalid assistant page URL."
|
|
47
|
+
msgstr ""
|
|
48
|
+
|
|
49
|
+
#. Default: "Submit question"
|
|
50
|
+
#: AISearchInput/components/SearchInput
|
|
51
|
+
#: AISearchInput/messages
|
|
52
|
+
msgid "Submit question"
|
|
53
|
+
msgstr ""
|
|
54
|
+
|
|
55
|
+
#. Default: "This assistant uses AI. Responses may contain inaccuracies."
|
|
56
|
+
#: AISearchInput/messages
|
|
57
|
+
msgid "This assistant uses AI. Responses may contain inaccuracies."
|
|
58
|
+
msgstr ""
|
|
@@ -11,4 +11,48 @@ msgstr ""
|
|
|
11
11
|
"Content-Transfer-Encoding: \n"
|
|
12
12
|
"Plural-Forms: \n"
|
|
13
13
|
|
|
14
|
+
#. Default: "AI Search Input"
|
|
15
|
+
#: AISearchInput/messages
|
|
16
|
+
msgid "AI Search Input"
|
|
17
|
+
msgstr ""
|
|
18
|
+
|
|
19
|
+
#. Default: "Ask your question..."
|
|
20
|
+
#: AISearchInput/components/SearchInput
|
|
21
|
+
#: AISearchInput/messages
|
|
22
|
+
msgid "Ask your question..."
|
|
23
|
+
msgstr ""
|
|
24
|
+
|
|
25
|
+
#. Default: "Assistant page is not configured. Please contact the site administrator."
|
|
26
|
+
#: AISearchInput/AISearchInputView
|
|
27
|
+
#: AISearchInput/messages
|
|
28
|
+
msgid "Assistant page is not configured. Please contact the site administrator."
|
|
29
|
+
msgstr ""
|
|
30
|
+
|
|
31
|
+
#. Default: "Deep research"
|
|
32
|
+
#: AISearchInput/components/DeepResearchToggle
|
|
33
|
+
#: AISearchInput/messages
|
|
34
|
+
msgid "Deep research"
|
|
35
|
+
msgstr ""
|
|
14
36
|
|
|
37
|
+
#. Default: "Deep research on"
|
|
38
|
+
#: AISearchInput/components/DeepResearchToggle
|
|
39
|
+
#: AISearchInput/messages
|
|
40
|
+
msgid "Deep research on"
|
|
41
|
+
msgstr ""
|
|
42
|
+
|
|
43
|
+
#. Default: "Invalid assistant page URL."
|
|
44
|
+
#: AISearchInput/AISearchInputView
|
|
45
|
+
#: AISearchInput/messages
|
|
46
|
+
msgid "Invalid assistant page URL."
|
|
47
|
+
msgstr ""
|
|
48
|
+
|
|
49
|
+
#. Default: "Submit question"
|
|
50
|
+
#: AISearchInput/components/SearchInput
|
|
51
|
+
#: AISearchInput/messages
|
|
52
|
+
msgid "Submit question"
|
|
53
|
+
msgstr ""
|
|
54
|
+
|
|
55
|
+
#. Default: "This assistant uses AI. Responses may contain inaccuracies."
|
|
56
|
+
#: AISearchInput/messages
|
|
57
|
+
msgid "This assistant uses AI. Responses may contain inaccuracies."
|
|
58
|
+
msgstr ""
|
package/locales/volto.pot
CHANGED
|
@@ -1,16 +1,60 @@
|
|
|
1
1
|
msgid ""
|
|
2
2
|
msgstr ""
|
|
3
3
|
"Project-Id-Version: Plone\n"
|
|
4
|
-
"POT-Creation-Date:
|
|
4
|
+
"POT-Creation-Date: 2026-07-07T08:22:35.802Z\n"
|
|
5
5
|
"Last-Translator: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
|
|
6
6
|
"Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
|
|
7
|
-
"MIME-Version: 1.0\n"
|
|
8
7
|
"Content-Type: text/plain; charset=utf-8\n"
|
|
9
8
|
"Content-Transfer-Encoding: 8bit\n"
|
|
10
9
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
|
10
|
+
"MIME-Version: 1.0\n"
|
|
11
11
|
"Language-Code: en\n"
|
|
12
12
|
"Language-Name: English\n"
|
|
13
13
|
"Preferred-Encodings: utf-8\n"
|
|
14
14
|
"Domain: volto\n"
|
|
15
15
|
|
|
16
|
+
#. Default: "AI Search Input"
|
|
17
|
+
#: AISearchInput/messages
|
|
18
|
+
msgid "AI Search Input"
|
|
19
|
+
msgstr ""
|
|
20
|
+
|
|
21
|
+
#. Default: "Ask your question..."
|
|
22
|
+
#: AISearchInput/components/SearchInput
|
|
23
|
+
#: AISearchInput/messages
|
|
24
|
+
msgid "Ask your question..."
|
|
25
|
+
msgstr ""
|
|
26
|
+
|
|
27
|
+
#. Default: "Assistant page is not configured. Please contact the site administrator."
|
|
28
|
+
#: AISearchInput/AISearchInputView
|
|
29
|
+
#: AISearchInput/messages
|
|
30
|
+
msgid "Assistant page is not configured. Please contact the site administrator."
|
|
31
|
+
msgstr ""
|
|
32
|
+
|
|
33
|
+
#. Default: "Deep research"
|
|
34
|
+
#: AISearchInput/components/DeepResearchToggle
|
|
35
|
+
#: AISearchInput/messages
|
|
36
|
+
msgid "Deep research"
|
|
37
|
+
msgstr ""
|
|
38
|
+
|
|
39
|
+
#. Default: "Deep research on"
|
|
40
|
+
#: AISearchInput/components/DeepResearchToggle
|
|
41
|
+
#: AISearchInput/messages
|
|
42
|
+
msgid "Deep research on"
|
|
43
|
+
msgstr ""
|
|
44
|
+
|
|
45
|
+
#. Default: "Invalid assistant page URL."
|
|
46
|
+
#: AISearchInput/AISearchInputView
|
|
47
|
+
#: AISearchInput/messages
|
|
48
|
+
msgid "Invalid assistant page URL."
|
|
49
|
+
msgstr ""
|
|
50
|
+
|
|
51
|
+
#. Default: "Submit question"
|
|
52
|
+
#: AISearchInput/components/SearchInput
|
|
53
|
+
#: AISearchInput/messages
|
|
54
|
+
msgid "Submit question"
|
|
55
|
+
msgstr ""
|
|
16
56
|
|
|
57
|
+
#. Default: "This assistant uses AI. Responses may contain inaccuracies."
|
|
58
|
+
#: AISearchInput/messages
|
|
59
|
+
msgid "This assistant uses AI. Responses may contain inaccuracies."
|
|
60
|
+
msgstr ""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eeacms/volto-eea-chatbot",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "@eeacms/volto-eea-chatbot: Volto add-on",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"author": "European Environment Agency: IDM2 A-Team",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"typescript": "^5.7.3"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
+
"@eeacms/volto-design-tokens": "*",
|
|
43
44
|
"@eeacms/volto-matomo": "*",
|
|
44
45
|
"@microsoft/fetch-event-source": "2.0.1",
|
|
45
46
|
"@plone-collective/volto-sentry": "*",
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useIntl } from 'react-intl';
|
|
3
|
+
import SidebarPortal from '@plone/volto/components/manage/Sidebar/SidebarPortal';
|
|
4
|
+
import BlockDataForm from '@plone/volto/components/manage/Form/BlockDataForm';
|
|
5
|
+
|
|
6
|
+
import AISearchInputView from './AISearchInputView';
|
|
7
|
+
import { AISearchInputSchema } from './schema';
|
|
8
|
+
|
|
9
|
+
const AISearchInputEdit = (props) => {
|
|
10
|
+
const { onChangeBlock, block, data } = props;
|
|
11
|
+
const intl = useIntl();
|
|
12
|
+
|
|
13
|
+
const schema = React.useMemo(
|
|
14
|
+
() => AISearchInputSchema({ intl, data }),
|
|
15
|
+
[data, intl],
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div>
|
|
20
|
+
<AISearchInputView {...props} isEditMode />
|
|
21
|
+
<SidebarPortal selected={props.selected}>
|
|
22
|
+
<BlockDataForm
|
|
23
|
+
schema={schema}
|
|
24
|
+
title={schema.title}
|
|
25
|
+
block={block}
|
|
26
|
+
onChangeBlock={onChangeBlock}
|
|
27
|
+
onChangeField={(id, value) => {
|
|
28
|
+
onChangeBlock(block, { ...data, [id]: value });
|
|
29
|
+
}}
|
|
30
|
+
formData={data}
|
|
31
|
+
/>
|
|
32
|
+
</SidebarPortal>
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default AISearchInputEdit;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { useHistory } from 'react-router-dom';
|
|
3
|
+
import { FormattedMessage } from 'react-intl';
|
|
4
|
+
import { trackEvent } from '@eeacms/volto-matomo/utils';
|
|
5
|
+
|
|
6
|
+
import IntroHeader from './components/IntroHeader';
|
|
7
|
+
import SearchInput from './components/SearchInput';
|
|
8
|
+
import PromptChips from './components/PromptChips';
|
|
9
|
+
import DeepResearchToggle from './components/DeepResearchToggle';
|
|
10
|
+
import DisclaimerText from './components/DisclaimerText';
|
|
11
|
+
|
|
12
|
+
import './styles.less';
|
|
13
|
+
|
|
14
|
+
const AISearchInputView = ({ data }) => {
|
|
15
|
+
const history = useHistory();
|
|
16
|
+
const [query, setQuery] = useState('');
|
|
17
|
+
const [error, setError] = useState(null);
|
|
18
|
+
const [deepResearchEnabled, setDeepResearchEnabled] = useState(
|
|
19
|
+
data.deepResearch === 'always_on' || data.deepResearch === 'user_on',
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const variant = data.stylingVariant || 'dark';
|
|
23
|
+
|
|
24
|
+
const handleSubmit = (message) => {
|
|
25
|
+
setError(null);
|
|
26
|
+
const q = (message || query).trim();
|
|
27
|
+
|
|
28
|
+
if (!q) return;
|
|
29
|
+
|
|
30
|
+
if (!data.assistantEndpoint) {
|
|
31
|
+
setError(
|
|
32
|
+
<FormattedMessage
|
|
33
|
+
id="Assistant page is not configured. Please contact the site administrator."
|
|
34
|
+
defaultMessage="Assistant page is not configured. Please contact the site administrator."
|
|
35
|
+
/>,
|
|
36
|
+
);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Build target URL
|
|
41
|
+
let targetUrl;
|
|
42
|
+
try {
|
|
43
|
+
targetUrl = new URL(data.assistantEndpoint, window.location.origin);
|
|
44
|
+
} catch {
|
|
45
|
+
setError(
|
|
46
|
+
<FormattedMessage
|
|
47
|
+
id="Invalid assistant page URL."
|
|
48
|
+
defaultMessage="Invalid assistant page URL."
|
|
49
|
+
/>,
|
|
50
|
+
);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
targetUrl.searchParams.set('query', q);
|
|
55
|
+
if (data.deepResearch !== 'unavailable') {
|
|
56
|
+
targetUrl.searchParams.set(
|
|
57
|
+
'deepResearch',
|
|
58
|
+
deepResearchEnabled ? 'true' : 'false',
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const targetString = targetUrl.pathname + targetUrl.search;
|
|
63
|
+
|
|
64
|
+
// Matomo tracking
|
|
65
|
+
trackEvent({
|
|
66
|
+
category: 'Chatbot',
|
|
67
|
+
action: 'AI Search Input: Question submitted',
|
|
68
|
+
name: q.substring(0, 100),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Navigate: client-side for same-origin, full for external
|
|
72
|
+
if (targetUrl.origin === window.location.origin) {
|
|
73
|
+
history.push(targetString);
|
|
74
|
+
} else {
|
|
75
|
+
window.location.href = targetUrl.toString();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const handleChipSelect = (message) => {
|
|
80
|
+
handleSubmit(message);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<div className={`ais-search-input ais-${variant}`}>
|
|
85
|
+
<IntroHeader
|
|
86
|
+
showIcon={data.showIcon}
|
|
87
|
+
blockTitle={data.blockTitle}
|
|
88
|
+
introText={data.introText}
|
|
89
|
+
/>
|
|
90
|
+
|
|
91
|
+
<SearchInput
|
|
92
|
+
placeholderText={data.placeholderText || 'Ask your question...'}
|
|
93
|
+
onSubmit={() => handleSubmit()}
|
|
94
|
+
value={query}
|
|
95
|
+
onChange={(value) => {
|
|
96
|
+
setQuery(value);
|
|
97
|
+
setError(null);
|
|
98
|
+
}}
|
|
99
|
+
error={error}
|
|
100
|
+
/>
|
|
101
|
+
|
|
102
|
+
{(data.examplePromptsEnabled && data.examplePrompts) ||
|
|
103
|
+
data.deepResearch !== 'unavailable' ? (
|
|
104
|
+
<div className="ais-controls-row">
|
|
105
|
+
{data.examplePromptsEnabled && data.examplePrompts && (
|
|
106
|
+
<PromptChips
|
|
107
|
+
prompts={data.examplePrompts}
|
|
108
|
+
onSelect={handleChipSelect}
|
|
109
|
+
/>
|
|
110
|
+
)}
|
|
111
|
+
<DeepResearchToggle
|
|
112
|
+
mode={data.deepResearch}
|
|
113
|
+
enabled={deepResearchEnabled}
|
|
114
|
+
onChange={setDeepResearchEnabled}
|
|
115
|
+
/>
|
|
116
|
+
</div>
|
|
117
|
+
) : (
|
|
118
|
+
<DeepResearchToggle
|
|
119
|
+
mode={data.deepResearch}
|
|
120
|
+
enabled={deepResearchEnabled}
|
|
121
|
+
onChange={setDeepResearchEnabled}
|
|
122
|
+
/>
|
|
123
|
+
)}
|
|
124
|
+
|
|
125
|
+
<DisclaimerText disclaimerText={data.disclaimerText} />
|
|
126
|
+
</div>
|
|
127
|
+
);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export default AISearchInputView;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FormattedMessage } from 'react-intl';
|
|
3
|
+
|
|
4
|
+
const DeepResearchToggle = ({ mode, enabled, onChange }) => {
|
|
5
|
+
if (mode === 'unavailable' || !mode) return null;
|
|
6
|
+
|
|
7
|
+
if (mode === 'always_on') {
|
|
8
|
+
return (
|
|
9
|
+
<div className="ais-deep-research">
|
|
10
|
+
<small className="ais-deep-research-label">
|
|
11
|
+
<FormattedMessage
|
|
12
|
+
id="Deep research on"
|
|
13
|
+
defaultMessage="Deep research on"
|
|
14
|
+
/>
|
|
15
|
+
</small>
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div className="ais-deep-research">
|
|
22
|
+
<label className="ais-toggle">
|
|
23
|
+
<input
|
|
24
|
+
type="checkbox"
|
|
25
|
+
checked={enabled}
|
|
26
|
+
onChange={(e) => onChange(e.target.checked)}
|
|
27
|
+
/>
|
|
28
|
+
<span className="ais-toggle-slider" />
|
|
29
|
+
<FormattedMessage id="Deep research" defaultMessage="Deep research" />
|
|
30
|
+
</label>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default DeepResearchToggle;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { serializeNodes } from '@plone/volto-slate/editor/render';
|
|
3
|
+
|
|
4
|
+
const DisclaimerText = ({ disclaimerText }) => {
|
|
5
|
+
if (!disclaimerText) return null;
|
|
6
|
+
|
|
7
|
+
return <div className="ais-disclaimer">{serializeNodes(disclaimerText)}</div>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default DisclaimerText;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import SVGIcon from '@eeacms/volto-eea-chatbot/ChatBlock/components/Icon';
|
|
3
|
+
import SparkleIcon from '@eeacms/volto-eea-chatbot/icons/sparkle.svg';
|
|
4
|
+
import { serializeNodes } from '@plone/volto-slate/editor/render';
|
|
5
|
+
|
|
6
|
+
const IntroHeader = ({ showIcon, blockTitle, introText }) => {
|
|
7
|
+
if (!showIcon && !blockTitle && !introText) return null;
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<div className="ais-intro-header">
|
|
11
|
+
{showIcon && (
|
|
12
|
+
<SVGIcon name={SparkleIcon} size={20} className="ais-icon" />
|
|
13
|
+
)}
|
|
14
|
+
<div className="ais-intro-content">
|
|
15
|
+
{blockTitle && <span className="ais-block-title">{blockTitle}</span>}
|
|
16
|
+
{introText && (
|
|
17
|
+
<div className="ais-intro-slate">{serializeNodes(introText)}</div>
|
|
18
|
+
)}
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default IntroHeader;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const PromptChips = ({ prompts, onSelect }) => {
|
|
4
|
+
if (!prompts || prompts.length === 0) return null;
|
|
5
|
+
|
|
6
|
+
return (
|
|
7
|
+
<div className="ais-prompt-chips">
|
|
8
|
+
{prompts.map((prompt, index) => (
|
|
9
|
+
<button
|
|
10
|
+
key={index}
|
|
11
|
+
type="button"
|
|
12
|
+
className="ais-chip"
|
|
13
|
+
onClick={() => onSelect(prompt.message || prompt.label)}
|
|
14
|
+
>
|
|
15
|
+
{prompt.label}
|
|
16
|
+
</button>
|
|
17
|
+
))}
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default PromptChips;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FormattedMessage } from 'react-intl';
|
|
3
|
+
import SVGIcon from '@eeacms/volto-eea-chatbot/ChatBlock/components/Icon';
|
|
4
|
+
import SendIcon from '@eeacms/volto-eea-chatbot/icons/send.svg';
|
|
5
|
+
|
|
6
|
+
const SearchInput = ({ placeholderText, onSubmit, value, onChange, error }) => {
|
|
7
|
+
const handleKeyDown = (e) => {
|
|
8
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
9
|
+
e.preventDefault();
|
|
10
|
+
onSubmit();
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div className="ais-search-input-field">
|
|
16
|
+
<input
|
|
17
|
+
type="text"
|
|
18
|
+
value={value}
|
|
19
|
+
onChange={(e) => onChange(e.target.value)}
|
|
20
|
+
onKeyDown={handleKeyDown}
|
|
21
|
+
placeholder={placeholderText}
|
|
22
|
+
aria-label={
|
|
23
|
+
<FormattedMessage
|
|
24
|
+
id="Ask your question..."
|
|
25
|
+
defaultMessage="Ask your question..."
|
|
26
|
+
/>
|
|
27
|
+
}
|
|
28
|
+
aria-invalid={!!error}
|
|
29
|
+
aria-describedby={error ? 'ais-input-error' : undefined}
|
|
30
|
+
/>
|
|
31
|
+
<button
|
|
32
|
+
type="button"
|
|
33
|
+
onClick={onSubmit}
|
|
34
|
+
className="ais-submit-btn"
|
|
35
|
+
aria-label={
|
|
36
|
+
<FormattedMessage
|
|
37
|
+
id="Submit question"
|
|
38
|
+
defaultMessage="Submit question"
|
|
39
|
+
/>
|
|
40
|
+
}
|
|
41
|
+
>
|
|
42
|
+
<SVGIcon name={SendIcon} size={24} />
|
|
43
|
+
</button>
|
|
44
|
+
{error && (
|
|
45
|
+
<div id="ais-input-error" className="ais-input-error" role="alert">
|
|
46
|
+
{error}
|
|
47
|
+
</div>
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default SearchInput;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import sparkleSVG from '@eeacms/volto-eea-chatbot/icons/sparkle.svg';
|
|
2
|
+
import AISearchInputView from './AISearchInputView';
|
|
3
|
+
import AISearchInputEdit from './AISearchInputEdit';
|
|
4
|
+
import { AISearchInputSchema } from './schema';
|
|
5
|
+
|
|
6
|
+
export default function installAISearchInputBlock(config) {
|
|
7
|
+
config.blocks.blocksConfig.eeaAISearchInput = {
|
|
8
|
+
id: 'eeaAISearchInput',
|
|
9
|
+
title: 'AI Search Input',
|
|
10
|
+
icon: sparkleSVG,
|
|
11
|
+
group: 'common',
|
|
12
|
+
view: AISearchInputView,
|
|
13
|
+
edit: AISearchInputEdit,
|
|
14
|
+
restricted: ({ user }) => {
|
|
15
|
+
if (user?.roles) {
|
|
16
|
+
return !user.roles.find((role) => role === 'Manager');
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
},
|
|
20
|
+
mostUsed: false,
|
|
21
|
+
blockHasOwnFocusManagement: false,
|
|
22
|
+
sidebarTab: 1,
|
|
23
|
+
schema: AISearchInputSchema,
|
|
24
|
+
security: {
|
|
25
|
+
addPermission: [],
|
|
26
|
+
view: [],
|
|
27
|
+
},
|
|
28
|
+
variations: [],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return config;
|
|
32
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { defineMessages } from 'react-intl';
|
|
2
|
+
|
|
3
|
+
export default defineMessages({
|
|
4
|
+
aiSearchInput: {
|
|
5
|
+
id: 'AI Search Input',
|
|
6
|
+
defaultMessage: 'AI Search Input',
|
|
7
|
+
},
|
|
8
|
+
askYourQuestion: {
|
|
9
|
+
id: 'Ask your question...',
|
|
10
|
+
defaultMessage: 'Ask your question...',
|
|
11
|
+
},
|
|
12
|
+
submit: {
|
|
13
|
+
id: 'Submit question',
|
|
14
|
+
defaultMessage: 'Submit question',
|
|
15
|
+
},
|
|
16
|
+
deepResearch: {
|
|
17
|
+
id: 'Deep research',
|
|
18
|
+
defaultMessage: 'Deep research',
|
|
19
|
+
},
|
|
20
|
+
deepResearchOn: {
|
|
21
|
+
id: 'Deep research on',
|
|
22
|
+
defaultMessage: 'Deep research on',
|
|
23
|
+
},
|
|
24
|
+
defaultDisclaimer: {
|
|
25
|
+
id: 'This assistant uses AI. Responses may contain inaccuracies.',
|
|
26
|
+
defaultMessage:
|
|
27
|
+
'This assistant uses AI. Responses may contain inaccuracies.',
|
|
28
|
+
},
|
|
29
|
+
noEndpointError: {
|
|
30
|
+
id: 'Assistant page is not configured. Please contact the site administrator.',
|
|
31
|
+
defaultMessage:
|
|
32
|
+
'Assistant page is not configured. Please contact the site administrator.',
|
|
33
|
+
},
|
|
34
|
+
invalidEndpointError: {
|
|
35
|
+
id: 'Invalid assistant page URL.',
|
|
36
|
+
defaultMessage: 'Invalid assistant page URL.',
|
|
37
|
+
},
|
|
38
|
+
});
|