diff options
Diffstat (limited to 'vnext/src')
-rw-r--r-- | vnext/src/components/Message.js | 12 | ||||
-rw-r--r-- | vnext/src/components/Thread.js | 145 |
2 files changed, 139 insertions, 18 deletions
diff --git a/vnext/src/components/Message.js b/vnext/src/components/Message.js index 53c2a033..5667047c 100644 --- a/vnext/src/components/Message.js +++ b/vnext/src/components/Message.js @@ -12,7 +12,7 @@ export default function Message(props) { const msg = props.data; const visitor = props.visitor; return ( - <article itemProp="blogPost" itemScope="" itemType="http://schema.org/BlogPosting" itemRef="org"> + <div className="msg-cont" itemProp="blogPost" itemScope="" itemType="http://schema.org/BlogPosting" itemRef="org"> <header className="h"> <span itemProp="author" itemScope="" itemType="http://schema.org/Person"> <a href={`/${msg.user.uname}/`} itemProp="url" rel="author"><span itemProp="name">{msg.user.uname}</span></a> @@ -30,7 +30,9 @@ export default function Message(props) { <Tags data={msg.tags || []} /> </div> </header> - <p itemProp="description" dangerouslySetInnerHTML={{ __html: format(msg.body, msg.mid, (msg.tags || []).indexOf('code') >= 0) }}></p> + <div className="msg-txt"> + <p itemProp="description" dangerouslySetInnerHTML={{ __html: format(msg.body, msg.mid, (msg.tags || []).indexOf('code') >= 0) }}></p> + </div> {msg.photo && <p className="ir"><a href={`//i.juick.com/p/${msg.mid}.${msg.attach}`} data-fname={`${msg.mid}.${msg.attach}`}> <img itemProp="image" src={`//i.juick.com/p/${msg.mid}.${msg.attach}`} alt="" /></a> @@ -87,7 +89,8 @@ export default function Message(props) { <a href="#" className="a-privacy">Открыть доступ</a> )} </nav> - </article> + {props.children} + </div> ); } @@ -103,7 +106,8 @@ Message.propTypes = { user: UserType, timestamp: PropTypes.string.isRequired, body: PropTypes.string - }) + }), + children: PropTypes.node }; Tags.propTypes = { diff --git a/vnext/src/components/Thread.js b/vnext/src/components/Thread.js index 16a662cc..9b26e378 100644 --- a/vnext/src/components/Thread.js +++ b/vnext/src/components/Thread.js @@ -1,23 +1,29 @@ import React from 'react'; import * as qs from 'query-string'; +import moment from 'moment'; import Message from './Message'; import Spinner from './Spinner'; +import Avatar from './Avatar'; + +import { format } from '../utils/embed'; export default class Thread extends React.Component { constructor(props) { super(props); this.state = { + msg: {}, replies: [] }; + this.loaded = this.loaded.bind(this); } componentDidMount() { this.loadReplies(); } loadReplies() { - this.setState({ replies: []}) + this.setState({ replies: [] }) const { mid } = this.props.match.params; - let params = { + let params = { mid: mid } if (this.props.visitor && this.props.visitor.hash) { @@ -25,20 +31,131 @@ export default class Thread extends React.Component { }; const url = `https://api.juick.com/thread?${qs.stringify(params)}`; fetch(url) - .then(response => { - return response.json() + .then(response => { + return response.json() + }) + .then(data => { + let msg = data.shift(); + this.setState({ + msg: msg, + replies: data }) - .then(data => - this.setState({ replies: data }) - ).catch(ex => { - console.log(ex); - }); + } + ).catch(ex => { + console.log(ex); + }); + } + loaded() { + return this.state.msg.mid; } render() { - return this.state.replies && this.state.replies.length > 0 ? ( - <Message data={this.state.replies[0]} visitor={this.props.visitor}/> - ) : ( - <Spinner /> - ); + const msg = this.state.msg; + return ( + <React.Fragment> + <ul id="0"> + <li className="msg msgthread"> + { + this.loaded() ? ( + <Message data={msg} visitor={this.props.visitor}> + <form className="msg-comment-target"> + <input type="hidden" name="mid" value={msg.mid} /> + <div className="msg-comment"> + <div className="ta-wrapper"> + <textarea name="body" rows="1" className="reply" placeholder="Write a comment..."></textarea> + </div> + </div> + </form> + { + msg.recomm && ( + <div className="msg-recomms">{`Recommended by (${msg.recomm.length}):`} + { + msg.recomm.map((it, index) => ( + <a href="/{{ it }}/">{it}</a> + )) + } + </div> + ) + } + </Message> + ) : ( + <Spinner /> + ) + } + </li> + </ul> + { + this.loaded() && ( + <React.Fragment> + <div className="title2"> + { + this.props.visitor.uid > 0 && + <img src={`https://api.juick.com/thread/mark_read/${msg.mid}-${msg.rid || 0}.gif?hash=${this.props.visitor.hash}`} /> + } + <h2>{`Replies (${msg.replies})`}</h2> + </div> + <ul id="replies"> + { + this.state.replies.map((msg) => ( + <li id={msg.rid} key={msg.rid} className="msg"> + <div className="msg-cont"> + <div className="msg-header"> + {!msg.user.banned ? ( + <React.Fragment> + <span itemProp="author" itemScope="" itemType="http://schema.org/Person"> + <a href={`/${msg.user.uname}/`} itemProp="url" rel="author"><span itemProp="name">{msg.user.uname}</span></a> + </span><Avatar user={msg.user} /> + </React.Fragment>) : ( + <React.Fragment> + <span>[удалено]:</span><Avatar user={{ uid: 0 }} /> + </React.Fragment> + )} + <div className="msg-ts"> + <a href={`/${msg.user.uname}/${msg.mid}`}> + <time itemProp="datePublished dateModified" itemType="http://schema.org/Date" dateTime={msg.timestamp} + title={moment.utc(msg.timestamp).local().format('lll')}> + {moment.utc(msg.timestamp).fromNow()} + </time> + </a> + </div> + </div> + <div className="msg-txt"><p dangerouslySetInnerHTML={{ __html: format(msg.body, msg.mid, (msg.tags || []).indexOf('code') >= 0) }}></p></div> + { + msg.photo && + <p className="ir"><a href={`//i.juick.com/p/${msg.mid}.${msg.attach}`} data-fname={`${msg.mid}.${msg.attach}`}> + <img itemProp="image" src={`//i.juick.com/p/${msg.mid}.${msg.attach}`} alt="" /></a> + </p> + } + <div className="msg-links">{`/${msg.rid}`} + { + msg.replyto > 0 && + ( + <a href={`#${msg.replyto}`}> in reply to {msg.to.uname} </a> + ) + } + { + this.props.visitor.uid > 0 ? ( + <React.Fragment> + <span>· </span> + <a href={`/post?body=%23${msg.mid}/${msg.rid}%20`} className="a-thread-comment">Reply</a> + <div className="msg-comment-target msg-comment-hidden"></div> + </React.Fragment> + ) : ( + <React.Fragment> + <span> · </span><a href="#" className="a-login">Reply</a> + </React.Fragment> + ) + } + </div> + </div> + </li> + )) + } + </ul> + </React.Fragment> + ) + } + </React.Fragment> + ) + } } |