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.
\n
To know more:
\n
    \n
  1. \n Methods and resources for omics studies: A curated collection of EMBL-EBI on-demand training.\n
  2. \n
  3. \n MetaboLights: Quick tour.\n
  4. \n
  5. \n Chemical biology: A curated set of EMBL-EBI online courses.\n
  6. \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 = ` -
-
-
-
Tell us more (optional)
- -
-
- - - - -
-
Comments
- - -
-
- `; - chatbotContainer.appendChild(feedbackPosTemplate); - - // Create feedback negative template - const feedbackNegTemplate = document.createElement("template"); - feedbackNegTemplate.id = "feedback-negative-template"; - feedbackNegTemplate.innerHTML = ` -
-
-
-
Tell us more (optional)
- -
-
- - - - -
-
Comments
- - -
-
- `; - chatbotContainer.appendChild(feedbackNegTemplate); - - // Create user message template - const userTemplate = document.createElement("template"); - userTemplate.id = "user-message-template"; - userTemplate.innerHTML = ` -
-
- You - You -
-
-
Hello!
-
-
- `; - chatbotContainer.appendChild(userTemplate); - - // Create assistant message template - const assistantTemplate = document.createElement("template"); - assistantTemplate.id = "assistant-message-template"; - assistantTemplate.innerHTML = ` -
-
- AI Assistant - AI Assistant -
-
-
How can I help you?
-
-
-
- `; - chatbotContainer.appendChild(assistantTemplate); - - // Create loading indicator template - const loadingTemplate = document.createElement("template"); - loadingTemplate.id = "loading-indicator-template"; - loadingTemplate.innerHTML = ` -
-
- AI Assistant - 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 ( <> -
-
-
-
- - -
-
- - -
- -
- Select up to 3 services - - Clear all - -
-
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    - {vfchatbotStandaloneConfig.welcome_logo_alt} -
    -

    {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