5d60d33db1
Volledige Foodlinkk Command Center uitbreiding met social automatisering, reclamefolder filters, Proxmox monitoring en documentatie.
78 lines
3.8 KiB
HTML
78 lines
3.8 KiB
HTML
{% extends "base.html" %}
|
|
{% block content %}
|
|
<div x-data="monitorPage()">
|
|
<header class="page-header">
|
|
<h1>Site Monitor</h1>
|
|
<p class="subtitle page-tip">Websites volgen — alles in PostgreSQL. <a href="/browser">Browser research ↗</a></p>
|
|
</header>
|
|
<div class="kpi-grid">
|
|
<div class="kpi-card clickable-kpi"><div class="kpi-label">Active sites</div><div class="kpi-value">{{ stats.active_sites }}</div></div>
|
|
<div class="kpi-card amber clickable-kpi"><div class="kpi-label">Changes 24h</div><div class="kpi-value">{{ stats.changes_24h }}</div></div>
|
|
</div>
|
|
<section class="panel">
|
|
<h2>Website toevoegen</h2>
|
|
<form class="form-grid" style="display:flex;flex-wrap:wrap;gap:0.5rem;align-items:center" @submit.prevent="addSite">
|
|
<input class="form-input" style="flex:2;min-width:200px" placeholder="https://..." x-model="form.url" required />
|
|
<input class="form-input" style="flex:1;min-width:120px" placeholder="Naam" x-model="form.name" />
|
|
<button class="btn btn-primary" type="submit">Toevoegen</button>
|
|
<button type="button" class="btn btn-secondary" @click="crawlAll()">Alles crawlen</button>
|
|
</form>
|
|
</section>
|
|
<section class="panel">
|
|
<h2>Gemonitorde websites</h2>
|
|
<table class="data-table"><thead><tr><th>Naam</th><th>URL</th><th>Laatste titel</th><th>Laatst gecheckt</th><th>Acties</th></tr></thead>
|
|
<tbody>{% for s in sites %}
|
|
<tr>
|
|
<td>{{ s.name }}</td>
|
|
<td style="max-width:220px;overflow:hidden;text-overflow:ellipsis" title="{{ s.url }}">{{ s.url }}</td>
|
|
<td>{{ s.last_title or '—' }}</td>
|
|
<td>{{ s.last_crawled or '—' }}</td>
|
|
<td class="btn-group">
|
|
<button class="btn btn-sm" @click="crawlOne({{ s.id }})">Crawl</button>
|
|
<button class="btn btn-sm btn-secondary" @click="toggle({{ s.id }})">{{ 'Pauze' if s.is_active else 'Activeer' }}</button>
|
|
<button class="btn btn-sm btn-reject" @click="remove({{ s.id }}, false)">Verwijder</button>
|
|
</td></tr>{% else %}
|
|
<tr><td colspan="5" class="empty-state">Geen sites.</td></tr>
|
|
{% endfor %}</tbody></table>
|
|
<p class="page-tip" style="margin-top:0.75rem">Verwijder = permanent uit database. Pauze = tijdelijk uitgeschakeld.</p>
|
|
</section>
|
|
<div class="grid-2">
|
|
<section class="panel"><h2>Wijzigingen</h2>
|
|
<ul>{% for c in page_changes %}<li><strong>{{ c.name or c.url }}</strong> · {{ c.changed_at }}</li>{% else %}<li class="empty-state">Geen wijzigingen</li>{% endfor %}</ul>
|
|
</section>
|
|
<section class="panel"><h2>Crawl logs</h2>
|
|
<ul>{% for l in crawl_logs %}<li><span class="badge">{{ l.status }}</span> {{ l.message }} <small>{{ l.logged_at }}</small></li>{% endfor %}</ul>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
{% block scripts %}
|
|
<script>
|
|
function monitorPage() {
|
|
return {
|
|
form: { url: '', name: '' },
|
|
async addSite() {
|
|
try {
|
|
await Cockpit.api('/monitor/sites', { method: 'POST', body: JSON.stringify(this.form) });
|
|
Cockpit.toast('Site toegevoegd', 'success'); location.reload();
|
|
} catch (e) { Cockpit.toast(e.message, 'error'); }
|
|
},
|
|
async crawlAll() {
|
|
await Cockpit.api('/monitor/trigger-crawl', { method: 'POST', body: '{}' });
|
|
Cockpit.toast('Crawl gestart', 'success'); setTimeout(() => location.reload(), 2000);
|
|
},
|
|
async crawlOne(id) {
|
|
await Cockpit.api('/monitor/trigger-crawl', { method: 'POST', body: JSON.stringify({ site_id: id }) });
|
|
Cockpit.toast('Crawl gestart', 'success'); setTimeout(() => location.reload(), 2000);
|
|
},
|
|
async toggle(id) { await Cockpit.api('/monitor/sites/' + id + '/toggle', { method: 'PATCH' }); location.reload(); },
|
|
async remove(id) {
|
|
if (!confirm('Website permanent verwijderen uit monitoring?')) return;
|
|
await Cockpit.api('/monitor/sites/' + id + '?hard=true', { method: 'DELETE' });
|
|
Cockpit.toast('Verwijderd', 'success'); location.reload();
|
|
}
|
|
};
|
|
}
|
|
</script>
|
|
{% endblock %}
|