Molodetz blogrol volgens DPP-template
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
<!-- retoor <retoor@molodetz.nl> -->
|
||||
{% extends "admin/base_admin.html" %}
|
||||
{% block admin_content %}
|
||||
<h1>Auditlog</h1>
|
||||
<div class="table-wrap">
|
||||
<table class="admin-table">
|
||||
<thead><tr><th>Tijd</th><th>Gebeurtenis</th><th>Categorie</th><th>Actor</th><th>Resultaat</th></tr></thead>
|
||||
<tbody>
|
||||
{% for row in rows %}
|
||||
<tr><td>{{ local_dt(row.created_at) }}</td><td><code>{{ row.event_key }}</code></td><td><a href="?category={{ row.category }}">{{ row.category }}</a></td><td>{{ row.actor_kind }}</td><td><span class="status {{ 'failed' if row.result == 'denied' else 'done' }}">{{ row.result }}</span></td></tr>
|
||||
{% else %}
|
||||
<tr><td colspan="5" class="muted">Nog geen regels.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,27 @@
|
||||
<!-- retoor <retoor@molodetz.nl> -->
|
||||
{% extends "admin/base_admin.html" %}
|
||||
{% block admin_content %}
|
||||
<h1>Back-ups</h1>
|
||||
<form class="actions" method="post" action="/admin/backups">
|
||||
<select name="target" aria-label="Doel">{% for target in ['database', 'uploads', 'keys', 'full'] %}<option value="{{ target }}">{{ target }}</option>{% endfor %}</select>
|
||||
<button class="button" type="submit">Back-up inplannen</button>
|
||||
</form>
|
||||
<div class="table-wrap">
|
||||
<table class="admin-table">
|
||||
<thead><tr><th>Doel</th><th>Status</th><th>Grootte</th><th>Aangemaakt</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
{% for row in backups %}
|
||||
<tr>
|
||||
<td>{{ row.target }}</td>
|
||||
<td><span class="status {{ row.status }}">{{ row.status }}</span>{% if row.error %}<br><span class="muted">{{ row.error }}</span>{% endif %}</td>
|
||||
<td>{{ row.size_label if row.size_bytes else '' }}</td>
|
||||
<td>{{ local_dt(row.created_at) }}</td>
|
||||
<td>{% if can_download and row.status == 'done' %}<a class="button ghost small" href="/admin/backups/{{ row.uid }}/download">Download</a>{% endif %}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="5" class="muted">Nog geen back-ups.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,25 @@
|
||||
<!-- retoor <retoor@molodetz.nl> -->
|
||||
{% extends "base.html" %}
|
||||
{% block main_class %}wide{% endblock %}
|
||||
{% block extra_head %}<link rel="stylesheet" href="{{ static_url('/static/css/admin.css') }}">{% block admin_head %}{% endblock %}{% endblock %}
|
||||
{% block content %}
|
||||
<div class="admin-layout">
|
||||
<nav class="admin-nav" aria-label="Beheer">
|
||||
<a href="/admin" class="{{ nav_active(request, '/admin', exact=True) }}">Overzicht</a>
|
||||
<a href="/admin/posts" class="{{ nav_active(request, '/admin/posts') }}">Berichten</a>
|
||||
<a href="/admin/joins" class="{{ nav_active(request, '/admin/joins') }}">Aanmeldingen</a>
|
||||
<a href="/admin/services" class="{{ nav_active(request, '/admin/services') }}">Services</a>
|
||||
<a href="/admin/backups" class="{{ nav_active(request, '/admin/backups') }}">Back-ups</a>
|
||||
<a href="/admin/trash" class="{{ nav_active(request, '/admin/trash') }}">Prullenbak</a>
|
||||
<a href="/admin/users" class="{{ nav_active(request, '/admin/users') }}">Accounts</a>
|
||||
<a href="/admin/settings" class="{{ nav_active(request, '/admin/settings') }}">Instellingen</a>
|
||||
<a href="/admin/audit" class="{{ nav_active(request, '/admin/audit') }}">Auditlog</a>
|
||||
<a href="/admin/stats" class="{{ nav_active(request, '/admin/stats') }}">Statistieken</a>
|
||||
<a href="/profile/api-key">API-sleutel</a>
|
||||
<a href="/docs/beheer">Docs</a>
|
||||
</nav>
|
||||
<div class="admin-main">
|
||||
{% block admin_content %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,12 @@
|
||||
<!-- retoor <retoor@molodetz.nl> -->
|
||||
{% extends "admin/base_admin.html" %}
|
||||
{% block admin_content %}
|
||||
<h1>Beheer</h1>
|
||||
<div class="stat-cards">
|
||||
<div class="stat-card"><span class="value">{{ post_count }}</span><span class="name">Berichten</span></div>
|
||||
<div class="stat-card"><span class="value">{{ open_joins }}</span><span class="name">Open aanmeldingen</span></div>
|
||||
<div class="stat-card"><span class="value">{{ user_count }}</span><span class="name">Accounts</span></div>
|
||||
<div class="stat-card"><span class="value">{{ deleted_count }}</span><span class="name">In prullenbak</span></div>
|
||||
</div>
|
||||
<div class="actions"><a class="button" href="/admin/posts/new">Nieuw bericht</a><a class="button ghost" href="/admin/joins">Aanmeldingen bekijken</a></div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,31 @@
|
||||
<!-- retoor <retoor@molodetz.nl> -->
|
||||
{% extends "admin/base_admin.html" %}
|
||||
{% block admin_content %}
|
||||
<h1>Aanmeldingen</h1>
|
||||
<div class="table-wrap">
|
||||
<table class="admin-table">
|
||||
<thead><tr><th>Wie</th><th>Contact</th><th>Werk</th><th>Bericht</th><th>Status</th><th>Ontvangen</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
{% for item in requests %}
|
||||
<tr>
|
||||
<td>{{ item.name }}</td>
|
||||
<td>{{ item.contact }}</td>
|
||||
<td>{% if item.repo_url %}<a href="{{ item.repo_url }}" rel="nofollow noopener" target="_blank">{{ item.repo_url }}</a>{% if item.link_status %}<br><span class="muted">{{ item.link_status }}{% if item.link_title %}: {{ item.link_title }}{% endif %}</span>{% endif %}{% else %}<span class="muted">geen</span>{% endif %}</td>
|
||||
<td>{{ item.message }}</td>
|
||||
<td><span class="status {{ item.status }}">{{ item.status }}</span></td>
|
||||
<td>{{ local_dt(item.created_at) }}</td>
|
||||
<td class="actions">
|
||||
<form method="post" action="/admin/joins/{{ item.uid }}/status">
|
||||
<select name="status" aria-label="Status">{% for value in ['open', 'contacted', 'accepted', 'declined'] %}<option value="{{ value }}" {% if item.status == value %}selected{% endif %}>{{ value }}</option>{% endfor %}</select>
|
||||
<button class="button ghost small" type="submit">Zet</button>
|
||||
</form>
|
||||
{% if item.repo_url %}<form method="post" action="/admin/joins/{{ item.uid }}/check"><button class="button ghost small" type="submit" data-loading>Link controleren</button></form>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="7" class="muted">Nog geen aanmeldingen.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,31 @@
|
||||
<!-- retoor <retoor@molodetz.nl> -->
|
||||
{% extends "admin/base_admin.html" %}
|
||||
{% block admin_content %}
|
||||
<h1>{{ 'Bericht bewerken' if post else 'Nieuw bericht' }}</h1>
|
||||
<form class="form wide" method="post" action="{{ '/admin/posts/' ~ post.uid if post else '/admin/posts' }}" data-form>
|
||||
<div class="field"><label for="title">Titel</label><input id="title" type="text" name="title" required minlength="3" maxlength="200" value="{{ post.title if post else '' }}"></div>
|
||||
{% set _selected = post.topic if post else 'rol' %}
|
||||
{% include "_topic_selector.html" %}
|
||||
<div class="editor">
|
||||
<div class="field">
|
||||
<label for="body">Tekst (markdown)</label>
|
||||
<textarea id="body" name="body" required minlength="10" data-preview-source>{{ post.body if post else '' }}</textarea>
|
||||
<span class="help">Markdown met GFM. Emoji via :shortcode:. Voorbeeld rechts is een live voorbeeld; de gepubliceerde versie wordt op de server gerenderd.</span>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Voorbeeld</label>
|
||||
<dp-content class="preview prose" data-preview-target></dp-content>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="status">Status</label>
|
||||
<select id="status" name="status">
|
||||
<option value="draft" {% if not post or post.status == 'draft' %}selected{% endif %}>Concept</option>
|
||||
<option value="published" {% if post and post.status == 'published' %}selected{% endif %}>Gepubliceerd</option>
|
||||
</select>
|
||||
</div>
|
||||
<label class="check"><input type="checkbox" name="is_placeholder" value="true" {% if post and post.is_placeholder %}checked{% endif %}> Markeer als placeholder</label>
|
||||
<div class="actions"><button class="button" type="submit" data-loading>Opslaan</button><a class="button ghost" href="/admin/posts">Annuleren</a></div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block extra_js %}<script type="module" src="{{ static_url('/static/js/utils/EditorPreview.js') }}"></script>{% endblock %}
|
||||
@@ -0,0 +1,28 @@
|
||||
<!-- retoor <retoor@molodetz.nl> -->
|
||||
{% extends "admin/base_admin.html" %}
|
||||
{% block admin_content %}
|
||||
<h1>Berichten</h1>
|
||||
<div class="actions"><a class="button" href="/admin/posts/new">Nieuw bericht</a></div>
|
||||
<div class="table-wrap">
|
||||
<table class="admin-table">
|
||||
<thead><tr><th>Titel</th><th>Onderwerp</th><th>Status</th><th>Bijgewerkt</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
{% for post in posts %}
|
||||
<tr>
|
||||
<td><a href="/posts/{{ post.slug }}">{{ plain_title(post.title) }}</a>{% if post.is_placeholder %} <span class="tag-placeholder">Placeholder</span>{% endif %}</td>
|
||||
<td>{{ TOPICS.get(post.topic, post.topic) }}</td>
|
||||
<td><span class="status {{ post.status }}">{{ post.status }}</span></td>
|
||||
<td>{{ local_dt(post.updated_at) }}</td>
|
||||
<td class="actions">
|
||||
<a class="button ghost small" href="/admin/posts/{{ post.uid }}/edit">Bewerken</a>
|
||||
<form method="post" action="/admin/posts/{{ post.uid }}/publish"><button class="button ghost small" type="submit">{{ 'Depubliceren' if post.status == 'published' else 'Publiceren' }}</button></form>
|
||||
<form method="post" action="/admin/posts/{{ post.uid }}/delete" data-confirm="Bericht naar de prullenbak verplaatsen?"><button class="button danger small" type="submit">Verwijderen</button></form>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="5" class="muted">Nog geen berichten.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,53 @@
|
||||
<!-- retoor <retoor@molodetz.nl> -->
|
||||
{% extends "admin/base_admin.html" %}
|
||||
{% block admin_content %}
|
||||
<h1>{{ service.title }}</h1>
|
||||
<p class="muted">{{ service.description }}</p>
|
||||
<div data-service-monitor="detail" data-service="{{ service.name }}">
|
||||
<div class="tabs" role="tablist" data-tabs>
|
||||
<button type="button" class="active" data-tab="overview">Overzicht</button>
|
||||
<button type="button" data-tab="config">Configuratie</button>
|
||||
<button type="button" data-tab="logs">Logs</button>
|
||||
</div>
|
||||
<section data-panel="overview">
|
||||
<p>Status: <span class="status {{ service.status }}" data-field="status">{{ service.status }}</span></p>
|
||||
<div class="stat-cards" data-field="cards">
|
||||
{% for card in service.metrics.cards or [] %}<div class="stat-card"><span class="value">{{ card.value }}</span><span class="name">{{ card.label }}</span></div>{% endfor %}
|
||||
</div>
|
||||
<div class="actions">
|
||||
<form method="post" action="/admin/services/{{ service.name }}/command"><input type="hidden" name="verb" value="{{ 'stop' if service.enabled else 'start' }}"><button class="button ghost small" type="submit">{{ 'Stop' if service.enabled else 'Start' }}</button></form>
|
||||
<form method="post" action="/admin/services/{{ service.name }}/command"><input type="hidden" name="verb" value="run"><button class="button ghost small" type="submit">Nu draaien</button></form>
|
||||
<form method="post" action="/admin/services/{{ service.name }}/command"><input type="hidden" name="verb" value="clear"><button class="button ghost small" type="submit">Logs wissen</button></form>
|
||||
</div>
|
||||
</section>
|
||||
<section data-panel="config" hidden>
|
||||
<form class="form" method="post" action="/admin/services/{{ service.name }}/config">
|
||||
{% for group in service.fields | map(attribute='group') | unique %}
|
||||
<span class="label">{{ group }}</span>
|
||||
{% for field in service.fields if field.group == group %}
|
||||
<div class="field">
|
||||
<label for="f-{{ field.key }}">{{ field.label }}</label>
|
||||
{% if field.type in ('bool', 'select') %}
|
||||
<select id="f-{{ field.key }}" name="{{ field.key }}">
|
||||
{% for option in (field.options if field.type == 'select' else ['0', '1']) %}
|
||||
<option value="{{ option }}" {% if field.value == option | string %}selected{% endif %}>{{ option }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% elif field.type == 'text' %}
|
||||
<textarea id="f-{{ field.key }}" name="{{ field.key }}">{{ field.value }}</textarea>
|
||||
{% else %}
|
||||
<input id="f-{{ field.key }}" type="{{ 'password' if field.secret else ('number' if field.type == 'int' else 'text') }}" name="{{ field.key }}" value="{{ field.value }}" {% if field.minimum is not none %}min="{{ field.minimum }}"{% endif %} {% if field.maximum is not none %}max="{{ field.maximum }}"{% endif %}>
|
||||
{% endif %}
|
||||
{% if field.help %}<span class="help">{{ field.help }}</span>{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
<div class="actions"><button class="button" type="submit">Opslaan</button></div>
|
||||
</form>
|
||||
</section>
|
||||
<section data-panel="logs" hidden>
|
||||
<pre class="log-tail" data-field="logs">{{ service.logs | join('\n') }}</pre>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block extra_js %}<script type="module" src="{{ static_url('/static/js/utils/ServiceMonitor.js') }}"></script>{% endblock %}
|
||||
@@ -0,0 +1,25 @@
|
||||
<!-- retoor <retoor@molodetz.nl> -->
|
||||
{% extends "admin/base_admin.html" %}
|
||||
{% block admin_content %}
|
||||
<h1>Services</h1>
|
||||
<div class="table-wrap">
|
||||
<table class="admin-table" data-service-monitor="index">
|
||||
<thead><tr><th>Service</th><th>Status</th><th>Laatste run</th><th>Volgende run</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
{% for service in services %}
|
||||
<tr data-service="{{ service.name }}">
|
||||
<td><a href="/admin/services/{{ service.name }}">{{ service.title }}</a><br><span class="muted">{{ service.description }}</span></td>
|
||||
<td><span class="status {{ service.status }}" data-field="status">{{ service.status }}</span></td>
|
||||
<td data-field="last_run">{{ local_dt(service.last_run) }}</td>
|
||||
<td data-field="next_run">{{ local_dt(service.next_run) }}</td>
|
||||
<td class="actions">
|
||||
<form method="post" action="/admin/services/{{ service.name }}/command"><input type="hidden" name="verb" value="{{ 'stop' if service.enabled else 'start' }}"><button class="button ghost small" type="submit">{{ 'Stop' if service.enabled else 'Start' }}</button></form>
|
||||
<form method="post" action="/admin/services/{{ service.name }}/command"><input type="hidden" name="verb" value="run"><button class="button ghost small" type="submit">Nu draaien</button></form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block extra_js %}<script type="module" src="{{ static_url('/static/js/utils/ServiceMonitor.js') }}"></script>{% endblock %}
|
||||
@@ -0,0 +1,18 @@
|
||||
<!-- retoor <retoor@molodetz.nl> -->
|
||||
{% extends "admin/base_admin.html" %}
|
||||
{% block admin_content %}
|
||||
<h1>Instellingen</h1>
|
||||
<form class="form" method="post" action="/admin/settings">
|
||||
{% for key, value in settings.items() %}
|
||||
<div class="field">
|
||||
<label for="s-{{ key }}">{{ key }}</label>
|
||||
{% if key in ('maintenance_mode', 'friendly_404') %}
|
||||
<select id="s-{{ key }}" name="{{ key }}"><option value="0" {% if value == '0' %}selected{% endif %}>0</option><option value="1" {% if value == '1' %}selected{% endif %}>1</option></select>
|
||||
{% else %}
|
||||
<input id="s-{{ key }}" type="text" name="{{ key }}" value="{{ value }}">
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="actions"><button class="button" type="submit">Opslaan</button></div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,19 @@
|
||||
<!-- retoor <retoor@molodetz.nl> -->
|
||||
{% extends "admin/base_admin.html" %}
|
||||
{% block admin_content %}
|
||||
<h1>Statistieken</h1>
|
||||
<div class="tabs" role="tablist" data-tabs>
|
||||
<button type="button" class="active" data-tab="paths">Paden</button>
|
||||
<button type="button" data-tab="days">Per dag</button>
|
||||
</div>
|
||||
<section data-panel="paths">
|
||||
<table class="admin-table"><thead><tr><th>Pad</th><th>Hits</th></tr></thead><tbody>
|
||||
{% for row in top_paths %}<tr><td>{{ row.path }}</td><td>{{ row.hits }}</td></tr>{% else %}<tr><td colspan="2" class="muted">Nog geen data.</td></tr>{% endfor %}
|
||||
</tbody></table>
|
||||
</section>
|
||||
<section data-panel="days" hidden>
|
||||
<table class="admin-table"><thead><tr><th>Dag</th><th>Hits</th></tr></thead><tbody>
|
||||
{% for row in daily %}<tr><td>{{ format_date(row.day) }}</td><td>{{ row.hits }}</td></tr>{% else %}<tr><td colspan="2" class="muted">Nog geen data.</td></tr>{% endfor %}
|
||||
</tbody></table>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,26 @@
|
||||
<!-- retoor <retoor@molodetz.nl> -->
|
||||
{% extends "admin/base_admin.html" %}
|
||||
{% block admin_content %}
|
||||
<h1>Prullenbak</h1>
|
||||
<div class="table-wrap">
|
||||
<table class="admin-table">
|
||||
<thead><tr><th>Soort</th><th>Item</th><th>Verwijderd</th><th>Door</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
{% for item in items %}
|
||||
<tr>
|
||||
<td>{{ item.table }}</td>
|
||||
<td>{{ item.label }}</td>
|
||||
<td>{{ local_dt(item.deleted_at) }}</td>
|
||||
<td>{{ item.deleted_by }}</td>
|
||||
<td class="actions">
|
||||
<form method="post" action="/admin/trash/restore"><input type="hidden" name="stamp" value="{{ item.deleted_at }}"><button class="button ghost small" type="submit">Herstellen</button></form>
|
||||
<form method="post" action="/admin/trash/purge" data-confirm="Definitief verwijderen? Dit kan niet ongedaan worden gemaakt."><input type="hidden" name="stamp" value="{{ item.deleted_at }}"><button class="button danger small" type="submit">Definitief</button></form>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="5" class="muted">De prullenbak is leeg.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,25 @@
|
||||
<!-- retoor <retoor@molodetz.nl> -->
|
||||
{% extends "admin/base_admin.html" %}
|
||||
{% block admin_content %}
|
||||
<h1>Accounts</h1>
|
||||
<div class="table-wrap">
|
||||
<table class="admin-table">
|
||||
<thead><tr><th>Naam</th><th>Rol</th><th>Sinds</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
{% for user in users %}
|
||||
<tr>
|
||||
<td>{{ user.username }}{% if is_primary_admin(user) %} <span class="muted">(primair)</span>{% endif %}</td>
|
||||
<td>{{ user.role }}</td>
|
||||
<td>{{ local_dt(user.created_at, 'date') }}</td>
|
||||
<td>
|
||||
<form class="actions" method="post" action="/admin/users/{{ user.uid }}/role">
|
||||
<select name="role" aria-label="Rol"><option value="Admin" {% if user.role == 'Admin' %}selected{% endif %}>Admin</option><option value="Member" {% if user.role == 'Member' %}selected{% endif %}>Member</option></select>
|
||||
<button class="button ghost small" type="submit">Zet</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user