Merge pull request #101 from coralproject/bio

Settings Structure and Coral UI Components
This commit is contained in:
Riley Davis
2016-11-29 10:41:40 -07:00
committed by GitHub
25 changed files with 444 additions and 145 deletions
+156 -127
View File
@@ -3,7 +3,7 @@ import {
itemActions,
Notification,
notificationActions,
authActions
authActions,
} from '../../coral-framework';
import {connect} from 'react-redux';
import CommentBox from '../../coral-plugin-commentbox/CommentBox';
@@ -19,6 +19,8 @@ import LikeButton from '../../coral-plugin-likes/LikeButton';
import PermalinkButton from '../../coral-plugin-permalinks/PermalinkButton';
import SignInContainer from '../../coral-sign-in/containers/SignInContainer';
import UserBox from '../../coral-sign-in/components/UserBox';
import {TabBar, Tab, TabContent} from '../../coral-ui';
import SettingsContainer from '../../coral-settings/containers/SettingsContainer';
const {addItem, updateItem, postItem, getStream, postAction, deleteAction, appendItemArray} = itemActions;
const {addNotification, clearNotification} = notificationActions;
@@ -46,11 +48,27 @@ const mapDispatchToProps = (dispatch) => ({
},
appendItemArray: (item, property, value, addToFront, itemType) =>
dispatch(appendItemArray(item, property, value, addToFront, itemType)),
logout: () => dispatch(logout())
logout: () => dispatch(logout()),
});
class CommentStream extends Component {
constructor (props) {
super(props);
this.state = {
activeTab: 0
};
this.changeTab = this.changeTab.bind(this);
}
changeTab (tab) {
this.setState({
activeTab: tab
});
}
static propTypes = {
items: PropTypes.object.isRequired,
addItem: PropTypes.func.isRequired,
@@ -90,137 +108,148 @@ class CommentStream extends Component {
const rootItem = this.props.items.assets && this.props.items.assets[rootItemId];
const {actions, users, comments} = this.props.items;
const {loggedIn, user, showSignInDialog} = this.props.auth;
const {activeTab} = this.state;
return <div className={showSignInDialog ? 'expandForSignin' : ''}>
{
rootItem
? <div>
<div id="commentBox">
<InfoBox
content={this.props.config.infoBoxContent}
enable={this.props.config.infoBoxEnable}/>
<Count
id={rootItemId}
items={this.props.items}/>
{loggedIn && <UserBox user={user} logout={this.props.logout} />}
<CommentBox
addNotification={this.props.addNotification}
postItem={this.props.postItem}
appendItemArray={this.props.appendItemArray}
updateItem={this.props.updateItem}
id={rootItemId}
premod={this.props.config.moderation}
reply={false}
author={user}
/>
{!loggedIn && <SignInContainer />}
</div>
{
rootItem.comments && rootItem.comments.map((commentId) => {
const comment = comments[commentId];
return <div className="comment" key={commentId}>
<hr aria-hidden={true}/>
<AuthorName author={users[comment.author_id]}/>
<PubDate created_at={comment.created_at}/>
<Content body={comment.body}/>
<div className="commentActionsLeft">
<ReplyButton
updateItem={this.props.updateItem}
id={commentId}
showReply={comment.showReply}/>
<LikeButton
addNotification={this.props.addNotification}
id={commentId}
like={actions[comment.like]}
postAction={this.props.postAction}
deleteAction={this.props.deleteAction}
addItem={this.props.addItem}
updateItem={this.props.updateItem}
currentUser={this.props.auth.user}/>
</div>
<div className="commentActionsRight">
<FlagButton
addNotification={this.props.addNotification}
id={commentId}
flag={actions[comment.flag]}
postAction={this.props.postAction}
deleteAction={this.props.deleteAction}
addItem={this.props.addItem}
updateItem={this.props.updateItem}
currentUser={this.props.auth.user}/>
<PermalinkButton
comment_id={commentId}
asset_id={comment.asset_id}/>
</div>
<ReplyBox
addNotification={this.props.addNotification}
postItem={this.props.postItem}
appendItemArray={this.props.appendItemArray}
updateItem={this.props.updateItem}
id={rootItemId}
author={user}
parent_id={commentId}
premod={this.props.config.moderation}
showReply={comment.showReply}/>
{
comment.children &&
comment.children.map((replyId) => {
let reply = this.props.items.comments[replyId];
return <div className="reply" key={replyId}>
<hr aria-hidden={true}/>
<AuthorName author={users[reply.author_id]}/>
<PubDate created_at={reply.created_at}/>
<Content body={reply.body}/>
<div className="replyActionsLeft">
<ReplyButton
<TabBar onChange={this.changeTab} activeTab={activeTab}>
<Tab><Count id={rootItemId} items={this.props.items}/></Tab>
<Tab>Settings</Tab>
</TabBar>
<TabContent show={activeTab === 0}>
<div id="commentBox">
<InfoBox
content={this.props.config.infoBoxContent}
enable={this.props.config.infoBoxEnable}
/>
{loggedIn && <UserBox user={user} logout={this.props.logout} />}
<CommentBox
addNotification={this.props.addNotification}
postItem={this.props.postItem}
appendItemArray={this.props.appendItemArray}
updateItem={this.props.updateItem}
id={rootItemId}
premod={this.props.config.moderation}
reply={false}
author={user}
/>
{!loggedIn && <SignInContainer />}
</div>
{
rootItem.comments && rootItem.comments.map((commentId) => {
const comment = comments[commentId];
return <div className="comment" key={commentId}>
<hr aria-hidden={true}/>
<AuthorName author={users[comment.author_id]}/>
<PubDate created_at={comment.created_at}/>
<Content body={comment.body}/>
<div className="commentActionsLeft">
<ReplyButton
updateItem={this.props.updateItem}
id={commentId}
showReply={comment.showReply}/>
<LikeButton
addNotification={this.props.addNotification}
id={commentId}
like={actions[comment.like]}
postAction={this.props.postAction}
deleteAction={this.props.deleteAction}
addItem={this.props.addItem}
updateItem={this.props.updateItem}
currentUser={this.props.auth.user}/>
</div>
<div className="commentActionsRight">
<FlagButton
addNotification={this.props.addNotification}
id={commentId}
flag={actions[comment.flag]}
postAction={this.props.postAction}
deleteAction={this.props.deleteAction}
addItem={this.props.addItem}
updateItem={this.props.updateItem}
currentUser={this.props.auth.user}/>
<PermalinkButton
comment_id={commentId}
asset_id={comment.asset_id}/>
</div>
<ReplyBox
addNotification={this.props.addNotification}
postItem={this.props.postItem}
appendItemArray={this.props.appendItemArray}
updateItem={this.props.updateItem}
id={rootItemId}
author={user}
parent_id={commentId}
premod={this.props.config.moderation}
showReply={comment.showReply}/>
{
comment.children &&
comment.children.map((replyId) => {
let reply = this.props.items.comments[replyId];
return <div className="reply" key={replyId}>
<hr aria-hidden={true}/>
<AuthorName author={users[reply.author_id]}/>
<PubDate created_at={reply.created_at}/>
<Content body={reply.body}/>
<div className="replyActionsLeft">
<ReplyButton
updateItem={this.props.updateItem}
id={replyId}
showReply={reply.showReply}/>
<LikeButton
addNotification={this.props.addNotification}
id={replyId}
like={this.props.items.actions[reply.like]}
postAction={this.props.postAction}
deleteAction={this.props.deleteAction}
addItem={this.props.addItem}
updateItem={this.props.updateItem}
currentUser={this.props.auth.user}/>
</div>
<div className="replyActionsRight">
<FlagButton
addNotification={this.props.addNotification}
id={replyId}
flag={this.props.items.actions[reply.flag]}
postAction={this.props.postAction}
deleteAction={this.props.deleteAction}
addItem={this.props.addItem}
updateItem={this.props.updateItem}
currentUser={this.props.auth.user}/>
<PermalinkButton
comment_id={reply.parent_id}
asset_id={rootItemId}
/>
</div>
<ReplyBox
addNotification={this.props.addNotification}
postItem={this.props.postItem}
appendItemArray={this.props.appendItemArray}
updateItem={this.props.updateItem}
id={replyId}
id={rootItemId}
author={user}
parent_id={commentId}
child_id={replyId}
premod={this.props.config.moderation}
showReply={reply.showReply}/>
<LikeButton
addNotification={this.props.addNotification}
id={replyId}
like={this.props.items.actions[reply.like]}
postAction={this.props.postAction}
deleteAction={this.props.deleteAction}
addItem={this.props.addItem}
updateItem={this.props.updateItem}
currentUser={this.props.auth.user}/>
</div>
<div className="replyActionsRight">
<FlagButton
addNotification={this.props.addNotification}
id={replyId}
flag={this.props.items.actions[reply.flag]}
postAction={this.props.postAction}
deleteAction={this.props.deleteAction}
addItem={this.props.addItem}
updateItem={this.props.updateItem}
currentUser={this.props.auth.user}/>
<PermalinkButton
comment_id={reply.parent_id}
asset_id={rootItemId}
/>
</div>
<ReplyBox
addNotification={this.props.addNotification}
postItem={this.props.postItem}
appendItemArray={this.props.appendItemArray}
updateItem={this.props.updateItem}
id={rootItemId}
author={user}
parent_id={commentId}
child_id={replyId}
premod={this.props.config.moderation}
showReply={reply.showReply}/>
</div>;
})
}
</div>;
})
}
<Notification
notifLength={4500}
clearNotification={this.props.clearNotification}
notification={this.props.notification}/>
</div>;
})
}
</div>;
})
}
<Notification
notifLength={4500}
clearNotification={this.props.clearNotification}
notification={this.props.notification}
/>
</TabContent>
<TabContent show={activeTab === 1}>
<SettingsContainer/>
</TabContent>
</div>
: 'Loading'
}
@@ -154,11 +154,6 @@ hr {
color: #F00;
}
/* Comment count styles */
.coral-plugin-comment-count-text {
margin-bottom: 15px;
}
.coral-plugin-pubdate-text {
color: #CCC;
display: inline-block;
+1 -1
View File
@@ -11,5 +11,5 @@ export {
itemActions,
I18n,
notificationActions,
authActions
authActions,
};
+1 -1
View File
@@ -14,5 +14,5 @@ export default combineReducers({
config,
items,
notification,
auth
auth,
});
+21
View File
@@ -0,0 +1,21 @@
.bio textarea {
width: 100%;
box-sizing: border-box;
border-radius: 2px;
min-height: 100px;
margin: 10px 0;
border: solid 1px #d8d8d8;
}
.bio h1 {
font-size: 16px;
margin: 3px 0;
}
.bio p {
margin: 3px 0;
}
.actions {
text-align: right;
}
+16
View File
@@ -0,0 +1,16 @@
import React from 'react';
import styles from './Bio.css';
import {Button} from '../../coral-ui';
export default () => (
<div className={styles.bio}>
<h1>Bio</h1>
<p>Tell the community about yourself</p>
<textarea />
<div className={styles.actions}>
<Button cStyle='cancel' raised>Cancel</Button>
<Button cStyle='success'>Save Changes</Button>
</div>
</div>
);
@@ -0,0 +1,15 @@
import React from 'react';
import styles from './CommentHistory.css';
export default ({comments = []}) => (
<div className={styles.header}>
<h1>Comments</h1>
<ul>
{comments.map(() => (
<li>
{/* Comment Data*/}
</li>
))}
</ul>
</div>
);
@@ -0,0 +1,8 @@
.header h1 {
margin: 4px 0;
}
.header h2 {
font-size: 13px;
}
@@ -0,0 +1,10 @@
import React from 'react';
import styles from './SettingsHeader.css';
export default () => (
<div className={styles.header}>
<h1>Jackson</h1>
<h2>jackson_persona@gmail.com</h2>
</div>
);
@@ -0,0 +1,61 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {TabBar, Tab} from '../../coral-ui';
import Bio from '../components/Bio';
import CommentHistory from '../components/CommentHistory';
import SettingsHeader from '../components/SettingsHeader';
class SignInContainer extends Component {
constructor (props) {
super(props);
this.state = {
activeTab: 0
};
this.handleTabChange = this.handleTabChange.bind(this);
}
componentWillMount () {
// Get Bio
// Fetch commentHistory
}
handleTabChange(tab) {
this.setState({
activeTab: tab
});
}
render() {
//const {embedStream} = this.props;
const {activeTab} = this.state;
return (
<div>
<SettingsHeader />
<TabBar onChange={this.handleTabChange} activeTab={activeTab} cStyle='material'>
<Tab>All Comments (120)</Tab>
<Tab>Profile Settings</Tab>
</TabBar>
{ activeTab === 0 && <CommentHistory {...this.props}/> }
{ activeTab === 1 && <Bio {...this.props}/> }
</div>
);
}
}
const mapStateToProps = () => ({
});
const mapDispatchToProps = dispatch => ({
getBio: () => dispatch(),
getHistory: () => dispatch(),
handleSaveChanges: () => dispatch(),
handleCancel: () => dispatch()
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(SignInContainer);
View File
@@ -34,7 +34,7 @@ class ForgotContent extends React.Component {
id="email"
name="email" />
</div>
<Button type="submit" cStyle="black" className={styles.signInButton}>
<Button type="submit" cStyle="black" className={styles.signInButton} full>
{lang.t('signIn.recoverPassword')}
</Button>
{
@@ -16,7 +16,7 @@ const SignInContent = ({handleChange, formData, ...props}) => (
</h1>
</div>
<div className={styles.socialConnections}>
<Button cStyle="facebook" onClick={props.fetchSignInFacebook}>
<Button cStyle="facebook" onClick={props.fetchSignInFacebook} full>
{lang.t('signIn.facebookSignIn')}
</Button>
</div>
@@ -44,7 +44,7 @@ const SignInContent = ({handleChange, formData, ...props}) => (
<div className={styles.action}>
{
!props.auth.isLoading ?
<Button type="submit" cStyle="black" className={styles.signInButton}>
<Button type="submit" cStyle="black" className={styles.signInButton} full>
{lang.t('signIn.signIn')}
</Button>
:
@@ -17,7 +17,7 @@ const SignUpContent = ({handleChange, formData, ...props}) => (
</h1>
</div>
<div className={styles.socialConnections}>
<Button cStyle="facebook" onClick={props.fetchSignInFacebook}>
<Button cStyle="facebook" onClick={props.fetchSignInFacebook} full>
{lang.t('signIn.facebookSignUp')}
</Button>
</div>
@@ -69,7 +69,7 @@ const SignUpContent = ({handleChange, formData, ...props}) => (
/>
<div className={styles.action}>
{ !props.auth.isLoading && !props.auth.successSignUp && (
<Button type="submit" cStyle="black" className={styles.signInButton}>
<Button type="submit" cStyle="black" className={styles.signInButton} full>
{lang.t('signIn.signUp')}
</Button>
)}
@@ -132,7 +132,7 @@ class SignInContainer extends Component {
const {auth, showSignInDialog} = this.props;
return (
<div>
<Button onClick={showSignInDialog}>
<Button onClick={showSignInDialog} full>
Sign in to comment
</Button>
<SignDialog
+32 -3
View File
@@ -23,8 +23,7 @@
text-align: center;
line-height: 36px;
vertical-align: middle;
width: 100%;
margin: 0;
margin: 2px;
}
.type--black {
@@ -46,4 +45,34 @@
.type--facebook:hover {
background-color: #365899;
border-color: #365899;
}
}
.type--success {
color: white;
background: #2376d8;
}
.type--success:hover {
color: white;
background: #2782ee;
}
.type--cancel {
color: white;
background: #2E343B;
}
.type--cancel:hover {
color: white;
background: #4f5c67;
}
.full {
width: 100%;
margin: 0;
}
.raised {
background: rgba(158,158,158,.2);
box-shadow: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);
}
+8 -2
View File
@@ -1,9 +1,15 @@
import React from 'react';
import styles from './Button.css';
const Button = ({cStyle = 'local', children, className, ...props}) => (
const Button = ({cStyle = 'local', children, className, raised, full, ...props}) => (
<button
className={`${styles.button} ${styles[`type--${cStyle}`]} ${className}`}
className={`
${styles.button}
${styles[`type--${cStyle}`]}
${className}
${full && styles.full}
${raised && styles.button}
`}
{...props}
>
{children}
+8
View File
@@ -0,0 +1,8 @@
li.base--active {
background: white;
}
li.material--active {
font-weight: bold;
border-bottom: solid 2px black;
}
+13
View File
@@ -0,0 +1,13 @@
import React from 'react';
import styles from './Tab.css';
export default ({children, tabId, active, onTabClick, cStyle = 'base'}) => (
<li
key={tabId}
className={active ? styles[`${cStyle}--active`] : ''}
onClick={() => onTabClick(tabId)}
>
{children}
</li>
);
+43
View File
@@ -0,0 +1,43 @@
.base {
list-style: none;
border-bottom: solid 1px #D8D8D8;
padding: 0;
}
.base li {
color: #4E5259;
border: solid 1px #D8D8D8;
background: #F0F0F0;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
display: inline-block;
border-bottom: none;
padding: 8px 10px;
margin-right: -1px;
user-select: none;
}
.base li:hover {
background: #f3f3f3;
cursor: pointer;
}
.material {
list-style: none;
border: none;
padding: 0;
}
.material li {
color: black;
border: none;
border-bottom: solid 2px white;
background: white;
padding: 8px 0;
margin-right: 40px;
}
.material li:hover {
background: white;
border-bottom: solid 2px grey;
}
+35
View File
@@ -0,0 +1,35 @@
import React from 'react';
import styles from './TabBar.css';
export class TabBar extends React.Component {
constructor(props) {
super(props);
this.handleClickTab = this.handleClickTab.bind(this);
}
handleClickTab(tabId) {
if (this.props.onChange) {
this.props.onChange(tabId);
}
}
render() {
const {children, activeTab, cStyle = 'base'} = this.props;
return (
<div>
<ul className={`${styles.base} ${cStyle ? styles[cStyle] : ''}`}>
{React.Children.map(children, (child, tabId) =>
React.cloneElement(child, {
tabId,
active: tabId === activeTab,
onTabClick: this.handleClickTab,
cStyle
})
)}
</ul>
</div>
);
}
}
export default TabBar;
+6
View File
@@ -0,0 +1,6 @@
import React from 'react';
export default ({children, show = true}) => (
show ? <div>{children}</div> : null
);
+4
View File
@@ -1,3 +1,7 @@
export {default as Dialog} from './components/Dialog';
export {default as CoralLogo} from './components/CoralLogo';
export {default as FabButton} from './components/FabButton';
export {default as TabBar} from './components/TabBar';
export {default as Tab} from './components/Tab';
export {default as TabContent} from './components/TabContent';
export {default as Button} from './components/Button';