| 1 | <div class="container admin-comments-page">
|
|---|
| 2 | <p><a href="/admin" class="btn">← Beheer</a></p>
|
|---|
| 3 | <h1>Comment moderation</h1>
|
|---|
| 4 |
|
|---|
| 5 | <p class="muted">
|
|---|
| 6 | Mode for this site: <strong><%= moderationMode %></strong>
|
|---|
| 7 | <% if (moderationMode === 'trust') { %>
|
|---|
| 8 | — comments are auto-approved. Switch to <em>moderate</em> in
|
|---|
| 9 | <a href="/admin/sites/<%= site.slug %>/edit">site settings</a> to queue them.
|
|---|
| 10 | <% } else { %>
|
|---|
| 11 | — new comments require approval before showing up on posts.
|
|---|
| 12 | <% } %>
|
|---|
| 13 | </p>
|
|---|
| 14 |
|
|---|
| 15 | <% if (success) { %><div class="audio-flash audio-flash--ok"><%= success %></div><% } %>
|
|---|
| 16 | <% if (error) { %><div class="audio-flash audio-flash--err"><%= error %></div><% } %>
|
|---|
| 17 |
|
|---|
| 18 | <h2>Pending (<%= pending.length %>)</h2>
|
|---|
| 19 | <% if (!pending.length) { %>
|
|---|
| 20 | <p class="muted">Nothing waiting.</p>
|
|---|
| 21 | <% } else { %>
|
|---|
| 22 | <ol class="moderation-list">
|
|---|
| 23 | <% pending.forEach(function(c) { %>
|
|---|
| 24 | <li class="moderation-item">
|
|---|
| 25 | <div class="moderation-meta">
|
|---|
| 26 | <strong><%= c.author_username %></strong>
|
|---|
| 27 | <% if (c.parent_comment_id) { %><span class="muted">(reply)</span><% } %>
|
|---|
| 28 | on <a href="<%= siteUrlBase %>/<%= c.post_slug %>"><%= c.post_title || c.post_slug %></a>
|
|---|
| 29 | <span class="muted">· <%= formatDateTime(c.created_at) %></span>
|
|---|
| 30 | </div>
|
|---|
| 31 | <blockquote class="moderation-content"><%= c.content %></blockquote>
|
|---|
| 32 | <div class="moderation-actions">
|
|---|
| 33 | <form method="post" action="<%= siteUrlBase %>/admin/comments/<%= c.id %>/approve" style="display:inline">
|
|---|
| 34 | <button type="submit" class="btn btn-primary">Approve</button>
|
|---|
| 35 | </form>
|
|---|
| 36 | <form method="post" action="<%= siteUrlBase %>/admin/comments/<%= c.id %>/reject" style="display:inline">
|
|---|
| 37 | <button type="submit" class="btn btn-danger">Reject</button>
|
|---|
| 38 | </form>
|
|---|
| 39 | </div>
|
|---|
| 40 | </li>
|
|---|
| 41 | <% }); %>
|
|---|
| 42 | </ol>
|
|---|
| 43 | <% } %>
|
|---|
| 44 |
|
|---|
| 45 | <h2>Recent decisions</h2>
|
|---|
| 46 | <% if (!recent.length) { %>
|
|---|
| 47 | <p class="muted">Nothing yet.</p>
|
|---|
| 48 | <% } else { %>
|
|---|
| 49 | <ul class="decision-list">
|
|---|
| 50 | <% recent.forEach(function(c) { %>
|
|---|
| 51 | <li class="decision-card decision-card--<%= c.status %>">
|
|---|
| 52 | <span class="status-pill status-pill--<%= c.status %>"><%= c.status %></span>
|
|---|
| 53 | <div class="decision-main">
|
|---|
| 54 | <span class="decision-author"><%= c.author_username %></span>
|
|---|
| 55 | <a class="decision-post" href="<%= siteUrlBase %>/<%= c.post_slug %>"><%= c.post_title || c.post_slug %></a>
|
|---|
| 56 | </div>
|
|---|
| 57 | <span class="decision-date"><%= formatDateTime(c.created_at) %></span>
|
|---|
| 58 | </li>
|
|---|
| 59 | <% }); %>
|
|---|
| 60 | </ul>
|
|---|
| 61 | <% } %>
|
|---|
| 62 | </div>
|
|---|
| 63 |
|
|---|
| 64 | <style>
|
|---|
| 65 | .admin-comments-page { max-width: 900px; margin: 3rem auto; padding: 0 1rem; }
|
|---|
| 66 | .admin-comments-page h1 { font-family: var(--font-display, serif); font-size: 2rem; margin: 0 0 1rem; }
|
|---|
| 67 | .admin-comments-page h2 { font-family: var(--font-display, serif); font-size: 1.25rem; margin: 1.5rem 0 0.75rem; }
|
|---|
| 68 | .muted { color: var(--ink-muted, var(--ink-soft)); }
|
|---|
| 69 | .muted a { color: var(--accent); }
|
|---|
| 70 |
|
|---|
| 71 | .moderation-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 1rem; }
|
|---|
| 72 | .moderation-item {
|
|---|
| 73 | background: var(--paper-2);
|
|---|
| 74 | border: 1px solid var(--rule);
|
|---|
| 75 | border-radius: 8px;
|
|---|
| 76 | padding: 1rem;
|
|---|
| 77 | }
|
|---|
| 78 | .moderation-meta { font-size: 0.85rem; margin-bottom: 0.5rem; color: var(--ink-soft); }
|
|---|
| 79 | .moderation-meta a { color: var(--accent); }
|
|---|
| 80 | .moderation-content {
|
|---|
| 81 | margin: 0 0 0.75rem;
|
|---|
| 82 | padding: 0.5rem 0.75rem;
|
|---|
| 83 | border-left: 3px solid var(--accent);
|
|---|
| 84 | background: var(--paper);
|
|---|
| 85 | white-space: pre-wrap;
|
|---|
| 86 | word-wrap: break-word;
|
|---|
| 87 | color: var(--ink);
|
|---|
| 88 | }
|
|---|
| 89 | .moderation-actions { display: flex; gap: 0.5rem; }
|
|---|
| 90 |
|
|---|
| 91 | .status-pill {
|
|---|
| 92 | display: inline-block; padding: 0.1rem 0.5rem; border-radius: 10px;
|
|---|
| 93 | font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;
|
|---|
| 94 | }
|
|---|
| 95 | .status-pill--approved { background: rgba(40, 160, 90, 0.15); color: #2a9d5e; }
|
|---|
| 96 | .status-pill--rejected { background: rgba(200, 60, 60, 0.15); color: #c33; }
|
|---|
| 97 | .status-pill--pending { background: var(--paper); color: var(--ink-muted, var(--ink-soft)); }
|
|---|
| 98 |
|
|---|
| 99 | /* Recent decisions als cards (i.p.v. een platte tabel) */
|
|---|
| 100 | .decision-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
|
|---|
| 101 | .decision-card {
|
|---|
| 102 | display: flex; align-items: center; gap: 0.85rem;
|
|---|
| 103 | padding: 0.7rem 0.9rem;
|
|---|
| 104 | background: var(--paper-2); border: 1px solid var(--rule);
|
|---|
| 105 | border-left: 3px solid var(--rule); border-radius: 10px;
|
|---|
| 106 | }
|
|---|
| 107 | .decision-card--approved { border-left-color: #2a9d5e; }
|
|---|
| 108 | .decision-card--rejected { border-left-color: #c33; }
|
|---|
| 109 | .decision-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
|
|---|
| 110 | .decision-author { font-weight: 600; }
|
|---|
| 111 | .decision-post { color: var(--accent); text-decoration: none; font-size: 0.88rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|---|
| 112 | .decision-post:hover { text-decoration: underline; }
|
|---|
| 113 | .decision-date { flex: 0 0 auto; color: var(--ink-muted, var(--ink-soft)); font-size: 0.8rem; white-space: nowrap; font-variant-numeric: tabular-nums; }
|
|---|
| 114 | @media (max-width: 520px) {
|
|---|
| 115 | .decision-card { flex-wrap: wrap; }
|
|---|
| 116 | .decision-date { width: 100%; }
|
|---|
| 117 | }
|
|---|
| 118 |
|
|---|
| 119 | .audio-flash { padding: 0.75rem 1rem; border-radius: 6px; margin: 1rem 0; font-size: 0.9rem; }
|
|---|
| 120 | .audio-flash--ok { background: rgba(40, 160, 90, 0.15); color: #2a9d5e; border: 1px solid rgba(40, 160, 90, 0.3); }
|
|---|
| 121 | .audio-flash--err { background: rgba(200, 60, 60, 0.15); color: #c33; border: 1px solid rgba(200, 60, 60, 0.3); }
|
|---|
| 122 | </style>
|
|---|