Merge branch 'master' into update-on-post-comment

This commit is contained in:
Belén Curcio
2017-02-16 13:36:39 -03:00
committed by GitHub
29 changed files with 210 additions and 83 deletions
@@ -22,17 +22,17 @@
}
}
.formField {
.textField {
margin-top: 15px;
}
.formField label {
.textField label {
font-size: 1.08em;
font-weight: bold;
margin-bottom: 5px;
}
.formField input {
.textField input {
width: 100%;
display: block;
border: none;
@@ -1,6 +1,6 @@
import React from 'react';
import styles from './style.css';
import {FormField, Button} from 'coral-ui';
import {TextField, Button} from 'coral-ui';
const AddOrganizationName = props => {
const {handleSettingsChange, handleSettingsSubmit, install} = props;
@@ -12,8 +12,8 @@ const AddOrganizationName = props => {
</p>
<div className={styles.form}>
<form onSubmit={handleSettingsSubmit}>
<FormField
className={styles.FormField}
<TextField
className={styles.TextField}
id="organizationName"
type="text"
label='Organization name'
@@ -1,6 +1,6 @@
import React from 'react';
import styles from './style.css';
import {FormField, Button, Spinner} from 'coral-ui';
import {TextField, Button, Spinner} from 'coral-ui';
const InitialStep = props => {
const {handleUserChange, handleUserSubmit, install} = props;
@@ -8,8 +8,8 @@ const InitialStep = props => {
<div className={styles.step}>
<div className={styles.form}>
<form onSubmit={handleUserSubmit}>
<FormField
className={styles.formField}
<TextField
className={styles.textField}
id="email"
type="email"
label='Email address'
@@ -19,8 +19,8 @@ const InitialStep = props => {
noValidate
/>
<FormField
className={styles.formField}
<TextField
className={styles.textField}
id="username"
type="text"
label='Username'
@@ -29,8 +29,8 @@ const InitialStep = props => {
errorMsg={install.errors.username}
/>
<FormField
className={styles.formField}
<TextField
className={styles.textField}
id="password"
type="password"
label='Password'
@@ -39,8 +39,8 @@ const InitialStep = props => {
errorMsg={install.errors.password}
/>
<FormField
className={styles.formField}
<TextField
className={styles.textField}
id="confirmPassword"
type="password"
label='Confirm Password'
@@ -1,6 +1,6 @@
import React from 'react';
import styles from './style.css';
import {Button, Select, Option, FormField} from 'coral-ui';
import {Button, Select, Option, TextField} from 'coral-ui';
const InviteTeamMembers = props => {
const {nextStep} = props;
@@ -14,19 +14,19 @@ const InviteTeamMembers = props => {
<div className={styles.form}>
<form>
<FormField
className={styles.formField}
<TextField
className={styles.textField}
id="email"
type="email"
label='Email address' required/>
<FormField
className={styles.formField}
<TextField
className={styles.textField}
id="username"
type="text"
label='Username' required/>
<div className={styles.formField}>
<div className={styles.textField}>
<label htmlFor='role'>Assing a role</label>
<Select id='role' label='Select Role'>
<Option>Admin</Option>
@@ -33,7 +33,7 @@
margin: 30px 0;
}
.formField {
.textField {
text-align: left;
label {
@@ -35,3 +35,7 @@ p {
.wrapper {
margin-bottom: 20px;
}
.hidden {
display: none;
}
@@ -1,12 +1,13 @@
import React from 'react';
import {Button, Checkbox} from 'coral-ui';
import {Button, Checkbox, TextField} from 'coral-ui';
import styles from './ConfigureCommentStream.css';
import I18n from 'coral-framework/modules/i18n/i18n';
import translations from '../translations.json';
const lang = new I18n(translations);
export default ({handleChange, handleApply, changed, ...props}) => (
export default ({handleChange, handleApply, changed, updateQuestionBoxContent, ...props}) => (
<form onSubmit={handleApply}>
<div className={styles.wrapper}>
<div className={styles.container}>
@@ -32,25 +33,31 @@ export default ({handleChange, handleApply, changed, ...props}) => (
title: lang.t('configureCommentStream.enablePremod'),
description: lang.t('configureCommentStream.enablePremodDescription')
}} />
{/* To be implimented
<ul>
<li>
<Checkbox
className={styles.checkbox}
cStyle={changed ? 'green' : 'darkGrey'}
name="premodLinks"
onChange={handleChange}
defaultChecked={props.premodLinks}
info={{
title: lang.t('configureCommentStream.enablePremodLinks'),
description: lang.t('configureCommentStream.enablePremodDescription')
}} />
</li>
</ul>
*/}
</li>
<li>
<Checkbox
className={styles.checkbox}
cStyle={changed ? 'green' : 'darkGrey'}
name="qboxenable"
onChange={handleChange}
defaultChecked={props.questionBoxEnable}
info={{
title: lang.t('configureCommentStream.enableQuestionBox'),
description: lang.t('configureCommentStream.enableQuestionBoxDescription')
}} />
<div className={`${props.questionBoxEnable ? null : styles.hidden}`} >
<TextField
id="qboxcontent"
onChange={updateQuestionBoxContent}
rows={3}
value={props.questionBoxContent}
label={lang.t('configureCommentStream.includeQuestionHere')}
/>
</div>
</li>
</ul>
</div>
</form>
);
@@ -21,18 +21,23 @@ class ConfigureStreamContainer extends Component {
this.toggleStatus = this.toggleStatus.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleApply = this.handleApply.bind(this);
this.updateQuestionBoxContent = this.updateQuestionBoxContent.bind(this);
}
handleApply (e) {
e.preventDefault();
const {elements} = e.target;
const premod = elements.premod.checked;
const questionBoxEnable = elements.qboxenable.checked;
const questionBoxContent = elements.qboxcontent.value;
// const premodLinks = elements.premodLinks.checked;
const {changed} = this.state;
const newConfig = {
moderation: premod ? 'PRE' : 'POST'
moderation: premod ? 'PRE' : 'POST',
questionBoxEnable,
questionBoxContent
};
if (changed) {
@@ -45,12 +50,20 @@ class ConfigureStreamContainer extends Component {
}
}
handleChange () {
handleChange (e) {
if (e.target && e.target.id === 'qboxenable') {
this.props.asset.settings.questionBoxEnable = e.target.checked;
}
this.setState({
changed: true
});
}
updateQuestionBoxContent(e) {
this.props.asset.settings.questionBoxContent = e.target.value;
this.handleChange(e);
}
toggleStatus () {
this.props.updateStatus(
this.props.asset.closedAt === null ? 'closed' : 'open'
@@ -66,6 +79,8 @@ class ConfigureStreamContainer extends Component {
render () {
const status = this.props.asset.closedAt === null ? 'open' : 'closed';
const premod = this.props.asset.settings.moderation === 'PRE';
const questionBoxEnable = this.props.asset.settings.questionBoxEnable;
const questionBoxContent = this.props.asset.settings.questionBoxContent;
return (
<div>
@@ -75,6 +90,9 @@ class ConfigureStreamContainer extends Component {
changed={this.state.changed}
premodLinks={false}
premod={premod}
updateQuestionBoxContent={this.updateQuestionBoxContent}
questionBoxEnable={questionBoxEnable}
questionBoxContent={questionBoxContent}
/>
<hr />
<h3>{status === 'open' ? 'Close' : 'Open'} Comment Stream</h3>
@@ -94,7 +112,7 @@ const mapStateToProps = (state) => ({
const mapDispatchToProps = dispatch => ({
updateStatus: status => dispatch(updateOpenStatus(status)),
updateConfiguration: newConfig => dispatch(updateConfiguration(newConfig))
updateConfiguration: newConfig => dispatch(updateConfiguration(newConfig)),
});
export default compose(
+10 -4
View File
@@ -7,18 +7,24 @@
"enablePremod": "Enable Premoderation",
"enablePremodDescription": "Moderators must approve any comment before its published.",
"enablePremodLinks": "Pre-Moderate Comments Containing Links",
"enablePremodLinksDescription": "Moderators must approve any comment containing a link before its published."
"enablePremodLinksDescription": "Moderators must approve any comment containing a link before its published.",
"enableQuestionBox": "Ask readers a question",
"enableQuestionBoxDescription": "This question will appear at the top of this comment stram. Ask readers about a certain issue in the article or pose discussion questions, etc.",
"includeQuestionHere": "Write your question here."
}
},
"es": {
"configureCommentStream": {
"apply": "Aplicar",
"title": "Configurar los comentarios",
"description": "Como Administrador puedes modificar las opciones de los comentarios en este artículo",
"description": "Como Administrador/a puedes modificar las opciones de los comentarios en este artículo",
"enablePremod": "Activar Pre Moderación",
"enablePremodDescription": "Los Moderadores deben aprobar cualquier comentario antes de su publicación",
"enablePremodDescription": "Los y las Moderadoras deben aprobar cualquier comentario antes de su publicación",
"enablePremodLinks": "Pre-Moderar Commentarios que contienen Links",
"enablePremodLinksDescription": "Los Moderadores deben probar cualquier comentario que contengan links antes de su publicación."
"enablePremodLinksDescription": "Los y las Moderadoras deben probar cualquier comentario que contengan links antes de su publicación.",
"enableQuestionBox": "Hacer una pregunta a los y las lectoras.",
"enableQuestionBoxDescription": "Esta pregunta aparecera en la parte de arriba del hilo de comentarios.",
"includeQuestionHere": "Escribir la pregunta aquí."
}
}
}
+13
View File
@@ -17,6 +17,7 @@ import PubDate from 'coral-plugin-pubdate/PubDate';
import {ReplyBox, ReplyButton} from 'coral-plugin-replies';
import FlagComment from 'coral-plugin-flags/FlagComment';
import LikeButton from 'coral-plugin-likes/LikeButton';
import LoadMore from 'coral-embed-stream/src/LoadMore';
import styles from './Comment.css';
@@ -89,6 +90,7 @@ class Comment extends React.Component {
showSignInDialog,
postLike,
postFlag,
loadMore,
setActiveReplyBox,
activeReplyBox,
deleteAction
@@ -171,6 +173,17 @@ class Comment extends React.Component {
comment={reply} />;
})
}
{
comment.replies &&
<div className='coral-load-more-replies'>
<LoadMore
id={asset.id}
comments={comment.replies}
parentId={comment.id}
moreComments={comment.replyCount > comment.replies.length}
loadMore={loadMore}/>
</div>
}
</div>
);
}
+6
View File
@@ -16,6 +16,7 @@ import {Notification, notificationActions, authActions, assetActions, pym} from
import Stream from './Stream';
import InfoBox from 'coral-plugin-infobox/InfoBox';
import QuestionBox from 'coral-plugin-questionbox/QuestionBox';
import {ModerationLink} from 'coral-plugin-moderation';
import Count from 'coral-plugin-comment-count/CommentCount';
import CommentBox from 'coral-plugin-commentbox/CommentBox';
@@ -114,6 +115,10 @@ class Embed extends Component {
content={asset.settings.infoBoxContent}
enable={asset.settings.infoBoxEnable}
/>
<QuestionBox
content={asset.settings.questionBoxContent}
enable={asset.settings.questionBoxEnable}
/>
<RestrictedContent restricted={banned} restrictedComp={
<SuspendedAccount
canEditName={user && user.canEditName}
@@ -150,6 +155,7 @@ class Embed extends Component {
currentUser={user}
postLike={this.props.postLike}
postFlag={this.props.postFlag}
loadMore={this.props.loadMore}
deleteAction={this.props.deleteAction}
showSignInDialog={this.props.showSignInDialog}
comments={asset.comments} />
+12 -6
View File
@@ -1,28 +1,34 @@
import React, {PropTypes} from 'react';
import I18n from 'coral-framework/modules/i18n/i18n';
import translations from 'coral-framework/translations.json';
import {ADDTL_COMMENTS_ON_LOAD_MORE} from 'coral-framework/constants/comments';
import {Button} from 'coral-ui';
const lang = new I18n(translations);
const loadMoreComments = (assetId, comments, loadMore) => {
const loadMoreComments = (assetId, comments, loadMore, parentId) => {
if (!comments.length) {
return;
}
const cursor = parentId
? comments[1].created_at
: comments[comments.length - 1].created_at;
loadMore({
limit: 10,
cursor: comments[comments.length - 1].created_at,
limit: ADDTL_COMMENTS_ON_LOAD_MORE,
cursor,
assetId,
sort: 'REVERSE_CHRONOLOGICAL'
parent_id: parentId,
sort: parentId ? 'CHRONOLOGICAL' : 'REVERSE_CHRONOLOGICAL'
});
};
const LoadMore = ({assetId, comments, loadMore, moreComments}) => (
const LoadMore = ({assetId, comments, loadMore, moreComments, parentId}) => (
moreComments
? <Button
className='coral-load-more'
onClick={() => loadMoreComments(assetId, comments, loadMore)}>
onClick={() => loadMoreComments(assetId, comments, loadMore, parentId)}>
{
lang.t('loadMore')
}
+2
View File
@@ -39,6 +39,7 @@ class Stream extends React.Component {
addNotification,
postFlag,
postLike,
loadMore,
deleteAction,
showSignInDialog,
refetch
@@ -59,6 +60,7 @@ class Stream extends React.Component {
currentUser={currentUser}
postLike={postLike}
postFlag={postFlag}
loadMore={loadMore}
deleteAction={deleteAction}
showSignInDialog={showSignInDialog}
key={comment.id}
+26 -1
View File
@@ -62,7 +62,7 @@ hr {
.coral-plugin-infobox-info {
top: 0;
border: 0;
background: rgb(105,105,105);
background: rgb(35,118,216);
color: white;
width: 100%;
text-align: center;
@@ -72,6 +72,21 @@ hr {
display: block;
}
/* Question Box Styles */
.coral-plugin-questionbox-info {
top: 0;
border: 0;
background: rgb(105,105,105);
color: white;
width: 100%;
text-align: center;
padding: 10px;
margin-bottom: 0px;
font-weight: bold;
display: block;
}
.hidden {
visibility: hidden;
display: none;
@@ -317,3 +332,13 @@ button.coral-load-more {
button.coral-load-more:hover {
background-color: #4399FF;
}
.coral-load-more-replies {
width: 100%;
display: flex;
justify-content: center;
}
.coral-load-more-replies button.coral-load-more {
width: initial;
}
@@ -0,0 +1 @@
export const ADDTL_COMMENTS_ON_LOAD_MORE = 10;
@@ -35,13 +35,28 @@ export const queryStream = graphql(STREAM_QUERY, {
asset_id,
sort
},
updateQuery: (oldData, {fetchMoreResult:{data:{new_top_level_comments}}}) => ({
...oldData,
asset: {
...oldData.asset,
comments: [...oldData.asset.comments, ...new_top_level_comments]
updateQuery: (oldData, {fetchMoreResult:{data:{new_top_level_comments}}}) =>
// If loading more replies
parent_id ? {
...oldData,
asset: {
...oldData.asset,
comments: oldData.asset.comments.map((comment) =>
comment.id === parent_id
? {...comment, replies: [...comment.replies, ...new_top_level_comments]}
: comment)
}
}
// If loading more top-level comments
: {
...oldData,
asset: {
...oldData.asset,
comments: [...oldData.asset.comments, ...new_top_level_comments]
}
}
})
});
}
})
@@ -3,6 +3,7 @@
query LoadMoreComments($limit: Int = 5, $cursor: Date, $parent_id: ID, $asset_id: ID, $sort: SORT_ORDER) {
new_top_level_comments: comments(query: {limit: $limit, cursor: $cursor, parent_id: $parent_id, asset_id: $asset_id, sort: $sort}) {
...commentView
replyCount
replies(limit: 3) {
...commentView
}
@@ -11,6 +11,8 @@ query AssetQuery($asset_url: String!) {
moderation
infoBoxEnable
infoBoxContent
questionBoxEnable
questionBoxContent
closeTimeout
closedMessage
charCountEnable
@@ -20,6 +22,7 @@ query AssetQuery($asset_url: String!) {
commentCount
comments(limit: 10) {
...commentView
replyCount
replies(limit: 3) {
...commentView
}
@@ -0,0 +1,10 @@
import React from 'react';
const packagename = 'coral-plugin-questionbox';
const QuestionBox = ({enable, content}) =>
<div
className={`${packagename}-info ${enable ? null : 'hidden'}` }>
{content}
</div>;
export default QuestionBox;
+1 -1
View File
@@ -50,7 +50,7 @@ class Stream extends Component {
}
}
// Initialize GraphQL queries or mutations with the `gql` tag
// Initialize GraphQL queries or mutations with the gql tag
const StreamQuery = gql`fragment commentView on Comment {
id
body
@@ -1,5 +1,5 @@
import React from 'react';
import FormField from 'coral-ui/components/FormField';
import TextField from 'coral-ui/components/TextField';
import Alert from './Alert';
import Button from 'coral-ui/components/Button';
import {Dialog} from 'coral-ui';
@@ -28,7 +28,7 @@ const CreateDisplayNameDialog = ({open, handleClose, offset, formData, handleSub
<label htmlFor="username">{lang.t('createdisplay.yourusername')}</label>
{ props.auth.error && <Alert>{props.auth.error}</Alert> }
<form id="saveDisplayName" onSubmit={handleSubmitDisplayName}>
<FormField
<TextField
id="username"
type="string"
label={lang.t('createdisplay.username')}
@@ -26,7 +26,7 @@ class ForgotContent extends React.Component {
<h1>{lang.t('signIn.recoverPassword')}</h1>
</div>
<form onSubmit={this.handleSubmit}>
<div className={styles.formField}>
<div className={styles.textField}>
<label htmlFor="email">{lang.t('signIn.email')}</label>
<input
ref={input => this.emailInput = input}
@@ -1,6 +1,6 @@
import React, {PropTypes} from 'react';
import Alert from './Alert';
import {Button, FormField, Spinner, Success} from 'coral-ui';
import {Button, TextField, Spinner, Success} from 'coral-ui';
import styles from './styles.css';
import I18n from 'coral-framework/modules/i18n/i18n';
import translations from '../translations';
@@ -32,7 +32,7 @@ const SignInContent = ({
auth.emailVerificationFailure
? <form onSubmit={handleResendVerification}>
<p>{lang.t('signIn.requestNewVerifyEmail')}</p>
<FormField
<TextField
id="confirm-email"
type="email"
label={lang.t('signIn.email')}
@@ -54,14 +54,14 @@ const SignInContent = ({
</h1>
</div>
<form onSubmit={handleSignIn}>
<FormField
<TextField
id="email"
type="email"
label={lang.t('signIn.email')}
value={formData.email}
onChange={handleChange}
/>
<FormField
<TextField
id="password"
type="password"
label={lang.t('signIn.password')}
@@ -1,6 +1,6 @@
import React, {PropTypes} from 'react';
import Alert from './Alert';
import {Button, FormField, Spinner, Success} from 'coral-ui';
import {Button, TextField, Spinner, Success} from 'coral-ui';
import styles from './styles.css';
import I18n from 'coral-framework/modules/i18n/i18n';
import translations from '../translations';
@@ -79,7 +79,7 @@ class SignUpContent extends React.Component {
</h1>
</div>
<form onSubmit={handleSignUp}>
<FormField
<TextField
id="email"
type="email"
label={lang.t('signIn.email')}
@@ -88,7 +88,7 @@ class SignUpContent extends React.Component {
errorMsg={errors.email}
onChange={handleChange}
/>
<FormField
<TextField
id="username"
type="text"
label={lang.t('signIn.username')}
@@ -97,7 +97,7 @@ class SignUpContent extends React.Component {
errorMsg={errors.username}
onChange={handleChange}
/>
<FormField
<TextField
id="password"
type="password"
label={lang.t('signIn.password')}
@@ -108,7 +108,7 @@ class SignUpContent extends React.Component {
minLength="8"
/>
{ errors.password && <span className={styles.hint}> Password must be at least 8 characters. </span> }
<FormField
<TextField
id="confirmPassword"
type="password"
label={lang.t('signIn.confirmPassword')}
@@ -1,14 +1,14 @@
.formField {
.textField {
margin-top: 15px;
}
.formField label {
.textField label {
font-size: 1.08em;
font-weight: bold;
margin-bottom: 5px;
}
.formField input {
.textField input {
width: 100%;
display: block;
border: none;
@@ -1,8 +1,8 @@
import React, {PropTypes} from 'react';
import styles from './FormField.css';
import styles from './TextField.css';
const FormField = ({className, showErrors = false, errorMsg, label, ...props}) => (
<div className={`${styles.formField} ${className ? className : ''}`}>
const TextField = ({className, showErrors = false, errorMsg, label, ...props}) => (
<div className={`${styles.textField} ${className ? className : ''}`}>
<label htmlFor={props.id}>
{label}
</label>
@@ -15,7 +15,7 @@ const FormField = ({className, showErrors = false, errorMsg, label, ...props}) =
</div>
);
FormField.propTypes = {
TextField.propTypes = {
label: PropTypes.string,
value: PropTypes.string,
onChange: PropTypes.func,
@@ -23,4 +23,4 @@ FormField.propTypes = {
type: PropTypes.string
};
export default FormField;
export default TextField;
+1 -1
View File
@@ -13,7 +13,7 @@ export {default as Icon} from './components/Icon';
export {default as List} from './components/List';
export {default as Item} from './components/Item';
export {default as Card} from './components/Card';
export {default as FormField} from './components/FormField';
export {default as TextField} from './components/TextField';
export {default as Success} from './components/Success';
export {default as Pager} from './components/Pager';
export {default as Wizard} from './components/Wizard';
+2
View File
@@ -308,6 +308,8 @@ type Settings {
infoBoxEnable: Boolean
infoBoxContent: String
questionBoxEnable: Boolean
questionBoxContent: String
closeTimeout: Int
closedMessage: String
charCountEnable: Boolean
+8
View File
@@ -32,6 +32,14 @@ const SettingSchema = new Schema({
type: String,
default: ''
},
questionBoxEnable: {
type: Boolean,
default: false
},
questionBoxContent: {
type: String,
default: ''
},
organizationName: {
type: String
},