123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- import React from 'react';
- import { Link } from 'react-router'; // jshint ignore:line
- import ReadIcon from 'misago/components/threads-list/read-icon'; // jshint ignore:line
- import ThreadOptions from 'misago/components/threads-list/thread-options'; // jshint ignore:line
- import escapeHtml from 'misago/utils/escape-html';
- const LAST_POSTER_URL = '<a href="%(url)s" class="poster-title">%(user)s</a>';
- const LAST_POSTER_SPAN = '<span class="poster-title">%(user)s</span>';
- const LAST_REPLY_URL = '<a href="%(url)s" class="last-title" title="%(absolute)s">%(relative)s</a>';
- export class Category extends React.Component {
- getClassName() {
- if (this.props.category.css_class) {
- return 'thread-category thread-category-' + this.props.category.css_class;
- } else {
- return 'thread-category';
- }
- }
- getUrl() {
- return this.props.category.absolute_url + this.props.list.path;
- }
- render() {
- /* jshint ignore:start */
- return <Link to={this.getUrl()} className={this.getClassName()}>
- {this.props.category.name}
- </Link>;
- /* jshint ignore:end */
- }
- }
- export default class extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- isSelected: false
- };
- }
- getPath() {
- let top = this.props.categories[this.props.thread.top_category];
- let bottom = this.props.categories[this.props.thread.category];
- if (top && bottom && top.id !== bottom.id) {
- /* jshint ignore:start */
- return <li className="thread-path">
- <Category category={top} list={this.props.list} />
- <span className="path-separator material-icon">
- arrow_forward
- </span>
- <Category category={bottom} list={this.props.list} />
- </li>;
- /* jshint ignore:end */
- } else if (top || bottom) {
- /* jshint ignore:start */
- return <li className="thread-path">
- <Category category={top || bottom} list={this.props.list} />
- </li>;
- /* jshint ignore:end */
- } else {
- return null;
- }
- }
- getClosedLabel() {
- if (this.props.thread.is_closed) {
- /* jshint ignore:start */
- return <li className="thread-closed">
- {gettext("Closed")}
- </li>;
- /* jshint ignore:end */
- } else {
- return null;
- }
- }
- getNewLabel() {
- if (!this.props.thread.is_read) {
- /* jshint ignore:start */
- return <li className="thread-new-posts"
- title={gettext("Go to first unread post")}>
- <a href={this.props.thread.new_post_url}>
- {gettext("New posts")}
- </a>
- </li>;
- /* jshint ignore:end */
- } else {
- return null;
- }
- }
- getRepliesCount() {
- /* jshint ignore:start */
- let message = ngettext(
- "%(replies)s reply",
- "%(replies)s replies",
- this.props.thread.replies);
- return <li className="thread-replies">
- <a href={this.props.thread.absolute_url}>
- {interpolate(message, {
- replies: this.props.thread.replies,
- }, true)}
- </a>
- </li>;
- /* jshint ignore:end */
- }
- getLastReplyDate() {
- return interpolate(LAST_REPLY_URL, {
- url: escapeHtml(this.props.thread.last_post_url),
- absolute: escapeHtml(this.props.thread.last_post_on.format('LLL')),
- relative: escapeHtml(this.props.thread.last_post_on.fromNow())
- }, true);
- }
- getLastPoster() {
- if (this.props.thread.last_poster_url) {
- return interpolate(LAST_POSTER_URL, {
- url: escapeHtml(this.props.thread.last_poster_url),
- user: escapeHtml(this.props.thread.last_poster_name)
- }, true);
- } else {
- return interpolate(LAST_POSTER_SPAN, {
- user: escapeHtml(this.props.thread.last_poster_name)
- }, true);
- }
- }
- getLastReply() {
- /* jshint ignore:start */
- return <li className="thread-last-reply"
- dangerouslySetInnerHTML={{__html: interpolate(
- escapeHtml(gettext("last reply by %(user)s %(date)s")), {
- date: this.getLastReplyDate(),
- user: this.getLastPoster()
- }, true)}} />;
- /* jshint ignore:end */
- }
- getOptions() {
- if (this.props.user.id) {
- /* jshint ignore:start */
- return <ThreadOptions thread={this.props.thread}
- selectThread={this.props.selectThread}
- isSelected={this.props.isSelected} />;
- /* jshint ignore:end */
- } else {
- return null;
- }
- }
- getClassName() {
- if (this.props.thread.is_read) {
- if (this.props.isSelected) {
- return 'list-group-item thread-read thread-selected';
- } else {
- return 'list-group-item thread-read';
- }
- } else {
- if (this.props.isSelected) {
- return 'list-group-item thread-new thread-selected';
- } else {
- return 'list-group-item thread-new';
- }
- }
- }
- render () {
- /* jshint ignore:start */
- return <li className={this.getClassName()}>
- <ReadIcon thread={this.props.thread} />
- <div className="thread-main">
- <a href={this.props.thread.absolute_url} className="item-title thread-title">
- {this.props.thread.title}
- </a>
- <ul className="list-inline">
- {this.getNewLabel()}
- {this.getClosedLabel()}
- {this.getPath()}
- {this.getRepliesCount()}
- {this.getLastReply()}
- </ul>
- </div>
- {this.getOptions()}
- </li>;
- /* jshint ignore:end */
- }
- }
|