Changeset 1e2e9e7 in Klonkt
- Timestamp:
- 06/19/2026 09:38:20 AM (3 months ago)
- Branches:
- main
- Children:
- 8cdb377
- Parents:
- f4b7b6a
- Files:
-
- 1 added
- 4 edited
-
CHANGELOG.md (modified) (1 diff)
-
src/routes/posts.js (modified) (4 diffs)
-
src/views/pages/fan-gate.ejs (modified) (1 diff)
-
src/views/pages/post.ejs (modified) (2 diffs)
-
src/views/partials/post-nav.ejs (added)
Legend:
- Unmodified
- Added
- Removed
-
CHANGELOG.md
rf4b7b6a r1e2e9e7 15 15 16 16 ### Gewijzigd 17 - De Newer/Older-postnavigatie staat nu รณรณk op de fan-gate (login-wall van een 18 fan-only post), zodat een bezoeker niet vastloopt maar verder kan bladeren. 19 Nav verhuisd naar een gedeeld partial (`partials/post-nav.ejs`). 17 20 - Login gesplitst: de publieke loginpagina (`/auth/login`) toont voor bezoekers nu 18 21 **alleen** Google-login (luisteraars/fans). De beheerders-login (gebruikersnaam + -
src/routes/posts.js
rf4b7b6a r1e2e9e7 394 394 }); 395 395 396 // Newer/Older-buren over ALLE posts in feed-volgorde. Gedeeld door de volledige 397 // post-render รฉn de fan-gate (premium fan_only), zodat de navigatie overal gelijk 398 // is. Solo: binnen de site (pinned eerst, dan datum). Hub: globaal op datum. 399 function postNeighbors(site, post, isHub) { 400 const urlBaseFor = (p) => (isHub && p && p.site_slug) ? `/user/${p.site_slug}` : ''; 401 const ordered = isHub 402 ? db.prepare(` 403 SELECT p.id, p.slug, p.title, s.slug AS site_slug 404 FROM posts p JOIN sites s ON s.id = p.site_id 405 WHERE p.status = 'published' 406 ORDER BY p.published_at DESC 407 `).all() 408 : db.prepare(` 409 SELECT id, slug, title FROM posts 410 WHERE site_id = ? AND status = 'published' 411 ORDER BY (pinned = 0) ASC, pinned ASC, published_at DESC 412 `).all(site.id); 413 const idx = ordered.findIndex((p) => p.id === post.id); 414 const newerPost = idx > 0 ? ordered[idx - 1] : null; 415 const olderPost = (idx >= 0 && idx < ordered.length - 1) ? ordered[idx + 1] : null; 416 if (newerPost) newerPost._urlBase = urlBaseFor(newerPost); 417 if (olderPost) olderPost._urlBase = urlBaseFor(olderPost); 418 return { newerPost, olderPost }; 419 } 420 396 421 // ==================== VIEW POST (last route รขโฌโ catches /:slug) ==================== 397 422 router.get('/:slug', (req, res, next) => { … … 419 444 // teaser mag elders wel als lokkertje verschijnen). 420 445 if (post.fan_only && !(req.session && req.session.user)) { 446 // Zelfde Newer/Older-navigatie als op een gewone post, zodat de bezoeker op 447 // de fan-gate niet vastloopt maar verder kan bladeren. 448 const { newerPost, olderPost } = postNeighbors(site, post, res.locals.tenancy === 'hub'); 421 449 return renderPage(req, res, 'pages/fan-gate', { 422 450 pageTitle: post.title || 'Alleen voor fans', … … 424 452 fgTitle: post.title || '', 425 453 fgNext: (res.locals.siteUrlBase || '') + '/' + post.slug, 454 newerPost, 455 olderPost, 426 456 }); 427 457 } … … 545 575 const urlBaseFor = (p) => (isHub && p && p.site_slug) ? `/user/${p.site_slug}` : ''; 546 576 547 // Newer/Older over ALLE posts, in de canonieke feed-volgorde โ niet alleen de 548 // pinned-stack. Solo: binnen de site, pinned eerst op rank, dan op datum 549 // (zelfde volgorde als de homepage-feed). Hub: globaal op datum over alle 550 // sites. De vorige positie in de lijst = "Newer" (โ omhoog), de volgende = 551 // "Older" (โ omlaag). Pinned posts zitten zo gewoon in de doorlopende reeks. 552 const ordered = isHub 553 ? db.prepare(` 554 SELECT p.id, p.slug, p.title, s.slug AS site_slug 555 FROM posts p JOIN sites s ON s.id = p.site_id 556 WHERE p.status = 'published' 557 ORDER BY p.published_at DESC 558 `).all() 559 : db.prepare(` 560 SELECT id, slug, title FROM posts 561 WHERE site_id = ? AND status = 'published' 562 ORDER BY (pinned = 0) ASC, pinned ASC, published_at DESC 563 `).all(site.id); 564 const _idx = ordered.findIndex((p) => p.id === post.id); 565 const newerPost = _idx > 0 ? ordered[_idx - 1] : null; 566 const olderPost = (_idx >= 0 && _idx < ordered.length - 1) ? ordered[_idx + 1] : null; 567 if (newerPost) newerPost._urlBase = urlBaseFor(newerPost); 568 if (olderPost) olderPost._urlBase = urlBaseFor(olderPost); 577 // Newer/Older over ALLE posts (gedeelde helper โ ook door de fan-gate gebruikt). 578 const { newerPost, olderPost } = postNeighbors(site, post, isHub); 569 579 570 580 // โโ Related posts: same-tag matching with recency fallback โโโโโ -
src/views/pages/fan-gate.ejs
rf4b7b6a r1e2e9e7 1 <div class="container"> 2 <%# Zelfde post-navigatie (Newer/Older) als op een gewone post, zodat een 3 bezoeker op de fan-gate niet vastloopt maar verder kan bladeren. %> 4 <%- include('../partials/post-nav', { newerPost: (typeof newerPost !== 'undefined' ? newerPost : null), olderPost: (typeof olderPost !== 'undefined' ? olderPost : null) }) %> 5 </div> 6 1 7 <section class="fg"> 2 8 <div class="fg-card"> -
src/views/pages/post.ejs
rf4b7b6a r1e2e9e7 7 7 <article class="container post-page"> 8 8 9 <%# Navigatie over ALLE posts โ BOVEN de post (Newer links, Older rechts). %> 10 <% if (newerPost || olderPost) { %> 11 <nav class="post-nav post-nav--top"> 12 <% if (newerPost) { %> 13 <a class="post-nav-prev" href="<%= newerPost._urlBase || '' %>/<%= newerPost.slug %>"<% if (!newerPost._urlBase) { %> 14 hx-get="/<%= newerPost.slug %>?partial=1" hx-target="#pcms-main" 15 hx-push-url="/<%= newerPost.slug %>" hx-indicator="#pcms-loading"<% } %>> 16 <span class="post-nav-label">โ Newer</span> 17 <span class="post-nav-title"><%= newerPost.title %></span> 18 </a> 19 <% } else { %> 20 <div class="post-nav-prev is-empty" aria-hidden="true"> 21 <span class="post-nav-label">โ Newer</span> 22 <span class="post-nav-title">Nieuwste post</span> 23 </div> 24 <% } %> 25 <% if (olderPost) { %> 26 <a class="post-nav-next" href="<%= olderPost._urlBase || '' %>/<%= olderPost.slug %>"<% if (!olderPost._urlBase) { %> 27 hx-get="/<%= olderPost.slug %>?partial=1" hx-target="#pcms-main" 28 hx-push-url="/<%= olderPost.slug %>" hx-indicator="#pcms-loading"<% } %>> 29 <span class="post-nav-label">Older โ</span> 30 <span class="post-nav-title"><%= olderPost.title %></span> 31 </a> 32 <% } else { %> 33 <div class="post-nav-next is-empty" aria-hidden="true"> 34 <span class="post-nav-label">Older โ</span> 35 <span class="post-nav-title">Oudste post</span> 36 </div> 37 <% } %> 38 </nav> 39 <% } %> 9 <%# Navigatie over ALLE posts โ BOVEN de post (gedeeld partial). %> 10 <%- include('../partials/post-nav', { newerPost: newerPost, olderPost: olderPost }) %> 40 11 41 12 <% if (post.cover_image_url) { %> … … 290 261 .tag:hover { background: var(--accent); color: white; } 291 262 .post-actions { display: flex; gap: 0.5rem; margin: 2rem 0; padding: 1rem; background: var(--paper-2); border-radius: 6px; flex-wrap: wrap; } 292 .post-nav { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--rule); }293 /* Boven de post: geen lijn/gap erboven, maar een scheidingslijn ERONDER (naar de content). */294 .post-nav--top { margin-top: 0; padding-top: 0; border-top: 0; margin-bottom: 2rem; padding-bottom: 2rem; border-bottom: 1px solid var(--rule); }295 .post-nav-prev, .post-nav-next { display: flex; flex-direction: column; padding: 1rem; background: var(--paper-2); border-radius: 6px; text-decoration: none; color: var(--ink); }296 /* Lege plek (geen nieuwere/oudere post): zelfde kaart, uitgegrijsd + niet klikbaar,297 zodat elke post dezelfde twee-kaarten-structuur houdt. */298 .post-nav-prev.is-empty, .post-nav-next.is-empty { opacity: 0.4; cursor: default; }299 .post-nav-prev.is-empty .post-nav-title, .post-nav-next.is-empty .post-nav-title { font-weight: 400; font-style: italic; color: var(--ink-muted); }300 .post-nav-next { text-align: right; align-items: flex-end; }301 .post-nav-label { font-size: 0.8rem; color: var(--ink-muted); margin-bottom: 0.25rem; }302 .post-nav-title { font-weight: 500; }303 @media (max-width: 600px) { .post-nav { grid-template-columns: 1fr; } }304 263 305 264 /* ============================================================
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)