tjtanjin / react-chatbotify

A modern React library for creating a flexible and extensible chatbot.
https://react-chatbotify.com
MIT License
148 stars 68 forks source link

if my outputMessage contain https then i have to show options else no options is this possible? #89

Closed ajaysingh7623 closed 1 month ago

ajaysingh7623 commented 1 month ago

image image image

tjtanjin commented 1 month 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.

ajaysingh7623 commented 1 month ago

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?

tjtanjin commented 1 month ago

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.

ajaysingh7623 commented 1 month ago

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

) }, chatButton: { icon: ${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

image

tjtanjin commented 1 month ago

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.

ajaysingh7623 commented 1 month ago

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

) }, chatButton: { icon: ${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 ?

ajaysingh7623 commented 1 month ago
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?
tjtanjin commented 1 month ago

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.

tjtanjin commented 1 month ago

Hey @ajaysingh7623, I assume the help on discord was sufficient - if not you can continue the discussion there as well 😊