- Timestamp:
- 06/14/2026 06:07:51 PM (3 months ago)
- Branches:
- main
- Children:
- c869272
- Parents:
- b94c08e
- Location:
- src/views
- Files:
-
- 2 added
- 13 edited
-
pages/account.ejs (modified) (6 diffs)
-
pages/admin-settings.ejs (modified) (2 diffs)
-
pages/admin-users.ejs (modified) (4 diffs)
-
pages/admin.ejs (modified) (1 diff)
-
pages/artists-directory.ejs (added)
-
pages/home.ejs (modified) (1 diff)
-
pages/hub-home.ejs (modified) (3 diffs)
-
pages/my-site.ejs (modified) (1 diff)
-
pages/post.ejs (modified) (4 diffs)
-
pages/viewer-blocked.ejs (added)
-
partials/bottom-tab.ejs (modified) (1 diff)
-
partials/footer.ejs (modified) (1 diff)
-
partials/profile-sheet.ejs (modified) (1 diff)
-
partials/topnav.ejs (modified) (2 diffs)
-
shell.ejs (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/views/pages/account.ejs
rb94c08e r8afbdd6 12 12 <% if (error) { %><div class="ax-flash ax-flash-err"><%= error %></div><% } %> 13 13 14 <% if (isViewer) { %> 15 <div class="ax-viewer-note" role="note"> 16 <span class="ax-viewer-ico" aria-hidden="true">👁️</span> 17 <div> 18 <strong>Kijker-modus</strong> 19 <span>Dit is een demo-account. Je kunt alles bekijken, maar niets wijzigen — ook geen foto of bio.</span> 20 </div> 21 </div> 22 <% } %> 23 14 24 <%# ── PROFILE ────────────────────────────────────────────── %> 15 25 <section class="ax-card"> … … 17 27 18 28 <div class="ax-profile-id"> 19 <form action="/account/avatar" method="post" enctype="multipart/form-data" class="ax-avatar-form"> 20 <label class="ax-avatar-wrap" title="Klik om je foto te wijzigen"> 21 <span class="ax-profile-avatar"> 22 <% if (account.avatar_url) { %> 23 <img src="<%= account.avatar_url %>" alt=""> 24 <% } else { %> 25 <span><%= account.username.charAt(0).toUpperCase() %></span> 26 <% } %> 27 </span> 28 <span class="ax-avatar-edit" aria-hidden="true"> 29 <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg> 30 </span> 31 <input type="file" name="avatar" accept="image/jpeg,image/png,image/webp,image/gif" onchange="this.form.submit()" hidden> 32 </label> 33 </form> 29 <% if (canMutate) { %> 30 <form action="/account/avatar" method="post" enctype="multipart/form-data" class="ax-avatar-form"> 31 <label class="ax-avatar-wrap" title="Klik om je foto te wijzigen"> 32 <span class="ax-profile-avatar"> 33 <% if (account.avatar_url) { %> 34 <img src="<%= account.avatar_url %>" alt=""> 35 <% } else { %> 36 <span><%= account.username.charAt(0).toUpperCase() %></span> 37 <% } %> 38 </span> 39 <span class="ax-avatar-edit" aria-hidden="true"> 40 <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg> 41 </span> 42 <input type="file" name="avatar" accept="image/jpeg,image/png,image/webp,image/gif" onchange="this.form.submit()" hidden> 43 </label> 44 </form> 45 <% } else { %> 46 <span class="ax-profile-avatar ax-profile-avatar-static"> 47 <% if (account.avatar_url) { %> 48 <img src="<%= account.avatar_url %>" alt=""> 49 <% } else { %> 50 <span><%= account.username.charAt(0).toUpperCase() %></span> 51 <% } %> 52 </span> 53 <% } %> 34 54 <div class="ax-profile-meta"> 35 55 <div class="ax-profile-name"><%= account.username %></div> … … 38 58 <div class="ax-profile-joined">Lid sinds <%= formatDate(account.created_at) %></div> 39 59 <% } %> 40 <% if (account.avatar_url ) { %>60 <% if (account.avatar_url && canMutate) { %> 41 61 <form action="/account/avatar/remove" method="post" class="ax-avatar-remove"> 42 62 <button type="submit" class="ax-linkbtn">Foto verwijderen</button> … … 46 66 </div> 47 67 48 <form action="/account/profile" method="post" class="ax-form ax-form-bio"> 49 <label class="ax-field"> 50 <span>Bio</span> 51 <textarea name="bio" rows="3" maxlength="500" placeholder="Een korte regel over jezelf"><%= account.bio || '' %></textarea> 52 </label> 53 <div class="ax-form-actions"> 54 <button type="submit" class="ax-btn ax-btn-primary">Bio opslaan</button> 55 </div> 56 </form> 68 <% if (canMutate) { %> 69 <form action="/account/profile" method="post" class="ax-form ax-form-bio"> 70 <label class="ax-field"> 71 <span>Bio</span> 72 <textarea name="bio" rows="3" maxlength="500" placeholder="Een korte regel over jezelf"><%= account.bio || '' %></textarea> 73 </label> 74 <div class="ax-form-actions"> 75 <button type="submit" class="ax-btn ax-btn-primary">Bio opslaan</button> 76 </div> 77 </form> 78 <% } else { %> 79 <div class="ax-form ax-form-bio"> 80 <label class="ax-field"> 81 <span>Bio</span> 82 <textarea rows="3" disabled placeholder="Geen bio"><%= account.bio || '' %></textarea> 83 </label> 84 </div> 85 <% } %> 57 86 </section> 58 87 59 88 <%# ── WACHTWOORD ────────────────────────────────────────── %> 89 <%# In kijker-modus geen wachtwoord-sectie (niets te wijzigen). %> 90 <% if (canMutate) { %> 60 91 <% if (hasPassword) { %> 61 92 <section class="ax-card"> … … 87 118 </section> 88 119 <% } %> 120 <% } %> 89 121 90 122 </div> … … 107 139 .ax-flash-ok { background: rgba(40,160,90,.15); color: #2a9d5e; border: 1px solid rgba(40,160,90,.3); } 108 140 .ax-flash-err { background: rgba(200,60,60,.15); color: #c33; border: 1px solid rgba(200,60,60,.3); } 141 142 /* ─── Kijker-modus notice ──────────────────────────────────────── */ 143 .ax-viewer-note { 144 display: flex; align-items: flex-start; gap: 0.75rem; 145 padding: 0.85rem 1rem; margin-bottom: 1rem; 146 border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--rule)); 147 border-left: 3px solid var(--accent); 148 border-radius: 10px; 149 background: color-mix(in srgb, var(--accent) 8%, var(--paper)); 150 } 151 .ax-viewer-ico { font-size: 1.1rem; line-height: 1.4; } 152 .ax-viewer-note strong { display: block; font-size: 0.92rem; } 153 .ax-viewer-note span { color: var(--ink-muted, var(--ink-soft)); font-size: 0.85rem; } 154 .ax-profile-avatar-static { flex-shrink: 0; } 155 .ax-form-bio textarea:disabled { opacity: 0.7; cursor: default; } 109 156 110 157 /* ─── Cards ────────────────────────────────────────────────────── */ -
src/views/pages/admin-settings.ejs
rb94c08e r8afbdd6 24 24 <span> 25 25 <strong>Hub</strong> — bedrijfssite met <code>/user/</code>. 26 <small>Jij (admin) wijst gebruikers een eigen PrutFoliotoe. Gesloten cirkel: geen open registratie.</small>26 <small>Jij (admin) wijst gebruikers een eigen Klonkt Hub toe. Gesloten cirkel: geen open registratie.</small> 27 27 </span> 28 28 </label> … … 36 36 <p class="set-help"> 37 37 De openbare hub-pagina (<code>/</code>) is generiek — van geen enkele gebruiker. 38 Hier stel je de naam en intro in. Jouw eigen PrutFolioblijft los bestaan onder <code>/user/</code>.38 Hier stel je de naam en intro in. Jouw eigen Klonkt Hub blijft los bestaan onder <code>/user/</code>. 39 39 </p> 40 40 <form method="post" action="/admin/settings" class="set-form"> -
src/views/pages/admin-users.ejs
rb94c08e r8afbdd6 5 5 <div> 6 6 <h1>Users</h1> 7 <p class="ax-tagline">Beheer gebruikers, rollen, en verwijderingen. </p>7 <p class="ax-tagline">Beheer gebruikers, rollen, en verwijderingen. Rol <strong>kijker</strong> = alles bekijken (incl. Beheer), niets wijzigen — handig voor demo's.</p> 8 8 </div> 9 9 </header> … … 58 58 <label class="ax-role"> 59 59 <span>Rol</span> 60 <select name="role" onchange="this.form.submit()" <% if (u.id === user.id) { %>disabled<% } %>> 60 <select name="role" onchange="this.form.submit()" <% if (u.id === user.id || !canMutate) { %>disabled<% } %>> 61 <option value="kijker" <%= u.role === 'kijker' ? 'selected' : '' %>>kijker</option> 61 62 <option value="member" <%= u.role === 'member' ? 'selected' : '' %>>member</option> 62 63 <option value="admin" <%= u.role === 'admin' ? 'selected' : '' %>>admin</option> … … 66 67 </form> 67 68 68 <form method="post" action="/admin/users/<%= u.id %>/readonly" class="ax-role-form"> 69 <label class="ax-role ax-ro" title="Alleen-lezen: kan alles bekijken, niets wijzigen"> 70 <span>Kijk-modus</span> 71 <input type="checkbox" name="readonly" value="1" <%= u.readonly ? 'checked' : '' %> 72 onchange="this.form.submit()" <% if (u.id === user.id) { %>disabled<% } %>> 73 </label> 74 </form> 75 76 <% if (u.id !== user.id) { %> 69 <% if (u.id !== user.id && canMutate) { %> 77 70 <% var _warn = (u.post_count + u.site_count > 0) 78 71 ? ('Dit verwijdert ook hun site + ' + u.post_count + ' post(s). ') … … 83 76 </form> 84 77 <% } else { %> 85 <%# Lege plek zodat de kolommen (rol/kijk-modus) op elke rij uitlijnen. %>78 <%# Lege plek zodat de rol-kolom op elke rij uitlijnt. %> 86 79 <span class="ax-icon-btn-spacer" aria-hidden="true"></span> 87 80 <% } %> -
src/views/pages/admin.ejs
rb94c08e r8afbdd6 2 2 <h1>Beheer</h1> 3 3 <% if (tenancy === 'hub') { %> 4 <p class="admin-tagline">Hub-modus — bedrijfssite met gebruikers, elk hun eigen PrutFolio.</p>4 <p class="admin-tagline">Hub-modus — bedrijfssite met gebruikers, elk hun eigen Klonkt Hub.</p> 5 5 <% } else { %> 6 6 <p class="admin-tagline">Solo-modus — jouw site.</p> -
src/views/pages/home.ejs
rb94c08e r8afbdd6 25 25 <h1>Hier is het nog stil.</h1> 26 26 <p>Nog geen posts. Spannend.</p> 27 <% if (user && permissions.canCreatePost(user, site)) { %>27 <% if (user && canMutate && permissions.canCreatePost(user, site)) { %> 28 28 <p style="margin-top:2rem"> 29 29 <a class="btn" href="<%= _base %>/posts/new" -
src/views/pages/hub-home.ejs
rb94c08e r8afbdd6 33 33 <%# ── ARTIESTEN-ROSTER ─────────────────────────────────────────── %> 34 34 <% if (artists && artists.length) { %> 35 <% var _total = (typeof totalArtists !== 'undefined') ? totalArtists : artists.length; %> 36 <% var _hasMore = _total > artists.length; %> 35 37 <section class="hub-sec"> 36 <h2 class="hub-sec-title">Artiesten</h2> 38 <h2 class="hub-sec-title"> 39 Artiesten 40 <% if (_hasMore) { %><span class="hub-sec-count"><%= _total %></span><% } %> 41 </h2> 37 42 <div class="roster"> 38 43 <% artists.forEach(function(a){ %> … … 48 53 <% }); %> 49 54 </div> 55 <% if (_hasMore) { %> 56 <div class="hub-more"> 57 <a class="hub-more-link" href="/artiesten">Alle <%= _total %> artiesten <span aria-hidden="true">→</span></a> 58 </div> 59 <% } %> 50 60 </section> 51 61 <% } %> … … 131 141 } 132 142 .hub-sec-title::after { content: ''; flex: 1; height: 1px; background: var(--rule); } 143 .hub-sec-count { 144 font-family: var(--font-ui, system-ui); font-size: 0.8rem; font-weight: 700; 145 color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); 146 padding: 0.1rem 0.55rem; border-radius: 99px; order: 1; 147 } 148 .hub-more { margin-top: 1.25rem; text-align: center; } 149 .hub-more-link { 150 display: inline-flex; align-items: center; gap: 0.4rem; 151 padding: 0.6rem 1.3rem; border: 1px solid var(--rule); border-radius: 99px; 152 background: var(--paper-2); color: var(--ink); text-decoration: none; 153 font-weight: 600; font-size: 0.92rem; transition: border-color 140ms, background 140ms; 154 } 155 .hub-more-link:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 7%, var(--paper-2)); } 133 156 134 157 /* ── Roster (artiesten) ───────────────────────────────────────────── */ -
src/views/pages/my-site.ejs
rb94c08e r8afbdd6 1 1 <div class="container admin-page"> 2 2 <p><a href="/" class="btn">← Overzicht</a></p> 3 <h1>Mijn PrutFolio</h1>3 <h1>Mijn Klonkt Hub</h1> 4 4 <p class="admin-tagline"><%= mySite.title %></p> 5 5 -
src/views/pages/post.ejs
rb94c08e r8afbdd6 103 103 <div class="comment-content"><%= c.content %></div> 104 104 <div class="comment-actions"> 105 <% if (user ) { %>105 <% if (user && canMutate) { %> 106 106 <button type="button" class="comment-reply-btn" data-reply-to="<%= c.id %>">Reply</button> 107 107 <% } %> … … 114 114 115 115 <!-- Inline reply form (hidden by default) --> 116 <% if (user ) { %>116 <% if (user && canMutate) { %> 117 117 <form method="post" action="<%= _base %>/comments" class="comment-reply-form" hidden data-reply-form-for="<%= c.id %>"> 118 118 <input type="hidden" name="post_slug" value="<%= post.slug %>"> … … 163 163 164 164 <!-- Top-level comment form (only for logged-in users for now) --> 165 <% if (user ) { %>165 <% if (user && canMutate) { %> 166 166 <form method="post" action="<%= _base %>/comments" class="comment-form"> 167 167 <input type="hidden" name="post_slug" value="<%= post.slug %>"> … … 172 172 <button type="submit" class="btn btn-primary">Post comment</button> 173 173 </form> 174 <% } else { %>174 <% } else if (!user) { %> 175 175 <p class="comments-login-cta"> 176 176 <a href="/auth/login?next=<%= encodeURIComponent(_base + '/' + post.slug + '#comments') %>" class="btn">Log in to comment</a> 177 177 </p> 178 <% } else { %> 179 <p class="comments-login-cta" style="color:var(--ink-muted)">👁️ Kijker-modus — reageren is uitgeschakeld.</p> 178 180 <% } %> 179 181 </section> -
src/views/partials/bottom-tab.ejs
rb94c08e r8afbdd6 11 11 const _siteUrlBase = (typeof siteUrlBase !== 'undefined' && siteUrlBase) ? siteUrlBase : ''; 12 12 const _path = (typeof currentPath !== 'undefined' && currentPath) ? currentPath : '/'; 13 const _canPost = !!(user && permissions && permissions.canCreatePost && permissions.canCreatePost(user, site)); 13 const _canPost = !!(user && (typeof canMutate === 'undefined' || canMutate) 14 && permissions && permissions.canCreatePost && permissions.canCreatePost(user, site)); 14 15 const _hasPrutter = !!(user && site && site.enable_prutter && (typeof tenancy !== 'undefined' && tenancy === 'hub')); 15 16 const _ownProfile = user ? ('/users/' + user.username) : null; -
src/views/partials/footer.ejs
rb94c08e r8afbdd6 2 2 <div class="container site-footer-inner"> 3 3 <div> 4 <span>© <%= new Date().getFullYear() %> <%= (site && site.title) || ' PrutFolio' %></span>4 <span>© <%= new Date().getFullYear() %> <%= (site && site.title) || 'Klonkt' %></span> 5 5 </div> 6 6 <div class="footer-meta"> 7 <span> PrutFolio v1</span>7 <span>Klonkt Hub Beta</span> 8 8 <%# Mobile-only theme toggle. On desktop the topnav has its own toggle 9 9 so we hide this one to avoid two visible toggles at once. The same -
src/views/partials/profile-sheet.ejs
rb94c08e r8afbdd6 14 14 15 15 const _isAdmin = (user.role === 'god' || user.role === 'admin'); 16 const _canPost = !!(typeof permissions !== 'undefined' 16 const _canPost = !!((typeof canMutate === 'undefined' || canMutate) 17 && typeof permissions !== 'undefined' 17 18 && permissions 18 19 && permissions.canCreatePost -
src/views/partials/topnav.ejs
rb94c08e r8afbdd6 16 16 const _hasSearch = !site || site.show_search === undefined || site.show_search; 17 17 const _hasPrutter = user && site && site.enable_prutter && (typeof tenancy !== 'undefined' && tenancy === 'hub'); 18 const _canPost = user && permissions && permissions.canCreatePost && permissions.canCreatePost(user, site); 18 const _canPost = user && (typeof canMutate === 'undefined' || canMutate) 19 && permissions && permissions.canCreatePost && permissions.canCreatePost(user, site); 19 20 %> 20 21 … … 36 37 hx-push-url="<%= _siteUrlBase %>/" hx-indicator="#pcms-loading"><%= site.title %></a> 37 38 <% } else { %> 38 <a class="site-title" href="/"> PrutFolio</a>39 <a class="site-title" href="/">Klonkt</a> 39 40 <% } %> 40 41 </div> -
src/views/shell.ejs
rb94c08e r8afbdd6 239 239 <body class="<%= bodyClass || 'on-home' %> has-bottom-tab" data-feed-view="<%= _e(safeSite.feed_view_default || 'timeline') %>" data-grid-cols="3" data-site-base="<%= _e((typeof siteUrlBase !== 'undefined' && siteUrlBase) ? siteUrlBase : '') %>"> 240 240 241 <% if (user && user.readonly) { %> 242 <div style="position:sticky;top:0;z-index:50;background:#e8b04b;color:#1a1a1a;text-align:center;font-size:0.85rem;font-weight:600;padding:0.4rem 1rem;"> 243 👁️ Demo — alleen-lezen: je kunt alles bekijken, maar niets wijzigen. 241 <% if (typeof isViewer !== 'undefined' && isViewer) { %> 242 <div class="viewer-banner" role="status"> 243 <span class="viewer-banner-ico" aria-hidden="true">👁️</span> 244 <span class="viewer-banner-text"><strong>Kijker-modus</strong> — je kunt alles bekijken, maar niets wijzigen.</span> 244 245 </div> 246 <style> 247 .viewer-banner { 248 position: sticky; top: 0; z-index: 60; 249 display: flex; align-items: center; justify-content: center; gap: 0.5rem; 250 padding: 0.5rem 1rem; 251 background: linear-gradient(90deg, 252 color-mix(in srgb, var(--accent) 88%, #000) 0%, 253 var(--accent) 100%); 254 color: #fff; 255 font-size: 0.85rem; line-height: 1.3; 256 box-shadow: 0 1px 6px color-mix(in srgb, var(--accent) 45%, transparent); 257 } 258 .viewer-banner-ico { font-size: 1rem; } 259 .viewer-banner-text strong { font-weight: 700; } 260 </style> 245 261 <% } %> 246 262
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)