Skip to content

Commit

Permalink
Merge pull request #82 from CaptainFact/staging
Browse files Browse the repository at this point in the history
Staging
  • Loading branch information
Betree authored Feb 20, 2018
2 parents f182b93 + 5836247 commit cb1c911
Show file tree
Hide file tree
Showing 37 changed files with 471 additions and 208 deletions.
3 changes: 1 addition & 2 deletions app/assets/assets/help/en/reputation.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ These rules are subject to change, especially as the number of users grows.

| Action | Reputation gain |
|----------------------------------------------------------------|--------------------------|
| Your email is verified | +15pts
| You link your account to one of your social network's profile | +15pts
| Verify you email or link a third-party account | +15pts
| One of your comments is voted up | +2pts
| One of your sourced comment is voted up | +3pts
| Someone approves one of your modifications in history | +5pts
Expand Down
2 changes: 1 addition & 1 deletion app/assets/assets/help/fr/privacy.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Nous ne vendrons **jamais** vos données personelles et il n'y a pas grand chose
toutes les façons : on ne collecte que ce dont on a besoin pour faire fonctionner le site.

Vous devez par contre considérer toutes vos intéractions (votes, commentaires...)
comme **publiques**. Vous êtes libre d'utiliser votre vrai non ou juste un bon view
comme **publiques**. Vous êtes libre d'utiliser votre vrai nom ou juste un bon vieux
pseudonyme si c'est ce que vous préférez.

Bien que rien ne soit infaible, nous faisons attention à la sécurité et essayons de suivre les
Expand Down
6 changes: 3 additions & 3 deletions app/assets/assets/help/fr/reputation.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ Gagner en réputation vous permet de débloquer des nouveaux
[privilèges](/help/privileges). Vous pouvez gagner jusqu'à 25 points de réputation par
jour (les compteurs sont réinitialisés à minuit).

Ces règles sont sujettes à évolution dans le temps.
Ces règles sont sujettes à évolution dans le temps, en particulier avec la
montée du nombre d'utilisateurs.


# Pour gagner de la réputation

| Action | Gain |
|----------------------------------------------------------------|------------------|
| Faire vérifier son email | +15pts
| Relier au moins un compte tierce (Facebook) | +15pts
| Vérifier son email ou relier un compte tierce (Facebook) | +15pts
| Un de vos commentaires recoit un vote positif | +2pts
| Un de vos commentaires **sourcé** recoit un vote positif | +3pts
| Quelqu'un approuve une de vos modifications dans l'historique | +5pts
Expand Down
2 changes: 1 addition & 1 deletion app/assets/assets/locales/en/home.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"creatingAnAccount": "creating an account",
"invitation": "Ask for an invitation",
"inviteFriend": "Invite a friend",
"footer": "Created with {{iconLove}} in New Caledonia using ",
"footer": "Created with {{iconLove}} using ",
"emailPlaceholder": "Email address",
"inviteSuccess": "Invitation request confirmed !",
"error_invalid_email": "Invalid email address"
Expand Down
1 change: 1 addition & 0 deletions app/assets/assets/locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"remove": "Remove",
"delete": "Delete",
"reply": "Reply",
"addToThread": "Add to thread",
"approve": "Approve",
"refute": "Refute",
"edit": "Edit",
Expand Down
4 changes: 2 additions & 2 deletions app/assets/assets/locales/en/videoDebate.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
"loadMore_replies": "Load more replies ({{count}})",
"loadMore_comments": "Load more comments ({{count}})",
"replyingTo": "Replying to",
"approve": "Confirm",
"approve_reply": "Confirm this comment",
"approve": "Approve",
"approve_reply": "Approve this comment",
"refute": "Refute",
"refute_reply": "Refute this comment",
"revealForm": "Add a source or comment"
Expand Down
2 changes: 1 addition & 1 deletion app/assets/assets/locales/fr/errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"action_already_done": "Cette action a déjà été effectuée",
"unauthenticated": "Vous devez vous connecter pour effectuer cette action",
"unauthorized": "Merci de vous (re)connecter pour continuer",
"noInternet": "La connection au serveur a échoué, éssayez de rafraichir la page"
"noInternet": "La connection au serveur a échoué, essayez de rafraichir la page"
},
"client": {
"joinCrashed": "La connection au serveur a échouée",
Expand Down
2 changes: 1 addition & 1 deletion app/assets/assets/locales/fr/home.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"creatingAnAccount": "créant un compte",
"invitation": "Demander une invitation",
"inviteFriend": "Inviter un ami",
"footer": "Créé avec {{iconLove}} en Nouvelle-Calédonie à l'aide d'",
"footer": "Créé avec {{iconLove}} à l'aide d'",
"emailPlaceholder": "Adresse email",
"inviteSuccess": "Demande d'invitation enregistrée !",
"error_invalid_email": "Adresse email invalide"
Expand Down
1 change: 1 addition & 0 deletions app/assets/assets/locales/fr/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"remove": "Retirer",
"delete": "Supprimer",
"reply": "Répondre",
"addToThread": "Ajouter à la suite",
"approve": "Confirmer",
"refute": "Réfuter",
"edit": "Éditer",
Expand Down
8 changes: 4 additions & 4 deletions app/assets/assets/locales/fr/videoDebate.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
"loadMore_replies": "Charger plus de réponses ({{count}})",
"loadMore_comments": "Charger plus de commentaires ({{count}})",
"replyingTo": "En réponse à",
"approve": "Confirmer",
"approve_reply": "Confirmer ce commentaire",
"refute": "Réfuter",
"refute_reply": "Réfuter ce commentaire",
"approve": "J'approuve",
"approve_reply": "J'approuve ce commentaire",
"refute": "Je réfute",
"refute_reply": "Je réfute ce commentaire",
"revealForm": "Ajouter une source ou un commentaire"
},
"video": {
Expand Down
185 changes: 90 additions & 95 deletions app/components/Comments/CommentDisplay.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ import {flashErrorUnauthenticated} from '../../state/flashes/reducer'
import UserPicture from '../Users/UserPicture'
import { USER_PICTURE_SMALL } from '../../constants'
import MediaLayout from '../Utils/MediaLayout'
import Vote from './Vote'


// TODO Use ReputationGuard to protect actions
// Add the following possibilities to reputationGuard :
// onUnauthorized = "hide" | "showMessage" | "flash"

@connect(({CurrentUser, VideoDebate}, props) => ({
currentUser: CurrentUser.data,
myVote: VideoDebate.comments.voted.get(props.comment.id, 0),
Expand All @@ -36,27 +41,97 @@ export class CommentDisplay extends React.PureComponent {
this.showRepliesToggle = this.showRepliesToggle.bind(this)

// Authenticated actions
this.vote = this.actionAuthenticated(this.vote.bind(this))
this.actionReply = this.actionAuthenticated(this.actionReply.bind(this))
this.handleFlag = this.actionAuthenticated(this.handleFlag.bind(this))
}

getRemoveOrFlag() {
const { currentUser, comment, isFlagged, t } = this.props
if (currentUser.id === comment.user.id)
return (
<a onClick={this.handleDelete.bind(this)}>
<Icon name="times"/>
<span> {t('actions.delete')}</span>
</a>
)
else return (
<a onClick={this.handleFlag}
className={classNames('action-report', {selected: isFlagged})}>
render() {
const { user, text, source, score, inserted_at, approve } = this.props.comment
const { t, withoutActions, withoutHeader, replyingTo, nesting, replies, myVote, isVoting, hideThread, className, richMedias=true } = this.props
const approveClass = approve !== null && (approve ? 'approve' : 'refute')
const isOwnComment = this.props.comment.user.id === this.props.currentUser.id

return (
<div>
<MediaLayout
className={classNames('comment', className, approveClass, {isBlurred: this.state.isBlurred, hasSource: !!source})}
ContainerType="article"
left={!withoutActions &&
<Vote isVoting={isVoting} score={score} myVote={myVote}
onVote={value => this.props.commentVote({comment: this.props.comment, value})}/>
}
content={
<div>
<div>
{!withoutHeader && <div className="comment-header">
<UserPicture user={user} size={USER_PICTURE_SMALL}/>
<UserAppellation user={user} withoutActions={withoutActions}/>
<span> - </span>
<TimeSince className="comment-time" time={inserted_at}/>
</div>}
{(text || (replyingTo && nesting > 6)) &&
<div className="comment-text">
{(replyingTo && nesting > 6) &&
<Tag style={{marginRight: 5}}>@{replyingTo.username}</Tag>
}
{ text }
</div>
}
{source && <Source withoutPlayer={!richMedias} source={source}/>}
</div>
{!withoutActions &&
<nav className="comment-actions">
{ isOwnComment ? this.renderOwnCommentActions() : this.renderOtherCommentActions()}
{ replies &&
<a onClick={this.showRepliesToggle}>
<Icon size="small" name={this.state.showReplies ? "eye-slash" : "eye"}/>
<span>
{t('videoDebate:comment.replies', {
context: this.state.showReplies ? 'hide' : 'show',
count: replies.size
})}
</span>
</a>
}
</nav>
}
</div>
}
/>
{!hideThread && replies &&
<CommentsContainer comments={this.state.showReplies ? replies : new List()}
nesting={nesting + 1}
replyingTo={user}/>
}
</div>
)
}

renderOwnCommentActions() {
return [
<a key="r" onClick={this.actionReply}>
<Icon name="plus"/>
<span> {this.props.t('actions.addToThread')}</span>
</a>,
<a key="d" onClick={this.handleDelete.bind(this)}>
<Icon name="times"/>
<span> {this.props.t('actions.delete')}</span>
</a>
]
}

renderOtherCommentActions() {
return [
<a key="r" onClick={this.actionReply}>
<Icon name="reply"/>
<span> {this.props.t('actions.reply')}</span>
</a>,
<a key="f" onClick={this.handleFlag}
className={classNames('action-report', {selected: this.props.isFlagged})}>
<Icon name="flag"/>
<span> {t(isFlagged ? 'actions.flagged' : 'actions.flag')}</span>
<span> {this.props.t(this.props.isFlagged ? 'actions.flagged' : 'actions.flag')}</span>
</a>
)
]
}

handleDelete() {
Expand Down Expand Up @@ -95,10 +170,6 @@ export class CommentDisplay extends React.PureComponent {
}
}

vote(value) {
this.props.commentVote({comment: this.props.comment, value})
}

showRepliesToggle() {
this.setState({showReplies: !this.state.showReplies})
}
Expand All @@ -107,80 +178,4 @@ export class CommentDisplay extends React.PureComponent {
const formName = `formAddComment-${this.props.comment.statement_id}`
this.props.change(formName, 'reply_to', this.props.comment)
}

render() {
const { user, text, source, score, inserted_at, approve } = this.props.comment
const { t, withoutActions, withoutHeader, replyingTo, nesting, replies, myVote, isVoting, hideThread, className, richMedias=true } = this.props
const approveClass = approve !== null && (approve ? 'approve' : 'refute')
return (
<div>
<MediaLayout
className={classNames('comment', className, approveClass, {isBlurred: this.state.isBlurred, hasSource: !!source})}
ContainerType="article"
left={
<figure>
{!withoutActions &&
<div className="vote">
<Icon name="chevron-up" isClickable={true}
className={classNames({ selected: myVote > 0 })}
onClick={() => myVote <= 0 ? this.vote(1) : this.vote(0)}/>
<div className="score">
{isVoting ? <span className="round-spinner"/> : score}
</div>
<Icon name="chevron-down" isClickable={true}
className={classNames({ selected: myVote < 0 })}
onClick={() => myVote >= 0 ? this.vote(-1) : this.vote(0)}/>
</div>
}
</figure>
}
content={
<div>
<div>
{!withoutHeader && <div className="comment-header">
<UserPicture user={user} size={USER_PICTURE_SMALL}/>
<UserAppellation user={user} withoutActions={withoutActions}/>
<span> - </span>
<TimeSince className="comment-time" time={inserted_at}/>
</div>}
{(text || replyingTo) &&
<div className="comment-text">
{nesting > 6 && replyingTo &&
<Tag style={{marginRight: 5}}>@{replyingTo.username}</Tag>
}
{ text }
</div>
}
{source && <Source withoutPlayer={!richMedias} source={source}/>}
</div>
{!withoutActions &&
<nav className="comment-actions">
<a onClick={this.actionReply}>
<Icon size="small" name="reply"/>
<span> {t('actions.reply')}</span>
</a>
{ this.getRemoveOrFlag() }
{ replies &&
<a onClick={this.showRepliesToggle}>
<Icon size="small" name={this.state.showReplies ? "eye-slash" : "eye"}/>
<span> {t('videoDebate:comment.replies', {
context: this.state.showReplies ? 'hide' : 'show',
count: replies.size
})}
</span>
</a>
}
</nav>
}
</div>
}
/>
{!hideThread && replies &&
<CommentsContainer comments={this.state.showReplies ? replies : new List()}
nesting={nesting + 1}
replyingTo={user}/>
}
</div>
)
}
}
21 changes: 11 additions & 10 deletions app/components/Comments/CommentForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { withRouter } from 'react-router'
import { renderField, validateLength, cleanStrMultiline } from "../FormUtils"
import { COMMENT_LENGTH, USER_PICTURE_LARGE } from "../../constants"
import TextareaAutosize from "../FormUtils/TextareaAutosize"
import { Icon } from '../Utils/Icon'
import CloseButton from '../Utils/CloseButton'
import Icon from '../Utils/Icon'
import Tag from '../Utils/Tag'
import UserAppellation from '../Users/UserAppellation'
import { postComment } from '../../state/video_debate/comments/effects'
Expand Down Expand Up @@ -92,16 +93,16 @@ export class CommentForm extends React.PureComponent {
<div>
{formValues && formValues.reply_to &&
<div>
<Tag size="medium" className="reply_to"
onClick={() => this.props.change('reply_to', null)}>
<Icon name="times" isClickable={true}/>
<Tag size="medium" className="reply_to">
<CloseButton onClick={() => this.props.change('reply_to', null)}/>
<span>
{t('comment.replyingTo')}&nbsp;
<UserAppellation user={formValues.reply_to.user}/>
</span>
</Tag>
<CommentDisplay className="quoted" richMedias={false} withoutActions withoutHeader hideThread
comment={formValues.reply_to}/>
<CommentDisplay className="quoted" richMedias={false}
comment={formValues.reply_to}
withoutActions withoutHeader hideThread/>
<br/>
</div>
}
Expand Down Expand Up @@ -137,13 +138,13 @@ export class CommentForm extends React.PureComponent {
<button key="comment" type="submit" className={classNames(commonClasses)}>
{this.props.t('comment.post', i18nParams)}
</button>,
<button key="approve" type="submit" className={classNames(commonClasses, 'is-success')}
onClick={this.postAndReset(values => this.props.postComment({...values, approve: true}))}>
{this.props.t('comment.approve', i18nParams)}
</button>,
<button key="refute" type="submit" className={classNames(commonClasses, 'is-danger')}
onClick={this.postAndReset(values => this.props.postComment({...values, approve: false}))}>
{this.props.t('comment.refute', i18nParams)}
</button>,
<button key="approve" type="submit" className={classNames(commonClasses, 'is-success')}
onClick={this.postAndReset(values => this.props.postComment({...values, approve: true}))}>
{this.props.t('comment.approve', i18nParams)}
</button>
])
}
Expand Down
2 changes: 1 addition & 1 deletion app/components/Comments/CommentsContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class CommentsContainer extends React.PureComponent {
return (
<div className={`comments-list ${className ? className : ''}`}>
{header && <div className="comments-list-header">{header}</div>}
<FlipMove enterAnimation="fade" leaveAnimation={false} typeName={null}>
<FlipMove enterAnimation="fade" leaveAnimation={false}>
{displayedComments.map(comment =>
<div key={comment.id}>
<CommentDisplay comment={comment} nesting={nesting} replyingTo={replyingTo}/>
Expand Down
Loading

0 comments on commit cb1c911

Please sign in to comment.