Merge branch 'wordlist' of github.com:coralproject/talk into wordlist

This commit is contained in:
David Jay
2016-12-06 12:54:39 -05:00
48 changed files with 1582 additions and 595 deletions
+155 -134
View File
@@ -7,6 +7,7 @@ import {
Notification,
notificationActions,
authActions,
configActions
} from '../../coral-framework';
import CommentBox from '../../coral-plugin-commentbox/CommentBox';
@@ -21,14 +22,17 @@ 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, Spinner} from '../../coral-ui';
import SettingsContainer from '../../coral-settings/containers/SettingsContainer';
import RestrictedContent from '../../coral-framework/components/RestrictedContent';
import SuspendedAccount from '../../coral-framework/components/SuspendedAccount';
import CloseCommentsInfo from '../../coral-framework/components/CloseCommentsInfo';
const {addItem, updateItem, postItem, getStream, postAction, deleteAction, appendItemArray} = itemActions;
const {addNotification, clearNotification} = notificationActions;
const {logout} = authActions;
const {logout, showSignInDialog} = authActions;
const {updateOpenStatus} = configActions;
class CommentStream extends Component {
@@ -40,6 +44,7 @@ class CommentStream extends Component {
};
this.changeTab = this.changeTab.bind(this);
this.toggleStatus = this.toggleStatus.bind(this);
}
changeTab (tab) {
@@ -48,6 +53,10 @@ class CommentStream extends Component {
});
}
toggleStatus () {
this.props.updateStatus(this.props.config.status === 'open' ? 'closed' : 'open');
}
static propTypes = {
items: PropTypes.object.isRequired,
addItem: PropTypes.func.isRequired,
@@ -56,31 +65,22 @@ class CommentStream extends Component {
componentDidMount () {
// Set up messaging between embedded Iframe an parent component
// Using recommended Pym init code which violates .eslint standards
const pym = new Pym.Child({polling: 100});
this.pym = new Pym.Child({polling: 100});
if (/https?\:\/\/([^?]+)/.test(pym.parentUrl)) {
this.props.getStream(pym.parentUrl);
} else {
this.props.getStream(window.location);
}
const path = /https?\:\/\/([^?#]+)/.exec(this.pym.parentUrl);
this.props.getStream(path[1] || window.location);
this.path = path;
this.pym.sendMessage('childReady');
}
render () {
if (Object.keys(this.props.items).length === 0) {
// Loading mock asset
this.props.postItem({
comments: [],
url: 'http://coralproject.net'
}, 'asset', 'assetTest');
}
// TODO: Replace teststream id with id from params
const rootItemId = this.props.items.assets && Object.keys(this.props.items.assets)[0];
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 {status} = this.props.config;
const {activeTab} = this.state;
return <div className={showSignInDialog ? 'expandForSignin' : ''}>
@@ -90,131 +90,145 @@ class CommentStream extends Component {
<TabBar onChange={this.changeTab} activeTab={activeTab}>
<Tab><Count id={rootItemId} items={this.props.items}/></Tab>
<Tab>Settings</Tab>
<Tab>Configure Stream</Tab>
</TabBar>
{loggedIn && <UserBox user={user} logout={this.props.logout} />}
{loggedIn && <UserBox user={user} logout={this.props.logout} />}
{/* Add to the restricted param a boolean if the user is suspended*/}
<RestrictedContent restricted={false} restrictedComp={<SuspendedAccount />}>
<TabContent show={activeTab === 0}>
<div id="commentBox">
<InfoBox
content={this.props.config.infoBoxContent}
enable={this.props.config.infoBoxEnable}
/>
<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}
/>
{
status === 'open'
? <div id="commentBox">
<InfoBox
content={this.props.config.infoBoxContent}
enable={this.props.config.infoBoxEnable}
/>
<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}
/>
</div>
: <p>Comments are closed for this thread.</p>
}
{!loggedIn && <SignInContainer />}
</div>
{
rootItem.comments && rootItem.comments.map((commentId) => {
const comment = comments[commentId];
return <div className="comment" key={commentId} id={`c_${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
{
rootItem.comments && rootItem.comments.map((commentId) => {
const comment = comments[commentId];
return <div className="comment" key={commentId} id={`c_${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]}
showSignInDialog={this.props.showSignInDialog}
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}
showSignInDialog={this.props.showSignInDialog}
updateItem={this.props.updateItem}
currentUser={this.props.auth.user}/>
<PermalinkButton
commentId={commentId}
articleURL={this.path}/>
</div>
<ReplyBox
addNotification={this.props.addNotification}
postItem={this.props.postItem}
appendItemArray={this.props.appendItemArray}
updateItem={this.props.updateItem}
id={commentId}
id={rootItemId}
author={user}
parent_id={commentId}
premod={this.props.config.moderation}
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
commentId={commentId}
articleURL={this.path}/>
</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} id={`c_${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
{
comment.children &&
comment.children.map((replyId) => {
let reply = this.props.items.comments[replyId];
return <div className="reply" key={replyId} id={`c_${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}
showSignInDialog={this.props.showSignInDialog}
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}
showSignInDialog={this.props.showSignInDialog}
deleteAction={this.props.deleteAction}
addItem={this.props.addItem}
updateItem={this.props.updateItem}
currentUser={this.props.auth.user}/>
<PermalinkButton
commentId={reply.parent_id}
articleURL={this.path}
/>
</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
commentId={reply.parent_id}
articleURL={this.path}
/>
</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>;
})
}
</div>;
})
}
})
}
<Notification
notifLength={4500}
clearNotification={this.props.clearNotification}
notification={this.props.notification}
/>
</TabContent>
<TabContent show={activeTab === 1}>
<SettingsContainer
@@ -222,7 +236,12 @@ class CommentStream extends Component {
userData={this.props.userData}
showSignInDialog={this.props.handleSignInDialog}
/>
{!loggedIn && <SignInContainer noButton/>}
</TabContent>
<TabContent show={activeTab === 2}>
<h3>{status === 'open' ? 'Close' : 'Open'} Comment Stream</h3>
<RestrictedContent restricted={!loggedIn}>
<CloseCommentsInfo onClick={this.toggleStatus} status={status} />
</RestrictedContent>
</TabContent>
</RestrictedContent>
<Notification
@@ -232,7 +251,7 @@ class CommentStream extends Component {
/>
</div>
:
<Spinner/>
<Spinner/>
}
</div>;
}
@@ -253,11 +272,13 @@ const mapDispatchToProps = (dispatch) => ({
getStream: (rootId) => dispatch(getStream(rootId)),
addNotification: (type, text) => dispatch(addNotification(type, text)),
clearNotification: () => dispatch(clearNotification()),
showSignInDialog: () => dispatch(showSignInDialog()),
postAction: (item, action, user, itemType) => dispatch(postAction(item, action, user, itemType)),
deleteAction: (item, action, user, itemType) => dispatch(deleteAction(item, action, user, itemType)),
appendItemArray: (item, property, value, addToFront, itemType) => dispatch(appendItemArray(item, property, value, addToFront, itemType)),
handleSignInDialog: () => dispatch(authActions.showSignInDialog()),
logout: () => dispatch(logout()),
updateStatus: status => dispatch(updateOpenStatus(status))
});
export default connect(mapStateToProps, mapDispatchToProps)(CommentStream);
+43 -2
View File
@@ -56,12 +56,14 @@ hr {
/* Info Box Styles */
.coral-plugin-infobox-info {
position: fixed;
top: 0;
border: 0;
background: rgb(105,105,105);
color: white;
border-radius: 2px;
width: 100%;
text-align: center;
padding: 10px;
margin-bottom: 10px;
font-weight: bold;
display: block;
}
@@ -195,3 +197,42 @@ hr {
float: right;
margin: 8px;
}
/* Close comments */
.close-comments-intro-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
}
.close-comments-intro-wrapper button {
width: 300px;
margin-left: 20px;
}
.close-comments-intro-wrapper button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.close-comments-message {
box-sizing: border-box;
width: 100%;
height: 100px;
}
.close-comments-confirm-wrapper {
float: right;
}
.close-comments-alert {
background-color: #d65344;
color: white;
font-size: 16px;
padding: 5px;
}
.close-comments-alert i.material-icons {
font-size: 16px !important;
}
+18
View File
@@ -0,0 +1,18 @@
import coralApi from '../helpers/response';
/* Config Actions */
/**
* Action name constants
*/
export const OPEN_COMMENTS = 'OPEN_COMMENTS';
export const CLOSE_COMMENTS = 'CLOSE_COMMENTS';
export const ADD_ITEM = 'ADD_ITEM';
export const updateOpenStatus = status => (dispatch, getState) => {
const assetId = getState().items.get('assets')
.keySeq()
.toArray()[0];
return coralApi(`/asset/${assetId}/status?status=${status}`, {method: 'PUT'})
.then(() => dispatch({type: status === 'open' ? OPEN_COMMENTS : CLOSE_COMMENTS}));
};
@@ -0,0 +1,23 @@
import React from 'react';
import {Button} from 'coral-ui';
export default ({status, onClick}) => (
status === 'open' ? (
<div className="close-comments-intro-wrapper">
<p>
This comment stream is currently open. By closing this comment stream,
no new comments may be submitted and all previous comments will still
be displayed.
</p>
<Button onClick={onClick}>Close Stream</Button>
</div>
) : (
<div className="close-comments-intro-wrapper">
<p>
This comment stream is currently closed. By opening this comment stream,
new comments may be submitted and displayed
</p>
<Button onClick={onClick}>Open Stream</Button>
</div>
)
);
+2
View File
@@ -4,6 +4,7 @@ import * as itemActions from './actions/items';
import I18n from './modules/i18n/i18n';
import * as notificationActions from './actions/notification';
import * as authActions from './actions/auth';
import * as configActions from './actions/config';
export {
Notification,
@@ -12,4 +13,5 @@ export {
I18n,
notificationActions,
authActions,
configActions
};
+14 -3
View File
@@ -1,19 +1,30 @@
/* @flow */
import {Map} from 'immutable';
import * as actions from '../actions/items';
import * as actions from '../actions/config';
const initialState = Map({
features: Map({})
features: Map({}),
status: 'open'
});
export default (state = initialState, action) => {
switch(action.type) {
// Override config if worked
case actions.UPDATE_SETTINGS:
return action.config;
case actions.OPEN_COMMENTS:
return state.set('status', 'open');
case actions.CLOSE_COMMENTS:
return state.set('status', 'closed');
case actions.ADD_ITEM:
return action.item_type === 'assets' ?
state.set('status', action.item.status)
: state;
default:
return state;
}
@@ -82,6 +82,7 @@ class CommentBox extends Component {
{ author && (
<Button
cStyle='darkGrey'
className={`${name}-button`}
onClick={this.postComment}>
{lang.t('post')}
</Button>
+2 -1
View File
@@ -4,10 +4,11 @@ import translations from './translations.json';
const name = 'coral-plugin-flags';
const FlagButton = ({flag, id, postAction, deleteAction, addItem, updateItem, addNotification, currentUser}) => {
const FlagButton = ({flag, id, postAction, deleteAction, addItem, showSignInDialog, updateItem, addNotification, currentUser}) => {
const flagged = flag && flag.current_user;
const onFlagClick = () => {
if (!currentUser) {
showSignInDialog();
return;
}
if (!flagged) {
+2 -1
View File
@@ -4,10 +4,11 @@ import translations from './translations.json';
const name = 'coral-plugin-flags';
const LikeButton = ({like, id, postAction, deleteAction, addItem, updateItem, currentUser}) => {
const LikeButton = ({like, id, postAction, deleteAction, addItem, showSignInDialog, updateItem, currentUser}) => {
const liked = like && like.current_user;
const onLikeClick = () => {
if (!currentUser) {
showSignInDialog();
return;
}
if (!liked) {
@@ -44,7 +44,7 @@ const SignInContent = ({handleChange, formData, ...props}) => (
<div className={styles.action}>
{
!props.auth.isLoading ?
<Button type="submit" cStyle="black" className={styles.signInButton} full>
<Button id='coralLogInButton' type="submit" cStyle="black" className={styles.signInButton} full>
{lang.t('signIn.signIn')}
</Button>
:
@@ -56,7 +56,7 @@ const SignInContent = ({handleChange, formData, ...props}) => (
<span><a onClick={() => props.changeView('FORGOT')}>{lang.t('signIn.forgotYourPass')}</a></span>
<span>
{lang.t('signIn.needAnAccount')}
<a onClick={() => props.changeView('SIGNUP')}>
<a onClick={() => props.changeView('SIGNUP')} id='coralRegister'>
{lang.t('signIn.register')}
</a>
</span>
@@ -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} full>
<Button type="submit" cStyle="black" id='coralSignUpButton' className={styles.signInButton} full>
{lang.t('signIn.signUp')}
</Button>
)}
@@ -132,7 +132,9 @@ class SignInContainer extends Component {
const {auth, showSignInDialog, noButton} = this.props;
return (
<div>
{!noButton && <Button onClick={showSignInDialog} full> Sign in to comment</Button>}
{!noButton && <Button id='coralSignInButton' onClick={showSignInDialog} full>
Sign in to comment
</Button>}
<SignDialog
open={auth.showSignInDialog}
view={auth.view}