diff --git a/web/app/components/comment/__action/_type/_edit/comment__action_type_edit.scss b/web/app/components/comment/__action/_type/_edit/comment__action_type_edit.scss new file mode 100644 index 00000000..656e430a --- /dev/null +++ b/web/app/components/comment/__action/_type/_edit/comment__action_type_edit.scss @@ -0,0 +1,7 @@ +.comment__action_type_edit { + color: #a6a6a6; + + &:hover { + color: #31c7c5; + } +} diff --git a/web/app/components/comment/__vote/comment__vote.scss b/web/app/components/comment/__vote/comment__vote.scss index cf6dc84c..dd3c9100 100644 --- a/web/app/components/comment/__vote/comment__vote.scss +++ b/web/app/components/comment/__vote/comment__vote.scss @@ -8,6 +8,7 @@ background: url('comment__vote.svg') center no-repeat; background-size: contain; cursor: pointer; + outline: none; &:hover { background-image: url('_selected/comment__vote_selected.svg'); diff --git a/web/app/components/comment/_editing/comment_editing.scss b/web/app/components/comment/_editing/comment_editing.scss new file mode 100644 index 00000000..bb546220 --- /dev/null +++ b/web/app/components/comment/_editing/comment_editing.scss @@ -0,0 +1,36 @@ +.comment_editing { + .comment__text { + display: none; + } + + .comment__input { + border: 12px solid #eee; + } + + .comment__score { + top: 4px; + right: 0; + } + + // it isn't mobile first, but it's fine here + @media (-moz-touch-enabled: 1) and (max-width: 768px), (pointer:coarse) and (max-width: 768px) { + border: 8px solid #eee; + padding-bottom: 0; + + .comment__body { + padding: 8px 8px 0; + } + + .comment__input { + border-left-width: 0; + border-right-width: 0; + border-bottom-width: 0; + border-top-width: 8px; + } + + .comment__score { + top: 12px; + right: 8px; + } + } +} diff --git a/web/app/components/comment/comment.jsx b/web/app/components/comment/comment.jsx index 49a91b24..8b4cca38 100644 --- a/web/app/components/comment/comment.jsx +++ b/web/app/components/comment/comment.jsx @@ -12,7 +12,8 @@ export default class Comment extends Component { super(props); this.state = { - isInputVisible: false, + isReplying: false, + isEditing: false, isUserIdVisible: false, }; @@ -20,7 +21,8 @@ export default class Comment extends Component { this.decreaseScore = this.decreaseScore.bind(this); this.increaseScore = this.increaseScore.bind(this); - this.toggleInputVisibility = this.toggleInputVisibility.bind(this); + this.toggleEditing = this.toggleEditing.bind(this); + this.toggleReplying = this.toggleReplying.bind(this); this.toggleCollapse = this.toggleCollapse.bind(this); this.toggleUserIdVisibility = this.toggleUserIdVisibility.bind(this); this.scrollToParent = this.scrollToParent.bind(this); @@ -63,18 +65,33 @@ export default class Comment extends Component { } } - toggleInputVisibility() { - const { isInputVisible } = this.state; - const onPrevReplyCb = store.get('onPrevReplyCb'); + toggleReplying() { + const { isReplying } = this.state; + const onPrevInputToggleCb = store.get('onPrevInputToggleCb'); - this.setState({ isInputVisible: !isInputVisible }); + this.setState({ isReplying: !isReplying }); - if (onPrevReplyCb) onPrevReplyCb(); + if (onPrevInputToggleCb) onPrevInputToggleCb(); - if (!isInputVisible) { - store.set('onPrevReplyCb', () => this.setState({ isInputVisible: false })); + if (!isReplying) { + store.set('onPrevInputToggleCb', () => this.setState({ isReplying: false })); } else { - store.set('onPrevReplyCb', null); + store.set('onPrevInputToggleCb', null); + } + } + + toggleEditing() { + const { isEditing } = this.state; + const onPrevInputToggleCb = store.get('onPrevInputToggleCb'); + + this.setState({ isEditing: !isEditing }); + + if (onPrevInputToggleCb) onPrevInputToggleCb(); + + if (!isEditing) { + store.set('onPrevInputToggleCb', () => this.setState({ isEditing: false })); + } else { + store.set('onPrevInputToggleCb', null); } } @@ -180,7 +197,15 @@ export default class Comment extends Component { this.props.onReply(...rest); this.setState({ - isInputVisible: false, + isReplying: false, + }); + } + + onEdit(...rest) { + this.props.onEdit(...rest); + + this.setState({ + isEditing: false, }); } @@ -202,7 +227,7 @@ export default class Comment extends Component { } } - render(props, { guest, isUserIdVisible, userBlocked, pinned, score, scoreIncreased, scoreDecreased, deleted, isInputVisible }) { + render(props, { guest, isUserIdVisible, userBlocked, pinned, score, scoreIncreased, scoreDecreased, deleted, isReplying, isEditing }) { const { data, mods = {} } = props; const isAdmin = !guest && store.get('user').admin; const isGuest = guest || !Object.keys(store.get('user')).length; @@ -240,7 +265,8 @@ export default class Comment extends Component { useless: userBlocked || deleted || (score <= USELESS_COMMENT_SCORE && !mods.pinned && !mods.disabled), // TODO: add default view mod or don't? view: o.user.admin ? 'admin' : null, - replying: isInputVisible, + replying: isReplying, + editing: isEditing, }; if (mods.view === 'preview') { @@ -344,8 +370,19 @@ export default class Comment extends Component { className="comment__action" role="button" tabIndex="0" - onClick={this.toggleInputVisibility} - >{isInputVisible ? 'Cancel' : 'Reply'} + onClick={this.toggleReplying} + >{isReplying ? 'Cancel' : 'Reply'} + ) + } + + { + !deleted && !mods.disabled && !!o.orig && isCurrentUser && ( + {isEditing ? 'Cancel' : 'Edit'} ) } @@ -423,16 +460,30 @@ export default class Comment extends Component { { - isInputVisible && ( + isReplying && ( ) } + + { + isEditing && ( + + ) + } ); } diff --git a/web/app/components/comment/index.js b/web/app/components/comment/index.js index 6538f931..68cf4b71 100644 --- a/web/app/components/comment/index.js +++ b/web/app/components/comment/index.js @@ -6,6 +6,7 @@ require('./comment.scss'); require('./__action/comment__action.scss'); require('./__action/_type/_collapse/comment__action_type_collapse.scss'); +require('./__action/_type/_edit/comment__action_type_edit.scss'); require('./__avatar/comment__avatar.scss'); require('./__avatar/_default/comment__avatar_default.scss'); @@ -34,6 +35,7 @@ require('./__vote/_type/_down/comment__vote_type_down.scss'); require('./__vote/_type/_up/comment__vote_type_up.scss'); require('./_level/comment_level.scss'); +require('./_editing/comment_editing.scss'); require('./_replying/comment_replying.scss'); require('./_useless/comment_useless.scss');