Closed ajaysingh7623 closed 3 months ago
Hey @ajaysingh7623, could you help elaborate on the issue you're facing? From the screenshot, you're not passing a function to options
. If there's some conditional logic you wish to use, then use a function instead of an array. It's similar to how message
and path
can take in a function as well.
from outputMessage string i will check whether string contains https then i will store in state and pass that state to options yes and it will help me to redirect to new page. but if there is no htps contain then there should be no options. it is possible to disable options props from function run?
You can store your output as a variable, then use a function for options
. Then, return an empty array if you don't want it to show up.
import axios from "axios"; import { ASSETS_URL } from "config/env"; import React, { useState } from "react"; import ChatBot from "react-chatbotify";
function ChatBotify() {
const [sessionHistory, setSessionHistory] = useState({
quote: "",
quoteID: ""
});
const [urlState, setUrlState] = useState("");
const [optionsEnabled, setOptionsEnabled] = useState(false);
console.log(urlState, optionsEnabled, "data");
async function run(params) {
const authToken = localStorage.getItem("authToken");
const payload = {
userinput: params?.userInput,
history: {
quote: sessionHistory?.quote || "",
quoteID: sessionHistory?.quoteID || ""
}
};
const url = "/api/start";
const config = {
headers: {
"Content-Type": "application/json",
Authorization: Bearer ${authToken}
}
};
try {
const response = await axios.post(url, payload, config);
if (response.data) {
const quote = response?.data?.session_history.quote;
const quoteID = response?.data?.session_history.quoteID;
setSessionHistory((prev) => ({
...prev,
quote: quote,
quoteID: quoteID
}));
const outputMessage =
response?.data?.bot_response +
" " +
response?.data?.next_step_recommendation;
const urlMatch = outputMessage.match(/(https?:\/\/[^\s]+)/);
if (urlMatch) {
setUrlState(urlMatch[0]);
setOptionsEnabled(true);
} else {
setUrlState("");
setOptionsEnabled(false);
}
params.streamMessage(outputMessage);
} else {
console.error("Unexpected response structure:", response);
return "Unexpected response from server.";
}
} catch (error) {
console.error("Error during Axios request:", error);
return "An error occurred while processing your request.";
}
}
const flow = {
start: {
message: "Hello, I am CPQ ChatBot, How Can I Help You!",
path: "model_loop"
},
model_loop: {
message: (params) => {
run(params);
},
options: optionsEnabled
? [
yes
,
"No"
]
: [],
path: "model_loop"
}
};
const themes = [ { id: "solid_purple_haze", version: "0.1.0" }, { id: "minimal_midnight", version: "0.1.0" } ];
return ( <ChatBot themes={themes} settings={{ audio: { disabled: false, defaultToggledOn: true, tapToPlay: true }, voice: { disabled: false }, chatHistory: { storageKey: "example_voice" }, userBubble: { dangerouslySetInnerHtml: true }, botBubble: { dangerouslySetInnerHtml: true }, header: { title: ( <div style={{ cursor: "pointer", margin: 0, fontSize: 20, fontWeight: "bold" }}
IQ BOT
${ASSETS_URL}/images/Hplogo.png
}
}}
flow={flow}
/>
);
}
export default ChatBotify;
i am using this logic but options is not enable when it is getting url link or there is other approach so,i can make my link enable so it should be clickable and move to new page. here i used dangerouslySetInnerHtml attriute also userBubble: { dangerouslySetInnerHtml: true }, botBubble: { dangerouslySetInnerHtml: true }, please help on this @tjtanjin
The options
attribute actually takes in an array of string, so a custom component wouldn't work. For your case you can consider using the component
attribute (or render
if you're on v1) to add your own custom component.
Alternatively, just use strings inside options
then handle the opening of links via params.userInput
in the next block.
import axios from "axios"; import { ASSETS_URL } from "config/env"; import React, { useState } from "react"; import ChatBot from "react-chatbotify";
function ChatBotify() {
const [sessionHistory, setSessionHistory] = useState({
quote: "",
quoteID: ""
});
const [urlState, setUrlState] = useState("");
const [optionsEnabled, setOptionsEnabled] = useState(false);
console.log(urlState, optionsEnabled, "data");
async function run(params) {
const authToken = localStorage.getItem("authToken");
const payload = {
userinput: params?.userInput,
history: {
quote: sessionHistory?.quote || "",
quoteID: sessionHistory?.quoteID || ""
}
};
const url = "api/start";
const config = {
headers: {
"Content-Type": "application/json",
Authorization: Bearer ${authToken}
}
};
try {
const response = await axios.post(url, payload, config);
if (response.data) {
const quote = response?.data?.session_history.quote;
const quoteID = response?.data?.session_history.quoteID;
setSessionHistory((prev) => ({
...prev,
quote: quote,
quoteID: quoteID
}));
const outputMessage =
response?.data?.bot_response +
" " +
response?.data?.next_step_recommendation;
const urlMatch = outputMessage.match(/https:\/\/[^\s)]+/);
if (urlMatch) {
setUrlState(urlMatch[0]);
setOptionsEnabled(true);
} else {
setUrlState("");
setOptionsEnabled(false);
}
params.streamMessage(outputMessage);
} else {
console.error("Unexpected response structure:", response);
return "Unexpected response from server.";
}
} catch (error) {
console.error("Error during Axios request:", error);
return "An error occurred while processing your request.";
}
}
const flow = {
start: {
message: "Hello, I am CPQ ChatBot, How Can I Help You!",
path: "model_loop"
},
model_loop: {
message: (params) => {
run(params);
},
options:
// optionsEnabled
// ?
[
<a href={${urlState}
} target="_blank">
yes
,
"No"
],
// : [],
path: "model_loop"
}
};
const themes = [ { id: "solid_purple_haze", version: "0.1.0" }, { id: "minimal_midnight", version: "0.1.0" } ];
return ( <ChatBot themes={themes} settings={{ audio: { disabled: false, defaultToggledOn: true, tapToPlay: true }, voice: { disabled: false }, chatHistory: { storageKey: "example_voice" }, userBubble: { dangerouslySetInnerHtml: true }, botBubble: { dangerouslySetInnerHtml: true }, header: { title: ( <div style={{ cursor: "pointer", margin: 0, fontSize: 20, fontWeight: "bold" }}
IQ BOT
${ASSETS_URL}/images/Hplogo.png
}
}}
flow={flow}
/>
);
}
export default ChatBotify;
i went render when i get response from api it contain https link then i have show options else options should not be visible. is there any true or false condition can i give to show options ?
model_loop: {
message: (params) => {
run(params);
},
path: optionsEnabled ? "next_loop" : "model_loop",
},
next_loop: {
// message: "You've selected an option. What would you like to do next?",
component: (
<div>
{optionsEnabled && (
<button
style={{ borderRadius: "12px" }}
onClick={() => {
window.open(urlState, "_blank");
}}
>
Yes
</button>
)}
</div>),
path: "model_loop"
}
i have few questions @tjtanjin
1. each block will execute only once?
2.it will support path: optionsEnabled ? "next_loop" : "model_loop", this ternary condition,
because i get response from api it contains https: then below that message button should be visible for yes and no so i can move to particular url
is this possible?
Hey @ajaysingh7623, I'm not sure I understand what you're trying to achieve but here's a quick summary:
If you want to use options
:
options: () => {
If (some condition to show options) {
return ["Yes", "No"];
} else {
return [];
}
},
If you want to use render
(component
in v2):
render: () => {
If (some condition to show component) {
return <MyComponent>;
}
},
If you want to open up a link when certain options are clicked, this example does it: https://react-chatbotify.com/docs/examples/faq_bot
To answer your further questions:
1) A block can execute multiple times if it is being repeatedly path-ed to.
2) Yes you can have conditionals in path
.
Hey @ajaysingh7623, I assume the help on discord was sufficient - if not you can continue the discussion there as well 😊