forked from retoor/devplacepy
Add `_alt_from_url` helper in Python rendering and `altFromUrl` in JS ContentRenderer to generate descriptive alt attributes from image filenames, replacing empty alt strings. Update image embed templates and Avatar component to use derived alt text. Migrate inline `style.width` assignments to CSS custom properties (`--poll-pct`, `--hud-xp`, `--quest-pct`, `--bar-pct`, `--quota-pct`) across PollManager, GameFarm, and profile/quest CSS for better maintainability. Introduce new admin, docs, projects, services, and base CSS utility classes. Add "Code Farm" docs page entry.
102 lines
5.0 KiB
HTML
102 lines
5.0 KiB
HTML
{% extends "admin_base.html" %}
|
|
{% block admin_content %}
|
|
<div class="admin-toolbar">
|
|
<h2>News - Curation</h2>
|
|
<span class="admin-count">{{ pagination.total }} articles</span>
|
|
</div>
|
|
|
|
<div class="admin-table-wrap">
|
|
<table class="admin-table">
|
|
<caption class="sr-only">Imported news articles with grade, status, and curation controls</caption>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" class="admin-news-col-title">Title</th>
|
|
<th scope="col">Source</th>
|
|
<th scope="col">Grade</th>
|
|
<th scope="col">Status</th>
|
|
<th scope="col">Img</th>
|
|
<th scope="col">Imported</th>
|
|
<th scope="col">Landing</th>
|
|
<th scope="col">Featured</th>
|
|
<th scope="col"><span class="sr-only">Actions</span></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for item in articles %}
|
|
<tr>
|
|
<td>
|
|
<a href="{{ item.article['url'] }}" target="_blank" rel="noopener" class="admin-news-title">
|
|
{{ render_title(item.article['title'][:80] ~ ('...' if item.article['title']|length > 80 else '')) }}
|
|
</a>
|
|
</td>
|
|
<td>{{ item.article['source_name'] }}</td>
|
|
<td>
|
|
{% if item.grade >= 9 %}
|
|
<span class="admin-grade admin-grade-top">{{ item.grade }}</span>
|
|
{% elif item.grade >= 7 %}
|
|
<span class="admin-grade admin-grade-high">{{ item.grade }}</span>
|
|
{% else %}
|
|
<span class="admin-grade">{{ item.grade }}</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
<div class="admin-news-status-cell">
|
|
<form method="POST" action="/admin/news/{{ item.article['uid'] }}/publish" class="admin-inline-form">
|
|
<button type="submit" class="admin-toggle-switch {% if item.article.get('status') == 'published' %}active{% endif %}" aria-pressed="{% if item.article.get('status') == 'published' %}true{% else %}false{% endif %}" aria-label="Toggle published status">
|
|
<span class="admin-toggle-knob"></span>
|
|
</button>
|
|
</form>
|
|
<span class="admin-news-status-label">
|
|
{% if item.article.get('status') == 'published' %}Published{% else %}Draft{% endif %}
|
|
</span>
|
|
</div>
|
|
</td>
|
|
<td class="admin-news-img-cell">
|
|
{% if item.has_image %}
|
|
<span title="Has image">🖼</span>
|
|
{% else %}
|
|
<span class="admin-news-img-empty">-</span>
|
|
{% endif %}
|
|
</td>
|
|
<td class="admin-news-date-cell">
|
|
{% if item.synced_at %}
|
|
{{ local_dt(item.synced_at) }}
|
|
{% else %}
|
|
{{ dt_ago(item.synced_at) if item.synced_at else item.time_ago }}
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
<form method="POST" action="/admin/news/{{ item.article['uid'] }}/landing" class="admin-inline-form">
|
|
<button type="submit" class="admin-toggle-switch {% if item.article.get('show_on_landing') %}active{% endif %}" aria-pressed="{% if item.article.get('show_on_landing') %}true{% else %}false{% endif %}" aria-label="Toggle landing page placement">
|
|
<span class="admin-toggle-knob"></span>
|
|
</button>
|
|
</form>
|
|
</td>
|
|
<td>
|
|
<form method="POST" action="/admin/news/{{ item.article['uid'] }}/toggle" class="admin-inline-form">
|
|
<button type="submit" class="admin-toggle-switch {% if item.article.get('featured') %}active{% endif %}" aria-pressed="{% if item.article.get('featured') %}true{% else %}false{% endif %}" aria-label="Toggle featured status">
|
|
<span class="admin-toggle-knob"></span>
|
|
</button>
|
|
</form>
|
|
</td>
|
|
<td>
|
|
<form method="POST" action="/admin/news/{{ item.article['uid'] }}/delete" class="admin-inline-form">
|
|
<button type="submit" class="admin-btn admin-btn-sm admin-btn-danger-text" data-confirm="Delete this article?" aria-label="Delete article">×</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{% include "_pagination.html" %}
|
|
|
|
{% if not articles %}
|
|
<div class="admin-empty">
|
|
<p>No news articles found. The news service runs hourly and fetches articles from the configured API.</p>
|
|
<p><a href="/admin/services">Check service status</a></p>
|
|
</div>
|
|
{% endif %}
|
|
{% endblock %}
|