rewrite draft using preact
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
.comment__avatar {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
display: inline-block;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin-right: 8px;
|
||||
border-radius: 4px;
|
||||
background: #eee;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.comment__info {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.comment__score-sign {
|
||||
font-size: 14px;
|
||||
vertical-align: 1px;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.comment__score-value {
|
||||
font-size: 14px;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
.comment__score {
|
||||
margin-left: 8px;
|
||||
font-size: 0;
|
||||
color: #666;
|
||||
cursor: default;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
.comment__text {
|
||||
p {
|
||||
margin: 0;
|
||||
|
||||
+ p {
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
.comment__time {
|
||||
margin-left: 8px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.comment__username {
|
||||
text-decoration: none;
|
||||
color: #19f;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.comment__vote_selected {
|
||||
border-top-color: #19f;
|
||||
cursor: default;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.comment__vote_type_up {
|
||||
transform: scale(1, -1);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
.comment__vote {
|
||||
display: inline-block;
|
||||
border-top: 9px solid #ccc;
|
||||
border-right: 7px solid transparent;
|
||||
border-left: 7px solid transparent;
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
border-top-color: #19f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
@import 'common/variables';
|
||||
|
||||
.comment_level {
|
||||
@for $i from 1 through 5 {
|
||||
&_#{$i} {
|
||||
margin-left: $i * $offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
.comment_view_admin {
|
||||
.comment__username {
|
||||
font-weight: 700;
|
||||
color: #ff4700;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import { h, Component } from 'preact';
|
||||
|
||||
import { vote } from 'common/api';
|
||||
import { url, userId } from 'common/settings';
|
||||
|
||||
export default class Comment extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const { score, votes } = props.data;
|
||||
|
||||
this.state = {
|
||||
score: score,
|
||||
scoreIncreased: userId in votes && votes[userId],
|
||||
scoreDecreased: userId in votes && !votes[userId],
|
||||
};
|
||||
|
||||
this.decreaseScore = this.decreaseScore.bind(this);
|
||||
this.increaseScore = this.increaseScore.bind(this);
|
||||
}
|
||||
|
||||
increaseScore() {
|
||||
const { score, scoreIncreased, scoreDecreased } = this.state;
|
||||
|
||||
if (scoreIncreased) return;
|
||||
|
||||
this.setState({
|
||||
scoreIncreased: !scoreDecreased,
|
||||
scoreDecreased: false,
|
||||
score: score + 1,
|
||||
});
|
||||
|
||||
vote({ id: this.props.data.id, url, value: 1 });
|
||||
}
|
||||
|
||||
decreaseScore() {
|
||||
const { score, scoreIncreased, scoreDecreased } = this.state;
|
||||
|
||||
if (scoreDecreased) return;
|
||||
|
||||
this.setState({
|
||||
scoreDecreased: !scoreIncreased,
|
||||
scoreIncreased: false,
|
||||
score: score - 1,
|
||||
});
|
||||
|
||||
vote({ id: this.props.data.id, url, value: -1 });
|
||||
}
|
||||
|
||||
render(props, { score, scoreIncreased, scoreDecreased }) {
|
||||
const { data, mix, mods = {} } = props;
|
||||
console.log('rerender', data.id)
|
||||
|
||||
const time = new Date(data.time);
|
||||
// TODO: which format for datetime should we choose?
|
||||
// TODO: add smth that will count 'hours ago'
|
||||
// TODO: check out stash's impl
|
||||
const timeStr = `${time.toLocaleDateString()} ${time.toLocaleTimeString()}`;
|
||||
const o = {
|
||||
...data,
|
||||
time: timeStr,
|
||||
score: {
|
||||
value: Math.abs(score),
|
||||
sign: score > 0 ? '+' : (score < 0 ? '−' : ''),
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
// TODO: add default view mod or don't?
|
||||
<div className={b('comment', props, { view: data.user.admin ? 'admin' : null })} data-id={o.id}>
|
||||
<img src={o.user.picture} alt="" className="comment__avatar"/>
|
||||
|
||||
<div className="comment__content">
|
||||
<div className="comment__info">
|
||||
<a href="#" className="comment__username">{o.user.name}</a>
|
||||
|
||||
<span className="comment__score">
|
||||
<span
|
||||
className={b('comment__vote', {}, { type: 'up', selected: scoreIncreased })}
|
||||
onClick={this.increaseScore}
|
||||
>vote up</span>
|
||||
<span className="comment__score-sign">{o.score.sign}</span>
|
||||
<span className="comment__score-value">{o.score.value}</span>
|
||||
<span
|
||||
className={b('comment__vote', {}, { type: 'down', selected: scoreDecreased })}
|
||||
onClick={this.decreaseScore}
|
||||
>vote down</span>
|
||||
</span>
|
||||
|
||||
<span className="comment__time">{o.time}</span>
|
||||
</div>
|
||||
|
||||
<div className="comment__text" dangerouslySetInnerHTML={{ __html: o.text }}/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
@import 'common/variables';
|
||||
|
||||
.comment {
|
||||
display: flex;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
margin-bottom: $offset;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
export { default } from './comment';
|
||||
|
||||
require('./comment.scss');
|
||||
|
||||
require('./__avatar/comment__avatar.scss');
|
||||
require('./__info/comment__info.scss');
|
||||
require('./__score/comment__score.scss');
|
||||
require('./__score-sign/comment__score-sign.scss');
|
||||
require('./__score-value/comment__score-value.scss');
|
||||
require('./__text/comment__text.scss');
|
||||
require('./__time/comment__time.scss');
|
||||
require('./__username/comment__username.scss');
|
||||
|
||||
require('./__vote/comment__vote.scss');
|
||||
require('./__vote/_selected/comment__vote_selected.scss');
|
||||
require('./__vote/_type/_up/comment__vote_type_up.scss');
|
||||
|
||||
require('./_level/comment_level.scss');
|
||||
|
||||
require('./_view/_admin/comment_view_admin.scss');
|
||||
@@ -1 +1,3 @@
|
||||
export { default } from './root';
|
||||
|
||||
require('./root.scss');
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
import { Component } from 'preact';
|
||||
import fetcher from 'common/fetcher';
|
||||
import { h, Component } from 'preact';
|
||||
import api from 'common/api';
|
||||
|
||||
import { url, id } from 'common/settings';
|
||||
|
||||
import Thread from 'components/thread';
|
||||
|
||||
export default class Root extends Component {
|
||||
componentDidMount() {
|
||||
// TODO: add preloader
|
||||
// TODO: all of these settings must be optional params
|
||||
fetcher
|
||||
.get('/find?url=https://radio-t.com/p/2017/12/16/podcast-576/&sort=time&format=tree')
|
||||
.then(this.loadData.bind(this));
|
||||
api.find({ url }).then(({ comments } = {}) => this.setState({ comments }));
|
||||
}
|
||||
|
||||
loadData(data) {
|
||||
this.setState({ data: JSON.stringify(data) })
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data } = this.state;
|
||||
|
||||
return data;
|
||||
render({}, { comments = [] }) {
|
||||
return (
|
||||
<div className="root" id={id}>
|
||||
{
|
||||
comments.map(thread => <Thread data={thread} mods={{ level: 0 }}/>)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
@import 'common/variables';
|
||||
|
||||
.root {
|
||||
margin-bottom: -$offset;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export { default } from './thread';
|
||||
|
||||
require('./thread.scss');
|
||||
@@ -0,0 +1,24 @@
|
||||
import { h, Component } from 'preact';
|
||||
|
||||
import Comment from 'components/comment';
|
||||
|
||||
export default class Thread extends Component {
|
||||
render(props, state) {
|
||||
const { data: { comment, replies = [] }, mix, mods = {} } = props;
|
||||
|
||||
return (
|
||||
<div className={b('thread', props)}>
|
||||
<Comment data={comment} mods={{ level: mods.level }}/>
|
||||
|
||||
{
|
||||
!!replies.length && replies.map(thread => (
|
||||
<Thread
|
||||
data={thread}
|
||||
mods={{ level: mods.level < 5 ? mods.level + 1 : mods.level }}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
@import 'common/variables';
|
||||
|
||||
.thread {
|
||||
margin-bottom: $offset;
|
||||
}
|
||||
Reference in New Issue
Block a user