Add Flask-based application for collecting and archiving Mastodon posts from configured accounts. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
112 lines
4.7 KiB
HTML
112 lines
4.7 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Statuses — Mastodon Collector{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h1>Collected Statuses <span class="text-muted text-sm">({{ total }})</span></h1>
|
|
<a href="{{ url_for('export_csv', account_id=current_account_id or '', type=current_type or '') }}"
|
|
class="btn btn-outline btn-sm">Export CSV</a>
|
|
</div>
|
|
|
|
<div class="card mb-4">
|
|
<form method="GET" action="{{ url_for('statuses_list') }}" class="form-inline">
|
|
<select name="account_id">
|
|
<option value="">All accounts</option>
|
|
{% for acct in accounts %}
|
|
<option value="{{ acct.id }}" {{ 'selected' if current_account_id == acct.id }}>
|
|
{{ acct.handle }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
|
|
<select name="type">
|
|
<option value="">All types</option>
|
|
<option value="post" {{ 'selected' if current_type == 'post' }}>Posts</option>
|
|
<option value="reply" {{ 'selected' if current_type == 'reply' }}>Replies</option>
|
|
<option value="mention" {{ 'selected' if current_type == 'mention' }}>Mentions</option>
|
|
<option value="reblog" {{ 'selected' if current_type == 'reblog' }}>Reblogs</option>
|
|
</select>
|
|
|
|
<input type="search" name="q" placeholder="Search text content..." value="{{ search }}" style="width: 260px;">
|
|
<button type="submit" class="btn btn-primary btn-sm">Filter</button>
|
|
{% if current_account_id or current_type or search %}
|
|
<a href="{{ url_for('statuses_list') }}" class="btn btn-outline btn-sm">Clear</a>
|
|
{% endif %}
|
|
</form>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Date</th>
|
|
<th>Account</th>
|
|
<th>Type</th>
|
|
<th>Content</th>
|
|
<th>Interactions</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for s in statuses %}
|
|
<tr>
|
|
<td class="text-sm" style="white-space:nowrap;">
|
|
{{ s.created_at.strftime('%Y-%m-%d %H:%M') if s.created_at }}
|
|
</td>
|
|
<td class="text-sm">{{ s.account.handle }}</td>
|
|
<td>
|
|
<span class="badge badge-{{ s.status_type }}">{{ s.status_type }}</span>
|
|
</td>
|
|
<td>
|
|
<div class="truncate status-content">
|
|
{{ s.text_content[:200] }}{% if s.text_content and s.text_content|length > 200 %}...{% endif %}
|
|
</div>
|
|
{% if s.tags %}
|
|
<div class="text-sm text-muted mt-2">
|
|
{% for t in s.tags %}
|
|
<span>#{{ t.name }}</span>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
</td>
|
|
<td class="text-sm text-muted" style="white-space:nowrap;">
|
|
↩ {{ s.replies_count }} ⟳ {{ s.reblogs_count }} ★ {{ s.favourites_count }}
|
|
</td>
|
|
<td>
|
|
<a href="{{ url_for('status_detail', status_db_id=s.id) }}" class="btn btn-outline btn-sm">View</a>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
{% if not statuses %}
|
|
<tr>
|
|
<td colspan="6" class="text-muted" style="text-align:center; padding: 24px;">
|
|
No statuses found. The collector runs every {{ (config.get('POLL_INTERVAL_SECONDS', 14400)|int // 3600) }} hours, or you can wait for the first collection cycle.
|
|
</td>
|
|
</tr>
|
|
{% endif %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{% if total_pages > 1 %}
|
|
<div class="pagination">
|
|
{% if page > 1 %}
|
|
<a href="{{ url_for('statuses_list', page=page-1, account_id=current_account_id, type=current_type, q=search) }}">← Prev</a>
|
|
{% endif %}
|
|
|
|
{% for p in range(1, total_pages + 1) %}
|
|
{% if p == page %}
|
|
<span class="current">{{ p }}</span>
|
|
{% elif p <= 3 or p >= total_pages - 2 or (p >= page - 2 and p <= page + 2) %}
|
|
<a href="{{ url_for('statuses_list', page=p, account_id=current_account_id, type=current_type, q=search) }}">{{ p }}</a>
|
|
{% elif p == 4 or p == total_pages - 3 %}
|
|
<span class="text-muted">…</span>
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
{% if page < total_pages %}
|
|
<a href="{{ url_for('statuses_list', page=page+1, account_id=current_account_id, type=current_type, q=search) }}">Next →</a>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
{% endblock %}
|