Skip to content

Commit f4383c0

Browse files
authored
Added a new WebChatProvider component to simplify the use of withWebC… (#9)
* feat: added WebChatProvider and CustomResponsePortalsContainer [skip ci] - Added a new WebChatProvider component to simplify the use of withWebChat and to add support for rendering custom responses. - Added a CustomResponsePortalsContainer component that can be used as a container to handle custom responses. - Also filled out more details in the types.
1 parent 418d2c6 commit f4383c0

22 files changed

+11003
-10103
lines changed

.eslintrc.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,13 @@ module.exports = {
3838
],
3939
plugins: ['jsdoc', 'simple-import-sort'],
4040
rules: {
41-
'no-use-before-define': 'off',
41+
'@typescript-eslint/explicit-module-boundary-types': 'off',
42+
'@typescript-eslint/no-explicit-any': 'off',
43+
camelcase: 'off',
4244
'import/extensions': 'off',
45+
'import/prefer-default-export': 'off',
4346
'react/jsx-filename-extension': [1, { extensions: ['.tsx', '.jsx'] }],
47+
'react/require-default-props': 'off',
48+
'no-use-before-define': 'off',
4449
},
4550
};

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,9 @@ typings/
4747
# Yarn Integrity file
4848
.yarn-integrity
4949

50-
# generate output
50+
# Generated output
5151
dist
52+
53+
# IntelliJ/WebStorm Files
54+
.idea
55+
*.iml

README.md

Lines changed: 40 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,17 @@
55

66
`@ibm-watson/assistant-web-chat-react` is a React library to extend the [web chat](https://cloud.ibm.com/docs/watson-assistant?topic=watson-assistant-deploy-web-chat) feature of [IBM Watson Assistant](https://www.ibm.com/cloud/watson-assistant) within your React application. This makes it easier to provide user-defined response types written in React, add content to custom elements with React, have the web chat and your site communicate more easily, and more.
77

8+
There are two utility functions provided by this library:
9+
10+
1. The `WebChatContainer` function is a functional component that makes use of `withWebChat` to load web chat when the component is mounted.
11+
2. The `withWebChat` function creates a high-order-component (HOC) that you can wrap around an existing component to inject `createWebChatInstance` into it so your component can create a new instance of web chat when appropriate. You can find more information in the [withWebChat documentation](./WITH_WEB_CHAT.md).
12+
813
<details>
914
<summary>Table of contents</summary>
1015

1116
- [Installation](#installation)
12-
- [How this works](#how-this-works)
13-
- [Usage](#usage)
14-
- [With a functional component](#with-a-functional-component)
15-
- [With a class component](#with-a-class-component)
16-
- [Render user_defined responses](#render-user_defined-responses)
17-
- [Render customElements](#render-custom-elements)
18-
- [Using with Carbon](#using-with-carbon)
19-
- [Using with TypeScript](#using-with-typescript)
20-
- [Writing tests](#writing-tests)
17+
- [Using WebChatContainer](#webchatcontainer)
2118
- [API](#api)
22-
- [withWebChat](#withwebchat)
23-
- [createWebChatInstance](#createwebchatinstance)
2419
- [Additional resources](#additional-resources)
2520
- [License](#license)
2621

@@ -40,231 +35,69 @@ Or using `yarn`:
4035
yarn add @ibm-watson/assistant-web-chat-react
4136
```
4237

43-
## How this works
44-
45-
This package allows you to inject a property called `createWebChatInstance` as a prop to a given React component. The `createWebChatInstance` method takes a [web chat configuration options object](https://web-chat.global.assistant.watson.cloud.ibm.com/docs.html?to=api-configuration#configurationobject) as an argument and returns an [instance](https://web-chat.global.assistant.watson.cloud.ibm.com/docs.html?to=api-instance-methods) of the web chat that you can now access inside your React application. Making the `instance` available for use inside your React component makes it easy for your React application and web chat to work in harmony, including allowing you to render React content inside web chat via [React portals](https://reactjs.org/docs/portals.html). Once you have an `instance` you can pass it into child components as a property or via context. You should not call `createWebChatInstance` again to access the `instance`, as it will create a *new* instance if you do so.
46-
47-
## Usage
48-
49-
### With a functional component
50-
51-
With a functional component, you can use the `useEffect` React hook to call the `createWebChatInstance` method provided as a prop.
52-
53-
```javascript
54-
import React, { useEffect } from 'react';
55-
import { withWebChat } from '@ibm-watson/assistant-web-chat-react';
56-
57-
const MyLocation = ({ location, createWebChatInstance }) => {
58-
59-
useEffect(() => {
60-
function onWebChatLoad(instance) {
61-
instance.render();
62-
}
63-
64-
// A web chat configuration options object as documented at https://web-chat.global.assistant.watson.cloud.ibm.com/docs.html?to=api-configuration#configurationobject
65-
const webChatOptions = {
66-
integrationID: 'XXXX',
67-
region: 'XXXX',
68-
serviceInstanceID: 'XXXX',
69-
onLoad: onWebChatLoad
70-
};
71-
72-
createWebChatInstance(webChatOptions);
73-
}, []);
74-
75-
return <div>I am here in {location}!</div>;
76-
};
77-
78-
// Wrap the component with the method returned by `withWebChat`.
79-
export default withWebChat()(MyLocation);
80-
```
81-
82-
You can now use the `MyLocation` component like you would any other. You can pass through any props you want, and `withWebChat` adds `createWebChatInstance` to the props.
83-
84-
```javascript
85-
import React from 'react';
86-
import MyLocation from './MyLocation';
87-
88-
// Notice we only pass in the "location" prop to the MyLocation component... "createWebChatInstance" is automatically added!
89-
const App = () => {
90-
return (
91-
<div>
92-
<div>Where are you located?</div>
93-
<MyLocation location="Boston" />
94-
</div>
95-
);
96-
}
97-
```
98-
99-
### With a class component
38+
## Using WebChatContainer
10039

101-
With a class-based component, you can use `componentDidMount` to call the `createWebChatInstance` method provided as a prop.
40+
The `WebChatContainer` function component is intended to make it as easy as possible to include web chat in your React application. To use, you simply need to render this component anywhere in your application and provide the [web chat configuration options object](https://web-chat.global.assistant.watson.cloud.ibm.com/docs.html?to=api-configuration#configurationobject) as a prop.
10241

10342
```javascript
104-
import React, { Component } from 'react';
105-
106-
class MyLocation extends Component {
107-
108-
// A web chat configuration options object as documented at https://web-chat.global.assistant.watson.cloud.ibm.com/docs.html?to=api-configuration#configurationobject
109-
webChatOptions = {
43+
function App() {
44+
const webChatOptions = {
11045
integrationID: 'XXXX',
11146
region: 'XXXX',
11247
serviceInstanceID: 'XXXX',
113-
onLoad: this.onWebChatLoad
48+
// subscriptionID: 'only on enterprise plans',
49+
// Note that there is no onLoad property here. The WebChatContainer component will override it with its own.
11450
};
115-
116-
componentDidMount() {
117-
const { createWebChatInstance } = this.props;
118-
createWebChatInstance(this.webChatOptions).then(instance => { this.onWebChatLoad(instance); });
119-
}
120-
121-
onWebChatLoad = (instance) => {
122-
instance.render();
123-
};
124-
125-
render() {
126-
const { location } = this.props;
127-
return <div>I am here in {location}!</div>;
128-
}
51+
return <WebChatContainer config={webChatOptions} />;
12952
}
130-
131-
export default withWebChat()(MyLocation);
13253
```
13354

134-
You can now use the `MyLocation` component like you would any other. You can pass through any props you want, and `withWebChat` will add `createWebChatInstance` to the props.
55+
This component is also capable of managing custom responses. To do so, you need to pass a `renderCustomResponse` function as a prop. This function should return a React component that will render the content for the specific message for that response. You should make sure that the `WebChatContainer` component does not get unmounted in the middle of the life of your application because it will lose all custom responses that were previously received by web chat.
13556

13657
```javascript
137-
import React, { Component } from 'react';
138-
import MyLocation from './MyLocation';
139-
140-
// Notice we only pass in the "location" prop to the MyLocation component... "createWebChatInstance" is automatically added!
141-
class App extends Component {
142-
render() {
143-
return (
144-
<div>
145-
<div>Where are you located?</div>
146-
<MyLocation location="Boston" />
147-
</div>
148-
);
149-
}
58+
function App() {
59+
const webChatOptions = {
60+
integrationID: 'XXXX',
61+
region: 'XXXX',
62+
serviceInstanceID: 'XXXX',
63+
// subscriptionID: 'only on enterprise plans',
64+
// Note that there is no onLoad property here. The WebChatContainer component will override it with its own.
65+
};
66+
return <WebChatContainer renderCustomResponse={renderCustomResponse} config={webChatOptions} />;
15067
}
151-
```
152-
### Using with TypeScript
153-
154-
The `withWebChat` package is written in TypeScript and includes types.
155-
In addition to `withWebChat`, this package exports the following types:
156-
157-
| Type | Description |
158-
|-----------------------|--------------------------------------------------------------------------------------|
159-
| AddedWithWebChatProps | The props that the withWebChat component adds to the component that is passed to it. |
160-
| WebChatConfig | The configuration options object to create a new web chat instance. |
161-
| WebChatInstance | The created instance of web chat. |
162-
| WithWebChatConfig | The optional configuration object for withWebChat |
163-
164-
16568

166-
```typescript
167-
import React, { useEffect } from 'react';
168-
import {
169-
withWebChat,
170-
AddedWithWebChatProps,
171-
WebChatConfig,
172-
WebChatInstance,
173-
WithWebChatConfig
174-
} from '@ibm-watson/assistant-web-chat-react';
175-
176-
interface MyLocationProps extends AddedWithWebChatProps {
177-
location: string;
69+
function renderCustomResponse(event) {
70+
return <div>My custom content</div>;
17871
}
179-
180-
const withWebChatConfig: WithWebChatConfig = {
181-
debug: true
182-
};
183-
184-
const MyLocation = ({ location, createWebChatInstance }: MyLocationProps) => {
185-
useEffect(() => {
186-
187-
function onWebChatLoad(instance: WebChatInstance) {
188-
instance.render();
189-
}
190-
191-
// A web chat configuration options object as documented at https://web-chat.global.assistant.watson.cloud.ibm.com/docs.html?to=api-configuration#configurationobject
192-
const webChatOptions: WebChatConfig = {
193-
integrationID: 'XXXX',
194-
region: 'XXXX',
195-
serviceInstanceID: 'XXXX',
196-
onLoad: onWebChatLoad
197-
};
198-
199-
createWebChatInstance(webChatOptions);
200-
}, []);
201-
202-
return <div>I am here in {location}!</div>;
203-
};
204-
205-
// Wrap the component with the method returned by `withWebChat`.
206-
export default withWebChat(withWebChatConfig)(MyLocation);
207-
208-
```
209-
210-
### Writing tests
211-
212-
It is recommended that you mock `createWebChatInstance` in your unit tests and not test the higher-order component. If you must include the higher-order component in your unit test, you might have to add some extra configuration to your unit test framework to account for the fact that web chat appends additional scripts to your web site.
213-
214-
For example, when using the [Jest testing framework](https://jestjs.io), you must add the following configuration to your `jest.config.js` file.
215-
216-
```javascript
217-
module.exports = {
218-
testEnvironmentOptions: {
219-
resources: 'usable',
220-
runScripts: 'dangerously',
221-
},
222-
};
22372
```
22473

22574
## API
22675

227-
### withWebChat
76+
### WebChatContainer API
22877

229-
The `withWebChat` method is a higher-order function that returns a higher-order component. It takes an optional configuration argument and returns a function that takes a component as an argument. This component will have `createWebChatInstance` injected as a prop.
78+
The `WebChatContainer` function is a functional component that makes use of `withWebChat` to load web chat when the component is mounted. It can also manage React portals for custom responses.
23079

231-
```javascript
232-
// enchance is the higher order component.
233-
const enhance = withWebChat(options);
80+
#### Props
23481

235-
// enhance takes the component as an argument and adds createWebChatInstance as a prop.
236-
export default enhance(Component)
237-
```
238-
239-
or in short form:
240-
241-
```javascript
242-
export default withWebChat(options)(Component)
243-
```
82+
`WebChatContainer` has the following props.
24483

245-
This syntax enables you to chain multiple higher-order components together. [See the higher-order components documentation](https://reactjs.org/docs/higher-order-components.html) from the React team for more information about how higher-order components work and how they can be composed together.
84+
| Attribute | Required | Type | Description |
85+
|-----------|----------|---------|-------------|
86+
| config | Yes | object | The [web chat configuration options object](https://web-chat.global.assistant.watson.cloud.ibm.com/docs.html?to=api-configuration#configurationobject). Note that any `onLoad` property will be ignored. |
87+
|
88+
| instanceRef | No | MutableRefObject | A convenience prop that is a reference to the web chat instance. This component will set the value of this ref using the `current` property when the instance has been created. |
89+
|
90+
| onBeforeRender | No | function | This is a callback function that is called after web chat has been loaded and before the `render` function is called. This function is passed a single argument which is the instance of web chat that was loaded. This function can be used to obtain a reference to the web chat instance if you want to make use of the instance functions that are available. |
91+
|
92+
| renderCustomResponse | No | function | This function is a callback function that will be called by this container to render custom responses. If this prop is provided, then the container will listen for custom response events from web chat and will generate a React portal for each event. This function will be called once during component render for each custom response event. This function takes two arguments. The first is the [custom response event](https://web-chat.global.assistant.watson.cloud.ibm.com/docs.html?to=api-events#customresponse) that triggered the custom response. The second is a convenience argument that is the instance of web chat. The function should return a `ReactNode` that renders the custom content for the response. |
93+
|
24694

247-
#### withWebChat options object
248-
249-
The `withWebChat` method takes an optional object as an argument. Most uses will never use these.
250-
251-
| Attribute | Required | Default | Type | Description |
252-
|-----------|----------|----------------------------------------------------------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
253-
| debug | No | false | boolean | If set to true, adds logging for setup and tear down process of web chat. Helpful for seeing if your application is aggressively mounting and remounting web chat. |
254-
| baseUrl | No | https://web-chat.global.assistant.watson.appdomain.cloud | string | Where externally loaded script for web chat are hosted. Used for internal development purposes. |
255-
256-
### createWebChatInstance
257-
258-
The `createWebChatInstance` method takes a [web chat configuration options object](https://web-chat.global.assistant.watson.cloud.ibm.com/docs.html?to=api-configuration#configurationobject) as an argument and returns a promise. This promise either will successfully resolve with the instance of the web chat, or will throw a descriptive error.
259-
260-
```javascript
261-
createWebChatInstance(config).then(instance => {}).catch(error => {});
262-
```
26395
## Additional resources
26496
- [Watson Assistant](https://www.ibm.com/cloud/watson-assistant)
26597
- [Watson Assistant web chat feature documentation](https://cloud.ibm.com/docs/watson-assistant?topic=watson-assistant-deploy-web-chat)
26698
- [Watson Assistant web chat API documentation](https://web-chat.global.assistant.watson.cloud.ibm.com/docs.html?to=api-overview)
26799
- [Higher order components](https://reactjs.org/docs/higher-order-components.html)
100+
268101
## License
269102

270103
This package is available under the [MIT License](./LICENSE).

0 commit comments

Comments
 (0)