microblog/app/templates/utils.html

592 lines
23 KiB
HTML

{% macro embed_csrf_token() %}
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
{% endmacro %}
{% macro embed_redirect_url(permalink_id=None) %}
<input type="hidden" name="redirect_url" value="{{ request.url }}{% if permalink_id %}#{{ permalink_id }}{% endif %}">
{% endmacro %}
{% macro admin_block_button(actor) %}
<form action="{{ request.url_for("admin_actions_block") }}" method="POST">
{{ embed_csrf_token() }}
{{ embed_redirect_url() }}
<input type="hidden" name="ap_actor_id" value="{{ actor.ap_id }}">
<input type="submit" value="block">
</form>
{% endmacro %}
{% macro admin_unblock_button(actor) %}
<form action="{{ request.url_for("admin_actions_unblock") }}" method="POST">
{{ embed_csrf_token() }}
{{ embed_redirect_url() }}
<input type="hidden" name="ap_actor_id" value="{{ actor.ap_id }}">
<input type="submit" value="unblock">
</form>
{% endmacro %}
{% macro admin_follow_button(actor) %}
<form action="{{ request.url_for("admin_actions_follow") }}" method="POST">
{{ embed_csrf_token() }}
{{ embed_redirect_url() }}
<input type="hidden" name="ap_actor_id" value="{{ actor.ap_id }}">
<input type="submit" value="follow">
</form>
{% endmacro %}
{% macro admin_like_button(ap_object_id, permalink_id) %}
<form action="{{ request.url_for("admin_actions_like") }}" method="POST">
{{ embed_csrf_token() }}
{{ embed_redirect_url(permalink_id) }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="like">
</form>
{% endmacro %}
{% macro admin_bookmark_button(ap_object_id, permalink_id) %}
<form action="{{ request.url_for("admin_actions_bookmark") }}" method="POST">
{{ embed_csrf_token() }}
{{ embed_redirect_url(permalink_id) }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="bookmark">
</form>
{% endmacro %}
{% macro admin_unbookmark_button(ap_object_id, permalink_id) %}
<form action="{{ request.url_for("admin_actions_unbookmark") }}" method="POST">
{{ embed_csrf_token() }}
{{ embed_redirect_url(permalink_id) }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="unbookmark">
</form>
{% endmacro %}
{% macro admin_pin_button(ap_object_id, permalink_id) %}
<form action="{{ request.url_for("admin_actions_pin") }}" method="POST">
{{ embed_csrf_token() }}
{{ embed_redirect_url(permalink_id) }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="pin">
</form>
{% endmacro %}
{% macro admin_unpin_button(ap_object_id, permalink_id) %}
<form action="{{ request.url_for("admin_actions_unpin") }}" method="POST">
{{ embed_csrf_token() }}
{{ embed_redirect_url(permalink_id) }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="unpin">
</form>
{% endmacro %}
{% macro admin_delete_button(ap_object_id) %}
<form action="{{ request.url_for("admin_actions_delete") }}" method="POST" onsubmit="return confirm('Do you really want to delete this object?');">
{{ embed_csrf_token() }}
{{ embed_redirect_url() }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="delete">
</form>
{% endmacro %}
{% macro admin_announce_button(ap_object_id, disabled=False, permalink_id=None) %}
<form action="{{ request.url_for("admin_actions_announce") }}" method="POST">
{{ embed_csrf_token() }}
{{ embed_redirect_url(permalink_id) }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="share" {% if disabled %}title="Cannot share non-public content" disabled{% endif %}>
</form>
{% endmacro %}
{% macro admin_undo_button(ap_object_id, action="undo", permalink_id=None) %}
<form action="{{ request.url_for("admin_actions_undo") }}" method="POST">
{{ embed_csrf_token() }}
{{ embed_redirect_url(permalink_id) }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="{{ action }}">
</form>
{% endmacro %}
{% macro sensitive_button(permalink_id) %}
<form action="{{ request.url }}#{{ permalink_id }}" method="GET">
<input type="hidden" name="show_sensitive" value="{{ permalink_id }}">
{% for k, v in request.query_params.items() %}
<input type="hidden" name="{{k}}" value="{{v}}">
{% endfor %}
<button type="submit" class="show-sensitive-btn">display sensitive content</button>
</form>
{% endmacro %}
{% macro hide_sensitive_button(permalink_id) %}
<form action="{{ request.url }}#{{ permalink_id }}" method="GET">
{% for k, v in request.query_params.items() %}
{% if not (k == "show_sensitive" and v == permalink_id) %}
<input type="hidden" name="{{k}}" value="{{v}}">
{% endif %}
{% endfor %}
<button type="submit" class="show-sensitive-btn">hide sensitive content</button>
</form>
{% endmacro %}
{% macro show_more_button(permalink_id) %}
<form action="{{ request.url }}#{{ permalink_id }}" method="GET">
<input type="hidden" name="show_more" value="{{ permalink_id }}">
{% for k, v in request.query_params.items() %}
<input type="hidden" name="{{k}}" value="{{v}}">
{% endfor %}
<button type="submit" class="show-more-btn">show more</button>
</form>
{% endmacro %}
{% macro show_less_button(permalink_id) %}
<form action="{{ request.url }}#{{ permalink_id }}" method="GET">
{% for k, v in request.query_params.items() %}
{% if not (k == "show_more" and v == permalink_id) %}
<input type="hidden" name="{{k}}" value="{{v}}">
{% endif %}
{% endfor %}
<button type="submit" class="show-more-btn">show less</button>
</form>
{% endmacro %}
{% macro admin_reply_button(ap_object_id) %}
<form action="/admin/new" method="GET">
<input type="hidden" name="in_reply_to" value="{{ ap_object_id }}">
<button type="submit">reply</button>
</form>
{% endmacro %}
{% macro admin_profile_button(ap_actor_id) %}
<form action="{{ url_for("admin_profile") }}" method="GET">
<input type="hidden" name="actor_id" value="{{ ap_actor_id }}">
<button type="submit">profile</button>
</form>
{% endmacro %}
{% macro admin_expand_button(ap_object_id) %}
<form action="{{ url_for("admin_object") }}" method="GET">
<input type="hidden" name="ap_id" value="{{ ap_object_id }}">
<button type="submit">expand</button>
</form>
{% endmacro %}
{% macro display_box_filters(route) %}
<nav class="flexbox box">
<ul>
<li>Filter by</li>
{% for ap_type in ["Note", "Article", "Page", "Question", "Like", "Announce", "Follow"] %}
<li><a href="{{ url_for(route) }}?filter_by={{ ap_type }}" {% if request.query_params.filter_by == ap_type %}class="active"{% endif %}>
{{ ap_type }}
</a>
</li>
{% endfor %}
{% if request.query_params.filter_by %}
<li>
<a href="{{ url_for(route) }}">Reset filter</a>
</li>
{% endif %}
</ul>
</nav>
{% endmacro %}
{% macro actor_action(inbox_object, text) %}
<div class="actor-action">
<a href="{{ url_for("admin_profile") }}?actor_id={{ inbox_object.actor.ap_id }}">{{ inbox_object.actor.display_name | clean_html(inbox_object.actor) | safe }}</a> {{ text }}
<span title="{{ inbox_object.ap_published_at.isoformat() }}">{{ inbox_object.ap_published_at | timeago }}</span>
</div>
{% endmacro %}
{% macro display_actor(actor, actors_metadata={}, embedded=False, with_details=False) %}
{% set metadata = actors_metadata.get(actor.ap_id) %}
{% if not embedded %}
<div class="ap-object">
{% endif %}
<div class="actor-box h-card p-author">
<div class="icon-box">
<img src="{{ actor.resized_icon_url }}" alt="{{ actor.display_name }}'s avatar" class="actor-icon u-photo">
</div>
<a href="{{ actor.url }}" class="u-url" style="">
<div><strong>{{ actor.display_name | clean_html(actor) | safe }}</strong></div>
<div class="actor-handle p-name">{{ actor.handle }}</div>
</a>
</div>
{% if is_admin and metadata %}
<div>
<nav class="flexbox actor-metadata">
<ul>
{% if metadata.is_following %}
<li>already following</li>
<li>{{ admin_undo_button(metadata.outbox_follow_ap_id, "unfollow")}}</li>
<li>{{ admin_profile_button(actor.ap_id) }}</li>
{% elif metadata.is_follow_request_sent %}
<li>follow request sent</li>
<li>{{ admin_undo_button(metadata.outbox_follow_ap_id, "undo follow") }}</li>
{% else %}
<li>{{ admin_follow_button(actor) }}</li>
{% endif %}
{% if metadata.is_follower %}
<li>follows you</li>
{% if not metadata.is_following %}
<li>{{ admin_profile_button(actor.ap_id) }}</li>
{% endif %}
</li>
{% endif %}
{% if actor.is_from_db %}
{% if actor.is_blocked %}
<li>blocked</li>
<li>{{ admin_unblock_button(actor) }}</li>
{% else %}
<li>{{ admin_block_button(actor) }}</li>
{% endif %}
{% endif %}
</ul>
</nav>
</div>
{% endif %}
{% if with_details %}
{% if actor.summary %}
<div class="p-note">
{{ actor.summary | clean_html(actor) | safe }}
</div>
{% endif %}
{% if actor.attachments %}
<div id="profile-props">
<dl>
{% for prop in actor.attachments %}
{% if prop.type == "PropertyValue" %}
<dt>{{ prop.name }}</dt>
<dd>{{ prop.value | clean_html(actor) | safe }}</dd>
{% endif %}
{% endfor %}
</dl>
</div>
{% endif %}
{% endif %}
{% if not embedded %}
</div>
{% endif %}
{% endmacro %}
{% macro display_og_meta(object) %}
{% if object.og_meta %}
{% for og_meta in object.og_meta %}
<div class="activity-og-meta" style="display:flex;column-gap: 20px;margin:20px 0;">
{% if og_meta.image %}
<div>
<img src="{{ og_meta.image | media_proxy_url }}" style="max-width:200px;max-height:100px;">
</div>
<div>
<a href="{{ og_meta.url }}">{{ og_meta.title }}</a>
{% if og_meta.site_name %}
<small style="display:block;">{{ og_meta.site_name }}</small>
{% endif %}
</div>
{% endif %}
</div>
{% endfor %}
{% endif %}
{% endmacro %}
{% macro display_attachments(object) %}
{% if object.attachments and object.sensitive and not object.permalink_id in request.query_params.getlist("show_sensitive") %}
{{ sensitive_button(object.permalink_id )}}
{% endif %}
{% if object.attachments and (not object.sensitive or (object.sensitive and object.permalink_id in request.query_params.getlist("show_sensitive"))) %}
{% if object.sensitive %}
{{ hide_sensitive_button(object.permalink_id) }}
{% endif %}
{% for attachment in object.attachments %}
{% if attachment.type == "Image" or (attachment | has_media_type("image")) %}
<img src="{{ attachment.resized_url or attachment.proxied_url }}"{% if attachment.name %} title="{{ attachment.name }}" alt="{{ attachment.name }}"{% endif %} class="attachment">
{% elif attachment.type == "Video" or (attachment | has_media_type("video")) %}
<video controls preload="metadata" src="{{ attachment.url | media_proxy_url }}"{% if attachment.name %} title="{{ attachment.name }}"{% endif %} class="attachment"></video>
{% elif attachment.type == "Audio" or (attachment | has_media_type("audio")) %}
<audio controls preload="metadata" src="{{ attachment.url | media_proxy_url }}"{% if attachment.name%} title="{{ attachment.name }}"{% endif %} style="width:480px;" class="attachment"></audio>
{% elif attachment.type == "Link" %}
<a href="{{ attachment.url }}" class="attachment" style="display:inline-block;margin-bottom: 15px;">{{ attachment.url }}</a>
{% else %}
<a href="{{ attachment.url | media_proxy_url }}"{% if attachment.name %} title="{{ attachment.name }}"{% endif %} class="attachment">{{ attachment.url }}</a>
{% endif %}
{% endfor %}
{% endif %}
{% endmacro %}
{% macro display_object(object, likes=[], shares=[], webmentions=[], expanded=False, actors_metadata={}, is_object_page=False) %}
{% set is_article_mode = object.is_from_outbox and object.ap_type == "Article" and is_object_page %}
{% if object.ap_type in ["Note", "Article", "Video", "Page", "Question"] %}
<div class="ap-object {% if expanded %}ap-object-expanded {% endif %}h-entry" id="{{ object.permalink_id }}">
{% if is_article_mode %}
<data class="h-card">
<data class="u-photo" value="{{ local_actor.icon_url }}"></data>
<data class="u-url" value="{{ local_actor.url}}"></data>
<data class="p-name" value="{{ local_actor.handle }}"></data>
</data>
{% else %}
{{ display_actor(object.actor, actors_metadata, embedded=True) }}
{% endif %}
{% if object.in_reply_to %}
<a href="{% if is_admin %}{{ url_for("get_lookup") }}?query={% endif %}{{ object.in_reply_to }}" title="{{ object.in_reply_to }}" class="in-reply-to" rel="nofollow">
in reply to {{ object.in_reply_to|truncate(64, True) }}
</a>
{% endif %}
{% if object.ap_type == "Article" %}
<h2 class="p-name" style="margin-top:0;">{{ object.name }}</h2>
{% endif %}
{% if is_article_mode %}
<time class="dt-published muted" datetime="{{ object.ap_published_at.replace(microsecond=0).isoformat() }}" title="{{ object.ap_published_at.replace(microsecond=0).isoformat() }}">{{ object.ap_published_at.strftime("%b %d, %Y") }}</time>
{% endif %}
{% if object.summary %}
<p class="p-summary">{{ object.summary | clean_html(object) | safe }}</p>
{% endif %}
{% if object.sensitive and object.permalink_id not in request.query_params.getlist("show_more") %}
{{ show_more_button(object.permalink_id) }}
{% endif %}
{% if not object.sensitive or (object.sensitive and object.permalink_id in request.query_params.getlist("show_more")) %}
{% if object.sensitive %}
{{ show_less_button(object.permalink_id) }}
{% endif %}
<div class="e-content">
{{ object.content | clean_html(object) | safe }}
</div>
{% endif %}
{% if object.ap_type == "Question" and (not object.sensitive or (object.sensitive and object.permalink_id in request.query_params.getlist("show_more"))) %}
{% set can_vote = is_admin and object.is_from_inbox and not object.is_poll_ended and not object.voted_for_answers %}
{% if can_vote %}
<form action="{{ request.url_for("admin_actions_vote") }}" method="POST">
{{ embed_csrf_token() }}
{{ embed_redirect_url(object.permalink_id) }}
<input type="hidden" name="in_reply_to" value="{{ object.ap_id }}">
{% endif %}
{% if object.poll_items %}
<ul style="list-style-type: none;padding:0;">
{% for item in object.poll_items %}
<li style="display:block;">
{% set pct = item | poll_item_pct(object.poll_voters_count) %}
<p style="margin:20px 0 10px 0;">
{% if can_vote %}
<input type="{% if object.is_one_of_poll %}radio{% else %}checkbox{% endif %}" name="name" value="{{ item.name }}" id="{{object.permalink_id}}-{{item.name}}">
<label for="{{object.permalink_id}}-{{item.name}}">
{% endif %}
{{ item.name | clean_html(object) | safe }}
{% if object.voted_for_answers and item.name in object.voted_for_answers %}
<span class="muted" style="padding-left:20px;">you voted for this answer</span>
{% endif %}
{% if can_vote %}
</label>
{% endif %}
<span style="float:right;">{{ pct }}% <span class="muted">({{ item.replies.totalItems }} votes)</span></span>
</p>
<svg class="poll-bar">
<line x1="0" y1="10px" x2="{{ pct or 1 }}%" y2="10px" style="stroke-width: 20px;"></line>
</svg>
</li>
{% endfor %}
</ul>
{% endif %}
{% if can_vote %}
<p class="form">
<input type="submit" value="vote">
</p>
</form>
{% endif %}
{% endif %}
{{ display_og_meta(object) }}
<div class="activity-attachment">
{{ display_attachments(object) }}
</div>
<nav class="flexbox activity-bar">
<ul>
<li>
<div><a href="{{ object.url }}"{% if object.is_from_inbox %} rel="nofollow"{% endif %} class="object-permalink u-url u-uid">permalink</a></div>
</li>
{% if not is_article_mode %}
<li>
<time class="dt-published" datetime="{{ object.ap_published_at.replace(microsecond=0).isoformat() }}" title="{{ object.ap_published_at.replace(microsecond=0).isoformat() }}">{{ object.ap_published_at | timeago }}</time>
</li>
{% endif %}
{% if object.ap_type == "Question" %}
{% if object.poll_end_time %}
<li>
{% if object.is_poll_ended %}ended{% else %}ends{% endif %}
<time title="{{ object.poll_end_time.replace(microsecond=0).isoformat() }}">
{{ object.poll_end_time | timeago }}
</time>
</li>
{% endif %}
<li>
{{ object.poll_voters_count }} voters
</li>
{% endif %}
{% if is_admin %}
<li>
{{ object.visibility.value }}
</li>
{% endif %}
{% if object.is_from_outbox %}
{% if object.likes_count %}
<li>
<a href="{{ object.url }}"><strong>{{ object.likes_count }}</strong> like{{ object.likes_count | pluralize }}</a>
</li>
{% endif %}
{% if object.announces_count %}
<li>
<a href="{{ object.url }}"><strong>{{ object.announces_count }}</strong> share{{ object.announces_count | pluralize }}</a>
</li>
{% endif %}
{% if object.webmentions_count %}
<li>
<a href="{{ object.url }}"><strong>{{ object.webmentions_count }}</strong> webmention{{ object.webmentions_count | pluralize }}</a>
</li>
{% endif %}
{% endif %}
{% if (object.is_from_outbox or is_admin) and object.replies_count %}
<li>
<a href="{% if is_admin and not object.is_from_outbox %}{{ url_for("admin_object") }}?ap_id={{ object.ap_id }}{% else %}{{ object.url }}{% endif %}"><strong>{{ object.replies_count }}</strong> repl{{ object.replies_count | pluralize("y", "ies") }}</a>
</li>
{% endif %}
</ul>
</nav>
{% if is_admin and (object.is_from_outbox or object.is_from_inbox) %}
<nav class="flexbox activity-bar">
<ul>
{% if object.is_from_outbox %}
<li>
{{ admin_delete_button(object.ap_id) }}
</li>
<li>
{% if object.is_pinned %}
{{ admin_unpin_button(object.ap_id, object.permalink_id) }}
{% else %}
{{ admin_pin_button(object.ap_id, object.permalink) }}
{% endif %}
</li>
{% endif %}
<li>
{{ admin_reply_button(object.ap_id) }}
</li>
{% if object.is_from_inbox %}
<li>
{% if object.liked_via_outbox_object_ap_id %}
{{ admin_undo_button(object.liked_via_outbox_object_ap_id, "unlike", object.permalink_id) }}
{% else %}
{{ admin_like_button(object.ap_id, object.permalink_id) }}
{% endif %}
</li>
<li>
{% if object.is_bookmarked %}
{{ admin_unbookmark_button(object.ap_id, object.permalink_id) }}
{% else %}
{{ admin_bookmark_button(object.ap_id, object.permalink_id) }}
{% endif %}
</li>
<li>
{% if object.announced_via_outbox_object_ap_id %}
{{ admin_undo_button(object.liked_via_outbox_object_ap_id, "unshare") }}
{% else %}
{{ admin_announce_button(object.ap_id, disabled=object.visibility not in [visibility_enum.PUBLIC, visibility_enum.UNLISTED], permalink_id=object.permalink_id) }}
{% endif %}
</li>
<li>
{{ admin_profile_button(object.actor.ap_id) }}
</li>
{% endif %}
<li>
{{ admin_expand_button(object.ap_id) }}
</li>
</ul>
</nav>
{% endif %}
{% if likes or shares or webmentions %}
<div style="display: flex;column-gap: 20px;flex-wrap: wrap;margin-top:20px;">
{% if likes %}
<div style="flex: 0 1 30%;max-width: 50%;">Likes
<div style="display: flex;column-gap: 20px;row-gap:20px;flex-wrap: wrap;margin-top:20px;">
{% for like in likes %}
<a href="{% if is_admin %}{{ url_for("admin_profile") }}?actor_id={{ like.actor.ap_id }}{% else %}{{ like.actor.url }}{% endif %}" title="{{ like.actor.handle }}" style="height:50px;" rel="noreferrer">
<img src="{{ like.actor.resized_icon_url }}" alt="{{ like.actor.handle}}" style="max-width:50px;">
</a>
{% endfor %}
</div>
</div>
{% endif %}
{% if shares %}
<div style="flex: 0 1 30%;max-width: 50%;">Shares
<div style="display: flex;column-gap: 20px;row-gap:20px;flex-wrap: wrap;margin-top:20px;">
{% for share in shares %}
<a href="{% if is_admin %}{{ url_for("admin_profile") }}?actor_id={{ share.actor.ap_id }}{% else %}{{ share.actor.url }}{% endif %}" title="{{ share.actor.handle }}" style="height:50px;" rel="noreferrer">
<img src="{{ share.actor.resized_icon_url }}" alt="{{ share.actor.handle}}" style="max-width:50px;">
</a>
{% endfor %}
</div>
</div>
{% endif %}
{% if webmentions %}
<div style="flex: 0 1 30%;max-width: 50%;">Webmentions
<div style="display: flex;column-gap: 20px;row-gap:20px;flex-wrap: wrap;margin-top:20px;">
{% for webmention in webmentions %}
{% set wm = webmention.as_facepile_item %}
{% if wm %}
<a href="{{ wm.url }}" title="{{ wm.actor_name }}" style="height:50px;" rel="noreferrer">
<img src="{{ wm.actor_icon_url | media_proxy_url }}" alt="{{ wm.actor_name }}" style="max-width:50px;">
</a>
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
</div>
{% endif %}
</div>
{% endif %}
{% endmacro %}