Skip to content

Commit

Permalink
Merge pull request Wolox#10 from Wolox/bug-fixes
Browse files Browse the repository at this point in the history
Bug fixes
  • Loading branch information
Martín Callegari authored Aug 24, 2017
2 parents 0ce4604 + bacb3a5 commit 8adf07f
Show file tree
Hide file tree
Showing 14 changed files with 86 additions and 19 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# react-chat-widget
![circle-ci](https://img.shields.io/circleci/project/github/Wolox/react-chat-widget.svg)
![npm](https://img.shields.io/npm/v/react-chat-widget.svg)

[![circle-ci](https://img.shields.io/circleci/project/github/Wolox/react-chat-widget.svg)](https://circleci.com/gh/Wolox/react-chat-widget)
[![npm](https://img.shields.io/npm/v/react-chat-widget.svg)](https://www.npmjs.com/package/react-chat-widget)
## Features

- Plain text message UI
Expand Down Expand Up @@ -136,20 +135,22 @@ export default App;
- **subtitle:** (PropTypes.string) Subtitle of the widget
- **senderPlaceHolder:** (PropTypes.string) The placeholder of the message input
- **profileAvatar:** (PropTypes.string.isRequired) The profile image that will be set on the responses
- **stylesInjected:** (Proptypes.object) The styles to be injected, see [styles](#Styles)
- **responseMessages:** (PropTypes.arrayOf(PropTypes.object).isRequired) Array of responses, see [messages](#Messages)
- **stylesInjected:** (Proptypes.object) The styles to be injected, see [styles](#styles)
- **responseMessages:** (PropTypes.arrayOf(PropTypes.object).isRequired) Array of responses, see [messages](#messages)
- **handleNewUserMessage:** (PropTypes.func.isRequired) Function to handle the user input, will receive the full text message when submitted

#### Styles

To inject styles you need to use the prop ** stylesInjected **, and send an object with the following options:
To inject styles you need to use the prop **stylesInjected**, and send an object with the following options:

```js
{
header: PropTypes.object, // Styles for the header section
launcher: PropTypes.object, // Styles for the launcher
message: PropTypes.object, // Styles for the user messages
responses: PropTypes.object, // Styles for the response messages
avatar: PropTypes.object, // Styles for the avatar picture
messagesContainer: PropTypes.object, // Styles for the messages container - where you can see the messages
responses: PropTypes.object, // Styles for the response messages, this will also affect the snippets
snippet: PropTypes.shape({ //Styles for the snippet message. You can only change the styles of the info section (where the actual link is)
info: PropTypes.object
})
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-chat-widget",
"version": "1.0.0",
"version": "1.0.1",
"description": "Chat web widget for React apps",
"main": "lib/index.js",
"repository": "[email protected]:Wolox/react-chat-widget.git",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import './styles.scss';
class Snippet extends PureComponent {
render() {
return (
<div className="snippet">
<div className="snippet" style={this.props.messageStyle}>
<h5 className="snippet-title">
{this.props.snippet.title}
</h5>
Expand All @@ -22,7 +22,8 @@ class Snippet extends PureComponent {

Snippet.propTypes = {
snippet: PROP_TYPES.SNIPPET,
styles: PropTypes.object // eslint-disable-line
styles: PropTypes.object, // eslint-disable-line
messageStyle: PropTypes.object // eslint-disable-line
};

export default Snippet;
19 changes: 15 additions & 4 deletions src/components/Conversation/components/Messages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,27 @@ import './styles.scss';

const isResponse = sender => sender === MESSAGE_SENDER.RESPONSE;

const scrollToBottom = () => {
const messagesDiv = document.getElementById('messages');
messagesDiv.scrollTop = messagesDiv.scrollHeight;
};

class Messages extends Component {
componentDidMount() {
scrollToBottom();
}

componentDidUpdate() {
const messagesDiv = document.getElementById('messages');
messagesDiv.scrollTop = messagesDiv.scrollHeight;
scrollToBottom();
}

render() {
return (
<div id="messages" className="messages-container">
<div id="messages" className="messages-container" style={this.props.containerStyles}>
{this.props.messages.map((message, index) =>
<div className="message" key={index}>
{isResponse(message.sender) &&
<img src={this.props.profileAvatar} className="avatar" alt="profile" />
<img src={this.props.profileAvatar} className="avatar" alt="profile" style={this.props.avatarStyles} />
}
{message.type === MESSAGES_TYPES.TEXT ?
<Message
Expand All @@ -33,6 +41,7 @@ class Messages extends Component {
<Snippet
snippet={message}
styles={this.props.snippetStyles}
messageStyle={this.props.responsesStyles}
/>
}
</div>
Expand All @@ -45,7 +54,9 @@ class Messages extends Component {
Messages.propTypes = {
messages: PropTypes.arrayOf(PropTypes.object),
profileAvatar: PropTypes.string,
avatarStyles: PropTypes.object, // eslint-disable-line
messageStyles: PropTypes.object, // eslint-disable-line
containerStyles: PropTypes.object, // eslint-disable-line
responsesStyles: PropTypes.object, // eslint-disable-line
snippetStyles: PropTypes.object // eslint-disable-line
};
Expand Down
3 changes: 3 additions & 0 deletions src/components/Conversation/components/Messages/styles.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
@import "../../../../sass/variables.scss";

.messages-container {
background-color: $white;
height: 50vh;
max-height: 410px;
overflow-y: scroll;
Expand Down
37 changes: 37 additions & 0 deletions src/components/Conversation/components/Messages/test/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import moment from 'moment';
import { shallow } from 'enzyme';

import Messages from '../index';
import Message from '../components/Message';
import Snippet from '../components/Snippet';

describe('<Messages />', () => {
const responseMessages = [
{
text: 'Response message 1',
type: 'text',
timestamp: moment().format(),
sender: 'response'
}, {
title: 'Link title',
link: 'link',
type: 'link',
timestamp: moment().format()
}
];

const messagesComponent = shallow(
<Messages
messages={responseMessages}
/>
);

it('should render a Message component', () => {
expect(messagesComponent.find(Message)).toHaveLength(1);
});

it('should render a Snippet component', () => {
expect(messagesComponent.find(Snippet)).toHaveLength(1);
});
});
6 changes: 5 additions & 1 deletion src/components/Conversation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ const Conversation = props =>
/>
<Messages
messages={props.messages}
profileAvatar={props.profileAvatar}
containerStyles={props.containerStyles}
avatarStyles={props.avatarStyles}
messageStyles={props.messageStyles}
responsesStyles={props.responsesStyles}
snippetStyles={props.snippetStyles}
profileAvatar={props.profileAvatar}
/>
<Sender
sendMessage={props.sendMessage}
Expand All @@ -32,7 +34,9 @@ Conversation.propTypes = {
sendMessage: PropTypes.func,
senderPlaceHolder: PropTypes.string,
profileAvatar: PropTypes.string,
avatarStyles: PropTypes.object, // eslint-disable-line
headerStyles: PropTypes.object, // eslint-disable-line
containerStyles: PropTypes.object, // eslint-disable-line
messageStyles: PropTypes.object, // eslint-disable-line
responsesStyles: PropTypes.object, // eslint-disable-line
snippetStyles: PropTypes.object // eslint-disable-line
Expand Down
2 changes: 1 addition & 1 deletion src/components/Conversation/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
@import "../../sass/animation.scss";

.conversation-container {
@include animation(0, 0.5s, slide-in);
border-radius: 10px;
box-shadow: 0px 2px 10px 1px $grey-3;
@include animation(0, 0.5s, slide-in);
}

.slide-out {
Expand Down
1 change: 1 addition & 0 deletions src/components/Launcher/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
@import "../../sass/animation.scss";

.launcher {
@include animation(0, 0.5s, slide-in);
align-self: flex-end;
background-color: $turqois-1;
border: 0;
Expand Down
2 changes: 2 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ const PROP_TYPES = {
STYLES: PropTypes.shape({
header: PropTypes.object,
launcher: PropTypes.object,
avatar: PropTypes.object,
messagesContainer: PropTypes.object,
message: PropTypes.object,
responses: PropTypes.object,
snippet: PropTypes.shape({
Expand Down
4 changes: 2 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class Widget extends Component {
};
this.setState(prevState => ({
messages: prevState.messages.concat([newMessage])
}), this.props.handleNewUserMessage(text));
}), () => this.props.handleNewUserMessage(text));
}

handleMessageSubmit = (event) => {
Expand Down Expand Up @@ -77,7 +77,7 @@ Widget.propTypes = {
handleNewUserMessage: PropTypes.func.isRequired,
senderPlaceHolder: PropTypes.string,
stylesInjected: PROP_TYPES.STYLES,
profileAvatar: PropTypes.string.isRequired
profileAvatar: PropTypes.string
};

Widget.defaultProps = {
Expand Down
2 changes: 2 additions & 0 deletions src/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const WidgetLayout = props =>
messages={props.messages}
sendMessage={props.sendMessage}
senderPlaceHolder={props.senderPlaceHolder}
containerStyles={props.stylesInjected.messagesContainer}
avatarStyles={props.stylesInjected.avatar}
headerStyles={props.stylesInjected.header}
messageStyles={props.stylesInjected.message}
responsesStyles={props.stylesInjected.responses}
Expand Down
1 change: 1 addition & 0 deletions src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
position: fixed;
right: 0;
width: 90vw;
z-index: 9999;
}
6 changes: 5 additions & 1 deletion src/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import assetMock from 'tests-mocks/fileMock';
import Widget from '../index';
import WidgetLayout from '../layout';


describe('<Widget />', () => {
const profile = assetMock;
const handleUserMessage = jest.fn();
Expand Down Expand Up @@ -68,6 +67,11 @@ describe('<Widget />', () => {
expect(widgetComponent.state('messages').length).toBe(0);
});

it('should set the attribute sender with value response to each new response in the array', () => {
widgetComponent.instance().mergeMessages(newResponseMessage);
expect(newResponseMessage[0].sender).toBe('response');
});

it('should call mergeMessages when component will receive props', () => {
widgetComponent.instance().mergeMessages = jest.fn();
widgetComponent.instance().componentWillReceiveProps({ responseMessages: newResponseMessage });
Expand Down

0 comments on commit 8adf07f

Please sign in to comment.