From bb5cc381e097c9789d0f4e5f41a666893d598fce Mon Sep 17 00:00:00 2001 From: imOscarCrespo Date: Thu, 22 Aug 2019 13:01:12 +0200 Subject: [PATCH 01/44] add: commits from another branch that was done --- .../botonic-react/src/components/button.jsx | 1 + .../src/components/persistentMenu.jsx | 11 ++--- .../botonic-react/src/webchat/webchat.jsx | 42 ++++++++++++------- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/packages/botonic-react/src/components/button.jsx b/packages/botonic-react/src/components/button.jsx index 00cd290be2..abd1868775 100644 --- a/packages/botonic-react/src/components/button.jsx +++ b/packages/botonic-react/src/components/button.jsx @@ -37,6 +37,7 @@ export const Button = props => { else if (props.path) sendPayload(`__PATH_PAYLOAD__${props.path}`) else if (props.payload) sendPayload(props.payload) else if (props.url) window.open(props.url) + else if (props.onClick) props.onClick() } const renderBrowser = () => { diff --git a/packages/botonic-react/src/components/persistentMenu.jsx b/packages/botonic-react/src/components/persistentMenu.jsx index ba276c7966..54f6e024b3 100644 --- a/packages/botonic-react/src/components/persistentMenu.jsx +++ b/packages/botonic-react/src/components/persistentMenu.jsx @@ -1,17 +1,12 @@ import React from 'react' -import { isBrowser } from '@botonic/core' -import { Message } from './message' export const PersistentMenu = props => { return (
{props.children} diff --git a/packages/botonic-react/src/webchat/webchat.jsx b/packages/botonic-react/src/webchat/webchat.jsx index babb50ad6a..e189a27854 100644 --- a/packages/botonic-react/src/webchat/webchat.jsx +++ b/packages/botonic-react/src/webchat/webchat.jsx @@ -26,6 +26,7 @@ import { isDev, msgToBotonic } from '../utils' import Logo from './botonic_react_logo100x100.png' import EmojiPicker from 'emoji-picker-react' import LogoMenu from './menuButton.svg' +import { Button } from '../components/button' const getScriptBaseURL = () => { let scriptBaseURL = document @@ -69,6 +70,8 @@ export const Webchat = forwardRef((props, ref) => { const [botonicState, saveState, deleteState] = useLocalStorage('botonicState') const [menuIsOpened, setMenuIsOpened] = useState(false) const [emojiIsOpened, setemojiIsOpened] = useState(false) + const [isRegex, setIsRegex] = useState(false) + console.log('renderitzo') // Load initial state from localStorage useEffect(() => { let { user, messages, session, lastRoutePath, devSettings } = @@ -154,6 +157,10 @@ export const Webchat = forwardRef((props, ref) => { menuIsOpened ? setMenuIsOpened(false) : setMenuIsOpened(true) } + const closeMenu = () => { + setMenuIsOpened(false) + } + const sendInput = async input => { let isRegex = false let inputMessage = null @@ -216,17 +223,20 @@ export const Webchat = forwardRef((props, ref) => { useImperativeHandle(ref, () => ({ addBotResponse: ({ response, session, lastRoutePath }) => { - updateTyping(false) - if (Array.isArray(response)) response.map(r => addMessageComponent(r)) - else if (response) addMessageComponent(response) - if (session) { - updateSession(session) - let action = session._botonic_action || '' - let handoff = action.startsWith('create_case') - if (handoff && isDev()) addMessageComponent() - updateHandoff(handoff) + console.log(isRegex) + if (!isRegex) { + updateTyping(false) + if (Array.isArray(response)) response.map(r => addMessageComponent(r)) + else if (response) addMessageComponent(response) + if (session) { + updateSession(session) + let action = session._botonic_action || '' + let handoff = action.startsWith('create_case') + if (handoff && isDev()) addMessageComponent() + updateHandoff(handoff) + } + if (lastRoutePath) updateLastRoutePath(lastRoutePath) } - if (lastRoutePath) updateLastRoutePath(lastRoutePath) }, setTyping: typing => updateTyping(typing), addUserMessage: message => sendInput(message), @@ -416,11 +426,12 @@ export const Webchat = forwardRef((props, ref) => { {Object.values(props.persistentMenu).map((e, i) => { return ( -

sendPayload(e.payload)}> + ) })} + )} {!webchatState.handoff && @@ -436,7 +447,7 @@ export const Webchat = forwardRef((props, ref) => {

{ onKeyDown={e => onKeyDown(e)} style={{ display: 'flex', - padding: '8px 10px', + paddingLeft: '10px', fontSize: 14, border: 'none', resize: 'none', overflow: 'auto', - outline: 'none' + outline: 'none', + marginTop: '13px' }} />
From cb3924531f0be763378def4fe743c8705c1366cf Mon Sep 17 00:00:00 2001 From: imOscarCrespo Date: Thu, 22 Aug 2019 13:02:58 +0200 Subject: [PATCH 02/44] fix: remove consoles --- packages/botonic-react/src/webchat/webchat.jsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/botonic-react/src/webchat/webchat.jsx b/packages/botonic-react/src/webchat/webchat.jsx index e189a27854..2ea43ada69 100644 --- a/packages/botonic-react/src/webchat/webchat.jsx +++ b/packages/botonic-react/src/webchat/webchat.jsx @@ -71,7 +71,6 @@ export const Webchat = forwardRef((props, ref) => { const [menuIsOpened, setMenuIsOpened] = useState(false) const [emojiIsOpened, setemojiIsOpened] = useState(false) const [isRegex, setIsRegex] = useState(false) - console.log('renderitzo') // Load initial state from localStorage useEffect(() => { let { user, messages, session, lastRoutePath, devSettings } = @@ -223,7 +222,6 @@ export const Webchat = forwardRef((props, ref) => { useImperativeHandle(ref, () => ({ addBotResponse: ({ response, session, lastRoutePath }) => { - console.log(isRegex) if (!isRegex) { updateTyping(false) if (Array.isArray(response)) response.map(r => addMessageComponent(r)) From b4a9821d1f131db5e01c356f42bc198412a58f42 Mon Sep 17 00:00:00 2001 From: guinii Date: Thu, 22 Aug 2019 19:20:29 +0200 Subject: [PATCH 03/44] fix(docu): two typos errors and two broken links --- .../2.creating-your-first-bot.mdx | 69 +++++++++---------- docs/3.main-concepts/3.rcml.mdx | 34 ++++----- 2 files changed, 50 insertions(+), 53 deletions(-) diff --git a/docs/2.getting-started/2.creating-your-first-bot.mdx b/docs/2.getting-started/2.creating-your-first-bot.mdx index 75ef84cd96..a0916e4dcb 100644 --- a/docs/2.getting-started/2.creating-your-first-bot.mdx +++ b/docs/2.getting-started/2.creating-your-first-bot.mdx @@ -6,7 +6,6 @@ menu: 2. Getting Started import { NextButton } from '../components/nextButton.tsx' - # **Creating Your First Bot** Now that you have [Botonic and its dependencies installed](/getting-started/installation), you can build your first bot! @@ -29,19 +28,19 @@ To start a new bot, open your terminal/command prompt and run: botonic new testBot blank ``` -* `new` will tell the CLI to create a new bot. -* `testBot` will be the directory name for your project. -* `blank` will be the starter template for your project. +- `new` will tell the CLI to create a new bot. +- `testBot` will be the directory name for your project. +- `blank` will be the starter template for your project. Along with creating your project, this will also install node modules for the application, and make the first build. Along with the blank template, Botonic also provides the following official templates: -* `tutorial`: a bot that explains you some basic concepts in Botonic. This template has lots of comments in its code so you can learn by reading through the source files. -* `childs`: a simple example on how `childRoutes` works. -* `dynamic_carousel`: a bot that gets data from an external API and renders a Carousel (see: [RCML](/main-concepts/rich-conversational-markup-language)). -* `handoff`: a simple bot that transfer the conversation into Hubtype Desk. (see: [human handOff](/tutorials-and-examples/human-handoff)) -* `intent`: a bot that use external AI like DialogFlow. +- `tutorial`: a bot that explains you some basic concepts in Botonic. This template has lots of comments in its code so you can learn by reading through the source files. +- `childs`: a simple example on how `childRoutes` works. +- `dynamic_carousel`: a bot that gets data from an external API and renders a Carousel (see: [RCML](/main-concepts/rich-conversational-markup-language)). +- `handoff`: a simple bot that transfer the conversation into Hubtype Desk. (see: [human handOff](/tutorials-and-examples/human-handoff)) +- `intent`: a bot that use external AI like DialogFlow. If you don’t specify a template at the start, you will be prompted to pick one. @@ -53,19 +52,20 @@ Now, you can `cd` into the folder that was created. To get a quick preview of yo cd testBot botonic serve ``` -*If you are running windows use `npm run start` instead of `botonic serve`* + +_If you are running windows use `npm run start` instead of `botonic serve`_ This will give you a local browser url where you can have a chat session with your bot. Just type any text and press enter to send a message to the bot. If you started with the "blank" template the bot will always respond with "I don't understand you". ## Project Structure -* `routes.js`: Here you'll define routes, which maps user inputs and payloads to actions. You can use imported subroutes from other files. -* `integrations.js`: Define your integrations keys with 3rd party services, like NLP platforms. -* `locales`: Locales are objects from which your bot takes your multilanguage definitions. This is useful if you want that your bot addresses to different audiences. The `locales/index.js` file is where all the languages are imported. -* `webviews`: Webviews are small web pages that pop up in the middle of the conversation flow. This lets you offer experiences and features that might be difficult to offer with message bubbles, such as picking products to buy, seats to book, or dates to reserve. -* `actions`: Actions are the units of logic that your bot can perform and where the responses of your bot are defined. You are free to organize them into subdirectories. -* `assets`: Assets is where you can store all the media required for your bot. -* `...`: The rest of the files are needed for the [babel](https://babeljs.io/) and [Botonic](https://github.com/hubtype/botonic) project configuration. We suggest you to not modify its contents, and if not, it's at your own risk! +- `routes.js`: Here you'll define routes, which maps user inputs and payloads to actions. You can use imported subroutes from other files. +- `integrations.js`: Define your integrations keys with 3rd party services, like NLP platforms. +- `locales`: Locales are objects from which your bot takes your multilanguage definitions. This is useful if you want that your bot addresses to different audiences. The `locales/index.js` file is where all the languages are imported. +- `webviews`: Webviews are small web pages that pop up in the middle of the conversation flow. This lets you offer experiences and features that might be difficult to offer with message bubbles, such as picking products to buy, seats to book, or dates to reserve. +- `actions`: Actions are the units of logic that your bot can perform and where the responses of your bot are defined. You are free to organize them into subdirectories. +- `assets`: Assets is where you can store all the media required for your bot. +- `...`: The rest of the files are needed for the [babel](https://babeljs.io/) and [Botonic](https://github.com/hubtype/botonic) project configuration. We suggest you to not modify its contents, and if not, it's at your own risk! ## Adding basic functionality to your bot @@ -78,14 +78,12 @@ The first step is to create a route that captures any text. Edit your `src/route ```javascript import Echo from './actions/echo' -export const routes = [ - {path: 'echo', text: /^.+$/, action: Echo} -] +export const routes = [{ path: 'echo', text: /^.+$/, action: Echo }] ``` -* `path: 'echo'` means the path that the bot flow has taken. -* `text: /^.+$/` means that this route will capture any text that matches this regular expression. -* `action: "echo"` means that when a user input is matched by this rule, the action named "echo" (that we're going to create in the next step) will be triggered. +- `path: 'echo'` means the path that the bot flow has taken. +- `text: /^.+$/` means that this route will capture any text that matches this regular expression. +- `action: "echo"` means that when a user input is matched by this rule, the action named "echo" (that we're going to create in the next step) will be triggered. ### Create an action @@ -106,16 +104,17 @@ export default class extends React.Component { This is the code that will be executed when the user types anything. As you can see, this is just a React component. -* `render`: this is where you construct the answer of your bot. In this example we return just one message 'Text' whose content is the user input. This data is stored in the variable `context.input.data`. +- `render`: this is where you construct the answer of your bot. In this example we return just one message 'Text' whose content is the user input. This data is stored in the variable `context.input.data`. > ### NOTE: -> Usually the `render` method spits out HTML code in a typical React project. However, this is sent to messaging platforms like Whatsapp or Facebook Messenger so sending HTML won't work. We've created this HTML-like language called [Rich Conversational Markup Language (RCML)](/api/rich-conversational-markup-language) to help you construct the bot response in a dynamic way. +> +> Usually the `render` method spits out HTML code in a typical React project. However, this is sent to messaging platforms like Whatsapp or Facebook Messenger so sending HTML won't work. We've created this HTML-like language called [Rich Conversational Markup Language (RCML)](/main-concepts/rich-conversational-markup-language) to help you construct the bot response in a dynamic way. Now try to execute `botonic serve` again and type "hello world" 😊 ## Adding Natural Language Understanding -You can go a long way capturing user inputs using regular expressions, but it obviously has its limitations. As you find yourself adding more and more functionality to your bot you get to a point where you need Natural [Language Understanding (NLU)](/api/nlu) capabilities. +You can go a long way capturing user inputs using regular expressions, but it obviously has its limitations. As you find yourself adding more and more functionality to your bot you get to a point where you need Natural [Language Understanding (NLU)](/main-concepts/nlu) capabilities. NLU lets you capture user inputs by "intent" instead of parsing its raw text. An intent represents all the different ways users can express a unit of meaning that is valid for your bot. For example, you can group the sentences "What's the weather in California?" and "Do you know if it's sunny today in California?" to the intent `get_weather` and the parameter `city=California`. You can then map that intent to an action using a route. @@ -153,18 +152,18 @@ import Smalltalk from './actions/smalltalk' import Echo from './actions/echo' export const routes = [ - {path:'age', intent: "smalltalk.agent.age", action: Age}, - {path:'smalltalk', intent: /^smalltalk/, action: Smalltalk}, - {path: 'echo', text: /^.+$/, action: Echo} + { path: 'age', intent: 'smalltalk.agent.age', action: Age }, + { path: 'smalltalk', intent: /^smalltalk/, action: Smalltalk }, + { path: 'echo', text: /^.+$/, action: Echo } ] ``` -* `{path:'age', intent: "smalltalk.agent.age", action: Age}` will match exactly the intent "smalltalk.agent.age". -* `{path:'smalltalk', intent: /^smalltalk/, action: Smalltalk}` will match any other "smalltalk" intent. +- `{path:'age', intent: "smalltalk.agent.age", action: Age}` will match exactly the intent "smalltalk.agent.age". +- `{path:'smalltalk', intent: /^smalltalk/, action: Smalltalk}` will match any other "smalltalk" intent. Routes are checked in order, that's why we put the more specific ones first and the more generic at the end. -Finally, just crete a couple of actions that respond to these intents: +Finally, just create a couple of actions that respond to these intents: **src/actions/age.js** @@ -189,9 +188,7 @@ export default class extends React.Component { render() { return ( <> - - I'm not interested in talking about that... - + I'm not interested in talking about that... ) @@ -201,4 +198,4 @@ export default class extends React.Component { That's it! You can run `botonic serve` and play a little bit. Try adding more routes/actions for different Dialogflow intents. When you're ready, go to the next section to learn how to put your bot in production and publish it to messaging platforms like Facebook Messenger. - \ No newline at end of file + diff --git a/docs/3.main-concepts/3.rcml.mdx b/docs/3.main-concepts/3.rcml.mdx index 9ab1a62c8c..a3a8a619a0 100644 --- a/docs/3.main-concepts/3.rcml.mdx +++ b/docs/3.main-concepts/3.rcml.mdx @@ -41,7 +41,7 @@ In order to create a line break, you new to use `{'\\n'}`. _Example of how it looks in the Messenger platform:_ @@ -51,22 +51,22 @@ _Example of how it looks in the Messenger platform:_ I will show you three quickreplies. One with a payload, one to go to an action and another to pass values to that action: - Cool - Take me to paradise - To a better paradise + Cool + Take me to paradise + To a better paradise ``` _Example of how it looks in the Messenger platform:_ > #### NOTE: > -> Buttons and quickreplies can have an url link, a payload attached, a href attribute, or an action to be triggered. When passing parameters through actions as seen in the example, the data will be accessiblein the field `params` inside the `botonicInit` function. +> Buttons and quickreplies can have an url link, a payload attached, a href attribute, or an action to be triggered. When passing parameters through actions as seen in the example, the data will be accessible in the field `params` inside the `botonicInit` function. ## Carousel @@ -129,7 +129,7 @@ export default class extends React.Component { _Example of how it looks in the Messenger app:_ @@ -139,17 +139,17 @@ You can send all this types of media files: ```javascript <> - -
)} - {!webchatState.handoff && - Object.keys(props.persistentMenu).length != 0 && ( - <> + {!webchatState.handoff && ( +
+ {Object.keys(props.persistentMenu).length != 0 && (
handleMenu()} />
-