- Timestamp:
- 06/19/2026 03:46:42 AM (3 months ago)
- Branches:
- main
- Children:
- 1794fac
- Parents:
- 91094a4
- Location:
- src
- Files:
-
- 2 added
- 5 edited
-
config/database.js (modified) (1 diff)
-
routes/admin-stats.js (modified) (2 diffs)
-
routes/linkbio.js (added)
-
server.js (modified) (2 diffs)
-
views/pages/admin-stats.ejs (modified) (1 diff)
-
views/pages/admin.ejs (modified) (1 diff)
-
views/pages/linkbio.ejs (added)
Legend:
- Unmodified
- Added
- Removed
-
src/config/database.js
r91094a4 r37edecd 219 219 ); 220 220 `); 221 222 // Link-in-bio klikstatistiek (premium #6). Per (site, url) een teller; de 223 // link-in-bio-pagina linkt via /links/go/:i dat de klik telt en doorstuurt. 224 db.exec(` 225 CREATE TABLE IF NOT EXISTS link_clicks ( 226 site_id TEXT NOT NULL, 227 url TEXT NOT NULL, 228 clicks INTEGER DEFAULT 0, 229 updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, 230 PRIMARY KEY (site_id, url) 231 ); 232 `); 221 233 } 222 234 -
src/routes/admin-stats.js
r91094a4 r37edecd 10 10 11 11 import express from 'express'; 12 import db from '../config/database.js'; 12 13 import { renderPage } from '../middleware/render.js'; 13 14 import { requireGod } from '../middleware/auth.js'; … … 21 22 return res.status(403).send('Statistieken is een premium-functie — koppel Patreon in Beheer → Instellingen.'); 22 23 } 24 // Link-in-bio klikken (premium #6) voor de huidige site. 25 let linkClicks = []; 26 if (res.locals.site) { 27 try { 28 linkClicks = db.prepare( 29 'SELECT url, clicks FROM link_clicks WHERE site_id = ? AND clicks > 0 ORDER BY clicks DESC LIMIT 50' 30 ).all(res.locals.site.id); 31 } catch { linkClicks = []; } 32 } 23 33 renderPage(req, res, 'pages/admin-stats', { 24 34 pageTitle: 'Statistieken', 25 35 bodyClass: 'on-admin', 26 36 stats: getStats(14), 37 linkClicks, 27 38 }); 28 39 }); -
src/server.js
r91094a4 r37edecd 56 56 import adminNewsletterRoutes from './routes/admin-newsletter.js'; 57 57 import downloadRoutes from './routes/download.js'; 58 import linkbioRoutes from './routes/linkbio.js'; 58 59 59 60 if (!process.env.SESSION_SECRET) { … … 273 274 app.use('/', newsletterRoutes); // /nieuwsbrief in/uitschrijven (premium; niet-premium: next()) 274 275 app.use('/', downloadRoutes); // /downloads + /download/:id download-voor-email (premium) 276 app.use('/', linkbioRoutes); // /links link-in-bio + klikstats (premium) 275 277 app.use('/', postsRoutes); 276 278 -
src/views/pages/admin-stats.ejs
r91094a4 r37edecd 65 65 </section> 66 66 </div> 67 68 <% if (typeof linkClicks !== 'undefined' && linkClicks.length) { %> 69 <section class="stats-top" style="margin-top:1.2rem"> 70 <h2>🔗 Link-in-bio klikken</h2> 71 <ol> 72 <% linkClicks.forEach(function(l){ %> 73 <li><a href="<%= l.url %>" target="_blank" rel="noopener"><%= l.url.replace(/^https?:\/\//,'').slice(0,48) %></a><span class="stats-count"><%= l.clicks %></span></li> 74 <% }); %> 75 </ol> 76 </section> 77 <% } %> 67 78 </div> 68 79 -
src/views/pages/admin.ejs
r91094a4 r37edecd 36 36 <% if (tenancy !== 'hub' && primarySite) { %><a href="/pers" class="btn" target="_blank">📰 Perskit</a><% } %> 37 37 <% if (tenancy !== 'hub' && primarySite) { %><a href="/downloads" class="btn" target="_blank">⬇ Downloads</a><% } %> 38 <% if (tenancy !== 'hub' && primarySite) { %><a href="/links" class="btn" target="_blank">🔗 Link-in-bio</a><% } %> 38 39 <% } %> 39 40 <a href="/admin/updates" class="btn">🔄 Updates</a>
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)