diff --git a/craco.config.js b/craco.config.js
new file mode 100644
index 0000000..cfae699
--- /dev/null
+++ b/craco.config.js
@@ -0,0 +1,49 @@
+const path = require("path");
+
+module.exports = {
+ webpack: {
+ configure: (webpackConfig) => {
+ const oneOfRule = webpackConfig.module.rules.find(rule => Array.isArray(rule.oneOf));
+ if (oneOfRule) {
+ oneOfRule.oneOf.forEach(rule => {
+ if (
+ rule.loader &&
+ rule.loader.includes("babel-loader") &&
+ rule.exclude
+ ) {
+ const originalExclude = rule.exclude;
+ rule.exclude = (input) => {
+ if (
+ typeof input === "string" &&
+ input.replace(/\\/g, "/").includes("node_modules/@visual-framework/vf-chatbot")
+ ) {
+ return false;
+ }
+ if (typeof originalExclude === "function") {
+ return originalExclude(input);
+ }
+ if (Array.isArray(originalExclude)) {
+ return originalExclude.some(ex => input.includes(ex));
+ }
+ return false;
+ };
+
+ // Add this: force automatic runtime for our package
+ if (!rule.options) rule.options = {};
+ if (!rule.options.overrides) rule.options.overrides = [];
+ rule.options.overrides.push({
+ test: /@visual-framework[\\\/]vf-chatbot/,
+ presets: [
+ [
+ "@babel/preset-react",
+ { runtime: "automatic" }
+ ]
+ ]
+ });
+ }
+ });
+ }
+ return webpackConfig;
+ }
+ }
+};
\ No newline at end of file
diff --git a/package.json b/package.json
index ba635dc..5c1dae6 100644
--- a/package.json
+++ b/package.json
@@ -4,6 +4,7 @@
"private": true,
"homepage": "/vf-react/",
"dependencies": {
+ "@craco/craco": "^7.1.0",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
@@ -15,13 +16,17 @@
"@visual-framework/vf-box": "^2.4.0",
"@visual-framework/vf-button": "3.0.2",
"@visual-framework/vf-card": "2.7.2",
- "@visual-framework/vf-chatbot-action-prompt": "^1.0.0-beta.1",
- "@visual-framework/vf-chatbot-feedback": "^1.0.0-beta.1",
- "@visual-framework/vf-chatbot-prompt": "^1.0.0-beta.1",
- "@visual-framework/vf-chatbot-selector": "^1.0.0-beta.1",
- "@visual-framework/vf-chatbot-sources": "^1.0.0-beta.1",
- "@visual-framework/vf-chatbot-standalone": "^1.0.0-beta.1",
- "@visual-framework/vf-chatbot-welcome": "^1.0.0-beta.1",
+ "@visual-framework/vf-chatbot": "latest",
+ "@visual-framework/vf-chatbot-action-prompt": "latest",
+ "@visual-framework/vf-chatbot-dialog": "latest",
+ "@visual-framework/vf-chatbot-fab": "latest",
+ "@visual-framework/vf-chatbot-feedback": "latest",
+ "@visual-framework/vf-chatbot-modal": "latest",
+ "@visual-framework/vf-chatbot-prompt": "latest",
+ "@visual-framework/vf-chatbot-selector": "latest",
+ "@visual-framework/vf-chatbot-sources": "latest",
+ "@visual-framework/vf-chatbot-standalone": "latest",
+ "@visual-framework/vf-chatbot-welcome": "latest",
"@visual-framework/vf-content": "1.6.16",
"@visual-framework/vf-core": "2.2.47",
"@visual-framework/vf-extensions-react": "^0.0.8",
@@ -50,10 +55,10 @@
"web-vitals": "^2.1.4"
},
"scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test",
- "eject": "react-scripts eject"
+ "start": "craco start",
+ "build": "craco build",
+ "test": "craco test",
+ "eject": "craco eject"
},
"browserslist": {
"production": [
@@ -66,5 +71,9 @@
"last 1 firefox version",
"last 1 safari version"
]
+ },
+ "devDependencies": {
+ "@babel/plugin-syntax-jsx": "^7.27.1",
+ "@babel/preset-react": "^7.27.1"
}
}
diff --git a/public/assets/vf-chatbot/assets/vf-chatbot--avatar-user.svg b/public/assets/vf-chatbot/assets/vf-chatbot--avatar-user.svg
new file mode 100644
index 0000000..d9e9a53
--- /dev/null
+++ b/public/assets/vf-chatbot/assets/vf-chatbot--avatar-user.svg
@@ -0,0 +1,3 @@
+
diff --git a/public/assets/vf-chatbot/assets/vf-chatbot--icon-16x16-dark-green.svg b/public/assets/vf-chatbot/assets/vf-chatbot--icon-16x16-dark-green.svg
new file mode 100644
index 0000000..1bd078f
--- /dev/null
+++ b/public/assets/vf-chatbot/assets/vf-chatbot--icon-16x16-dark-green.svg
@@ -0,0 +1,4 @@
+
diff --git a/public/assets/vf-chatbot/assets/vf-chatbot--icon-24x24-dark-green.svg b/public/assets/vf-chatbot/assets/vf-chatbot--icon-24x24-dark-green.svg
new file mode 100644
index 0000000..0bb0697
--- /dev/null
+++ b/public/assets/vf-chatbot/assets/vf-chatbot--icon-24x24-dark-green.svg
@@ -0,0 +1,4 @@
+
diff --git a/public/assets/vf-chatbot/assets/vf-chatbot--icon-32x32-dark-green.svg b/public/assets/vf-chatbot/assets/vf-chatbot--icon-32x32-dark-green.svg
new file mode 100644
index 0000000..6388d34
--- /dev/null
+++ b/public/assets/vf-chatbot/assets/vf-chatbot--icon-32x32-dark-green.svg
@@ -0,0 +1,4 @@
+
diff --git a/public/assets/vf-chatbot/assets/vf-chatbot--icon-close.svg b/public/assets/vf-chatbot/assets/vf-chatbot--icon-close.svg
new file mode 100644
index 0000000..3b0417b
--- /dev/null
+++ b/public/assets/vf-chatbot/assets/vf-chatbot--icon-close.svg
@@ -0,0 +1,10 @@
+
diff --git a/public/assets/vf-chatbot/assets/vf-chatbot--icon-minimize.svg b/public/assets/vf-chatbot/assets/vf-chatbot--icon-minimize.svg
new file mode 100644
index 0000000..a0ec4fc
--- /dev/null
+++ b/public/assets/vf-chatbot/assets/vf-chatbot--icon-minimize.svg
@@ -0,0 +1,3 @@
+
diff --git a/public/assets/vf-chatbot/assets/vf-chatbot--icon-send.svg b/public/assets/vf-chatbot/assets/vf-chatbot--icon-send.svg
new file mode 100644
index 0000000..0849ecc
--- /dev/null
+++ b/public/assets/vf-chatbot/assets/vf-chatbot--icon-send.svg
@@ -0,0 +1,4 @@
+
diff --git a/public/assets/vf-chatbot/assets/vf-chatbot-qa.json b/public/assets/vf-chatbot/assets/vf-chatbot-qa.json
new file mode 100644
index 0000000..9a001e3
--- /dev/null
+++ b/public/assets/vf-chatbot/assets/vf-chatbot-qa.json
@@ -0,0 +1,96 @@
+{
+ "predefinedQA": {
+ "What is Metabolights?": {
+ "answer": "
MetaboLights is an open access repository for metabolomics studies, including raw experimental data and associated metadata.
\nTo know more:
\n\n - \n Methods and resources for omics studies: A curated collection of EMBL-EBI on-demand training.\n
\n - \n MetaboLights: Quick tour.\n
\n - \n Chemical biology: A curated set of EMBL-EBI online courses.\n
\n
"
+ },
+ "Learn how to apply bioinformatics tools in your academic work": {
+ "answer": "Our Tools and Services portal provides access to commonly used resources in genomics, proteomics, and more. We also offer tutorials and use cases to guide integration into your academic projects."
+ },
+ "Start a guided learning path in bioinformatics": {
+ "answer": "Great! You can begin with our structured courses and learning paths designed for beginners at the EMBL-EBI Training Portal. Perfect for students and early-stage researchers.",
+ "sources": [
+ {
+ "domain": "ebi.ac.uk",
+ "title": "EMBL-EBI Training",
+ "url": "https://www.ebi.ac.uk/training/",
+ "description": "Delivering world-class training in data-driven life sciences."
+ }
+ ]
+ },
+ "Find resources and tools for structural biology analysis": {
+ "answer": "Discover tools for structural biology, including protein modeling, domain analysis, and sequence alignment. Visit our Tools & Services portal to access popular resources.",
+ "sources": [
+ {
+ "domain": "github.com",
+ "title": "Structural Biology",
+ "url": "https://github.com/pengzhangzhi/Awesome-Computational-Structural-Biology?utm_source=chatgpt.com",
+ "description": "Awesome Computational Structural Biology (GitHub) – curated list of tools, tutorials, and courses"
+ },
+ {
+ "domain": "hwi.buffalo.edu",
+ "title": "Structural Biology Resource Page",
+ "url": "https://hwi.buffalo.edu/structural-biology-resources/?utm_source=chatgpt.com",
+ "description": "Structural Biology Resource Page – links to cryo-EM, crystallography, and X-ray data collection info from Hauptman-Woodward Institute"
+ },
+ {
+ "domain": "www.creative-biostructure.com",
+ "title": "Structural Biology Tools",
+ "url": "https://www.creative-biostructure.com/structural-biology-tools.htm?srsltid=AfmBOooqvJ0ksY6p6Pryq1diKVWPxNK0t68zKnuyMuTB0_k1IABozOXO&utm_source=chatgpt.com",
+ "description": "Creative Biostructure – lists structural resources and software across core techniques like crystallography and cryo-EM"
+ }
+ ]
+ },
+ "How can I submit genomic data to EMBL-EBI?": {
+ "answer": "To submit genomic data, visit the EMBL-EBI submission portal, where you’ll find step-by-step guides and tools for submitting sequencing data, assemblies, annotations, and more.",
+ "sources": [
+ {
+ "domain": "ebi.ac.uk",
+ "title": "EMBL's European Bioinformatics Institute",
+ "url": "https://www.ebi.ac.uk/",
+ "description": "Run BLAST searches against comprehensive sequence databases at EMBL-EBI."
+ },
+ {
+ "domain": "ena-docs.readthedocs.io",
+ "title": "ENA Documentation",
+ "url": "https://ena-docs.readthedocs.io/en/latest/",
+ "description": "ENA Documentation"
+ }
+ ]
+ },
+ "Access documentation and developer tools": {
+ "answer": "Explore the databse, where you can find model predictions, usage documentation, API access, and links to related publications. Developers can also access integration guides through the EMBL-EBI API Hub.",
+ "sources": [
+ {
+ "domain": "ebi.ac.uk",
+ "title": "EMBL-EBI APIs and Tools",
+ "url": "https://www.ebi.ac.uk/services",
+ "description": "Browse services by domain (genomics, proteomics, etc.) and access APIs."
+ },
+ {
+ "domain": "ebi.ac.uk",
+ "title": "EMBL-EBI API Documentation",
+ "url": "https://www.ebi.ac.uk/about/api",
+ "description": "RESTful APIs for tools like BLAST, InterProScan, Clustal Omega, etc."
+ }
+ ]
+ },
+ "Discover upcoming bioinformatics workshops for beginners": {
+ "answer": "Start your learning journey with our Training Events Calendar, featuring upcoming live webinars, virtual workshops, and in-person courses. Many sessions are designed for beginners and cover topics like genomics, data standards, and tool usage."
+ }
+ },
+ "fallbackResponses": [
+ {
+ "answer": "I'm sorry, I'm having trouble connecting to my knowledge base right now. Could you try again in a moment?",
+ "prompts": [
+ {
+ "action_text": "Contact support team",
+ "action_url": "tel:+44 1223 494 444"
+ },
+ {
+ "action_text": "Submit a support request",
+ "action_url": "https://www.ebi.ac.uk/about/contact/support/"
+ }
+ ]
+ }
+ ]
+}
diff --git a/public/assets/vf-chatbot/assets/vf-chatbot-selector-llms.json b/public/assets/vf-chatbot/assets/vf-chatbot-selector-llms.json
new file mode 100644
index 0000000..f803d2b
--- /dev/null
+++ b/public/assets/vf-chatbot/assets/vf-chatbot-selector-llms.json
@@ -0,0 +1,37 @@
+{
+ "routes": [
+ {
+ "id": "gpt4-turbo",
+ "title": "GPT-4 Turbo",
+ "selected": true
+ },
+ {
+ "id": "claude3-opus",
+ "title": "Claude 3 Opus"
+ },
+ {
+ "id": "gemini-ultra",
+ "title": "Gemini Ultra"
+ },
+ {
+ "id": "llama3",
+ "title": "LLaMA 3"
+ },
+ {
+ "id": "mixtral",
+ "title": "Mixtral 8x7B"
+ },
+ {
+ "id": "palm3",
+ "title": "PaLM 3"
+ },
+ {
+ "id": "gpt4-vision",
+ "title": "GPT-4 Vision"
+ },
+ {
+ "id": "claude3-sonnet",
+ "title": "Claude 3 Sonnet"
+ }
+ ]
+}
diff --git a/public/assets/vf-chatbot/assets/vf-chatbot-selector-services.json b/public/assets/vf-chatbot/assets/vf-chatbot-selector-services.json
new file mode 100644
index 0000000..9c00673
--- /dev/null
+++ b/public/assets/vf-chatbot/assets/vf-chatbot-selector-services.json
@@ -0,0 +1,52 @@
+{
+ "routes": [
+ {
+ "id": "ensembl",
+ "title": "Ensembl"
+ },
+ {
+ "id": "uniprot",
+ "title": "UniProt"
+ },
+ {
+ "id": "pfam",
+ "title": "Pfam"
+ },
+ {
+ "id": "interpro",
+ "title": "InterPro"
+ },
+ {
+ "id": "chembl",
+ "title": "ChEMBL"
+ },
+ {
+ "id": "pdbe",
+ "title": "PDBe"
+ },
+ {
+ "id": "expression-atlas",
+ "title": "Expression Atlas"
+ },
+ {
+ "id": "pride",
+ "title": "PRIDE"
+ },
+ {
+ "id": "arrayexpress",
+ "title": "ArrayExpress"
+ },
+ {
+ "id": "intact",
+ "title": "IntAct"
+ },
+ {
+ "id": "reactome",
+ "title": "Reactome"
+ },
+ {
+ "id": "metabolights",
+ "title": "MetaboLights"
+ }
+ ]
+}
diff --git a/src/App.jsx b/src/App.jsx
index ffd2a3c..9fc55e9 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,4 +1,4 @@
-import React, { useEffect } from 'react';
+import { useEffect } from 'react';
import { BrowserRouter as Router, Routes, Route, useLocation } from 'react-router-dom';
import Header from './components/Header';
import Footer from './components/Footer';
@@ -12,6 +12,8 @@ import VFBlockquote from './components/VFBlockquote';
import VFHero from './components/VFHero';
import VFBanner from './components/VFBanner';
import VFTabs from './components/VFTabs';
+// import VFChatbot from './vf-chatbot-components/vf-chatbot/vf-chatbot.react';
+import VFChatbot from '@visual-framework/vf-chatbot/vf-chatbot.react';
// Create a wrapper component to handle route changes
function RouteChangeHandler({ children }) {
@@ -32,13 +34,100 @@ function RouteChangeHandler({ children }) {
}
function App() {
- // Use HashRouter instead of BrowserRouter for GitHub Pages
+ // Example modal config (customize as needed)
+ const chatbotConfig = {
+ type: "modal",
+ title: "AI Assistant",
+ welcome_logo: true,
+ welcome_message: "Welcome! I'm here to help",
+ welcome_logo_alt: "AI Assistant",
+ welcome_suggestions_title: "Try asking me:",
+ input_placeholder: "Ask me ...",
+ welcome_max_suggestions: 4,
+ disclaimer: 'Disclaimer: This chatbot is designed to assist you with general information and basic inquiries. See our disclaimer notes.',
+ footnote: 'Review AI generated content for accuracy. Leave feedback.',
+ icons: {
+ assistant_avatar: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--icon-16x16-dark-green.svg`,
+ user_avatar: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--avatar-user.svg`,
+ send_button: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--icon-send.svg`,
+ main_logo_url: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--icon-32x32-dark-green.svg`,
+ minimize: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--icon-minimize.svg`,
+ close: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--icon-close.svg`
+ },
+ api: {
+ chat_endpoint: false,
+ feedback_endpoint: false,
+ qa_data_url: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot-qa.json`,
+ headers:{
+ "Content-Type": "application/json",
+ "Authorization": "Bearer your-token"
+ },
+ timeout: 10000
+ },
+ features: {
+ enable_welcome: true,
+ enable_feedback: true,
+ enable_sources: true,
+ enable_welcome_suggestions: true,
+ enable_typing_indicator: true,
+ enable_disclaimer: true,
+ enable_predefined_qa: true,
+ enable_fallback_responses: true,
+ enable_qa_data_loading: true,
+ enable_instant_feedback: false
+ },
+ behavior: {
+ auto_scroll: true,
+ typing_delay: 800,
+ show_scrollbar: false
+ },
+ selectorContext: {
+ chatbotRoutes: {
+ multiSelect: false,
+ showSearch: true,
+ showSearchThreshold: 5,
+ routes: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot-selector-llms.json`,
+ placeholder: "Search",
+ title: "Services",
+ selector_logo_url: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--icon-24x24-dark-green.svg`,
+ selector_logo_title: "AI Assistant"
+ }
+ },
+ handlers: {
+ on_message_send: "handleMessageSend",
+ on_response_receive: "handleResponseReceive",
+ on_feedback_submit: "handleFeedbackSubmit",
+ on_suggestion_click: "handleSuggestionClick",
+ on_error: "handleError",
+ on_conversation_start: "handleConversationStart",
+ on_conversation_end: "handleConversationEnd",
+ on_fab_click: "handleFabClick",
+ on_dialog_confirm: "handleDialogConfirm",
+ on_dialog_cancel: "handleDialogCancel",
+ on_minimize: "handleMinimize"
+ },
+ feedback_options: {
+ positive: [
+ { id: "accurate", label: "Accurate" },
+ { id: "easy", label: "Easy to understand" },
+ { id: "formatted", label: "Well formatted" }
+ ],
+ negative: [
+ { id: "inaccurate", label: "Inaccurate" },
+ { id: "nocontext", label: "Did not use context" },
+ { id: "poorformat", label: "Poorly formatted" }
+ ]
+ },
+ "enable_session_persistence": true,
+ "restore_minimized_state": true
+ };
+
return (
- } />
+ >} />
} />
} />
} />
diff --git a/src/components/Chatbot/index.jsx b/src/components/Chatbot/index.jsx
index 5ec5199..f519d1e 100644
--- a/src/components/Chatbot/index.jsx
+++ b/src/components/Chatbot/index.jsx
@@ -1,553 +1,109 @@
-import React, { useEffect, useRef } from "react";
-import { initVFChatbotStandalone } from "@visual-framework/vf-chatbot-standalone/vf-chatbot-standalone.js";
-
-function Chatbot() {
- const chatbotRef = useRef(null);
-
- // Define config outside the useEffect so it's accessible to JSX
- const vfchatbotStandaloneConfig = {
- title: "AI Assistant",
- welcome_logo: `${process.env.PUBLIC_URL}/assets/chatbot/vf-chatbot--icon-64x64-dark-green.svg`,
- welcome_message: "Hello! How can I help you today?",
- welcome_logo_alt: "AI Assistant",
- welcome_suggestions_title: "Try asking me:",
- input_placeholder: "Ask me ...",
- welcome_max_suggestions: 4,
- disclaimer: 'Disclaimer: This chatbot is designed to assist you with general information and basic inquiries. See our disclaimer notes.',
- footnote: 'Review AI generated content for accuracy. Leave feedback.',
- icons: {
- assistant_avatar: `${process.env.PUBLIC_URL}/assets/chatbot/vf-chatbot--icon-16x16-dark-green.svg`,
- user_avatar: `${process.env.PUBLIC_URL}/assets/chatbot/vf-chatbot--avatar-user.svg`,
- send_button: `${process.env.PUBLIC_URL}/assets/chatbot/vf-chatbot--icon-send.svg`,
- main_logo_url: `${process.env.PUBLIC_URL}/assets/chatbot/vf-chatbot--icon-32x32-dark-green.svg`,
- },
- api: {
- chat_endpoint: false,//"/api/chat",
- feedback_endpoint: "/api/feedback",
- qa_data_url: `${process.env.PUBLIC_URL}/assets/chatbot/vf-chatbot-qa.json`,
- headers: {
- "Content-Type": "application/json",
- Authorization: "Bearer your-token",
- },
- timeout: 10000,
- },
- features: {
- // enable_welcome: true,
- enable_feedback: true,
- enable_sources: true,
- // enable_welcome_suggestions: true,
- enable_typing_indicator: true,
- // enable_disclaimer: true,
- enable_predefined_qa: true,
- // enable_fallback_responses: true,
- enable_qa_data_loading: true,
- enable_instant_feedback: false
- },
- behavior: {
- auto_scroll: true,
- typing_delay: 800,
+import VFChatbot from "@visual-framework/vf-chatbot/vf-chatbot.react";
+
+// Example config, matching the Nunjucks context
+const chatbotConfig = {
+ type: "standalone",
+ title: "AI Assistant",
+ welcome_logo: true,
+ welcome_message: "Welcome! I am here to help",
+ welcome_logo_alt: "AI Assistant",
+ welcome_suggestions_title: "Try asking me:",
+ input_placeholder: "Ask me ...",
+ welcome_max_suggestions: 4,
+ disclaimer:
+ 'Disclaimer: This chatbot is designed to assist you with general information and basic inquiries. See our disclaimer notes.',
+ footnote:
+ 'Review AI generated content for accuracy. Leave feedback.',
+ icons: {
+ assistant_avatar: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--icon-16x16-dark-green.svg`,
+ user_avatar: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--avatar-user.svg`,
+ send_button: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--icon-send.svg`,
+ main_logo_url: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--icon-32x32-dark-green.svg`,
+ minimize: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--icon-minimize.svg`,
+ close: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--icon-close.svg`
+ },
+ api: {
+ chat_endpoint: false,
+ feedback_endpoint: false,
+ qa_data_url: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot-qa.json`,
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer your-token"
},
- selectorContext: {
- chatbotRoutes: {
- multiSelect: true,
- maxMultiSelect: 3,
- showSearch: true,
- showSearchThreshold: 5,
- showAllServices: true,
- showAllServicesSelected: true,
- routes: `${process.env.PUBLIC_URL}/assets/chatbot/vf-chatbot-selector-services.json`,
- placeholder: "Select services",
- title: "Services"
- }
- },
- handlers: {
- on_message_send: "handleMessageSend",
- on_response_receive: "handleResponseReceive",
- on_feedback_submit: "handleFeedbackSubmit",
- on_suggestion_click: "handleSuggestionClick",
- on_error: "handleError",
- on_conversation_start: "handleConversationStart",
- on_conversation_end: "handleConversationEnd",
+ timeout: 10000
+ },
+ features: {
+ enable_welcome: true,
+ enable_feedback: true,
+ enable_sources: true,
+ enable_welcome_suggestions: true,
+ enable_typing_indicator: true,
+ enable_disclaimer: true,
+ enable_predefined_qa: true,
+ enable_fallback_responses: true,
+ enable_qa_data_loading: true,
+ enable_instant_feedback: false
+ },
+ behavior: {
+ auto_scroll: true,
+ typing_delay: 800,
+ show_scrollbar: false
+ },
+ selectorContext: {
+ chatbotRoutes: {
+ multiSelect: true,
+ maxMultiSelect: 3,
+ showSearch: true,
+ showSearchThreshold: 5,
+ showAllServices: true,
+ showAllServicesSelected: true,
+ routes: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot-selector-services.json`,
+ placeholder: "Select services",
+ title: "Services",
+ selector_logo_url: `${process.env.PUBLIC_URL}/assets/vf-chatbot/assets/vf-chatbot--icon-24x24-dark-green.svg`,
+ selector_logo_title: "AI Assistant"
}
- };
-
- useEffect(() => {
- if (!chatbotRef.current) return;
-
- // Create ALL templates programmatically to avoid React className issues
- const createAllTemplates = () => {
- // Get the chatbot standalone container
- const chatbotContainer = chatbotRef.current.querySelector(
- "[data-vf-js-chatbot-standalone]"
- );
- if (!chatbotContainer) {
- console.error("Chatbot container not found");
- return;
- }
-
- // Remove existing templates
- const templateIds = [
- "welcome-suggestion-template",
- "feedback-positive-template",
- "feedback-negative-template",
- "user-message-template",
- "assistant-message-template",
- "loading-indicator-template",
- "action-prompts-template",
- "single-action-prompt-template",
- ];
-
- templateIds.forEach((id) => {
- const existing = document.getElementById(id);
- if (existing) existing.remove();
- });
-
- // Create welcome suggestion template
- const welcomeTemplate = document.createElement("template");
- welcomeTemplate.id = "welcome-suggestion-template";
- welcomeTemplate.innerHTML = `
-
- `;
- chatbotContainer.appendChild(welcomeTemplate);
-
- // Create feedback positive template
- const feedbackPosTemplate = document.createElement("template");
- feedbackPosTemplate.id = "feedback-positive-template";
- feedbackPosTemplate.innerHTML = `
-
- `;
- chatbotContainer.appendChild(feedbackPosTemplate);
-
- // Create feedback negative template
- const feedbackNegTemplate = document.createElement("template");
- feedbackNegTemplate.id = "feedback-negative-template";
- feedbackNegTemplate.innerHTML = `
-
- `;
- chatbotContainer.appendChild(feedbackNegTemplate);
-
- // Create user message template
- const userTemplate = document.createElement("template");
- userTemplate.id = "user-message-template";
- userTemplate.innerHTML = `
-
-
-
You
-

-
-
-
- `;
- chatbotContainer.appendChild(userTemplate);
-
- // Create assistant message template
- const assistantTemplate = document.createElement("template");
- assistantTemplate.id = "assistant-message-template";
- assistantTemplate.innerHTML = `
-
-
-

-
AI Assistant
-
-
-
-
- `;
- chatbotContainer.appendChild(assistantTemplate);
-
- // Create loading indicator template
- const loadingTemplate = document.createElement("template");
- loadingTemplate.id = "loading-indicator-template";
- loadingTemplate.innerHTML = `
-
-
-

-
AI Assistant
-
-
-
- `;
- chatbotContainer.appendChild(loadingTemplate);
-
- // Create action prompts template
- const actionPromptsTemplate = document.createElement("template");
- actionPromptsTemplate.id = "action-prompts-template";
- actionPromptsTemplate.innerHTML = `
-
- `;
- chatbotContainer.appendChild(actionPromptsTemplate);
-
- // Create single action prompt template
- const singleActionTemplate = document.createElement("template");
- singleActionTemplate.id = "single-action-prompt-template";
- singleActionTemplate.innerHTML = `
-
- `;
- chatbotContainer.appendChild(singleActionTemplate);
-
- console.log("All templates created and added to chatbot container");
- };
-
- // Create all templates first
- createAllTemplates();
-
- // Define ALL handler functions
- let suggestionClickCount = 0;
- let messageCount = 0;
-
- window.handleMessageSend = function(eventData) {
- messageCount++;
- console.log(`Message sent (call #${messageCount}):`, eventData.message);
- };
-
- window.handleResponseReceive = function(eventData) {
- console.log('Response received:', eventData.response);
- };
-
- window.handleFeedbackSubmit = function(eventData) {
- console.log('Feedback submitted:', eventData);
- };
-
- window.handleSuggestionClick = function(eventData) {
- suggestionClickCount++;
- console.log(`Suggestion clicked (call #${suggestionClickCount}):`, eventData);
- console.log('Event data:', JSON.stringify(eventData, null, 2));
- };
-
- window.handleError = function(eventData) {
- console.log('Error occurred:', eventData);
- };
-
- window.handleConversationStart = function(eventData) {
- console.log('Conversation started:', eventData);
- };
-
- window.handleConversationEnd = function(eventData) {
- console.log('Conversation ended:', eventData);
- };
-
- // Initialize chatbot with proper cleanup check
- setTimeout(() => {
- // More thorough initialization check
- if (window.vfChatbotInitialized) {
- console.log('Global chatbot already initialized, skipping...');
- return;
- }
-
- const existingInstance = chatbotRef.current?.querySelector('[data-vf-chatbot-initialized]');
- if (existingInstance) {
- console.log('Component chatbot already initialized, skipping...');
- return;
- }
-
- if (typeof initVFChatbotStandalone === "function") {
- console.log('Starting chatbot initialization...');
- const chatbotInstances = initVFChatbotStandalone(vfchatbotStandaloneConfig);
-
- // Mark as initialized globally and on component
- window.vfChatbotInitialized = true;
- if (chatbotRef.current) {
- chatbotRef.current.setAttribute('data-vf-chatbot-initialized', 'true');
- }
-
- console.log("Chatbot initialized once:", chatbotInstances);
- }
- }, 200);
-
- // Complete cleanup function - remove ALL handlers
- return () => {
- console.log('Cleaning up chatbot handlers...');
-
- // Reset counters
- suggestionClickCount = 0;
- messageCount = 0;
-
- // Remove all handler functions
- delete window.handleMessageSend;
- delete window.handleResponseReceive;
- delete window.handleFeedbackSubmit;
- delete window.handleSuggestionClick;
- delete window.handleError;
- delete window.handleConversationStart;
- delete window.handleConversationEnd;
-
- // Remove global initialization flag
- delete window.vfChatbotInitialized;
-
- // Remove initialization marker
- if (chatbotRef.current) {
- chatbotRef.current.removeAttribute('data-vf-chatbot-initialized');
- }
-
- console.log('Cleanup completed');
- };
- }, []); // Empty dependency array - runs only once!
-
- // Update the return JSX to use config values:
+ },
+ handlers: {
+ on_message_send: "handleMessageSend",
+ on_response_receive: "handleResponseReceive",
+ on_feedback_submit: "handleFeedbackSubmit",
+ on_suggestion_click: "handleSuggestionClick",
+ on_error: "handleError",
+ on_conversation_start: "handleConversationStart",
+ on_conversation_end: "handleConversationEnd"
+ },
+ feedback_options: {
+ positive: [
+ { id: "accurate", label: "Accurate" },
+ { id: "easy", label: "Easy to understand" },
+ { id: "formatted", label: "Well formatted" }
+ ],
+ negative: [
+ { id: "inaccurate", label: "Inaccurate" },
+ { id: "nocontext", label: "Did not use context" },
+ { id: "poorformat", label: "Poorly formatted" }
+ ]
+ }
+};
+function Chatbot() {
return (
<>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
{vfchatbotStandaloneConfig.title}
-
- {vfchatbotStandaloneConfig.welcome_message}
-
-
-
-
- {vfchatbotStandaloneConfig.welcome_suggestions_title}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
>
);
}
-export default Chatbot;
+export default Chatbot;
\ No newline at end of file
diff --git a/src/styles/global.scss b/src/styles/global.scss
index e69de29..b25f308 100644
--- a/src/styles/global.scss
+++ b/src/styles/global.scss
@@ -0,0 +1,11 @@
+$vf-font-plex-mono-prefix: "~@visual-framework/vf-font-plex-mono/assets";
+$vf-font-plex-sans-prefix: "~@visual-framework/vf-font-plex-sans/assets";
+
+@import "~@visual-framework/vf-sass-starter/index";
+
+// Component styles
+
+@import "~@visual-framework/vf-link/vf-link.scss";
+@import "~@visual-framework/vf-chatbot/vf-chatbot.scss";
+@import "~@visual-framework/vf-chatbot-modal/index.scss";
+@import "~@visual-framework/vf-chatbot-standalone/index.scss";
\ No newline at end of file