Files
devplacepy/devplacepy/templates/admin_media.html
T
retoor 741d7aade6 docs: add block/mute user relations, emoji-sync CLI, and uid indexes
- Add `/block`, `/mute` endpoints with block/unblock and mute/unmute functionality in `routers/relations.py`, hiding blocked users' content everywhere except their own profile while muting only suppresses notifications
- Introduce `devplace emoji-sync` CLI command to regenerate `static/js/emoji-shortcodes.js` from the emoji library, documented in `CLAUDE.md` and wired in `cli.py`
- Create `get_blocked_uids()` database helper and apply it in `content.py` `load_detail()` to filter blocked users' posts from detail views
- Implement `_uid_index()` and `_drop_index()` helpers in `database.py` for unique uid indexes across tables, with `user_relations` added to `SOFT_DELETE_TABLES`
- Document new routes in `AGENTS.md` and `README.md`, including emoji shortcodes rendering behavior distinct from the emoji picker
2026-06-19 08:06:09 +00:00

44 lines
2.5 KiB
HTML

{% extends "admin_base.html" %}
{% block admin_content %}
<div class="admin-toolbar">
<h2>Media trash</h2>
<span class="admin-count">{{ pagination.total }} soft-deleted</span>
</div>
<div class="media-grid">
{% for item in media %}
<div class="media-tile" data-media-tile="{{ item['uid'] }}">
{% if item.get('is_image') and item.get('thumbnail_url') %}
<img src="{{ item['thumbnail_url'] }}" alt="{{ item.get('original_filename', '') }}" loading="lazy" class="gallery-thumb" data-lightbox data-full="{{ item['url'] }}">
{% elif item.get('is_image') %}
<img src="{{ item['url'] }}" alt="{{ item.get('original_filename', '') }}" loading="lazy" class="gallery-thumb" data-lightbox data-full="{{ item['url'] }}">
{% elif item.get('is_video') %}
<video src="{{ item['url'] }}" controls preload="metadata" class="gallery-video"></video>
{% else %}
<a href="{{ item['url'] }}" target="_blank" rel="noopener" class="non-image" download="{{ item.get('original_filename', 'file') }}">
<span class="icon">{{ file_icon_emoji(item.get('original_filename', 'file')) }}</span>
<span class="name">{{ item.get('original_filename', 'file') }}</span>
<span class="size">{{ format_file_size(item.get('file_size', 0)) }}</span>
</a>
{% endif %}
<div class="media-tile-meta">
<a href="/profile/{{ item['uploader'] }}" class="media-uploader">{{ item['uploader'] }}</a>
<span class="media-deleted-at">{{ local_dt(item['deleted_at']) }}</span>
</div>
<div class="media-tile-actions">
<form method="POST" action="/media/{{ item['uid'] }}/restore" class="admin-inline-form">
<button type="submit" class="admin-btn admin-btn-sm" aria-label="Restore {{ item.get('original_filename', 'media') }}"><span class="icon">&#x267B;&#xFE0F;</span> Restore</button>
</form>
<form method="POST" action="/admin/media/{{ item['uid'] }}/purge" class="admin-inline-form">
<button type="submit" class="admin-btn admin-btn-sm" data-confirm-danger data-confirm="Permanently delete this media? This cannot be undone." aria-label="Permanently delete {{ item.get('original_filename', 'media') }}"><span class="icon">&#x1F5D1;&#xFE0F;</span> Purge</button>
</form>
</div>
</div>
{% else %}
<div class="empty-state">Trash is empty.</div>
{% endfor %}
</div>
{% include "_pagination.html" %}
{% endblock %}