289 lines
14 KiB
HTML
289 lines
14 KiB
HTML
{% from 'common/icons.html' import icn_image, icn_spoiler, icn_info, icn_lock, icn_warn, icn_error, icn_bookmark, icn_megaphone %}
|
|
{% macro pager(current_page, page_count) %}
|
|
{% set left_start = [1, current_page - 5] | max %}
|
|
{% set right_end = [page_count, current_page + 5] | min %}
|
|
<div class="pager">
|
|
<span>Page:</span>
|
|
{% if current_page > 5 %}
|
|
<a href="?page=1" class="pagebutton">1</a>
|
|
{% if left_start > 2 %}
|
|
<span class="currentpage">…</span>
|
|
{% endif %}
|
|
{% endif %}
|
|
{% for i in range(left_start, current_page) %}
|
|
<a href="?page={{i}}" class="pagebutton">{{i}}</a>
|
|
{% endfor %}
|
|
{% if page_count > 0 %}
|
|
<span class="currentpage">{{current_page}}</span>
|
|
{% endif %}
|
|
{% for i in range(current_page + 1, right_end + 1) %}
|
|
<a href="?page={{i}}" class="pagebutton">{{i}}</a>
|
|
{% endfor %}
|
|
{% if right_end < page_count %}
|
|
{% if right_end < page_count - 1 %}
|
|
<span class="currentpage">…</span>
|
|
{% endif %}
|
|
<a href="?page={{page_count}}" class="pagebutton">{{page_count}}</a>
|
|
{% endif %}
|
|
</div>
|
|
{% endmacro %}
|
|
|
|
{% macro bookmark_button(type, id, message = "Bookmark…", require_reload=false) %}
|
|
{% set bid = type[0] + id | string %}
|
|
<div class="bookmark-dropdown">
|
|
<button type="button" class="contain-svg inline icon" data-bookmark-type="{{type}}" data-send="showBookmarkMenu" data-concept-id="{{id}}" data-bookmark-id="{{bid}}">{{ icn_bookmark(20) }}{{ message | safe }}</button>
|
|
<div class="bookmark-dropdown-inner" data-receive="showBookmarkMenu" data-bookmark-id="{{bid}}" data-require-reload={{require_reload | int}}></div>
|
|
</div>
|
|
{% endmacro %}
|
|
|
|
{% macro infobox(message, kind=InfoboxKind.INFO) %}
|
|
<div class="{{ "infobox " + InfoboxHTMLClass[kind] }}">
|
|
<span>
|
|
<div class="infobox-icon-container">
|
|
{%- if kind == InfoboxKind.INFO -%}
|
|
{{- icn_info() -}}
|
|
{%- elif kind == InfoboxKind.LOCK -%}
|
|
{{- icn_lock() -}}
|
|
{%- elif kind == InfoboxKind.WARN -%}
|
|
{{- icn_warn() -}}
|
|
{%- elif kind == InfoboxKind.ERROR -%}
|
|
{{- icn_error() -}}
|
|
{%- endif -%}
|
|
</div>
|
|
<span>
|
|
{% set m = message.split(';', maxsplit=1) %}
|
|
<strong>{{ m[0] }}</strong>
|
|
{%- if m[1] %}
|
|
{{ m[1] -}}
|
|
{%- endif -%}
|
|
</span>
|
|
</span>
|
|
</div>
|
|
{% endmacro %}
|
|
|
|
{% macro motd(motd_obj) %}
|
|
<div class="motd">
|
|
<div class="motd-icon-container contain-svg">
|
|
{{ icn_megaphone(80) }}
|
|
<i><abbr title="Message of the Day">MOTD</abbr></i>
|
|
</div>
|
|
<div class="motd-content-container">
|
|
<div class="motd-title">{{ motd_obj.title }}</div>
|
|
<div class="motd-body">{{ motd_obj.body_rendered | safe}}</div>
|
|
</div>
|
|
</div>
|
|
{% endmacro %}
|
|
|
|
{% macro timestamp(unix_ts) -%}
|
|
<span class="timestamp" data-utc="{{ unix_ts }}">{{ unix_ts | ts_datetime('%Y-%m-%d %H:%M')}} <abbr title="Server Time">ST</abbr></span>
|
|
{%- endmacro %}
|
|
|
|
{% macro babycode_editor_component(ta_name, ta_placeholder="Post body", optional=False, prefill="", banned_tags=[]) %}
|
|
<div class="babycode-editor-container tab-bar" data-receive="toggleTab">
|
|
<input type="hidden" id="babycode-banned-tags" value="{{banned_tags | unique | list | tojson | forceescape}}">
|
|
<div class="tab-buttons">
|
|
<button data-send="toggleTab" type=button class="tab-button active" data-target-id="tab-edit">Write</button>
|
|
<button data-send="babycodePreview toggleTab" type=button class="tab-button" data-target-id="tab-preview">Preview</button>
|
|
</div>
|
|
<div class="tab-content active" id="tab-edit">
|
|
<span class="babycode-button-container">
|
|
<button data-send="insertBabycodeTag" data-tag="b" class="babycode-button" type=button id="post-editor-bold" title="Insert Bold" {{"disabled" if "b" in banned_tags else ""}}><strong>B</strong></button>
|
|
<button data-send="insertBabycodeTag" data-tag="i" class="babycode-button" type=button id="post-editor-italics" title="Insert Italics" {{"disabled" if "i" in banned_tags else ""}}><em>I</em></button>
|
|
<button data-send="insertBabycodeTag" data-tag="s" class="babycode-button" type=button id="post-editor-strike" title="Insert Strikethrough" {{"disabled" if "s" in banned_tags else ""}}><del>S</del></button>
|
|
<button data-send="insertBabycodeTag" data-tag="u" class="babycode-button" type=button id="post-editor-underline" title="Insert Underline" {{"disabled" if "u" in banned_tags else ""}}><u>U</u></button>
|
|
<button data-send="insertBabycodeTag" data-tag="url=" data-prefill="link label" class="babycode-button" type=button id="post-editor-url" title="Insert Link" {{"disabled" if "url" in banned_tags else ""}}><code>://</code></button>
|
|
<button data-send="insertBabycodeTag" data-tag="code=" data-break-line="1" class="babycode-button" type=button id="post-editor-code" title="Insert Code block" {{"disabled" if "code" in banned_tags else ""}}><code></></code></button>
|
|
<button data-send="insertBabycodeTag" data-tag="img=" data-prefill="alt text" class="babycode-button contain-svg" type=button id="post-editor-img" title="Insert Image" {{"disabled" if "img" in banned_tags else ""}}>{{ icn_image() }}</button>
|
|
<button data-send="insertBabycodeTag" data-tag="ol" data-break-line="1" class="babycode-button" type=button id="post-editor-ol" title="Insert Ordered list" {{"disabled" if "ol" in banned_tags else ""}}>1.</button>
|
|
<button data-send="insertBabycodeTag" data-tag="ul" data-break-line="1" class="babycode-button" type=button id="post-editor-ul" title="Insert Unordered list" {{"disabled" if "u;" in banned_tags else ""}}>•</button>
|
|
<button data-send="insertBabycodeTag" data-tag="spoiler=" data-break-line="1" data-prefill="hidden content" class="babycode-button contain-svg" type=button id="post-editor-spoiler" title="Insert spoiler" {{"disabled" if "spoiler" in banned_tags else ""}}>{{ icn_spoiler() }}</button>
|
|
</span>
|
|
<textarea class="babycode-editor" name="{{ ta_name }}" id="babycode-content" placeholder="{{ ta_placeholder }}" {{ "required" if not optional else "" }} autocomplete="off" data-receive="insertBabycodeTag addQuote">{{ prefill }}</textarea>
|
|
<a href="{{ url_for("app.babycode_guide") }}" target="_blank">babycode guide</a>
|
|
{% if banned_tags %}
|
|
<div>Forbidden tags:</div>
|
|
<div>
|
|
<ul class="horizontal">
|
|
{% for tag in banned_tags | unique %}
|
|
<li><code class="inline-code">[{{ tag }}]</code></li>
|
|
{% endfor %}
|
|
</ul>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="tab-content" id="tab-preview" data-receive="babycodePreview">
|
|
<div id="babycode-preview-errors-container">Type something!</div>
|
|
<div id="babycode-preview-container"></div>
|
|
</div>
|
|
</div>
|
|
<script src="{{ "/static/js/babycode-editor.js" | cachebust }}"></script>
|
|
{% endmacro %}
|
|
|
|
{% macro babycode_editor_form(ta_name, prefill = "", cancel_url="", endpoint="") %}
|
|
{% set save_button_text = "Post reply" if not cancel_url else "Save" %}
|
|
<form class="post-edit-form" method="post" action={{ endpoint }}>
|
|
{{babycode_editor_component(ta_name, prefill = prefill)}}
|
|
{% if not cancel_url %}
|
|
<span>
|
|
<input type="checkbox" id="subscribe" name="subscribe" {{ "checked" if session.get('subscribe_by_default', default=true) else "" }}>
|
|
<label for="subscribe">Subscribe to thread</label>
|
|
</span>
|
|
{% endif %}
|
|
<span>
|
|
<input type="submit" value="{{ save_button_text }}">
|
|
{% if cancel_url %}
|
|
<a class="linkbutton warn" href="{{ cancel_url }}">Cancel</a>
|
|
{% endif %}
|
|
</span>
|
|
</form>
|
|
{% endmacro %}
|
|
|
|
{% macro full_post(
|
|
post, render_sig = True, is_latest = False,
|
|
editing = False, active_user = None, no_reply = false,
|
|
Reactions = none, show_thread_title = false,
|
|
show_bookmark = false, memo = None, bookmark_message = "Bookmark…",
|
|
reload_after_bookmark = false
|
|
) %}
|
|
{% set postclass = "post" %}
|
|
{% if editing %}
|
|
{% set postclass = postclass + " editing" %}
|
|
{% endif %}
|
|
{% set post_permalink = url_for("threads.thread", slug = post['thread_slug'], after = post['id'], _anchor = ("post-" + (post['id'] | string))) %}
|
|
<div class=" {{ postclass }}" id="post-{{ post['id'] }}" data-post-id="{{ post['id'] }}">
|
|
<div class="usercard">
|
|
<div class="usercard-inner">
|
|
<a href="{{ url_for("users.page", username=post['username']) }}" style="display: contents;">
|
|
<img src="{{ post['avatar_path'] }}" class="avatar">
|
|
</a>
|
|
<a href="{{ url_for("users.page", username=post['username']) }}" class="username-link">{{ post['username'] }}</a>
|
|
{% if post['status'] %}
|
|
<em class="user-status">{{ post['status'] }}</em>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="post-content-container" {{ "id=latest-post" if is_latest else "" }}>
|
|
<div class="post-info">
|
|
<span>
|
|
{% if memo -%}
|
|
Memo: <i>{{ memo }}</i> •
|
|
{%- endif %}
|
|
{% if show_thread_title %}
|
|
<a href="{{ url_for('threads.thread', slug=post.thread_slug) }}">Thread: {{ post.thread_title }}</a>
|
|
•
|
|
{% endif %}
|
|
<a href="{{ post_permalink }}" title="Permalink"><i>
|
|
{% if (post['edited_at'] | int) > (post['created_at'] | int) %}
|
|
Edited on {{ timestamp(post['edited_at']) }}
|
|
{% else %}
|
|
Posted on {{ timestamp(post['edited_at']) }}
|
|
{% endif %}
|
|
</i></a>
|
|
</span>
|
|
<span class="thread-actions">
|
|
{% set show_edit = false %}
|
|
{% if active_user %}
|
|
{% set show_edit = (active_user.id | string) == (post['user_id'] | string) and (not post['thread_is_locked'] or active_user.is_mod()) and not no_reply %}
|
|
{% endif %}
|
|
{% if show_edit %}
|
|
<a class="linkbutton" href="{{ url_for('posts.edit', post_id=post.id, _anchor='babycode-content') }}">Edit</a>
|
|
{% endif %}
|
|
|
|
{% set show_reply = true %}
|
|
|
|
{% if not active_user %}
|
|
{% set show_reply = false %}
|
|
{% elif post['thread_is_locked'] and not active_user.is_mod() %}
|
|
{% set show_reply = false %}
|
|
{% elif active_user.is_guest() %}
|
|
{% set show_reply = false %}
|
|
{% elif editing %}
|
|
{% set show_reply = false %}
|
|
{% elif no_reply %}
|
|
{% set show_reply = false %}
|
|
{% endif %}
|
|
|
|
{% if show_reply %}
|
|
{% set qtext = "[url=%s]%s said:[/url]" | format(post_permalink, post['username']) %}
|
|
{% set reply_text = "%s\n[quote]\n%s\n[/quote]\n" | format(qtext, post['original_markup']) %}
|
|
<button data-send="addQuote" value="{{ reply_text }}" class="reply-button">Quote</button>
|
|
{% endif %}
|
|
|
|
{% set show_delete = false %}
|
|
|
|
{% if active_user %}
|
|
{% set show_delete = (((post['user_id'] | string) == (active_user.id | string) and not post['thread_is_locked']) or active_user.is_mod()) and not no_reply %}
|
|
{% endif %}
|
|
|
|
{% if show_delete %}
|
|
<button class="critical post-delete-button" value="{{ post['id'] }}">Delete</button>
|
|
{% endif %}
|
|
|
|
{% if show_bookmark %}
|
|
{{ bookmark_button(type="post", id=post.id, message=bookmark_message, require_reload=reload_after_bookmark)}}
|
|
{% endif %}
|
|
</span>
|
|
</div>
|
|
<div class="post-content">
|
|
{% if not editing %}
|
|
<div class="post-inner" data-post-permalink="{{ post_permalink }}" data-author-username="{{ post.username }}">{{ post['content'] | safe }}</div>
|
|
{% if render_sig and post['signature_rendered'] %}
|
|
<div class="signature-container">
|
|
{{ post['signature_rendered'] | safe }}
|
|
</div>
|
|
{% endif %}
|
|
{% else %}
|
|
{{ babycode_editor_form(cancel_url = post_permalink, prefill = post['original_markup'], ta_name = "new_content") }}
|
|
{% endif %}
|
|
</div>
|
|
{% if Reactions -%}
|
|
{% set can_react = true -%}
|
|
|
|
{% if not active_user -%}
|
|
{% set can_react = false -%}
|
|
{% elif post['thread_is_locked'] and not active_user.is_mod() -%}
|
|
{% set can_react = false -%}
|
|
{% elif active_user.is_guest() -%}
|
|
{% set can_react = false -%}
|
|
{% elif editing -%}
|
|
{% set can_react = false -%}
|
|
{% endif -%}
|
|
|
|
{% set reactions = Reactions.for_post(post.id) -%}
|
|
<div class="post-reactions">
|
|
{% for reaction in reactions %}
|
|
{% set reactors = Reactions.get_users(post.id, reaction.reaction_text) | map(attribute='username') | list %}
|
|
{% set reactors_trimmed = reactors[:10] %}
|
|
{% set reactors_str = reactors_trimmed | join (',\n') %}
|
|
{% if reactors | count > 10 %}
|
|
{% set reactors_str = reactors_str + '\n...and many others' %}
|
|
{% endif %}
|
|
{% set has_reacted = active_user is not none and active_user.username in reactors %}
|
|
<span class="reaction-container" data-emoji="{{ reaction.reaction_text }}" data-post-id="{{ post.id }}"><button type="button" class="reduced reaction-button {{"active" if has_reacted else ""}}" {{ "disabled" if not can_react else ""}} title="{{reactors_str}}"><img class=emoji src="/static/emoji/{{reaction.reaction_text}}.png"> x<span class="reaction-count" data-emoji="{{ reaction.reaction_text }}">{{reaction.c}}</span></button>
|
|
</span>
|
|
{% endfor %}
|
|
{% if can_react %}
|
|
<button type="button" class="reduced add-reaction-button" data-post-id="{{ post.id }}">Add reaction</button>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endmacro %}
|
|
|
|
{% macro accordion(hidden=false, disabled=false) %}
|
|
{% if disabled %}
|
|
{% set hidden = true %}
|
|
{% endif %}
|
|
<div class="accordion {{ "hidden" if hidden else ""}}" data-receive="toggleAccordion">
|
|
<div class="accordion-header">
|
|
<button type="button" class="accordion-toggle" {{"disabled" if disabled else ""}} data-send="toggleAccordion">{{ "+" if hidden else "-" }}</button>
|
|
{{ caller('header') }}
|
|
</div>
|
|
<div class="accordion-content {{ "hidden" if hidden else "" }}">
|
|
{{ caller('content') }}
|
|
</div>
|
|
</div>
|
|
{% endmacro %}
|