- Timestamp:
- 07/31/2026 06:55:59 PM (6 weeks ago)
- Branches:
- main
- Children:
- 17546af
- Parents:
- bfa6fa1
- Location:
- src/views
- Files:
-
- 7 edited
-
pages/admin-site-edit.ejs (modified) (2 diffs)
-
pages/admin-users.ejs (modified) (1 diff)
-
pages/admin.ejs (modified) (5 diffs)
-
pages/guardian.ejs (modified) (1 diff)
-
partials/bottom-tab.ejs (modified) (2 diffs)
-
partials/chrome.ejs (modified) (1 diff)
-
partials/topnav.ejs (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/views/pages/admin-site-edit.ejs
rbfa6fa1 r72ec6a4 14 14 <span class="slug-url"> 15 15 <span class="slug-url-host" id="slug-host" 16 data-prefix=" <%= (typeof tenancy !== 'undefined' && tenancy === 'hub') ? '/user/' : '/' %>">website.com/</span><input16 data-prefix="/">website.com/</span><input 17 17 type="text" name="slug" id="slug-input" class="slug-url-input" value="<%= site.slug %>" required <% if (!isNew) { %>readonly<% } %> 18 18 pattern="[a-z0-9_-]{2,40}" placeholder="<%= t('asite.slug_placeholder') %>" … … 24 24 <input type="text" name="title" value="<%= site.title || '' %>" required maxlength="200"> 25 25 </label> 26 <%# Assign (or reassign) owner — ONLY god AND only in hub mode. In hub this27 gives each user their own self-managed Klonkt. In solo (one site,28 one owner) this is pointless/confusing, so it's hidden. %>29 <% if (user && user.role === 'god' && (typeof tenancy !== 'undefined' && tenancy === 'hub')) { %>30 <label>31 <span><%= t('asite.owner') %> <small class="form-hint-inline"><%= t('asite.owner_hint') %></small></span>32 <% var _godSuffix = t('asite.owner_god_suffix'); %>33 <select name="owner_id">34 <% (typeof users !== 'undefined' ? users : []).forEach(function(u){ %>35 <option value="<%= u.id %>" <%= (site.owner_id === u.id) ? 'selected' : '' %>><%= u.username %><%= u.role === 'god' ? _godSuffix : '' %></option>36 <% }); %>37 </select>38 </label>39 <% } %>40 26 <label> 41 27 <span><%= t('asite.tagline') %> <small class="form-hint-inline"><%= t('asite.tagline_hint') %></small></span> -
src/views/pages/admin-users.ejs
rbfa6fa1 r72ec6a4 71 71 72 72 <div class="ax-user-controls"> 73 <%# Hub: give this user their own self-managed Klonkt — opens the74 new-site form with this user already pre-selected as owner. %>75 <% if (typeof tenancy !== 'undefined' && tenancy === 'hub' && canMutate) { %>76 <a href="/admin/sites/new?owner=<%= u.id %>" class="ax-icon-btn"77 aria-label="<%= t('ausr.new_klonkt_for', { name: u.username }) %>" title="<%= _u_newklonkt %>">+🌐</a>78 <% } %>79 73 <form method="post" action="/admin/users/<%= u.id %>/role" class="ax-role-form"> 80 74 <label class="ax-role"> -
src/views/pages/admin.ejs
rbfa6fa1 r72ec6a4 17 17 .prem-badge:hover{filter:brightness(1.08)} 18 18 </style> 19 <% if (tenancy === 'hub') { %> 20 <p class="admin-tagline"><%= t('admin.tagline_hub') %></p> 21 <% } else if (typeof circlesOn !== 'undefined' && circlesOn) { %> 19 <% if (typeof circlesOn !== 'undefined' && circlesOn) { %> 22 20 <p class="admin-tagline"><%= t('admin.tagline_cirkels') %></p> 23 21 <% } else { %> … … 26 24 27 25 <nav class="admin-quick-links" aria-label="<%= t('nav.admin') %>"> 28 <% if (tenancy === 'hub') { %>29 <a href="/admin/sites" class="btn"><%= t('admin.b_sites') %></a>30 <a href="/admin/users" class="btn"><%= t('admin.b_users') %></a>31 <a href="/admin/media" class="btn"><%= t('admin.b_media') %></a>32 <% if (typeof audioEnabled === 'undefined' || audioEnabled) { %>33 <a href="/admin/playlists" class="btn"><%= t('admin.b_playlists') %></a>34 <% } %>35 <% if (primarySite) { %><a href="/admin/seo" class="btn"><%= t('admin.b_seo') %></a><% } %>36 <a href="/admin/settings" class="btn"><%= t('admin.b_settings') %></a>37 <% } else { %>38 26 <a href="/posts/new" class="btn"><%= t('admin.b_newpost') %></a> 39 27 <a href="/admin/media" class="btn"><%= t('admin.b_media') %></a> … … 45 33 <% if (primarySite) { %><a href="/admin/seo" class="btn"><%= t('admin.b_seo') %></a><% } %> 46 34 <a href="/admin/settings" class="btn"><%= t('admin.b_settings') %></a> 47 <% } %>48 35 <% if (typeof premiumUnlocked === 'undefined' || premiumUnlocked) { %> 49 36 <a href="/admin/stats" class="btn"><%= t('admin.b_stats') %></a> 50 37 <a href="/admin/paid" class="btn"><%= t('admin.b_paid') %></a> 51 38 <a href="/admin/newsletter" class="btn"><%= t('admin.b_newsletter') %></a> 52 <% if ( tenancy !== 'hub' &&primarySite) { %><a href="/pers" class="btn" target="_blank"><%= t('admin.b_perskit') %></a><% } %>53 <% if ( tenancy !== 'hub' &&primarySite) { %><a href="/downloads" class="btn" target="_blank"><%= t('admin.b_downloads') %></a><% } %>54 <% if ( tenancy !== 'hub' &&primarySite) { %><a href="/links" class="btn" target="_blank"><%= t('admin.b_linkbio') %></a><% } %>39 <% if (primarySite) { %><a href="/pers" class="btn" target="_blank"><%= t('admin.b_perskit') %></a><% } %> 40 <% if (primarySite) { %><a href="/downloads" class="btn" target="_blank"><%= t('admin.b_downloads') %></a><% } %> 41 <% if (primarySite) { %><a href="/links" class="btn" target="_blank"><%= t('admin.b_linkbio') %></a><% } %> 55 42 <a href="/admin/shows" class="btn"><%= t('admin.b_agenda') %></a> 56 43 <% } %> … … 63 50 64 51 <div class="admin-stats"> 65 <% if (tenancy === 'hub') { %>66 <div class="stat-card"><div class="stat-num"><%= stats.users %></div><div class="stat-label"><%= t('admin.st_users') %></div></div>67 <div class="stat-card"><div class="stat-num"><%= stats.sites %></div><div class="stat-label"><%= t('admin.st_sites') %></div></div>68 <% } %>69 52 <div class="stat-card"><div class="stat-num"><%= stats.posts %></div><div class="stat-label"><%= t('admin.st_posts') %></div></div> 70 53 <div class="stat-card"><div class="stat-num"><%= stats.published %></div><div class="stat-label"><%= t('admin.st_published') %></div></div> … … 90 73 <% } %> 91 74 92 <% if (sites && sites.length) { %>93 <h2><%= t('admin.sec_sites') %></h2>94 <table class="admin-table">95 <thead>96 <tr><th><%= t('admin.th_slug') %></th><th><%= t('admin.th_title') %></th><th><%= t('admin.th_owner') %></th><th><%= t('admin.th_created') %></th></tr>97 </thead>98 <tbody>99 <% sites.forEach(function(s) { %>100 <tr>101 <td><code><%= s.slug %></code></td>102 <td><%= s.title %></td>103 <td><%= s.owner_username || '—' %></td>104 <td><%= formatDate(s.created_at) %></td>105 </tr>106 <% }); %>107 </tbody>108 </table>109 <% } %>110 111 <% if (users && users.length) { %>112 <h2><%= t('admin.sec_users') %></h2>113 <table class="admin-table">114 <thead>115 <tr><th><%= t('admin.th_username') %></th><th><%= t('admin.th_email') %></th><th><%= t('admin.th_role') %></th><th><%= t('admin.th_joined') %></th></tr>116 </thead>117 <tbody>118 <% users.forEach(function(u) { %>119 <tr>120 <td><%= u.username %></td>121 <td><%= u.email %></td>122 <td><span class="role-pill role-<%= u.role %>"><%= u.role %></span></td>123 <td><%= formatDate(u.created_at) %></td>124 </tr>125 <% }); %>126 </tbody>127 </table>128 <% } %>129 130 75 </div> 131 76 -
src/views/pages/guardian.ejs
rbfa6fa1 r72ec6a4 26 26 <span class="g-me" title="<%= t('guardian.acting_as') %>">@<%= state.site %></span> 27 27 <% } %> 28 <form method="post" action="/guardian/invite" style="display:inline">29 <button class="quiet small" type="submit">Invite a guardian</button>30 </form>31 28 </header> 32 29 -
src/views/partials/bottom-tab.ejs
rbfa6fa1 r72ec6a4 13 13 && permissions && permissions.canCreatePost && permissions.canCreatePost(user, site)); 14 14 const _ownProfile = user ? ('/users/' + user.username) : null; 15 const _isHub = (typeof tenancy !== 'undefined' && tenancy === 'hub'); 16 // Home in hub mode ALWAYS goes to the hub root (/), not to an artist's sub-home. 17 // In solo/circle _siteUrlBase is empty, so it stays '/'. 18 const _homeHref = (_isHub ? '' : _siteUrlBase) + '/'; 15 const _homeHref = _siteUrlBase + '/'; 19 16 20 17 // Strip site prefix for cleaner matching … … 26 23 27 24 let _active = null; 28 // In hub, Home is only active on the real hub root, not on an artist sub-home. 29 if (_isHub ? (_path === '/') : (_p === '/' || _p === '')) _active = 'home'; 25 if (_p === '/' || _p === '') _active = 'home'; 30 26 else if (_p.indexOf('/search') === 0 || _p.indexOf('/tag/') === 0 || _p.indexOf('/type/') === 0) _active = 'search'; 31 27 else if (_p === '/posts/new' || /^\/posts\/[^/]+\/edit$/.test(_p)) _active = 'create'; -
src/views/partials/chrome.ejs
rbfa6fa1 r72ec6a4 17 17 var _isAuth = typeof bodyClass === 'string' && bodyClass.indexOf('on-auth') >= 0; 18 18 var _isChat = typeof bodyClass === 'string' && bodyClass.indexOf('on-chat') >= 0; 19 var hubLanding = (typeof bodyClass === 'string' && bodyClass.indexOf('on-hub') >= 0) 20 || ((typeof tenancy !== 'undefined' && tenancy === 'hub') && !siteUrlBase && !_isAdmin); 19 var hubLanding = (typeof bodyClass === 'string' && bodyClass.indexOf('on-hub') >= 0); 21 20 // Zelfstandige premium-feature-pagina's hebben hun eigen kop → geen profielkop/ 22 21 // switcher, wél de topnav (Robin 2026-06-18: "bovenste weg, behoud de nav"). -
src/views/partials/topnav.ejs
rbfa6fa1 r72ec6a4 28 28 <% if (_isAdmin || _isSpecial) { %> 29 29 <a href="<%= _siteUrlBase %>/" class="nav-link nav-link-admin"><%= t('nav.back_to_site') %></a> 30 <% } else if (typeof tenancy !== 'undefined' && tenancy === 'hub') { %>31 <%# Hub: the brand navigates to the hub home via HTMX. The chrome is always32 rendered in hub mode and hidden on the landing via body.on-hub (CSS), so htmx33 can switch without a full reload → the audio player stays alive. %>34 <a class="nav-hub-home" href="/" aria-label="Home" title="Home"35 hx-get="/?partial=1" hx-target="#pcms-main" hx-swap="innerHTML" hx-push-url="/" hx-indicator="#pcms-loading">36 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>37 </a>38 <% } else if (site) { %>39 <a class="site-title" href="<%= _siteUrlBase %>/"40 hx-get="<%= _siteUrlBase %>/?partial=1" hx-target="#pcms-main" hx-swap="innerHTML"41 hx-push-url="<%= _siteUrlBase %>/" hx-indicator="#pcms-loading"><%= site.title %></a>42 30 <% } else { %> 43 31 <a class="site-title" href="/">Klonkt</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)