Admin improvements and design tweaks

main
Thomas Sileo 2022-07-03 22:01:47 +02:00
parent 1acefc679d
commit 45dc57b538
8 changed files with 139 additions and 118 deletions

View File

@ -158,15 +158,23 @@ async def admin_bookmarks(
models.InboxObject.ap_type.in_(
["Note", "Article", "Video", "Announce"]
),
models.InboxObject.is_hidden_from_stream.is_(False),
models.InboxObject.undone_by_inbox_object_id.is_(None),
models.InboxObject.is_bookmarked.is_(True),
)
.options(
joinedload(models.InboxObject.relates_to_inbox_object),
joinedload(models.InboxObject.relates_to_outbox_object).options(
joinedload(
models.OutboxObject.outbox_object_attachments
).options(joinedload(models.OutboxObjectAttachment.upload)),
),
joinedload(models.InboxObject.actor),
)
.order_by(models.InboxObject.ap_published_at.desc())
.limit(20)
)
).all()
# TODO: joinedload + unique
)
.unique()
.all()
)
return await templates.render_template(
db_session,
@ -185,7 +193,7 @@ async def admin_inbox(
filter_by: str | None = None,
cursor: str | None = None,
) -> templates.TemplateResponse:
where = [models.InboxObject.ap_type.not_in(["Accept"])]
where = [models.InboxObject.ap_type.not_in(["Accept", "Delete"])]
if filter_by:
where.append(models.InboxObject.ap_type == filter_by)
if cursor:
@ -253,7 +261,10 @@ async def admin_outbox(
filter_by: str | None = None,
cursor: str | None = None,
) -> templates.TemplateResponse:
where = [models.OutboxObject.ap_type.not_in(["Accept"])]
where = [
models.OutboxObject.ap_type.not_in(["Accept", "Delete"]),
models.OutboxObject.is_deleted.is_(False),
]
if filter_by:
where.append(models.OutboxObject.ap_type == filter_by)
if cursor:

View File

@ -1,8 +1,12 @@
$font-stack: Helvetica, sans-serif;
$background: #002B36; // solarized background color
// font-family: Inconsolata, monospace;
$text-color: #ccc;
$primary-color: #e14eea;
$secondary-color: #32cd32;
$form-background-color: #ccc;
$form-text-color: #222;
$muted-color: #586e75; // solarized comment text
// #93a1a1; solarized body text
@ -12,7 +16,7 @@ body {
font-size: 20px;
line-height: 32px;
background: $background;
color: #ccc;
color: $text-color;
margin: 0;
padding: 0;
display: flex;
@ -25,37 +29,52 @@ a {
.activity-main {
a {
color: #ddd;
color: $text-color;
}
}
.activity-wrap {
}
code, pre {
color: #859900; // #cb4b16; // #268bd2; // #2aa198;
color: $secondary-color; // #cb4b16; // #268bd2; // #2aa198;
font-family: 'Inconsolata, monospace';
}
.form {
input, select, textarea {
font-size: 20px;
border: 0;
padding: 5px;
background: $form-background-color;
color: $form-text-color;
&:focus {
outline: 1px solid $secondary-color;
}
}
input[type=submit] {
font-size: 20px;
outline: none;
background: $primary-color;
color: $form-text-color;
padding: 5px;
}
}
header {
.title {
font-size: 1.3em;
text-decoration: none;
.handle {
font-size: 0.85em;
color: #93a1a1;
color: $muted-color;
}
}
.counter {
color: #93a1a1;
color: $muted-color;
}
}
.purple {
color: #e14eea;
}
a {
color: #e14eea;
}
.green, a:hover {
color: #32cd32;
color: $primary-color;
&:hover {
color: $secondary-color;
}
}
#main {
flex: 1;
@ -69,7 +88,7 @@ footer {
width: 100%;
max-width: 960px;
margin: 20px auto;
color: #93a1a1;
color: $muted-color;
}
.actor-box {
display: flex;
@ -81,7 +100,7 @@ footer {
.actor-handle {
font-size: 0.85em;
line-height: 1em;
color: #93a1a1;
color: $muted-color;
}
.actor-icon {
margin-top: 5px;
@ -99,10 +118,6 @@ footer {
}
}
#admin {
}
.activity-bar {
input[type=submit], button {
font-size: 20px;
line-height: 32px;
@ -111,31 +126,13 @@ input[type=submit], button {
border: none;
padding: 0!important;
cursor: pointer;
color: #e14eea;
}
input[type=submit]:hover, button:hover {
color: #32cd32;
}
color: $muted-color;
&:hover {
color: $secondary-color;
}
}
nav.flexbox {
input[type=submit] {
font-size: 20px;
line-height: 32px;
font-family: "Inconsolata, monospace";
background: none!important;
border: none;
padding: 0!important;
cursor: pointer;
color: #e14eea;
}
input[type=submit]:hover {
color: #32cd32;
}
ul {
display: flex;
flex-wrap: wrap;
@ -185,9 +182,10 @@ nav.flexbox {
margin-left: 5px;
}
.actor-handle {
color: #93a1a1;
color: $muted-color;
}
.activity-date { float:right; }
.object-visibility { float:right;color: $muted-color;margin-right:10px; }
}
}
.activity-attachment {
@ -199,22 +197,20 @@ nav.flexbox {
}
}
.activity-bar {
display: flex;
margin-left: 60px;
margin-top: 10px;
.bar-item {
display: flex;
margin-right: 20px;
}
}
}
.actor-action {
padding-left:70px;
margin-top:20px;
margin-bottom:-10px;
span {
float: right;
color: $muted-color;
}
}
.actor-metadata {
color: $muted-color;
}
.emoji, .custom-emoji {
max-width: 25px;
}

View File

@ -4,17 +4,26 @@
{{ utils.display_box_filters("admin_inbox") }}
{% 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 }}</a> {{ text }}
<span>{{ inbox_object.ap_published_at | timeago }}</span>
</div>
{% endmacro %}
{% for inbox_object in inbox %}
{% if inbox_object.ap_type == "Announce" %}
{{ actor_action(inbox_object, "shared one of your post") }}
{{ utils.display_object(inbox_object.relates_to_anybox_object) }}
{% elif inbox_object.ap_type in ["Article", "Note", "Video"] %}
{{ utils.display_object(inbox_object) }}
{% elif inbox_object.ap_type == "Follow" %}
<div class="actor-action">
{{ inbox_object.actor.display_name }} followed you
<span>{{ inbox_object.ap_published_at | timeago }}</span>
</div>
{{ actor_action(inbox_object, "followed you") }}
{{ utils.display_actor(inbox_object.actor, actors_metadata) }}
{% elif inbox_object.ap_type == "Like" %}
{{ actor_action(inbox_object, "liked one of your post") }}
{{ utils.display_object(inbox_object.relates_to_anybox_object) }}
{% else %}
<p>
Implement {{ inbox_object.ap_type }}

View File

@ -7,7 +7,7 @@
{{ utils.display_object(in_reply_to_object) }}
{% endif %}
<form action="{{ request.url_for("admin_actions_new") }}" enctype="multipart/form-data" method="POST">
<form class="form" action="{{ request.url_for("admin_actions_new") }}" enctype="multipart/form-data" method="POST">
{{ utils.embed_csrf_token() }}
{{ utils.embed_redirect_url() }}
<p>
@ -24,12 +24,12 @@
<span class="ji"><img src="{{ emoji.icon.url }}" alt="{{ emoji.name }}" title="{{ emoji.name }}" class="custom-emoji"></span>
{% endfor %}
<textarea name="content" rows="10" cols="50" autofocus="autofocus" designMode="on" style="font-size:1.2em;width:95%;">{{ content }}</textarea>
<textarea name="content" rows="10" cols="50" autofocus="autofocus" designMode="on" placeholder="Hey!" style="font-size:1.2em;width:95%;">{{ content }}</textarea>
<p>
<input type="text" name="content_warning" placeholder="content warning (will mark the post as sensitive)" style="width:300px;">
<input type="text" name="content_warning" placeholder="content warning (will mark the post as sensitive)" style="width:95%;">
</p>
<p>
<input type="checkbox" name="is_sensitive" id="is_sensitive"> <label for="is_sensitive">Mark attachment(s) as sentive</label>
<input type="checkbox" name="is_sensitive" id="is_sensitive"> <label for="is_sensitive">Mark attachment(s) as sensitive</label>
</p>
<input type="hidden" name="in_reply_to" value="{{ request.query_params.in_reply_to }}">
<p>

View File

@ -16,7 +16,6 @@
<div class="actor-action">You followed</div>
{{ utils.display_actor(outbox_object.relates_to_actor, actors_metadata) }}
{% elif outbox_object.ap_type in ["Article", "Note", "Video"] %}
{% if outbox_object.is_deleted %}Deleted{% endif %}
{{ utils.display_object(outbox_object) }}
{% else %}
Implement {{ outbox_object.ap_type }}

View File

@ -4,7 +4,7 @@
<p>Interact with an ActivityPub object via its URL or look for a user using <i>@user@domain.tld</i></p>
<form action="{{ url_for("get_lookup") }}" method="GET">
<form class="form" action="{{ url_for("get_lookup") }}" method="GET">
<input type="text" name="query" value="{{ query if query else "" }}">
<input type="submit" value="Lookup">
</form>

View File

@ -4,7 +4,7 @@
{% include "header.html" %}
<h2>Remotely follow {{ local_actor.display_name }}</h2>
<form action="{{ url_for("post_remote_follow") }}" method="POST">
<form class="form" action="{{ url_for("post_remote_follow") }}" method="POST">
<input type="hidden" name="csrf_token" value="{{remote_follow_csrf_token}}">
<input type="text" name="profile" placeholder="you@instance.tld">
<input type="submit" value="Follow">

View File

@ -11,7 +11,7 @@
{{ embed_csrf_token() }}
{{ embed_redirect_url() }}
<input type="hidden" name="ap_actor_id" value="{{ actor.ap_id }}">
<input type="submit" value="Follow">
<input type="submit" value="follow">
</form>
{% endmacro %}
@ -20,7 +20,7 @@
{{ embed_csrf_token() }}
{{ embed_redirect_url() }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="Like">
<input type="submit" value="like">
</form>
{% endmacro %}
@ -29,7 +29,7 @@
{{ embed_csrf_token() }}
{{ embed_redirect_url() }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="Bookmark">
<input type="submit" value="bookmark">
</form>
{% endmacro %}
@ -38,7 +38,7 @@
{{ embed_csrf_token() }}
{{ embed_redirect_url() }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="Unbookmark">
<input type="submit" value="unbookmark">
</form>
{% endmacro %}
@ -47,7 +47,7 @@
{{ embed_csrf_token() }}
{{ embed_redirect_url() }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="Pin">
<input type="submit" value="pin">
</form>
{% endmacro %}
@ -56,7 +56,7 @@
{{ embed_csrf_token() }}
{{ embed_redirect_url() }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="Unpin">
<input type="submit" value="unpin">
</form>
{% endmacro %}
@ -65,7 +65,7 @@
{{ embed_csrf_token() }}
{{ embed_redirect_url() }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_id }}">
<input type="submit" value="Delete">
<input type="submit" value="delete">
</form>
{% endmacro %}
@ -74,7 +74,7 @@
{{ embed_csrf_token() }}
{{ embed_redirect_url() }}
<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 %}>
<input type="submit" value="share" {% if disabled %}title="Cannot share non-public content" disabled{% endif %}>
</form>
{% endmacro %}
@ -111,36 +111,40 @@
{% 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>
<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>
<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>
<button type="submit">expand</button>
</form>
{% endmacro %}
{% macro display_box_filters(route) %}
<p>Filter by
<nav class="flexbox">
<ul>
<li>Filter by</li>
{% for ap_type in ["Note", "Like", "Announce", "Follow"] %}
<a style="margin-right:12px;" href="{{ url_for(route) }}?filter_by={{ ap_type }}">
{% if request.query_params.filter_by == ap_type %}
<strong>{{ ap_type }}</strong>
{% else %}
{{ ap_type }}
{% endif %}</a>
{% endfor %}.
{% if request.query_params.filter_by %}<a href="{{ url_for(route) }}">Reset filter</a>{% endif %}</p>
</p>
<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 %}
</nav>
{% endmacro %}
{% macro display_actor(actor, actors_metadata) %}
@ -156,11 +160,11 @@
</div>
{% if is_admin and metadata %}
<div>
<nav class="flexbox">
<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_undo_button(metadata.outbox_follow_ap_id, "unfollow")}}</li>
{% elif metadata.is_follow_request_sent %}
<li>follow request sent</li>
{% else %}
@ -289,9 +293,9 @@
<strong>{{ object.actor.display_name }}</strong>
<a href="{{ object.actor.url}}" class="actor-handle p-author h-card">{{ object.actor.handle }}</a>
<span class="activity-date" title="{{ object.ap_published_at.isoformat() }}">
{{ object.visibility.value }}
<a href="{{ object.url }}" class="u-url u-uid"><time class="dt-published" datetime="{{ object.ap_published_at }}">{{ object.ap_published_at | timeago }}</time></a>
</span>
{% if is_admin %}<span class="object-visibility">{{ object.visibility.value }}</span>{% endif %}
{% if object.summary %}
<p class="p-summary">{{ object.summary | clean_html(object) | safe }}</p>
{% endif %}
@ -314,72 +318,74 @@
{{ display_attachments(object) }}
</div>
<div class="activity-bar">
<nav class="flexbox activity-bar">
<ul>
{% if object.is_from_outbox %}
<div class="bar-item">
<li>
<div class="comment-count">{{ object.likes_count }} like{{ object.likes_count | pluralize }}</div>
</div>
</li>
<div class="bar-item">
<li>
<div class="retweet-count">{{ object.announces_count }} share{{ object.announces_count | pluralize }}</div>
</div>
</li>
<div class="bar-item">
<li>
<div class="retweet-count">{{ object.replies_count }} repl{{ object.replies_count | pluralize("y", "ies") }}</div>
</div>
</li>
{% if is_admin %}
<div class="bar-item">
<li>
{{ admin_delete_button(object.ap_id) }}
</div>
<div class="bar-item">
</li>
<li>
{{ admin_reply_button(object.ap_id) }}
</div>
<div class="bar-item">
</li>
<li>
{% if object.is_pinned %}
{{ admin_unpin_button(object.ap_id) }}
{% else %}
{{ admin_pin_button(object.ap_id) }}
{% endif %}
</div>
</li>
{% endif %}
{% endif %}
{% if object.is_from_inbox %}
<div class="bar-item">
<li>
{% if object.liked_via_outbox_object_ap_id %}
{{ admin_undo_button(object.liked_via_outbox_object_ap_id, "Unlike") }}
{{ admin_undo_button(object.liked_via_outbox_object_ap_id, "unlike") }}
{% else %}
{{ admin_like_button(object.ap_id) }}
{% endif %}
</div>
<div class="bar-item">
</li>
<li>
{% if object.is_bookmarked %}
{{ admin_unbookmark_button(object.ap_id) }}
{% else %}
{{ admin_bookmark_button(object.ap_id) }}
{% endif %}
</div>
<div class="bar-item">
</li>
<li>
{% if object.announced_via_outbox_object_ap_id %}
{{ admin_undo_button(object.liked_via_outbox_object_ap_id, "Unshare") }}
{{ 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]) }}
{% endif %}
</div>
<div class="bar-item">
</li>
<li>
{{ admin_reply_button(object.ap_id) }}
</div>
<div class="bar-item">
</li>
<li>
{{ admin_profile_button(object.actor.ap_id) }}
</div>
<div class="bar-item">
</li>
<li>
{{ admin_expand_button(object.ap_id) }}
</div>
</li>
{% endif %}
</div>
</ul>
</nav>
</div>
{% endif %}
{% endmacro %}