Major cleanup. Moved a lot of CSS variables out too root of CSS for easier styling.

This commit is contained in:
Håvar Aambø Fosstveit
2018-12-18 12:13:47 +01:00
parent db9d423feb
commit 651cd6f737
44 changed files with 296 additions and 517 deletions
+101
View File
@@ -0,0 +1,101 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { withRoomContext } from '../../../RoomContext';
import MessageList from './MessageList';
class Chat extends Component
{
createNewMessage(text, sender, name, picture)
{
return {
type : 'message',
text,
time : Date.now(),
name,
sender,
picture
};
}
render()
{
const {
roomClient,
senderPlaceHolder,
disabledInput,
autofocus,
displayName,
picture
} = this.props;
return (
<div data-component='Chat'>
<MessageList />
<form
data-component='Sender'
onSubmit={(e) =>
{
e.preventDefault();
const userInput = e.target.message.value;
if (userInput)
{
const message = this.createNewMessage(userInput, 'response', displayName, picture);
roomClient.sendChatMessage(message);
}
e.target.message.value = '';
}}
>
<input
type='text'
className='new-message'
name='message'
placeholder={senderPlaceHolder}
disabled={disabledInput}
autoFocus={autofocus}
autoComplete='off'
/>
<input
type='submit'
className='send'
value='Send'
/>
</form>
</div>
);
}
}
Chat.propTypes =
{
roomClient : PropTypes.any.isRequired,
senderPlaceHolder : PropTypes.string,
disabledInput : PropTypes.bool,
autofocus : PropTypes.bool,
displayName : PropTypes.string,
picture : PropTypes.string
};
Chat.defaultProps =
{
senderPlaceHolder : 'Type a message...',
autofocus : false,
displayName : null
};
const mapStateToProps = (state) =>
{
return {
disabledInput : state.chatbehavior.disabledInput,
displayName : state.me.displayName,
picture : state.me.picture
};
};
const ChatContainer = withRoomContext(connect(
mapStateToProps
)(Chat));
export default ChatContainer;
@@ -0,0 +1,98 @@
import React, { Component } from 'react';
import { compose } from 'redux';
import PropTypes from 'prop-types';
import marked from 'marked';
import { connect } from 'react-redux';
import scrollToBottom from '../scrollToBottom';
const linkRenderer = new marked.Renderer();
linkRenderer.link = (href, title, text) =>
{
title = title ? title : href;
text = text ? text : href;
return (`<a target='_blank' href='${ href }' title='${ title }'>${ text }</a>`);
};
class MessageList extends Component
{
getTimeString(time)
{
return `${(time.getHours() < 10 ? '0' : '')}${time.getHours()}:${(time.getMinutes() < 10 ? '0' : '')}${time.getMinutes()}`;
}
render()
{
const {
chatmessages
} = this.props;
return (
<div data-component='MessageList' id='messages'>
<Choose>
<When condition={chatmessages.length > 0}>
{
chatmessages.map((message, i) =>
{
const messageTime = new Date(message.time);
const picture = (message.sender === 'response' ?
message.picture : this.props.myPicture) || 'resources/images/avatar-empty.jpeg';
return (
<div className='message' key={i}>
<div className={message.sender}>
<img className='message-avatar' src={picture} />
<div className='message-content'>
<div
className='message-text'
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html : marked.parse(
message.text,
{ sanitize: true, renderer: linkRenderer }
) }}
/>
<span className='message-time'>
{message.name} - {this.getTimeString(messageTime)}
</span>
</div>
</div>
</div>
);
})
}
</When>
<Otherwise>
<div className='empty'>
<p>No one has said anything yet...</p>
</div>
</Otherwise>
</Choose>
</div>
);
}
}
MessageList.propTypes =
{
chatmessages : PropTypes.arrayOf(PropTypes.object).isRequired,
myPicture : PropTypes.string
};
const mapStateToProps = (state) =>
{
return {
chatmessages : state.chatmessages,
myPicture : state.me.picture
};
};
const MessageListContainer = compose(
connect(mapStateToProps),
scrollToBottom()
)(MessageList);
export default MessageListContainer;