source: Klonkt/src/views/pages/admin-circle.ejs@ 247988e

main
Last change on this file since 247988e was 62b899d, checked in by roboburr <roboburr@…>, 3 months ago

Circle: strip shortcodes from summary + "Sync all now" button

[[playlist:..]]/[[track:..]]/[[album:..]]-shortcodes survived stripHtml (not
HTML) → appeared raw in the circle summary (buggy). Now stripped on ingest
(consumer) and on publish. Also added a global sync button on
Admin → Circle.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@…>

  • Property mode set to 100644
File size: 7.5 KB
Line 
1<div class="container admin-page">
2 <h1>Cirkel</h1>
3 <p><a href="/admin/settings" class="btn">&larr; Instellingen</a></p>
4
5 <% if (success) { %><div class="alert alert-success"><%= success %></div><% } %>
6 <% if (error) { %><div class="alert alert-error"><%= error %></div><% } %>
7
8 <% if (tenancy !== 'circle') { %>
9 <section class="set-card">
10 <p class="set-help">De modus staat niet op <strong>Cirkels</strong>. Zet 'm aan bij
11 <a href="/admin/settings">Instellingen</a> om je cirkel-feed te tonen op <code>/cirkel</code>.
12 Je kunt hieronder al wel bronnen klaarzetten.</p>
13 </section>
14 <% } %>
15
16 <section class="set-card" style="margin-top:1rem">
17 <h2>Mijn zichtbaarheid</h2>
18 <p class="set-help">Doe je mee aan cirkels? Dit maakt je <strong>al-publieke</strong> posts
19 ophaalbaar voor andere Klonkt-sites via een ondertekende feed
20 (<code>/.klonkt/outbox.json</code>). Het is een deelname-keuze, geen privacy-slot:
21 je posts blijven sowieso openbaar op je site, ook als dit uit staat. Wil je iets
22 afschermen, maak die post dan niet-publiek.</p>
23 <form method="post" action="/admin/circle/allow" class="set-form">
24 <label class="set-opt" style="align-items:center">
25 <input type="checkbox" name="allow_circle" value="on" <%= allowCircle ? 'checked' : '' %>>
26 <span><strong>Toon mijn site in cirkels van anderen</strong></span>
27 </label>
28 <button type="submit" class="btn btn-primary">Opslaan</button>
29 </form>
30 </section>
31
32 <section class="set-card" style="margin-top:1rem">
33 <h2>Klonkt-site toevoegen</h2>
34 <p class="set-help">Plak de basis-URL van een andere Klonkt-site. Asymmetrisch: jij toont
35 hen, los van of zij jou tonen.</p>
36 <form method="post" action="/admin/circle/add" class="set-form">
37 <label class="set-field">
38 <span>URL</span>
39 <input type="url" name="remote_url" placeholder="https://artiest.klonkt.com" required>
40 </label>
41 <label class="set-field">
42 <span>Label <small style="font-weight:400">— optioneel</small></span>
43 <input type="text" name="label" maxlength="80" placeholder="bijv. Joost Klein">
44 </label>
45 <button type="submit" class="btn btn-primary">Toevoegen</button>
46 </form>
47 </section>
48
49 <section class="set-card" style="margin-top:1rem">
50 <h2>In mijn cirkel (<%= links.length %>)</h2>
51 <% if (!links.length) { %>
52 <p class="set-help">Nog geen bronnen. Voeg er hierboven een toe.</p>
53 <% } else { %>
54 <form method="post" action="/admin/circle/sync-all" style="margin:0 0 .9rem">
55 <button type="submit" class="btn">&#8635; Alles nu synchroniseren</button>
56 </form>
57 <ul class="circ-list">
58 <% links.forEach(function(l){ %>
59 <li class="circ-item">
60 <div class="circ-main">
61 <strong><%= l.label || l.remote_url %></strong>
62 <small><%= l.remote_url %></small>
63 <div class="circ-status">
64 <% if (l.status === 'active') { %>
65 <span class="circ-badge ok">&#10003; actief</span>
66 <span class="circ-meta"><%= counts[l.id] || 0 %> posts<% if (l.last_synced) { %> &middot; laatst: <%= l.last_synced %><% } %></span>
67 <% } else if (l.status === 'outdated') { %>
68 <span class="circ-badge err">&#8635; versie-mismatch</span>
69 <div class="circ-reason"><%= l.last_error || 'Deze site draait een andere Klonkt-protocolversie — bijwerken nodig om te federeren.' %></div>
70 <% } else if (l.status === 'error') { %>
71 <span class="circ-badge err">&#9888; fout</span>
72 <% if (l.last_error) { %><div class="circ-reason"><%= l.last_error %></div><% } %>
73 <% } else if (l.status === 'paused') { %>
74 <span class="circ-badge">&#9208; gepauzeerd</span>
75 <% } else { %>
76 <%# Onbekende status: toon 'm rauw + eventuele reden i.p.v. stil "gepauzeerd". %>
77 <span class="circ-badge"><%= l.status %></span>
78 <% if (l.last_error) { %><div class="circ-reason"><%= l.last_error %></div><% } %>
79 <% } %>
80 </div>
81 </div>
82 <div class="circ-actions">
83 <form method="post" action="/admin/circle/<%= l.id %>/sync" style="display:inline">
84 <button type="submit" class="btn">Verversen</button>
85 </form>
86 <form method="post" action="/admin/circle/<%= l.id %>/remove" style="display:inline"
87 onsubmit="return confirm('Verwijderen uit je cirkel?')">
88 <button type="submit" class="btn btn-danger">Verwijder</button>
89 </form>
90 </div>
91 </li>
92 <% }); %>
93 </ul>
94 <% } %>
95 </section>
96</div>
97
98<style>
99.admin-page { max-width: 760px; margin: 3rem auto; padding: 0 1rem; }
100.admin-page h1 { font-family: var(--font-display, serif); font-size: 2rem; margin: 0 0 .25rem; }
101.set-card { background: var(--paper-2); border: 1px solid var(--rule); border-radius: 12px; padding: 1.25rem; }
102.set-card h2 { font-family: var(--font-display, serif); font-size: 1.25rem; margin: 0 0 .5rem; }
103.set-help { color: var(--ink-muted); font-size: .9rem; margin: 0 0 1rem; }
104.set-form { display: flex; flex-direction: column; gap: 1rem; }
105.set-opt { display: flex; gap: .75rem; align-items: flex-start; padding: .85rem 1rem; border: 1px solid var(--rule); border-radius: 8px; background: var(--paper); }
106.set-field { display: flex; flex-direction: column; gap: .3rem; }
107.set-field > span { font-size: .8rem; font-weight: 600; color: var(--ink-soft, var(--ink-muted)); }
108.set-field input { width: 100%; box-sizing: border-box; padding: .55rem .7rem; border: 1px solid var(--rule); border-radius: 6px; background: var(--paper); color: var(--ink); font: inherit; }
109.set-form .btn, .circ-actions .btn { align-self: flex-start; }
110.circ-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .6rem; }
111.circ-item { display: flex; justify-content: space-between; gap: 1rem; align-items: center; padding: .75rem 1rem; border: 1px solid var(--rule); border-radius: 8px; background: var(--paper); flex-wrap: wrap; }
112.circ-main { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
113.circ-main small { color: var(--ink-muted); font-size: .78rem; word-break: break-all; }
114.circ-actions { display: flex; gap: .4rem; flex-shrink: 0; }
115.circ-badge { font-size: .72rem; font-weight: 700; padding: .1rem .45rem; border-radius: 20px; background: var(--rule); white-space: nowrap; }
116.circ-badge.ok { background: #d1fae5; color: #065f46; }
117.circ-badge.err { background: #fee2e2; color: #991b1b; }
118.circ-status { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .5rem; margin-top: .25rem; font-size: .78rem; color: var(--ink-muted); }
119.circ-meta { color: var(--ink-muted); }
120/* Reden op een eigen regel onder de badge; normale woordafbreking (geen break-all
121 die hele zinnen midden in woorden knipt — dat zit op de URL-small, niet hier). */
122.circ-reason { flex-basis: 100%; line-height: 1.4; color: var(--ink-muted); word-break: normal; overflow-wrap: anywhere; }
123.btn-danger { background: #dc2626; color: #fff; border-color: #dc2626; }
124.btn-danger:hover { background: #b91c1c; border-color: #b91c1c; color: #fff; }
125.alert { padding: .75rem 1rem; border-radius: 6px; margin-bottom: 1rem; }
126.alert-success { background: #d1fae5; color: #065f46; border: 1px solid #a7f3d0; }
127.alert-error { background: #fee2e2; color: #991b1b; border: 1px solid #fca5a5; }
128</style>
Note: See TracBrowser for help on using the repository browser.