Skip to content

Instantly share code, notes, and snippets.

@eknowlton
Last active January 10, 2018 19:51
Show Gist options
  • Save eknowlton/010c008773ecacc53da3 to your computer and use it in GitHub Desktop.
Save eknowlton/010c008773ecacc53da3 to your computer and use it in GitHub Desktop.
ReactJS Chat integration with Slack
define(['react', 'jquery', 'moment'], function(React, jquery, moment) {
var ChatApp = {
users: [],
user: [],
messageCount: 0,
channel: [],
Message: React.createClass({
render: function () {
if(this.props.status == 'visible'){
messageClass = 'message messageVisible';
}else{
messageClass = 'message messagePending';
}
if(this.props.ts){
var date = moment.unix(this.props.ts).format("h:mm:ss a");
}
return (
<div className={messageClass} data-message-id={this.props.id}>
<img src={this.props.img} />
<span><strong>{this.props.name}</strong> <small> {date}</small></span>
<div className='messageText'> {this.props.children} </div>
</div>
);
}
}),
MessageList: React.createClass({
componentDidUpdate: function(){
var messageListNode = React.findDOMNode(this.refs.messageList);
var $messageListNode = $(messageListNode);
var scrollheight = $messageListNode[0].scrollHeight;
$messageListNode.scrollTop(scrollheight);
},
render: function () {
var messages = this.props.data.map(function (message) {
return (
<ChatApp.Message name={message.name} key={message.id} id={message.id} status={message.status} ts={message.ts} img={message.img}>
{message.text}
</ChatApp.Message>
);
});
return (
<div className='messageList' ref='messageList'>
<div className='alert alert-success'>Welcome to Reporting support. Please use this chat for issues you experience with Reporting.</div>
{messages}
</div>
);
}
}),
MessageForm: React.createClass({
handleSubmit: function(e){
e.preventDefault();
var text = React.findDOMNode(this.refs.message).value.trim();
if (!text) {
return;
}
ChatApp.messageCount++;
var messageSendData = {
"id": ChatApp.messageCount,
"type": "message",
"channel": ChatApp.channel.id,
"text": text
};
ChatApp.socket.send(JSON.stringify(messageSendData));
this.props.onMessageSubmit({text: text, id: ChatApp.messageCount});
React.findDOMNode(this.refs.message).value = '';
return;
},
componentDidMount: function(){
var text = $(React.findDOMNode(this.refs.message)).on('keydown', function(e){
if (e.keyCode == 13) {
$(React.findDOMNode(this.refs.messageSubmitForm)).submit();
}
}.bind(this));
},
render: function () {
if(this.props.socketState){
textarea = ( <input type='text' className='messageInput input-block-level' ref='message' /> );
}else{
textarea = ( <input type='text' className='messageInput input-block-level' ref='message' disabled='disabled' /> );
}
return (
<div className='messageForm'>
<form onSubmit={this.handleSubmit} className='form-inline' refs='messageSubmitForm'>
{textarea}
</form>
</div>
);
}
}),
ChatBox: React.createClass({
getInitialState: function() {
return {messages: [], socket: false};
},
componentDidMount: function() {
if(window.appConfig.slackToken){
$.get( 'https://slack.com/api/channels.join' ,{
token: window.appConfig.slackToken,
name: 'allboutmoney'
}).done(function(data){
if(data.ok) {
ChatApp.channel = data.channel;
$.get('https://slack.com/api/rtm.start?token=' + window.appConfig.slackToken)
.done(function (data) {
if (data.ok) {
ChatApp.socket = new WebSocket(data.url);
this.getUserInfo(data.self.id, function(user){
ChatApp.user = user;
});
// Open the socket
ChatApp.socket.onopen = function (event) {
this.setState({message: [], socket: true});
ChatApp.socket.onmessage = function (event) {
this.messageRecieve(event.data);
}.bind(this);
ChatApp.socket.onclose = function (event) {
console.log('The client has disconnected!');
};
}.bind(this);
} else {
alert('An error has occured. ( JS Error 4 )');
}
}.bind(this)).fail(function () {
console.log('Failed');
});
}else{
alert('An error occured. ( JS Error 5 ) ');
}
}.bind(this)).fail(function(){
alert('An error occured. ( JS Error 6 ) ');
}.bind(this));
}else{
$(document).on('click', this.refs.linkAccount.getDOMNode(), function(){
window.location = 'https://slack.com/oauth/authorize?client_id=' + encodeURIComponent(window.appConfig.slackClientId) + '&redirect_uri=' + encodeURIComponent(window.appConfig.slackRedirectUri) + '&state=' + encodeURIComponent(window.appConfig.slackState) + '&team=T03L85TS3&scope=client';
}.bind(this));
}
},
getUserInfo: function(userid, finished){
if(ChatApp.users[userid] == undefined) {
$.get('https://slack.com/api/users.info', {
token: window.appConfig.slackToken,
user: userid
}).success(function (data) {
if (data.ok) {
ChatApp.users[userid] = data.user;
finished(data.user);
} else {
alert('An error has occurred. ( JS Error 2 ) ');
}
}).error(function () {
alert('An error has occurred. ( JS Error 1 ) ');
});
}else{
finished(ChatApp.users[userid]);
}
},
handleSubmit: function(e){
e.preventDefault();
var Messages = this.state.messages;
var text = React.findDOMNode(this.refs.message).value.trim();
Messages.push({name: ChatApp.user.name, text: text});
this.setState({messages: Messages});
},
messageRecieve: function(data){
message = JSON.parse(data);
console.log('messageReceive: ', message);
var Messages = this.state.messages;
// only show messages from this channel
if(message.channel == ChatApp.channel.id && message.type == 'message' && !message.subtype) {
var Messages = this.state.messages;
this.getUserInfo(message.user, function(user){
Messages.push({name: user.name, text: message.text, id: message.ts, status: "visible", ts: message.ts, img: user.profile.image_24});
this.setState({messages: Messages});
}.bind(this));
}
if(message.reply_to != undefined){
$.each(Messages, function(index, value){
if(value.id == message.reply_to){
if(message.ok){
value.status = 'visible';
value.ts = message.ts;
}
}
});
this.setState({messages: Messages});
}
},
handleMessageSubmit: function(message){
var Messages = this.state.messages;
Messages.push({name: "Me", text: message.text, id: message.id, status: "pending", img: ChatApp.user.profile.image_24});
this.setState({messages: Messages});
},
render: function() {
if(window.appConfig.slackToken) {
return (
<div className='chatBox'>
<ChatApp.MessageList data={this.state.messages} />
<ChatApp.MessageForm onMessageSubmit={this.handleMessageSubmit} socketState={this.state.socket} />
</div>
);
}else{
return (
<a href='#' className='btn btn-success btn-block' ref='linkAccount'>Link your Slack account</a>
)
}
}
})
};
return ChatApp;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment