Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
fortin-mo authored Oct 11, 2019
2 parents 9d915ad + 528573d commit d1658fb
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 25 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### [0.6.1](https://https///compare/v0.6.0...v0.6.1) (2019-10-11)


### Bug Fixes

* cast messages text into string to prevent crashes ([4778ad8](https://https///commit/4778ad8))


### Features

* experimental sockjs support ([b1f7c9d](https://https///commit/b1f7c9d))

## [0.6.0](https://https///compare/v0.5.9...v0.6.0) (2019-10-03)

### 0.5.10 (2019-10-02)
Expand Down
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ const plugin = {
init: (args) => {
ReactDOM.render(
<Widget
protocol={args.protocol}
socketUrl={args.socketUrl}
socketPath={args.socketPath}
protocolOptions={args.protocolOptions}
interval={args.interval}
initPayload={args.initPayload}
title={args.title}
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rasa-webchat",
"version": "0.6.0",
"version": "0.6.1",
"description": "Chat web widget for React apps and Rasa Core chatbots",
"main": "lib/index.js",
"repository": "git@https://github.com/mrbot-ai/rasa-webchat.git",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const Header = ({
connectingText,
closeImage
}) =>
<div>
<div className="header-and-loading">
<div className="header">
<div className="header-buttons">
{
Expand Down
3 changes: 2 additions & 1 deletion src/components/Widget/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class Widget extends Component {
const { socket, storage } = this.props;

socket.on('bot_uttered', (botUttered) => {
this.messages.push(botUttered);
const newMessage = { ...botUttered, text: String(botUttered.text) };
this.messages.push(newMessage);
});

this.props.dispatch(pullSession());
Expand Down
15 changes: 13 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ import { store, initStore } from '../src/store/store';
import socket from './socket';

const ConnectedWidget = (props) => {
const sock = socket(props.socketUrl, props.customData, props.socketPath);
const storage = props.params.storage == "session" ? sessionStorage : localStorage
const sock = socket(
props.socketUrl,
props.customData,
props.socketPath,
props.protocol,
props.protocolOptions
);
const storage = props.params.storage === 'session' ? sessionStorage : localStorage;
initStore(
props.inputTextFieldHint,
props.connectingText,
Expand Down Expand Up @@ -47,8 +53,10 @@ ConnectedWidget.propTypes = {
interval: PropTypes.number,
title: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
subtitle: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
protocol: PropTypes.string,
socketUrl: PropTypes.string.isRequired,
socketPath: PropTypes.string,
protocolOptions: PropTypes.shape({}),
customData: PropTypes.shape({}),
handleNewUserMessage: PropTypes.func,
profileAvatar: PropTypes.string,
Expand All @@ -60,6 +68,7 @@ ConnectedWidget.propTypes = {
fullScreenMode: PropTypes.bool,
badge: PropTypes.number,
embedded: PropTypes.bool,
// eslint-disable-next-line react/forbid-prop-types
params: PropTypes.object,
openLauncherImage: PropTypes.string,
closeImage: PropTypes.string,
Expand All @@ -76,7 +85,9 @@ ConnectedWidget.defaultProps = {
connectingText: 'Waiting for server...',
fullScreenMode: false,
hideWhenNotConnected: true,
protocol: 'socketio',
socketUrl: 'http://localhost',
protocolOptions: {},
badge: 0,
embedded: false,
params: {
Expand Down
24 changes: 24 additions & 0 deletions src/socket-socketio.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import io from 'socket.io-client';

export default function (socketUrl, customData, path) {
const options = path ? { path } : {};
const socket = io(socketUrl, options);
socket.on('connect', () => {
console.log(`connect:${socket.id}`);
socket.customData = customData;
});

socket.on('connect_error', (error) => {
console.log(error);
});

socket.on('error', (error) => {
console.log(error);
});

socket.on('disconnect', (reason) => {
console.log(reason);
});

return socket;
}
93 changes: 93 additions & 0 deletions src/socket-sockjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import SockJS from 'sockjs-client';
import { Stomp } from '@stomp/stompjs';
import { EventEmitter } from 'events';

/*
This implementation mimics the SocketIO implementation.
*/
export default function (socketUrl, customData, _path, options) {
const socket = SockJS(socketUrl);
const stomp = Stomp.over(socket);

const MESSAGES_CHANNEL = options.messagesChannel || '/app/sendMessage';
const REPLY_TOPIC = options.replyTopic || '/user/queue/reply';
const SUBSCRIPTION_CHANNEL = options.subscriptionChannel || '/app/addUser';

const socketProxy = new EventEmitter();

const send = (message) => {
stomp.send(MESSAGES_CHANNEL, {}, JSON.stringify(message));
};

const extractSessionId = () => {
// eslint-disable-next-line no-underscore-dangle
const urlarray = socket._transport.url.split('/');
const index = urlarray.length - 2;
return urlarray[index];
};

socketProxy.on('user_uttered', (data) => {
send({
type: 'CHAT',
content: JSON.stringify(data),
sender: socketProxy.id
});
});

socketProxy.on('session_request', () => {
send({
type: 'SESSION_REQUEST',
content: JSON.stringify(options.authData || null),
sender: 'client'
});
});

socketProxy.onconnect = () => {
socketProxy.id = extractSessionId(socket);
socketProxy.customData = customData;
stomp.subscribe(REPLY_TOPIC, socketProxy.onIncomingMessage);
stomp.send(
SUBSCRIPTION_CHANNEL,
{},
JSON.stringify({ type: 'JOIN', sender: socketProxy.id })
);
};

socketProxy.onerror = (error) => {
// eslint-disable-next-line no-console
console.log(error);
};

socketProxy.onIncomingMessage = (payload) => {
const message = JSON.parse(payload.body);

if (message.type === 'JOIN') {
socketProxy.emit('connect');
} else if (message.type === 'LEAVE') {
socket.close();
socketProxy.emit('disconnect', 'server left');
} else if (message.type === 'SESSION_CONFIRM') {
socketProxy.emit('session_confirm', socketProxy.id);
} else if (message.type === 'CHAT') {
const agentMessage = JSON.parse(message.content);
delete agentMessage.recipient_id;
socketProxy.emit('bot_uttered', agentMessage);
} else if (message.type === 'SESSION_CONFIRM') {
socketProxy.emit('session_confirm', message.content);
}
};

socketProxy.close = () => {
socket.close();
};

stomp.connect({}, socketProxy.onconnect, socketProxy.onerror);

socket.onclose = () => {
// eslint-disable-next-line no-console
console.log('Closed sockjs connection');
socketProxy.emit('disconnect');
};

return socketProxy;
}
50 changes: 31 additions & 19 deletions src/socket.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
import io from 'socket.io-client';
// import io from 'socket.io-client';
import socketio from './socket-socketio';
import sockjs from './socket-sockjs';

export default function (socketUrl, customData, path) {
const options = path ? { path } : {};
const socket = io(socketUrl, options);
socket.on('connect', () => {
console.log(`connect:${socket.id}`);
socket.customData = customData;
});
const PROTOCOLS = { socketio, sockjs };
// export default function (socketUrl, customData, path) {
// const options = path ? { path } : {};
// const socket = io(socketUrl, options);
// socket.on('connect', () => {
// console.log(`connect:${socket.id}`);
// socket.customData = customData;
// });
export default function (socketUrl, customData, path, protocol, protocolOptions) {
protocol = protocol || 'socketio';
const socketProtocol = PROTOCOLS[protocol];

socket.on('connect_error', (error) => {
console.log(error);
});
if (socketProtocol !== undefined) {
return socketProtocol(socketUrl, customData, path, protocolOptions);
}
throw new Error(`Undefined socket protocol ${protocol}`);
}

socket.on('error', (error) => {
console.log(error);
});
// socket.on('connect_error', (error) => {
// console.log(error);
// });

socket.on('disconnect', (reason) => {
console.log(reason);
});
// socket.on('error', (error) => {
// console.log(error);
// });

return socket;
};
// socket.on('disconnect', (reason) => {
// console.log(reason);
// });

// return socket;
// };

0 comments on commit d1658fb

Please sign in to comment.