source: Klonkt/src/views/pages/admin-circle.ejs@ 49f698b

main
Last change on this file since 49f698b was 2520dcc, checked in by roboburr <roboburr@…>, 3 months ago

feat(cirkel): add site without typing https://

A bare domain (artiest.klonkt.com) is automatically prefixed with https://; a
typed http:// is upgraded to https:// (federation is intentionally https-only).
Field is now type=text (type=url blocked a bare domain before submission) with
inputmode=url + placeholder without a scheme.

Co-Authored-By: Claude <noreply@…>

  • Property mode set to 100644
File size: 7.9 KB
Line 
1<div class="container admin-page">
2 <h1><%= t('acir.title') %></h1>
3 <p><a href="/admin/settings" class="btn">&larr; <%= t('acir.back_settings') %></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"><%= t('acir.mode_off_1') %> <strong><%= t('acir.circles') %></strong>. <%= t('acir.mode_off_2') %>
11 <a href="/admin/settings"><%= t('acir.settings') %></a> <%= t('acir.mode_off_3') %> <code>/cirkel</code>.
12 <%= t('acir.mode_off_4') %></p>
13 </section>
14 <% } %>
15
16 <section class="set-card" style="margin-top:1rem">
17 <h2><%= t('acir.visibility_title') %></h2>
18 <p class="set-help"><%= t('acir.visibility_help_1') %> <strong><%= t('acir.all_public') %></strong> <%= t('acir.visibility_help_2') %>
19 (<code>/.klonkt/outbox.json</code>). <%= t('acir.visibility_help_3') %></p>
20 <form method="post" action="/admin/circle/allow" class="set-form">
21 <label class="set-opt" style="align-items:center">
22 <input type="checkbox" name="allow_circle" value="on" <%= allowCircle ? 'checked' : '' %>>
23 <span><strong><%= t('acir.show_in_circles') %></strong></span>
24 </label>
25 <button type="submit" class="btn btn-primary"><%= t('acir.save') %></button>
26 </form>
27 </section>
28
29 <section class="set-card" style="margin-top:1rem">
30 <h2><%= t('acir.add_title') %></h2>
31 <p class="set-help"><%= t('acir.add_help') %></p>
32 <form method="post" action="/admin/circle/add" class="set-form">
33 <label class="set-field">
34 <span><%= t('acir.url') %></span>
35 <input type="text" name="remote_url" inputmode="url" autocapitalize="off" autocorrect="off" spellcheck="false" placeholder="artiest.klonkt.com" required>
36 </label>
37 <label class="set-field">
38 <span><%= t('acir.label') %> <small style="font-weight:400">— <%= t('acir.optional') %></small></span>
39 <input type="text" name="label" maxlength="80" placeholder="<%= t('acir.label_ph') %>">
40 </label>
41 <button type="submit" class="btn btn-primary"><%= t('acir.add') %></button>
42 </form>
43 </section>
44
45 <section class="set-card" style="margin-top:1rem">
46 <h2><%= t('acir.in_circle', { n: links.length }) %></h2>
47 <% if (!links.length) { %>
48 <p class="set-help"><%= t('acir.no_sources') %></p>
49 <% } else { %>
50 <form method="post" action="/admin/circle/sync-all" style="margin:0 0 .9rem">
51 <button type="submit" class="btn">&#8635; <%= t('acir.sync_all') %></button>
52 </form>
53 <%
54 var _cActive = t('acir.st_active');
55 var _cPosts = t('acir.posts');
56 var _cLast = t('acir.last');
57 var _cMismatch = t('acir.st_mismatch');
58 var _cMismatchReason = t('acir.mismatch_reason');
59 var _cError = t('acir.st_error');
60 var _cPaused = t('acir.st_paused');
61 var _cRefresh = t('acir.refresh');
62 var _cRemove = t('acir.remove');
63 var _cRemoveConfirm = t('acir.remove_confirm');
64 %>
65 <ul class="circ-list">
66 <% links.forEach(function(l){ %>
67 <li class="circ-item">
68 <div class="circ-main">
69 <strong><%= l.label || l.remote_url %></strong>
70 <small><%= l.remote_url %></small>
71 <div class="circ-status">
72 <% if (l.status === 'active') { %>
73 <span class="circ-badge ok">&#10003; <%= _cActive %></span>
74 <span class="circ-meta"><%= counts[l.id] || 0 %> <%= _cPosts %><% if (l.last_synced) { %> &middot; <%= _cLast %>: <%= l.last_synced %><% } %></span>
75 <% } else if (l.status === 'outdated') { %>
76 <span class="circ-badge err">&#8635; <%= _cMismatch %></span>
77 <div class="circ-reason"><%= l.last_error || _cMismatchReason %></div>
78 <% } else if (l.status === 'error') { %>
79 <span class="circ-badge err">&#9888; <%= _cError %></span>
80 <% if (l.last_error) { %><div class="circ-reason"><%= l.last_error %></div><% } %>
81 <% } else if (l.status === 'paused') { %>
82 <span class="circ-badge">&#9208; <%= _cPaused %></span>
83 <% } else { %>
84 <%# Onbekende status: toon 'm rauw + eventuele reden i.p.v. stil "gepauzeerd". %>
85 <span class="circ-badge"><%= l.status %></span>
86 <% if (l.last_error) { %><div class="circ-reason"><%= l.last_error %></div><% } %>
87 <% } %>
88 </div>
89 </div>
90 <div class="circ-actions">
91 <form method="post" action="/admin/circle/<%= l.id %>/sync" style="display:inline">
92 <button type="submit" class="btn"><%= _cRefresh %></button>
93 </form>
94 <form method="post" action="/admin/circle/<%= l.id %>/remove" style="display:inline"
95 onsubmit="return confirm('<%= _cRemoveConfirm %>')">
96 <button type="submit" class="btn btn-danger"><%= _cRemove %></button>
97 </form>
98 </div>
99 </li>
100 <% }); %>
101 </ul>
102 <% } %>
103 </section>
104</div>
105
106<style>
107.admin-page { max-width: 760px; margin: 3rem auto; padding: 0 1rem; }
108.admin-page h1 { font-family: var(--font-display, serif); font-size: 2rem; margin: 0 0 .25rem; }
109.set-card { background: var(--paper-2); border: 1px solid var(--rule); border-radius: 12px; padding: 1.25rem; }
110.set-card h2 { font-family: var(--font-display, serif); font-size: 1.25rem; margin: 0 0 .5rem; }
111.set-help { color: var(--ink-muted); font-size: .9rem; margin: 0 0 1rem; }
112.set-form { display: flex; flex-direction: column; gap: 1rem; }
113.set-opt { display: flex; gap: .75rem; align-items: flex-start; padding: .85rem 1rem; border: 1px solid var(--rule); border-radius: 8px; background: var(--paper); }
114.set-field { display: flex; flex-direction: column; gap: .3rem; }
115.set-field > span { font-size: .8rem; font-weight: 600; color: var(--ink-soft, var(--ink-muted)); }
116.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; }
117.set-form .btn, .circ-actions .btn { align-self: flex-start; }
118.circ-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .6rem; }
119.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; }
120.circ-main { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
121.circ-main small { color: var(--ink-muted); font-size: .78rem; word-break: break-all; }
122.circ-actions { display: flex; gap: .4rem; flex-shrink: 0; }
123.circ-badge { font-size: .72rem; font-weight: 700; padding: .1rem .45rem; border-radius: 20px; background: var(--rule); white-space: nowrap; }
124.circ-badge.ok { background: #d1fae5; color: #065f46; }
125.circ-badge.err { background: #fee2e2; color: #991b1b; }
126.circ-status { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .5rem; margin-top: .25rem; font-size: .78rem; color: var(--ink-muted); }
127.circ-meta { color: var(--ink-muted); }
128/* Reden op een eigen regel onder de badge; normale woordafbreking (geen break-all
129 die hele zinnen midden in woorden knipt — dat zit op de URL-small, niet hier). */
130.circ-reason { flex-basis: 100%; line-height: 1.4; color: var(--ink-muted); word-break: normal; overflow-wrap: anywhere; }
131.btn-danger { background: #dc2626; color: #fff; border-color: #dc2626; }
132.btn-danger:hover { background: #b91c1c; border-color: #b91c1c; color: #fff; }
133.alert { padding: .75rem 1rem; border-radius: 6px; margin-bottom: 1rem; }
134.alert-success { background: #d1fae5; color: #065f46; border: 1px solid #a7f3d0; }
135.alert-error { background: #fee2e2; color: #991b1b; border: 1px solid #fca5a5; }
136</style>
Note: See TracBrowser for help on using the repository browser.