thread.html 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. {% extends "cranefly/layout.html" %}
  2. {% import "forms.html" as form_theme with context %}
  3. {% import "cranefly/editor.html" as editor with context %}
  4. {% import "cranefly/macros.html" as macros with context %}
  5. {% block title %}{{ macros.page_title(title=thread.name,parent=_("Private Threads"),page=pagination['page']) }}{% endblock %}
  6. {% block breadcrumb %}{{ super() }} <span class="divider"><i class="icon-chevron-right"></i></span></li>
  7. <li><a href="{{ url('private_threads') }}">{% trans %}Private Threads{% endtrans %}</a> <span class="divider"><i class="icon-chevron-right"></i></span></li>
  8. <li class="active">{{ thread.name }}
  9. {%- endblock %}
  10. {% block container %}
  11. <div class="page-header header-primary">
  12. <div class="container">
  13. {{ messages_list(messages) }}
  14. <ul class="breadcrumb" {{ macros.itemprop_bread() }}>
  15. {{ self.breadcrumb() }}</li>
  16. </ul>
  17. <h1>{{ thread.name }}</h1>
  18. <ul class="unstyled header-stats">
  19. {% if thread.moderated %}<li><i class="icon-eye-close"></i> {% trans %}Not Reviewed{% endtrans %}</li>{% endif %}
  20. <li><i class="icon-time"></i> {{ thread.last|reltimesince }}</li>
  21. <li><i class="icon-user"></i> {% if thread.start_poster_id %}<a href="{{ url('user', user=thread.start_poster_id, username=thread.start_poster_slug) }}">{{ thread.start_poster_name }}</a>{% else %}{{ thread.start_poster_name }}{% endif %}</li>
  22. <li><i class="icon-comment"></i> {% if thread.replies > 0 -%}
  23. {% trans count=thread.replies, replies=thread.replies|intcomma %}One reply{% pluralize %}{{ replies }} replies{% endtrans %}
  24. {%- else -%}
  25. {% trans %}No replies{% endtrans %}
  26. {%- endif %}</li>
  27. {% if thread.closed %}<li><i class="icon-lock"></i> {% trans %}Locked{% endtrans %}</li>{% endif %}
  28. <li class="stats-form">
  29. <form class="leave-form" action="{{ url('private_thread_remove_user', thread=thread.pk, slug=thread.slug) }}" method="post">
  30. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  31. <input type="hidden" name="user" value="{{ user.pk }}">
  32. <button type="submit" class="btn"><i class="icon-remove"></i> {% trans %}Leave Thread{% endtrans %}</button>
  33. </form>
  34. </li>
  35. </ul>
  36. </div>
  37. </div>
  38. <div class="container container-primary">
  39. {% if message %}
  40. <div class="messages-list">
  41. {{ macros.draw_message(message) }}
  42. </div>
  43. {% endif %}
  44. <div class="row">
  45. <div class="span9">
  46. <div class="thread-buttons">
  47. {{ pager() }}
  48. {% if acl.threads.can_reply(forum, thread) and (acl.private_threads.is_mod() or participants|length > 1) %}
  49. <a href="{{ url('private_thread_reply', thread=thread.pk, slug=thread.slug) }}" class="btn btn-inverse pull-right"><i class="icon-pencil"></i> {% trans %}Reply{% endtrans %}</a>
  50. {% endif %}
  51. {% if watcher %}
  52. <form action="{{ url('private_thread_unwatch', thread=thread.pk, slug=thread.slug) }}" class="form-inline pull-right" method="post"><input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}"><input type="hidden" name="retreat" value="{{ request_path }}"><button type="submit" class="btn btn-icon btn-success tooltip-top" title="{% trans %}Remove thread from watched list{% endtrans %}"><i class="icon-bookmark"></i></button></form>
  53. {% if watcher.email %}
  54. <form action="{{ url('private_thread_unwatch_email', thread=thread.pk, slug=thread.slug) }}" class="form-inline pull-right" method="post"><input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}"><input type="hidden" name="retreat" value="{{ request_path }}"><button type="submit" class="btn btn-icon btn-success tooltip-top" title="{% trans %}Don't e-mail me anymore if anyone replies to this thread{% endtrans %}"><i class="icon-envelope"></i></button></form>
  55. {% else %}
  56. <form action="{{ url('private_thread_watch_email', thread=thread.pk, slug=thread.slug) }}" class="form-inline pull-right" method="post"><input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}"><input type="hidden" name="retreat" value="{{ request_path }}"><button type="submit" class="btn btn-icon tooltip-top" title="{% trans %}E-mail me if anyone replies{% endtrans %}"><i class="icon-envelope"></i></button></form>
  57. {% endif %}
  58. {% else %}
  59. <form action="{{ url('private_thread_watch', thread=thread.pk, slug=thread.slug) }}" class="form-inline pull-right" method="post"><input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}"><input type="hidden" name="retreat" value="{{ request_path }}"><button type="submit" class="btn btn-icon tooltip-top" title="{% trans %}Add thread to watched list{% endtrans %}"><i class="icon-bookmark"></i></button></form>
  60. <form action="{{ url('private_thread_watch_email', thread=thread.pk, slug=thread.slug) }}" class="form-inline pull-right" method="post"><input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}"><input type="hidden" name="retreat" value="{{ request_path }}"><button type="submit" class="btn btn-icon tooltip-top" title="{% trans %}Add thread to watched list and e-mail me if anyone replies{% endtrans %}"><i class="icon-envelope"></i></button></form>
  61. {% endif %}
  62. {% if ignored_posts %}
  63. <form action="{{ url('private_thread_show_hidden', thread=thread.pk, slug=thread.slug) }}" class="form-inline pull-right" method="post"><input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}"><button type="submit" class="btn"><i class="icon-eye-open"></i> {% trans %}Show Hidden Replies{% endtrans %}</button></form>
  64. {% endif %}
  65. </div>
  66. <div class="thread-body">
  67. {% for post in posts %}
  68. <div id="post-{{ post.pk }}" class="post-wrapper">
  69. {% if post.message %}
  70. <div class="messages-list">
  71. {{ macros.draw_message(post.message) }}
  72. </div>
  73. {% endif %}
  74. {% if post.deleted and not acl.threads.can_see_deleted_posts(forum) %}
  75. <div class="post-body post-muted">
  76. {% if post.user_id %}
  77. <a href="{{ url('user', user=post.user.pk, username=post.user.username_slug) }}"><img src="{{ post.user.get_avatar(50) }}" alt="" class="user-avatar"></a>
  78. {% else %}
  79. <img src="{{ macros.avatar_guest(60) }}" alt="" class="user-avatar">
  80. {% endif %}
  81. <div class="post-content">
  82. <div class="post-header">
  83. <div class="post-header-compact">
  84. {% if post.user_id %}
  85. <a href="{{ url('user', user=post.user.pk, username=post.user.username_slug) }}" class="post-author">{{ post.user.username }}</a>{% if post.user.get_title() %} {{ user_label(post.user) }}{% endif %}
  86. {% else %}
  87. <span class="post-author">{{ post.user_name }}</span> <span class="label post-author-label post-label-guest">{% trans %}Unregistered{% endtrans %}</span>
  88. {% endif %}
  89. <span class="separator">&ndash;</span>
  90. <a href="{{ url('private_thread_find', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="post-date">{{ post.date|reltimesince }}</a>
  91. {% if post.edits %}
  92. <span class="separator">&ndash;</span>
  93. {% if acl.threads.can_see_changelog(user, forum, post) %}
  94. <a href="{{ url('private_thread_changelog', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="post-changelog tooltip-bottom" title="{% trans %}Show changelog{% endtrans %}">{% trans edits=post.edits %}One edit{% pluralize %}{{ edits }} edits{% endtrans %}</a>
  95. {% else %}
  96. <span class="post-changelog">{% trans edits=post.edits %}One edit{% pluralize %}{{ edits }} edits{% endtrans %}</span>
  97. {% endif %}
  98. {% endif %}
  99. </div>
  100. <a href="{{ url('private_thread_find', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="post-perma tooltip-left" title="{% trans %}Direct link to this post{% endtrans %}">#{{ pagination['start'] + loop.index }}</a>
  101. {% if not post.is_read %}
  102. <div class="post-extra">
  103. <span class="label label-warning">
  104. {% trans %}New{% endtrans %}
  105. </span>
  106. </div>
  107. {% endif %}
  108. </div>
  109. <div class="post-message">
  110. {% trans user=edit_user(post), date=post.delete_date|reltimesince|low %}{{ user }} has deleted this reply {{ date }}{% endtrans %}
  111. </div>
  112. </dv>
  113. </div>
  114. {% elif post.ignored %}
  115. <div class="post-body post-muted">
  116. <img src="{{ macros.avatar_guest(60) }}" alt="" class="user-avatar">
  117. <div class="post-arrow"></div>
  118. <div class="post-content">
  119. <div class="post-header">
  120. <div class="post-header-compact">
  121. <a href="{{ url('private_thread_find', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="post-date">{{ post.date|reltimesince }}</a>
  122. </div>
  123. <a href="{{ url('private_thread_find', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="post-perma tooltip-left" title="{% trans %}Direct link to this post{% endtrans %}">#{{ pagination['start'] + loop.index }}</a>
  124. {% if not post.is_read %}
  125. <div class="post-extra">
  126. <span class="label label-warning">
  127. {% trans %}New{% endtrans %}
  128. </span>
  129. </div>
  130. {% endif %}
  131. </div>
  132. <div class="post-message">
  133. {% trans %}This reply was posted by user that is on your ignored list.{% endtrans %}
  134. </div>
  135. </dv>
  136. </div>
  137. {% else %}
  138. <div class="post-body">
  139. {% if post.user_id %}
  140. <a href="{{ url('user', user=post.user.pk, username=post.user.username_slug) }}"><img src="{{ post.user.get_avatar(100) }}" alt="" class="user-avatar"></a>
  141. {% else %}
  142. <img src="{{ macros.avatar_guest(100) }}" alt="" class="user-avatar">
  143. {% endif %}
  144. <div class="post-arrow"></div>
  145. <div class="post-content">
  146. <div class="post-header">
  147. {% if post.user_id %}
  148. <a href="{{ url('user', user=post.user.pk, username=post.user.username_slug) }}" class="post-author">{{ post.user.username }}</a>{% if post.user.get_title() %} {{ user_label(post.user) }}{% endif %}
  149. {% else %}
  150. <span class="post-author">{{ post.user_name }}</span> <span class="label post-author-label post-label-guest">{% trans %}Unregistered{% endtrans %}</span>
  151. {% endif %}
  152. <span class="separator">&ndash;</span>
  153. <a href="{% if pagination['page'] > 1 -%}
  154. {{ url('private_thread', thread=thread.pk, slug=thread.slug, page=pagination['page']) }}
  155. {%- else -%}
  156. {{ url('private_thread', thread=thread.pk, slug=thread.slug) }}
  157. {%- endif %}#post-{{ post.pk }}" class="post-date">{{ post.date|reltimesince }}</a>
  158. {% if post.edits %}
  159. <span class="separator">&ndash;</span>
  160. {% if acl.threads.can_see_changelog(user, forum, post) %}
  161. <a href="{{ url('private_thread_changelog', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="post-changelog tooltip-bottom" title="{% trans %}Show changelog{% endtrans %}">{% trans edits=post.edits %}One edit{% pluralize %}{{ edits }} edits{% endtrans %}</a>
  162. {% else %}
  163. <span class="post-changelog">{% trans edits=post.edits %}One edit{% pluralize %}{{ edits }} edits{% endtrans %}</span>
  164. {% endif %}
  165. {% endif %}
  166. {% if posts_form %}
  167. <label class="checkbox post-checkbox"><input form="posts_form" name="{{ posts_form['list_items']['html_name'] }}" type="checkbox" class="checkbox-member" value="{{ post.pk }}"{% if posts_form['list_items']['has_value'] and ('' ~ post.pk) in posts_form['list_items']['value'] %} checked="checked"{% endif %}></label>
  168. {% endif %}
  169. <a href="{{ url('private_thread_find', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="post-perma tooltip-left" title="{% trans %}Direct link to this post{% endtrans %}">#{{ pagination['start'] + loop.index }}</a>
  170. <div class="post-extra">
  171. {% if post.protected and acl.threads.can_protect(forum) %}
  172. <span class="label label-info">
  173. {% trans %}Protected{% endtrans %}
  174. </span>
  175. {% endif %}
  176. {% if post.deleted %}
  177. <span class="label label-inverse">
  178. {% trans %}Deleted{% endtrans %}
  179. </span>
  180. {% endif %}
  181. {% if post.moderated %}
  182. <span class="label label-purple">
  183. {% trans %}Unreviewed{% endtrans %}
  184. </span>
  185. {% endif %}
  186. {% if acl.threads.can_mod_posts(forum) and post.reported %}
  187. <span class="label label-important">
  188. {% trans %}Reported{% endtrans %}
  189. </span>
  190. {% endif %}
  191. {% if not post.is_read %}
  192. <span class="label label-warning">
  193. {% trans %}New{% endtrans %}
  194. </span>
  195. {% endif %}
  196. </div>
  197. </div>
  198. <div class="post-message">
  199. <div class="markdown js-extra">
  200. <article>
  201. {{ post.post_preparsed|markdown_final|safe }}
  202. </article>
  203. </div>
  204. {% if post.has_attachments and acl.threads.can_download_attachments(user, forum, post) %}
  205. <div class="post-attachments">
  206. <h3>{% trans %}Attached files{% endtrans %}</h3>
  207. {% for row in post.attachments|batch(2) %}
  208. {% if not loop.first %}
  209. <hr>
  210. {% endif %}
  211. <div class="row-fluid">
  212. {% for attachment in row %}
  213. <div class="span6">
  214. <div class="post-attachment">
  215. <div class="attachment-image">
  216. <a href="{{ url('attachments_server', attachment=attachment.hash_id) }}">
  217. {% if attachment.is_image %}
  218. <img src="{{ url('attachments_thumbs_server', attachment=attachment.hash_id) }}" alt="">
  219. {% else %}
  220. <i class="icon-file"></i>
  221. {% endif %}
  222. </a>
  223. </div>
  224. <div class="attachment-body">
  225. <h4><a href="{{ url('attachments_server', attachment=attachment.hash_id) }}">{{ attachment.name }}</a></h4>
  226. <div class="attachment-details">
  227. {% if attachment.user_id %}
  228. <a href="{{ url('user', user=attachment.user_id, username=attachment.user_name_slug) }}">{{ attachment.user_name }}</a>,
  229. {% else %}
  230. {{ attachment.user_name }},
  231. {% endif %}
  232. {% if acl.users.can_see_users_trails() %}
  233. <abbr title="{{ attachment.agent }}">{{ attachment.ip }}</abbr>,
  234. {% endif %}
  235. {{ attachment.date|date }},
  236. {{ _(attachment.filetype.name) }}, {{ attachment.size|filesize }}
  237. </div>
  238. </div>
  239. </div>
  240. </div>
  241. {% endfor %}
  242. </div>
  243. {% endfor %}
  244. </div>
  245. {% endif %}
  246. {% if post.user.signature %}
  247. <div class="post-signature">
  248. <div class="markdown">
  249. {{ post.user.signature_preparsed|markdown_final|safe }}
  250. </div>
  251. </div>
  252. {% endif %}
  253. </div>
  254. <div class="post-footer">{% filter trim %}
  255. <div class="post-actions">
  256. {% if user.pk != post.user_id and post.user_id and acl.warnings.can_warn_members() %}
  257. <form action="{{ url('post_report', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="form-inline form-report" method="post" autocomplete="off">
  258. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  259. <input type="hidden" name="retreat" value="{{ request_path }}">
  260. <input type="hidden" name="reason" value="{% trans message=url('private_thread_find', thread=thread.pk, slug=thread.slug, post=post.pk), thread=thread.name %}Your message {{ message }} in thread "{{ thread }}" was found to violate community guidelines.{% endtrans %}">
  261. <button type="submit" class="btn btn-link tooltip-top" title="{% trans %}Warn user for this post.{% endtrans %}">{% trans %}Warn{% endtrans %}</button>
  262. </form>
  263. {% endif %}
  264. {% if acl.users.can_see_users_trails() -%}
  265. <a href="{{ url('private_post_info', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="post-trail">{% trans %}Info{% endtrans %}</a>
  266. {% endif %}
  267. {% if post.reported and acl.reports.can_handle() and acl.threads.can_mod_posts(forum) %}
  268. <a href="{{ url('private_post_report_show', thread=thread.pk, slug=thread.slug, post=post.pk) }}">{% trans %}Show report{% endtrans %}</a>
  269. {% endif %}
  270. {% if acl.reports.can_report() %}
  271. {% if post.reported_by(user) %}
  272. <a href="{{ url('private_post_report', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="tooltip-top" title="{% trans %}You have already reported this post.{% endtrans %}" disabled="disabled">{% trans %}Reported{% endtrans %}</a>
  273. {% else %}
  274. <form action="{{ url('private_post_report', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="form-inline form-report" method="post" autocomplete="off">
  275. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  276. <button type="submit" class="btn btn-link btn-report tooltip-top" title="{% trans %}Bring this post to moderator attention.{% endtrans %}">{% trans %}Report{% endtrans %}</button>
  277. </form>
  278. {% endif %}
  279. {% endif %}
  280. {% if acl.threads.can_edit_thread(user, forum, thread, post) and thread.start_post_id == post.pk %}
  281. <a href="{{ url('private_thread_edit', thread=thread.pk, slug=thread.slug) }}" class="post-edit">{% trans %}Edit{% endtrans %}</a>
  282. {% elif acl.threads.can_edit_reply(user, forum, thread, post) %}
  283. <a href="{{ url('private_post_edit', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="post-edit">{% trans %}Edit{% endtrans %}</a>
  284. {%- endif %}
  285. {% if acl.threads.can_reply(forum, thread) and (acl.private_threads.is_mod() or participants|length > 1) %}
  286. <a href="{{ url('private_thread_reply', thread=thread.pk, slug=thread.slug, quote=post.pk) }}" class="post-reply">{% trans %}Reply{% endtrans %}</a>
  287. {% endif %}
  288. </div>
  289. {% if post.pk == thread.start_post_id %}
  290. <div class="post-actions">
  291. {% if acl.threads.can_delete_thread(user, forum, thread, post) %}
  292. {% if post.deleted %}
  293. <form action="{{ url('private_thread_show', thread=thread.pk, slug=thread.slug) }}" class="form-inline" method="post">
  294. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  295. <button type="submit" class="btn btn-link btn-hide tooltip-top" title="{% trans %}Make this thread visible to other users{% endtrans %}">{% trans %}Restore{% endtrans %}</button>
  296. </form>
  297. {% else %}
  298. <form action="{{ url('private_thread_hide', thread=thread.pk, slug=thread.slug) }}" class="form-inline" method="post">
  299. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  300. <button type="submit" class="btn btn-link btn-hide tooltip-top" title="{% trans %}Hide this thread from other users{% endtrans %}">{% trans %}Hide{% endtrans %}</button>
  301. </form>
  302. {% endif %}
  303. {% endif %}
  304. {% if acl.threads.can_delete_thread(user, forum, thread, post) == 2 %}
  305. <form action="{{ url('private_thread_delete', thread=thread.pk, slug=thread.slug) }}" class="form-inline prompt-delete-thread" method="post">
  306. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  307. <button type="submit" class="btn btn-link tooltip-top" title="{% trans %}Delete this thread for good{% endtrans %}">{% trans %}Delete{% endtrans %}</button>
  308. </form>
  309. {% endif %}
  310. </div>
  311. {% elif post.pk != thread.start_post_id and acl.threads.can_delete_post(user, forum, thread, post) %}
  312. <div class="post-actions">
  313. {% if acl.threads.can_delete_post(user, forum, thread, post) %}
  314. {% if post.deleted %}
  315. <form action="{{ url('private_post_show', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="form-inline" method="post">
  316. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  317. <button type="submit" class="btn btn-link btn-hide tooltip-top" title="{% trans %}Make this reply visible to other users{% endtrans %}">{% trans %}Restore{% endtrans %}</button>
  318. </form>
  319. {% else %}
  320. <form action="{{ url('private_post_hide', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="form-inline" method="post">
  321. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  322. <button type="submit" class="btn btn-link btn-hide tooltip-top" title="{% trans %}Hide this reply from other users{% endtrans %}">{% trans %}Hide{% endtrans %}</button>
  323. </form>
  324. {% endif %}
  325. {% endif %}
  326. {% if acl.threads.can_delete_post(user, forum, thread, post) == 2 -%}
  327. <form action="{{ url('private_post_delete', thread=thread.pk, slug=thread.slug, post=post.pk) }}" class="form-inline prompt-delete-post" method="post">
  328. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  329. <button type="submit" class="btn btn-link tooltip-top" title="{% trans %}Delete this reply for good{% endtrans %}">{% trans %}Delete{% endtrans %}</button>
  330. </form>
  331. {% endif %}
  332. </div>
  333. {% endif %}
  334. {% endfilter %}</div>
  335. </div>
  336. </div>
  337. {% endif %}
  338. </div>
  339. {% if post.checkpoints_visible %}
  340. <div class="post-checkpoints">
  341. {% for checkpoint in post.checkpoints_visible %}
  342. <div class="post-checkpoint">
  343. <hr>
  344. <span>
  345. {%- if checkpoint.action == 'limit' -%}
  346. <i class="icon-lock"></i> {% trans %}This thread has reached its post limit and has been closed.{% endtrans %}
  347. {%- elif checkpoint.action == 'accepted' -%}
  348. <i class="icon-ok"></i> {% trans user=checkpoint_user(checkpoint), date=checkpoint.date|reltimesince|low %}{{ user }} accepted this thread {{ date }}{% endtrans %}
  349. {%- elif checkpoint.action == 'closed' -%}
  350. <i class="icon-lock"></i> {% trans user=checkpoint_user(checkpoint), date=checkpoint.date|reltimesince|low %}{{ user }} closed this thread {{ date }}{% endtrans %}
  351. {%- elif checkpoint.action == 'opened' -%}
  352. <i class="icon-lock"></i> {% trans user=checkpoint_user(checkpoint), date=checkpoint.date|reltimesince|low %}{{ user }} opened this thread {{ date }}{% endtrans %}
  353. {%- elif checkpoint.action == 'deleted' -%}
  354. <i class="icon-trash"></i> {% trans user=checkpoint_user(checkpoint), date=checkpoint.date|reltimesince|low %}{{ user }} deleted this thread {{ date }}{% endtrans %}
  355. {%- elif checkpoint.action == 'undeleted' -%}
  356. <i class="icon-trash"></i> {% trans user=checkpoint_user(checkpoint), date=checkpoint.date|reltimesince|low %}{{ user }} restored this thread {{ date }}{% endtrans %}
  357. {%- elif checkpoint.action == 'invited' -%}
  358. <i class="icon-plus-sign"></i> {% trans user=checkpoint_user(checkpoint), invited=checkpoint_target(checkpoint), date=checkpoint.date|reltimesince|low %}{{ user }} added {{ invited }} to thread {{ date }}{% endtrans %}
  359. {%- elif checkpoint.action == 'removed' -%}
  360. <i class="icon-remove-sign"></i> {% trans user=checkpoint_user(checkpoint), removed=checkpoint_target(checkpoint), date=checkpoint.date|reltimesince|low %}{{ user }} removed {{ removed }} from thread {{ date }}{% endtrans %}
  361. {%- elif checkpoint.action == 'left' -%}
  362. <i class="icon-remove-sign"></i> {% trans user=checkpoint_user(checkpoint), date=checkpoint.date|reltimesince|low %}{{ user }} left thread {{ date }}{% endtrans %}
  363. {%- endif -%}
  364. {% if user.is_authenticated() %}
  365. {% if acl.threads.can_delete_checkpoint(forum) %}
  366. {% if checkpoint.deleted %}
  367. <form action="{{ url('private_post_checkpoint_show', slug=thread.slug, thread=thread.pk, checkpoint=checkpoint.pk) }}" method="post" class="form-inline">
  368. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  369. <input type="hidden" name="retreat" value="{{ request_path }}#post-{{ post.pk }}">
  370. <button type="submit" class="btn btn-link btn-show">{% trans %}Restore{% endtrans %}</button>
  371. </form>
  372. {% else %}
  373. <form action="{{ url('private_post_checkpoint_hide', slug=thread.slug, thread=thread.pk, checkpoint=checkpoint.pk) }}" method="post" class="form-inline">
  374. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  375. <input type="hidden" name="retreat" value="{{ request_path }}#post-{{ post.pk }}">
  376. <button type="submit" class="btn btn-link btn-hide">{% trans %}Hide{% endtrans %}</button>
  377. </form>
  378. {% endif %}
  379. {% endif %}
  380. {% if acl.threads.can_delete_checkpoint(forum) == 2 %}
  381. <form action="{{ url('private_post_checkpoint_delete', slug=thread.slug, thread=thread.pk, checkpoint=checkpoint.pk) }}" method="post" class="form-inline prompt-delete-checkpoint">
  382. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  383. <input type="hidden" name="retreat" value="{{ request_path }}#post-{{ post.pk }}">
  384. <button type="submit" class="btn btn-link btn-delete">{% trans %}Delete{% endtrans %}</button>
  385. </form>
  386. {% endif %}
  387. {% endif %}
  388. </span>
  389. </div>
  390. {% endfor %}
  391. </div>
  392. {% endif %}
  393. {% endfor %}
  394. </div>
  395. {% if thread_form or posts_form %}
  396. <div class="thread-moderation">
  397. {% if thread_form%}
  398. <form id="thread_form" class="form-inline pull-left" action="{{ request_path }}" method="POST">
  399. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  400. <input type="hidden" name="origin" value="thread_form">
  401. {{ form_theme.field(thread_form.thread_action, attrs={'class': 'span3'}) }}
  402. <button type="submit" class="btn btn-danger">{% trans %}Go{% endtrans %}</button>
  403. </form>
  404. {% endif %}
  405. {% if posts_form %}
  406. <form id="posts_form" class="form-inline pull-right" action="{{ request_path }}" method="POST">
  407. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  408. <input type="hidden" name="origin" value="posts_form">
  409. {{ form_theme.field(posts_form.list_action, attrs={'class': 'span3'}) }}
  410. <button type="submit" class="btn btn-danger">{% trans %}Go{% endtrans %}</button>
  411. </form>
  412. {% endif %}
  413. </div>
  414. {% endif %}
  415. <div class="thread-buttons">
  416. {{ pager(false) }}
  417. {% if acl.threads.can_reply(forum, thread) and (acl.private_threads.is_mod() or participants|length > 1) %}
  418. <a href="{{ url('private_thread_reply', thread=thread.pk, slug=thread.slug) }}" class="btn btn-inverse pull-right"><i class="icon-pencil"></i> {% trans %}Reply{% endtrans %}</a>
  419. {% else %}
  420. <p class="lead thread-signin-message">{% trans %}This thread has too few participants.{% endtrans %}</p>
  421. {% endif %}
  422. </div>
  423. {% if acl.threads.can_reply(forum, thread) and (acl.private_threads.is_mod() or participants|length > 1) %}
  424. <div class="thread-quick-reply">
  425. <form action="{{ url('private_thread_reply', thread=thread.pk, slug=thread.slug) }}" method="post">
  426. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  427. <input type="hidden" name="quick_reply" value="1">
  428. <img src="{{ user.get_avatar(100) }}" alt="{% trans %}Your Avatar{% endtrans %}" class="user-avatar">
  429. {{ editor.editor(quick_reply.post, _('Post Reply'), zen=True, extra=editor_extra()) }}
  430. </form>
  431. </div>
  432. {% endif %}
  433. </div>
  434. <div class="span3">
  435. <div class="thread-participants">
  436. <h3>{% trans participants=participants|length -%}
  437. One participant
  438. {%- pluralize -%}
  439. {{ participants }} participants
  440. {%- endtrans %}</h3>
  441. <ul class="unstyled">{% for participant in participants %}
  442. <li>
  443. <img src="{{ participant.get_avatar(24) }}" alt="" class="avatar-small">
  444. <a href="{{ url('user', username=participant.username_slug, user=participant.pk) }}">{{ participant.username }}</a>
  445. {% if user.pk == thread.start_poster_id or acl.private_threads.is_mod() %}
  446. <form class="form-inline {% if user.pk == participant.pk %}leave-form{% else %}kick-form{% endif %} tooltip-left" action="{{ url('private_thread_remove_user', thread=thread.pk, slug=thread.slug) }}" method="post" title="{% if participant.pk == user.pk %}{% trans %}Leave this thread{% endtrans %}{% else %}{% trans %}Remove from this thread{% endtrans %}{% endif %}">
  447. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  448. <input type="hidden" name="retreat" value="{{ request_path }}">
  449. <input type="hidden" name="user" value="{{ participant.pk }}">
  450. <button type="submit" class="btn btn-{% if participant.pk == user.pk %}danger{% else %}inverse{% endif %} btn-small"><i class="icon-remove"></i></button>
  451. </form>
  452. {% endif %}
  453. </li>
  454. {% endfor %}
  455. </ul>
  456. {% if participants|length < 2 %}
  457. <p class="no-participants">{% trans %}This thread has too few participants. Invite other users to open it for new replies.{% endtrans %}</p>
  458. {% endif %}
  459. <h4>{% trans %}Invite User{% endtrans %}</h4>
  460. <div class="invite-participant">
  461. <form class="form-inline" action="{{ url('private_thread_invite_user', thread=thread.pk, slug=thread.slug) }}" method="post">
  462. <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
  463. <input type="hidden" name="retreat" value="{{ request_path }}">
  464. {{ form_theme.field(invite_form.username, attrs={'class': 'span2', 'placeholder': lang_user_to_invite()}) }}
  465. <button class="btn" type="submit"><i class="icon-plus"></i></button>
  466. </form>
  467. </div>
  468. </div>
  469. </div>
  470. </div>
  471. </div>
  472. {% endblock %}
  473. {% block stylesheets %}{{ super() }}
  474. <link href="{{ STATIC_URL }}cranefly/highlight/styles/monokai.css" rel="stylesheet">
  475. {% endblock %}
  476. {% block javascripts -%}
  477. {{ editor.zen() }}
  478. {{ super() }}
  479. <script src="{{ STATIC_URL }}cranefly/highlight/highlight.pack.js"></script>
  480. <script type="text/javascript">
  481. var l_post_reported = "{{ _('Reported!') }}";
  482. hljs.tabReplace = ' ';
  483. hljs.initHighlightingOnLoad();
  484. EnhancePostsMD();
  485. $(function () {
  486. $('.leave-form').submit(function() {
  487. var decision = confirm("{% if participants|length == 1 -%}
  488. {% trans %}Are you sure you want to leave this thread? It will be deleted after you leave!{% endtrans %}
  489. {%- else -%}
  490. {% trans %}Are you sure you want to leave this thread?{% endtrans %}
  491. {%- endif %}");
  492. return decision;
  493. });
  494. $('.kick-form').submit(function() {
  495. var decision = confirm("{% trans %}Are you sure you want to remove this member from this thread?{% endtrans %}");
  496. return decision;
  497. });
  498. $('#thread_form').submit(function() {
  499. if ($('#id_thread_action').val() == 'hard') {
  500. var decision = confirm("{% trans %}Are you sure you want to delete this thread? This action is not reversible!{% endtrans %}");
  501. return decision;
  502. }
  503. return true;
  504. });
  505. $('#posts_form').submit(function() {
  506. if ($('.post-checkbox[]:checked').length == 0) {
  507. alert("{% trans %}You have to select at least one post.{% endtrans %}");
  508. return false;
  509. }
  510. if ($('#id_list_action').val() == 'merge') {
  511. if ($('.post-checkbox[]:checked').length < 2) {
  512. alert("{% trans %}You have to select at least two posts you want to merge.{% endtrans %}");
  513. return false;
  514. }
  515. var decision = confirm("{% trans %}Are you sure you want to merge selected posts? This action is not reversible!{% endtrans %}");
  516. return decision;
  517. }
  518. if ($('#id_list_action').val() == 'hard') {
  519. var decision = confirm("{% trans %}Are you sure you want to delete selected posts? This action is not reversible!{% endtrans %}");
  520. return decision;
  521. }
  522. return true;
  523. });
  524. $('.prompt-delete-thread').submit(function() {
  525. var decision = confirm("{% trans %}Are you sure you want to delete this thread?{% endtrans %}");
  526. return decision;
  527. });
  528. $('.prompt-delete-post').submit(function() {
  529. var decision = confirm("{% trans %}Are you sure you want to delete this post?{% endtrans %}");
  530. return decision;
  531. });
  532. $('.prompt-delete-checkpoint').submit(function() {
  533. var decision = confirm("{% trans %}Are you sure you want to delete this checkpoint?{% endtrans %}");
  534. return decision;
  535. });
  536. });
  537. </script>
  538. {% if acl.threads.can_reply(forum, thread) %}
  539. {{ editor.js() }}
  540. {% endif %}
  541. {%- endblock %}
  542. {% macro user_label(user) -%}
  543. <{% if user.rank and user.rank.as_tab %}a href="{{ url('users', slug=user.rank.slug) }}"{% else %}span{% endif %} class="label post-author-label{% if user.rank and user.rank.style %} post-label-{{ user.rank.style }}{% endif %}">{{ user.get_title() }}</{% if user.rank and user.rank.as_tab%}a{% else %}span{% endif %}>
  544. {%- endmacro %}
  545. {% macro pager(extra=true) %}
  546. <div class="pagination pull-left">
  547. <ul>
  548. {% if pagination['total'] > 0 %}
  549. <li class="count">{{ macros.pager_label(pagination) }}</li>
  550. {%- if pagination['prev'] > 1 %}<li><a href="{{ url('private_thread', slug=thread.slug, thread=thread.id) }}" class="tooltip-top" title="{% trans %}Go to first page{% endtrans %}"><i class="icon-chevron-left"></i> {% trans %}First{% endtrans %}</a></li>{% endif -%}
  551. {%- if pagination['prev'] > 0 %}<li><a href="{%- if pagination['prev'] > 1 %}{{ url('private_thread', slug=thread.slug, thread=thread.id, page=pagination['prev']) }}{% else %}{{ url('private_thread', slug=thread.slug, thread=thread.id) }}{% endif %}" class="tooltip-top" title="{% trans %}Older Posts{% endtrans %}"><i class="icon-chevron-left"></i></a></li>{% endif -%}
  552. {%- if pagination['next'] > 0 %}<li><a href="{{ url('private_thread', slug=thread.slug, thread=thread.id, page=pagination['next']) }}" class="tooltip-top" title="{% trans %}Newest Posts{% endtrans %}"><i class="icon-chevron-right"></i></a></li>{% endif -%}
  553. {%- if pagination['next'] > 0 and pagination['next'] < pagination['total'] %}<li><a href="{{ url('private_thread', slug=thread.slug, thread=thread.id, page=pagination['total']) }}" class="tooltip-top" title="{% trans %}Go to last page{% endtrans %}">{% trans %}Last{% endtrans %} <i class="icon-chevron-right"></i></a></li>{% endif -%}
  554. {% endif %}
  555. {% if extra %}
  556. {% if not is_read %}<li><a href="{{ url('private_thread_new', slug=thread.slug, thread=thread.id) }}" class="tooltip-top" title="{% trans %}Go to first unread{% endtrans %}"><i class="icon-star"></i> {% trans %}First Unread{% endtrans %}</a></li>{% endif %}
  557. {% endif %}
  558. {% if thread.replies_reported > 0 and acl.threads.can_mod_posts(forum) %}<li><a href="{{ url('private_thread_reported', slug=thread.slug, thread=thread.id) }}" class="tooltip-top" title="{% trans %}Go to first reported post{% endtrans %}"><i class="icon-fire"></i> {% trans %}First Reported{% endtrans %}</a></li>{% endif %}
  559. </ul>
  560. </div>
  561. {% endmacro %}
  562. {% macro checkpoint_user(checkpoint) -%}
  563. {%- if checkpoint.user_id -%}
  564. <a href="{{ url('user', user=checkpoint.user_id, username=checkpoint.user_slug) }}">{{ checkpoint.user_name }}</a>
  565. {%- else -%}
  566. <strong>{{ checkpoint.user_name }}</strong>
  567. {%- endif -%}
  568. {%- endmacro %}
  569. {% macro checkpoint_target(checkpoint) -%}
  570. {%- if checkpoint.target_user_id -%}
  571. <a href="{{ url('user', user=checkpoint.target_user_id, username=checkpoint.target_user_slug) }}">{{ checkpoint.target_user_name }}</a>
  572. {%- else -%}
  573. <strong>{{ checkpoint.target_user_name }}</strong>
  574. {%- endif -%}
  575. {%- endmacro %}
  576. {% macro edit_user(post) -%}
  577. {%- if post.edit_user_id -%}
  578. <a href="{{ url('user', user=post.edit_user_id, username=post.edit_user_slug) }}">{{ post.edit_user_name }}</a>
  579. {%- else -%}
  580. <strong>{{ post.edit_user_name }}</strong>
  581. {%- endif -%}
  582. {%- endmacro %}
  583. {% macro editor_extra() %}
  584. <button id="editor-preview" name="preview" type="submit" class="btn pull-right">{% trans %}Full Editor{% endtrans %}</button>
  585. {% endmacro %}
  586. {# Language strings macros #}
  587. {% macro lang_user_to_invite() -%}{% trans %}User to invite...{% endtrans %}{%- endmacro %}