Merge branch 'develop' into activitypub

This commit is contained in:
Barış Soner Uşaklı
2024-09-12 10:32:40 -04:00
87 changed files with 825 additions and 195 deletions

View File

@@ -29,8 +29,8 @@
},
"dependencies": {
"@adactive/bootstrap-tagsinput": "0.8.2",
"@fontsource/inter": "5.0.20",
"@fontsource/poppins": "5.0.15",
"@fontsource/inter": "5.0.21",
"@fontsource/poppins": "5.0.16",
"@fortawesome/fontawesome-free": "6.6.0",
"@isaacs/ttlcache": "1.4.1",
"@nodebb/spider-detector": "2.0.3",
@@ -41,7 +41,7 @@
"autoprefixer": "10.4.20",
"bcryptjs": "2.4.3",
"benchpressjs": "2.5.1",
"body-parser": "1.20.2",
"body-parser": "1.20.3",
"bootbox": "6.0.0",
"bootstrap": "5.3.3",
"bootswatch": "5.3.3",
@@ -107,9 +107,9 @@
"nodebb-rewards-essentials": "1.0.0",
"nodebb-theme-harmony": "2.0.0-pre.33",
"nodebb-theme-lavender": "7.1.8",
"nodebb-theme-peace": "2.2.6",
"nodebb-theme-peace": "2.2.7",
"nodebb-theme-persona": "14.0.0-pre.1",
"nodebb-widget-essentials": "7.0.27",
"nodebb-widget-essentials": "7.0.28",
"nodemailer": "6.9.15",
"nprogress": "0.2.0",
"passport": "0.7.0",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "أحدث الأعضاء",
"top-posters": "اﻷكثر مشاركة",
"most-reputation": "أعلى سمعة",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Всички потребители",
"followed-users": "Followed Users",
"latest-users": "Последни потребители",
"top-posters": "С най-много публикации",
"most-reputation": "С най-много репутация",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "সর্বশেষ নিবন্ধিত সদস্যরা:",
"top-posters": "সর্বোচ্চ পোষ্টকারী",
"most-reputation": "সর্বোচ্চ সম্মাননাধারী",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Všichni uživatelé",
"followed-users": "Followed Users",
"latest-users": "Nejnovější uživatelé",
"top-posters": "Nejaktivnější",
"most-reputation": "Nejváženější",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Seneste brugere",
"top-posters": "Top Postere",
"most-reputation": "Mest Omdømme",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Alle Benutzer",
"followed-users": "Followed Users",
"latest-users": "Neuste Benutzer",
"top-posters": "Meiste Beiträge",
"most-reputation": "Höchstes Ansehen",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Πρόσφατοι Χρήστες",
"top-posters": "Top Δημοσιεύοντες",
"most-reputation": "Υψηλότερη Φήμη",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Latest Users",
"top-posters": "Top Posters",
"most-reputation": "Most Reputation",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Land lubbers",
"top-posters": "Top mateys",
"most-reputation": "Most Reputation",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Últimos usuarios",
"top-posters": "Top por mensajes",
"most-reputation": "Más reputados",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Hilised kasutajad",
"top-posters": "Top postitajad",
"most-reputation": "Kõige rohkem reputatsiooni",

View File

@@ -1,5 +1,6 @@
{
"all-users": "همه کاربران",
"followed-users": "Followed Users",
"latest-users": "آخرین کاربران",
"top-posters": "برترین فرستنده‌ها",
"most-reputation": "بیشترین اعتبار",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Kaikki käyttäjät",
"followed-users": "Followed Users",
"latest-users": "Viimeisimmät käyttäjät",
"top-posters": "Aktiivisimmat julkaisijat",
"most-reputation": "Maineikkain",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Tous les utilisateurs",
"followed-users": "Followed Users",
"latest-users": "Derniers inscrits",
"top-posters": "Utilisateurs les plus actifs",
"most-reputation": "Meilleur Réputation",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Últimos usuarios",
"top-posters": "Maiores Publicadores",
"most-reputation": "Máis Reputados",

View File

@@ -1,5 +1,6 @@
{
"all-users": "כל המשתמשים",
"followed-users": "Followed Users",
"latest-users": "משתמשים אחרונים",
"top-posters": "מפרסמים הכי הרבה",
"most-reputation": "המוניטין הגבוה ביותר",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Svi korisnici",
"followed-users": "Followed Users",
"latest-users": "Posljednji korisnici",
"top-posters": "Najviše objava",
"most-reputation": "Najveća reputacija",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Összes Felhasználó",
"followed-users": "Followed Users",
"latest-users": "Legújabb felhasználók",
"top-posters": "Legaktívabbak",
"most-reputation": "Legnépszerűbbek",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Բոլոր օգտատերերը",
"followed-users": "Followed Users",
"latest-users": "Վերջին օգտատերերը",
"top-posters": "Ամենաշատ գրառողները",
"most-reputation": "Ամենաբարձր վարկանիշը",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Pengguna Terakhir",
"top-posters": "Posting Terbanyak",
"most-reputation": "Reputasi Terbanyak",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Tutti gli utenti",
"followed-users": "Followed Users",
"latest-users": "Ultimi Utenti",
"top-posters": "Utenti più attivi",
"most-reputation": "Reputazione più alta",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "新しいユーザー",
"top-posters": "最も投稿したユーザー",
"most-reputation": "最も評価されたユーザー",

View File

@@ -1,5 +1,6 @@
{
"all-users": "모든 사용자",
"followed-users": "Followed Users",
"latest-users": "최신 사용자",
"top-posters": "최다 게시자",
"most-reputation": "가장 많은 평판",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Paskutiniai vartotojai",
"top-posters": "Geriausi autoriai",
"most-reputation": "Didžiausia reputacija",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Jaunākie lietotāji",
"top-posters": "Visvairāk rakstu",
"most-reputation": "Visvairāk ranga punktu",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Pengguna terkini",
"top-posters": "Pengirim terbanyak",
"most-reputation": "Reputasi terbaik",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Alle brukere",
"followed-users": "Followed Users",
"latest-users": "Seneste brukere",
"top-posters": "Flest innlegg",
"most-reputation": "Best omdømme",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Laatste gebruikers",
"top-posters": "Meest actieve leden",
"most-reputation": "Meeste reputatie",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Wszyscy użytkownicy",
"followed-users": "Followed Users",
"latest-users": "Nowi użytkownicy",
"top-posters": "Najwięcej postów",
"most-reputation": "Najwyższa reputacja",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Últimos Usuários",
"top-posters": "Principais Participantes",
"most-reputation": "Maior Reputação",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Utilizadores Recentes",
"top-posters": "Top de publicadores",
"most-reputation": "Maior Reputação",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Ultimii Utilizatori",
"top-posters": "Top Utilizatori",
"most-reputation": "Cei mai apreciați utilizatori",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Новые пользователи",
"top-posters": "Самые активные",
"most-reputation": "Лучшая репутация",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Abantu Bashya",
"top-posters": "Abashyizeho Byinshi",
"most-reputation": "Abafite Amanota Menshi",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Ùrtimos Impitadores",
"top-posters": "Prus Ativos",
"most-reputation": "Prus Famados",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Najnovší používatelia",
"top-posters": "Najaktívnejší",
"most-reputation": "Najváženejší",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Zadnji uporabniki",
"top-posters": "Najboljši uporabniki",
"most-reputation": "Največ ugleda",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Përdoruesit e fundit",
"top-posters": "Postuesit më të mirë",
"most-reputation": "Me Reputacion",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Сви корисници",
"followed-users": "Followed Users",
"latest-users": "Најновији корисници",
"top-posters": "Највише порука",
"most-reputation": "Највећи углед",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Alla användare",
"followed-users": "Followed Users",
"latest-users": "Senaste användarna",
"top-posters": "Flest inlägg",
"most-reputation": "Bäst rykte",

View File

@@ -1,5 +1,6 @@
{
"all-users": "ผู้ใช้งานทั้งหมด",
"followed-users": "Followed Users",
"latest-users": "ผู้ใช้งานล่าสุด",
"top-posters": "ผู้ที่โพสต์มากที่สุด",
"most-reputation": "ผู้ที่มีชื่อเสียงมากที่สุด",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Tüm kullanıcılar",
"followed-users": "Followed Users",
"latest-users": "En Yeni Kullanıcılar",
"top-posters": "En Fazla Gönderim Yapanlar",
"most-reputation": "En Saygınlar",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "Останні користувачі",
"top-posters": "Кращі автори",
"most-reputation": "Найбільша репутація",

View File

@@ -1,5 +1,6 @@
{
"all-users": "Tất Cả Người Dùng",
"followed-users": "Followed Users",
"latest-users": "Thành viên mới nhất",
"top-posters": "Thành viên đăng bài nhiều nhất",
"most-reputation": "Uy Tín Nhất",

View File

@@ -1,5 +1,6 @@
{
"all-users": "所有用户",
"followed-users": "Followed Users",
"latest-users": "最新用户",
"top-posters": "发帖排行",
"most-reputation": "声望排行",

View File

@@ -1,5 +1,6 @@
{
"all-users": "All Users",
"followed-users": "Followed Users",
"latest-users": "最新使用者",
"top-posters": "發文排行",
"most-reputation": "聲望排行",

View File

@@ -13,43 +13,19 @@
.tracking-tight { letter-spacing: -0.02em; }
@mixin btn-ghost-base {
display: flex;
align-items: center;
justify-content: center;
gap: ($spacer * 0.5);
border-radius: $border-radius-sm;
border-width: 1px;
border-color: transparent;
background-color: transparent;
padding: ($spacer * 0.25) ($spacer * 0.5);
text-align: left;
--bs-text-opacity: 1;
color: $btn-ghost-color;
font-family: $font-family-secondary;
cursor: pointer;
&:hover, &.active {
background-color: $btn-ghost-hover-color;
text-decoration: none;
}
}
// https://getbootstrap.com/docs/5.3/components/buttons/#variables
.btn-ghost {
@include btn-ghost-base();
line-height: 1.5rem;
> i {
line-height: 1.5rem;
}
--bs-btn-color: #{$btn-ghost-color};
--bs-btn-bg: transparent;
--bs-btn-border-color: transparent;
--bs-btn-box-shadow: none;
--bs-btn-hover-color: #{$btn-ghost-color};
--bs-btn-hover-bg: #{$btn-ghost-hover-color};
--bs-btn-hover-border-color: #{$btn-ghost-hover-color};
--bs-btn-active-bg: #{$btn-ghost-hover-color};
--bs-btn-active-border-color: transparent;
}
.btn-ghost-sm {
@include btn-ghost-base();
font-size: 0.875rem;
line-height: 1.25rem;
> i {
line-height: 1.25rem;
}
}
@include color-mode(dark) {
.btn-light {
@@ -58,10 +34,11 @@
.text-bg-light {
@extend .text-bg-dark;
}
.btn-ghost, .btn-ghost-sm {
.btn-ghost {
color: $btn-ghost-color-dark;
&:hover, &.active {
background-color: $btn-ghost-hover-color-dark;
border-color: $btn-ghost-hover-color-dark;
}
}
}

View File

@@ -1,12 +1,12 @@
#sidebar-left, #offcanvas {
.btn-ghost, .btn-ghost-sm {
.btn-ghost {
i {
color: $gray-500;
}
}
.accordion-body {
.btn-ghost-sm {
.btn-ghost.btn-sm {
padding-left: 38px!important;
}
}

View File

@@ -12,40 +12,15 @@ $btn-ghost-active-color-dark: lighten($btn-ghost-hover-color-dark, 5%)!default;
--btn-ghost-active-color: #{$btn-ghost-active-color-dark};
}
@mixin btn-ghost-base {
display: flex;
align-items: center;
justify-content: center;
gap: ($spacer * 0.5);
border-radius: $border-radius-sm;
border-width: 1px;
border-color: transparent;
background-color: transparent;
box-shadow: none;
padding: ($spacer * 0.25) ($spacer * 0.5);
text-align: left;
--bs-text-opacity: 1;
color: inherit !important;
cursor: pointer;
&:hover, &.active {
background-color: var(--btn-ghost-hover-color);
text-decoration: none;
}
}
// https://getbootstrap.com/docs/5.3/components/buttons/#variables
.btn-ghost {
@include btn-ghost-base();
line-height: 1.5rem;
> i {
line-height: 1.5rem;
}
}
.btn-ghost-sm {
@include btn-ghost-base();
font-size: 0.875rem;
line-height: 1.25rem;
> i {
line-height: 1.25rem;
}
--bs-btn-color: inherit!important;
--bs-btn-bg: transparent;
--bs-btn-border-color: transparent;
--bs-btn-box-shadow: none;
--bs-btn-hover-color: inherit;
--bs-btn-hover-bg: #{$btn-ghost-hover-color};
--bs-btn-hover-border-color: #{$btn-ghost-hover-color};
--bs-btn-active-bg: #{$btn-ghost-hover-color};
--bs-btn-active-border-color: transparent;
}

View File

@@ -36,4 +36,11 @@ html[data-dir="rtl"] {
h5 { font-size: 1.125rem; }
h6 { font-size: 1rem; }
}
}
.btn-link {
&:hover, &.active {
background-color: var(--btn-ghost-hover-color);
text-decoration: none;
}
}

View File

@@ -198,10 +198,10 @@ define('admin/extend/plugins', [
<li class="d-flex justify-content-between gap-1 pointer border-bottom pb-2" data-plugin="${plugin}">
${plugin}
<div class="d-flex gap-1">
<div class="btn-ghost-sm move-up">
<div class="btn btn-ghost btn-sm move-up">
<i class="fa fa-chevron-up"></i>
</div>
<div class="btn-ghost-sm move-down">
<div class="btn btn-ghost btn-sm move-down">
<i class="fa fa-chevron-down"></i>
</div>
</div>

View File

@@ -21,7 +21,7 @@ define('admin/settings', [
if (anchor.startsWith('section')) {
$this.parent().attr('id', anchor);
}
tocList.append(`<a class="btn-ghost-sm text-xs justify-content-start text-decoration-none" href="#${anchor}">${header}</a>`);
tocList.append(`<a class="btn btn-ghost btn-sm text-xs text-start text-decoration-none" href="#${anchor}">${header}</a>`);
});
const offset = mainHader.outerHeight(true);
// https://stackoverflow.com/a/11814275/583363

View File

@@ -8,9 +8,11 @@ const db = require('../database');
const posts = require('../posts');
const socketHelpers = require('../socket.io/helpers');
const topics = require('./index');
const categories = require('../categories');
const groups = require('../groups');
const user = require('../user');
const api = require('../api');
const plugins = require('../plugins');
const Scheduled = module.exports;
@@ -119,13 +121,21 @@ async function sendNotifications(uids, topicsData) {
}
});
return Promise.all(topicsData.map(
await Promise.all(topicsData.map(
(t, idx) => user.notifications.sendTopicNotificationToFollowers(t.uid, t, postsData[idx])
).concat(
postsData.map(p => topics.notifyTagFollowers(p, p.uid))
).concat(
postsData.map(p => categories.notifyCategoryFollowers(p, p.uid))
).concat(
topicsData.map(
(t, idx) => socketHelpers.notifyNew(t.uid, 'newTopic', { posts: [postsData[idx]], topic: t })
)
));
plugins.hooks.fire('action:topics.scheduled.notify', {
posts: postsData,
topics: topicsData,
});
}
async function updateUserLastposttimes(uids, topicsData) {

View File

@@ -588,7 +588,6 @@ module.exports = function (Topics) {
};
Topics.notifyTagFollowers = async function (postData, exceptUid) {
console.log();
let { tags } = postData.topic;
if (!tags.length) {
return;

View File

@@ -4,7 +4,7 @@
<div class="" role="tab">
<h6 class="mb-0 ps-2 d-flex justify-content-between align-items-center">
<span>{hooks.hookName}</span>
<button class="btn-ghost-sm" data-bs-toggle="collapse" data-bs-parent="#accordion" data-bs-target="#{hooks.index}" aria-expanded="true" aria-controls="{hooks.index}">View hooks ({hooks.count})</button>
<button class="btn btn-ghost btn-sm" data-bs-toggle="collapse" data-bs-parent="#accordion" data-bs-target="#{hooks.index}" aria-expanded="true" aria-controls="{hooks.index}">View hooks ({hooks.count})</button>
</h6>
</div>
<div id="{hooks.index}" class="accordion-collapse collapse" role="tabpanel">

View File

@@ -15,7 +15,7 @@
<div class="badge text-bg-light m-1 p-1 border d-inline-flex gap-1 align-items-center" data-uid="{admins.members.uid}">
{buildAvatar(admins.members, "24px", true)}
<a href="{config.relative_path}/user/{admins.members.userslug}">{admins.members.username}</a>
<button class="btn-ghost-sm p-0 remove-user-icon">
<button class="btn btn-ghost btn-sm p-0 remove-user-icon">
<i class="fa fa-fw fa-times"></i>
</button>
</div>
@@ -35,7 +35,7 @@
<div class="badge text-bg-light m-1 p-1 border d-inline-flex gap-1 align-items-center" data-uid="{globalMods.members.uid}">
{buildAvatar(globalMods.members, "24px", true)}
<a href="{config.relative_path}/user/{globalMods.members.userslug}">{globalMods.members.username}</a>
<button class="btn-ghost-sm p-0 remove-user-icon">
<button class="btn btn-ghost btn-sm p-0 remove-user-icon">
<i class="fa fa-fw fa-times"></i>
</button>
</div>
@@ -87,7 +87,7 @@
<div class="badge text-bg-light m-1 p-1 border d-inline-flex gap-1 align-items-center" data-uid="{categoryMods.moderators.uid}">
{buildAvatar(categoryMods.moderators, "24px", true)}
<a href="{config.relative_path}/user/{categoryMods.moderators.userslug}">{categoryMods.moderators.username}</a>
<button class="btn-ghost-sm p-0 remove-user-icon">
<button class="btn btn-ghost btn-sm p-0 remove-user-icon">
<i class="fa fa-fw fa-times" role="button"></i>
</button>
</div>

View File

@@ -4,7 +4,7 @@
<h4 class="fw-bold tracking-tight mb-0">[[admin/manage/categories:manage-categories]]</h4>
</div>
<div class="d-flex gap-1">
<button id="toggle-collapse-all" class="btn-ghost-sm text-nowrap" data-collapsed="0">[[admin/manage/categories:collapse-all]]</button>
<button id="toggle-collapse-all" class="btn btn-ghost btn-sm text-nowrap" data-collapsed="0">[[admin/manage/categories:collapse-all]]</button>
<!-- IMPORT admin/partials/category/selector-dropdown-right.tpl -->

View File

@@ -176,29 +176,31 @@
<div class="col-12 col-md-4 px-0 px-md-3 options acp-sidebar">
<div class="p-2 d-flex flex-column text-bg-light border rounded-1 gap-1">
<a href="{config.relative_path}/admin/manage/categories" class="btn-ghost-sm justify-content-start"><i class="fa fa-fw fa-chevron-left text-primary"></i> [[admin/manage/categories:back-to-categories]]</a>
<a href="{config.relative_path}/admin/manage/categories" class="btn btn-ghost btn-sm d-flex gap-2 align-items-center"><i class="fa fa-fw fa-chevron-left text-primary"></i> [[admin/manage/categories:back-to-categories]]</a>
<hr class="my-1"/>
<button class="btn-ghost-sm justify-content-start copy-settings">
<button class="btn btn-ghost btn-sm d-flex gap-2 align-items-center copy-settings">
<i class="fa fa-fw fa-files-o text-primary"></i> [[admin/manage/categories:copy-settings]]
</button>
<a class="btn-ghost-sm justify-content-start" href="{config.relative_path}/admin/manage/categories/{category.cid}/analytics"><i class="fa fa-fw fa-chart-simple text-primary"></i> [[admin/manage/categories:analytics]]</a>
<a class="btn btn-ghost btn-sm d-flex gap-2 align-items-center" href="{config.relative_path}/admin/manage/categories/{category.cid}/analytics"><i class="fa fa-fw fa-chart-simple text-primary"></i> [[admin/manage/categories:analytics]]</a>
<a href="{config.relative_path}/admin/manage/privileges/{category.cid}" class="btn-ghost-sm justify-content-start">
<a href="{config.relative_path}/admin/manage/privileges/{category.cid}" class="btn btn-ghost btn-sm d-flex gap-2 align-items-center">
<i class="fa fa-fw fa-lock text-primary"></i> [[admin/manage/categories:privileges]]
</a>
<a class="btn-ghost-sm justify-content-start" href="{config.relative_path}/admin/manage/categories/{category.cid}/federation"><i class="fa fa-fw fa-globe text-primary"></i> [[admin/manage/categories:federation]]</a>
<a class="btn btn-ghost btn-sm d-flex gap-2 align-items-center" href="{config.relative_path}/admin/manage/categories/{category.cid}/federation">
<i class="fa fa-fw fa-globe text-primary"></i> [[admin/manage/categories:federation]]
</a>
<a href="{config.relative_path}/category/{category.cid}" class="btn-ghost-sm justify-content-start">
<a href="{config.relative_path}/category/{category.cid}" class="btn btn-ghost btn-sm d-flex gap-2 align-items-center">
<i class="fa fa-fw fa-eye text-primary"></i> [[admin/manage/categories:view-category]]
</a>
<hr class="my-1"/>
<button data-action="toggle" data-disabled="{category.disabled}" class="btn-ghost-sm justify-content-start">
<button data-action="toggle" data-disabled="{category.disabled}" class="btn btn-ghost btn-sm d-flex gap-2 align-items-center">
{{{ if category.disabled }}}
<i class="fa fa-fw fa-check text-success"></i>
<span class="label">[[admin/manage/categories:enable]]</span>
@@ -208,7 +210,7 @@
{{{ end }}}
</button>
<button class="btn-ghost-sm purge justify-content-start">
<button class="btn btn-ghost btn-sm d-flex gap-2 align-items-center">
<i class="fa fa-fw fa-trash text-danger"></i> [[admin/manage/categories:purge]]
</button>

View File

@@ -6,7 +6,7 @@
<h4 class="fw-bold tracking-tight mb-0">[[admin/manage/groups:edit-group]]</h4>
<div component="group-selector" class="btn-group">
<button type="button" class="btn-ghost-sm dropdown-toggle w-100" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<button type="button" class="btn btn-ghost btn-sm dropdown-toggle w-100" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span component="group-selector-selected">{group.displayName}</span> <span class="caret"></span>
</button>
<div component="group-selector-search" class="hidden position-absolute w-100">
@@ -148,13 +148,13 @@
<div class="col-12 col-md-4 px-0 px-md-3 acp-sidebar">
<div class="p-2 d-flex flex-column text-bg-light border rounded-1 gap-1">
<a href="{config.relative_path}/admin/manage/groups" class="btn-ghost-sm justify-content-start"><i class="fa fa-fw fa-chevron-left text-primary"></i> [[admin/manage/groups:back-to-groups]]</a>
<a href="{config.relative_path}/admin/manage/groups" class="btn btn-ghost btn-sm d-flex gap-2 align-items-center"><i class="fa fa-fw fa-chevron-left text-primary"></i> [[admin/manage/groups:back-to-groups]]</a>
<hr class="my-1"/>
<div class="edit-privileges-selector w-100">
<div component="category-selector" class="btn-group w-100">
<button type="button" class="btn-ghost-sm justify-content-start flex-fill dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<button type="button" class="btn btn-ghost btn-sm d-flex gap-2 align-items-center flex-fill dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fa fa-fw fa-lock text-primary"></i> <span>[[admin/manage/groups:privileges]]</span> <span class="caret"></span>
</button>
<div component="category-selector-search" class="hidden position-absolute">
@@ -180,16 +180,16 @@
</div>
</div>
<a href="{config.relative_path}/api/admin/groups/{group.nameEncoded}/csv" class="btn-ghost-sm justify-content-start">
<a href="{config.relative_path}/api/admin/groups/{group.nameEncoded}/csv" class="btn btn-ghost btn-sm d-flex gap-2 align-items-center">
<i class="fa fa-fw fa-file-csv text-primary"></i>[[admin/manage/groups:members-csv]]</a>
<a href="{config.relative_path}/groups/{group.slug}" class="btn-ghost-sm justify-content-start">
<a href="{config.relative_path}/groups/{group.slug}" class="btn btn-ghost btn-sm d-flex gap-2 align-items-center">
<i class="fa fa-fw fa-eye text-primary"></i> [[admin/manage/groups:view-group]]
</a>
<hr class="my-1"/>
<button data-action="delete" class="btn-ghost-sm justify-content-start">
<button data-action="delete" class="btn btn-ghost btn-sm d-flex gap-2 align-items-center">
<i class="fa fa-fw fa-trash text-danger"></i> [[admin/manage/groups:delete]]
</button>
</div>

View File

@@ -1,4 +1,4 @@
<button type="button" class="btn-ghost-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<button type="button" class="btn btn-ghost btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span component="category-selector-selected">
<span class="category-item d-inline-flex align-items-center gap-1">
{{{ if (selectedCategory && !showCategorySelectLabel) }}}

View File

@@ -4,18 +4,18 @@
<!-- dashboard menu -->
<div class="d-flex flex-column">
<button class="btn-ghost justify-content-start" type="button" data-bs-toggle="collapse" data-bs-target="#collapseDashboard" aria-expanded="true" aria-controls="collapseDashboard">
<button class="btn btn-ghost btn-sm d-flex gap-2 align-items-center" type="button" data-bs-toggle="collapse" data-bs-target="#collapseDashboard" aria-expanded="true" aria-controls="collapseDashboard">
<i class="fa fa-fw fa-gauge"></i>
<div class="flex-1 font-serif text-sm fw-semibold">[[admin/menu:section-dashboard]]</div>
<div class="flex-1 font-serif text-sm fw-semibold text-start">[[admin/menu:section-dashboard]]</div>
</button>
<div id="collapseDashboard" class="accordion-collapse collapse" data-bs-parent="#accordionACP">
<div class="accordion-body p-0">
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/dashboard">[[admin/menu:dashboard/overview]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/dashboard/logins">[[admin/menu:dashboard/logins]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/dashboard/users">[[admin/menu:dashboard/users]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/dashboard/topics">[[admin/menu:dashboard/topics]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/dashboard/searches">[[admin/menu:dashboard/searches]]</a>
<div class="accordion-body p-0 d-grid">
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/dashboard">[[admin/menu:dashboard/overview]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/dashboard/logins">[[admin/menu:dashboard/logins]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/dashboard/users">[[admin/menu:dashboard/users]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/dashboard/topics">[[admin/menu:dashboard/topics]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/dashboard/searches">[[admin/menu:dashboard/searches]]</a>
</div>
</div>
</div>
@@ -23,40 +23,40 @@
<!-- manage menu -->
{{{ if showManageMenu }}}
<div class="d-flex flex-column">
<button class="btn-ghost justify-content-start" type="button" data-bs-toggle="collapse" data-bs-target="#collapseManage" aria-expanded="true" aria-controls="collapseManage">
<button class="btn btn-ghost btn-sm d-flex gap-2 align-items-center" type="button" data-bs-toggle="collapse" data-bs-target="#collapseManage" aria-expanded="true" aria-controls="collapseManage">
<i class="fa fa-fw fa-list"></i>
<div class="flex-1 font-serif text-sm fw-semibold">[[admin/menu:section-manage]]</div>
<div class="flex-1 font-serif text-sm fw-semibold text-start">[[admin/menu:section-manage]]</div>
</button>
<div id="collapseManage" class="accordion-collapse collapse" data-bs-parent="#accordionACP">
<div class="accordion-body p-0">
<div class="accordion-body p-0 d-grid">
{{{ if user.privileges.admin:categories }}}
<a class="btn-ghost-sm justify-content-start text-decoration-none" id="manage-categories" href="{relative_path}/admin/manage/categories">[[admin/menu:manage/categories]]</a>
<a class="btn btn-ghost btn-sm text-start" id="manage-categories" href="{relative_path}/admin/manage/categories">[[admin/menu:manage/categories]]</a>
{{{ end }}}
{{{ if user.privileges.admin:privileges }}}
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/manage/privileges">[[admin/menu:manage/privileges]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/manage/privileges">[[admin/menu:manage/privileges]]</a>
{{{ end }}}
{{{ if user.privileges.admin:users }}}
<a class="btn-ghost-sm justify-content-start text-decoration-none" id="manage-users" href="{relative_path}/admin/manage/users">[[admin/menu:manage/users]]</a>
<a class="btn btn-ghost btn-sm text-start" id="manage-users" href="{relative_path}/admin/manage/users">[[admin/menu:manage/users]]</a>
{{{ end }}}
{{{ if user.privileges.admin:groups }}}
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/manage/groups">[[admin/menu:manage/groups]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/manage/groups">[[admin/menu:manage/groups]]</a>
{{{ end }}}
{{{ if user.privileges.admin:admins-mods }}}
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/manage/admins-mods">[[admin/menu:manage/admins-mods]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/manage/admins-mods">[[admin/menu:manage/admins-mods]]</a>
{{{ end }}}
{{{ if user.privileges.admin:tags }}}
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/manage/tags">[[admin/menu:manage/tags]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/manage/tags">[[admin/menu:manage/tags]]</a>
{{{ end }}}
{{{ if user.privileges.superadmin }}}
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/manage/registration">[[admin/menu:manage/registration]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/manage/uploads">[[admin/menu:manage/uploads]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/manage/digest">[[admin/menu:manage/digest]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/manage/registration">[[admin/menu:manage/registration]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/manage/uploads">[[admin/menu:manage/uploads]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/manage/digest">[[admin/menu:manage/digest]]</a>
<hr/>
<h6 class="text-xs ps-4">[[pages:moderator-tools]]</h6>
<a class="btn-ghost-sm justify-content-start text-decoration-none" target="_top" href="{relative_path}/flags">[[admin/menu:manage/flagged-content]] <i class="fa fa-external-link"></i></a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" target="_top" href="{relative_path}/post-queue">[[admin/menu:manage/post-queue]] <i class="fa fa-external-link"></i></a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" target="_top" href="{relative_path}/ip-blacklist">[[admin/menu:manage/ip-blacklist]] <i class="fa fa-external-link"></i></a>
<a class="btn btn-ghost btn-sm text-start" target="_top" href="{relative_path}/flags">[[admin/menu:manage/flagged-content]] <i class="fa fa-external-link"></i></a>
<a class="btn btn-ghost btn-sm text-start" target="_top" href="{relative_path}/post-queue">[[admin/menu:manage/post-queue]] <i class="fa fa-external-link"></i></a>
<a class="btn btn-ghost btn-sm text-start" target="_top" href="{relative_path}/ip-blacklist">[[admin/menu:manage/ip-blacklist]] <i class="fa fa-external-link"></i></a>
{{{ end }}}
</div>
</div>
@@ -66,30 +66,30 @@
<!-- settings menu -->
{{{ if user.privileges.admin:settings }}}
<div class="d-flex flex-column">
<button class="btn-ghost justify-content-start" type="button" data-bs-toggle="collapse" data-bs-target="#collapseSettings" aria-expanded="true" aria-controls="collapseSettings">
<button class="btn btn-ghost btn-sm d-flex gap-2 align-items-center" type="button" data-bs-toggle="collapse" data-bs-target="#collapseSettings" aria-expanded="true" aria-controls="collapseSettings">
<i class="fa fa-fw fa-sliders"></i>
<div class="flex-1 font-serif text-sm fw-semibold">[[admin/menu:section-settings]]</div>
<div class="flex-1 font-serif text-sm fw-semibold text-start">[[admin/menu:section-settings]]</div>
</button>
<div id="collapseSettings" class="accordion-collapse collapse" data-bs-parent="#accordionACP">
<div class="accordion-body p-0">
<a class="btn-ghost-sm justify-content-start text-decoration-none" id="settings-general" href="{relative_path}/admin/settings/general">[[admin/menu:section-general]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/navigation">[[admin/menu:settings/navigation]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/user">[[admin/menu:settings/user]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/reputation">[[admin/menu:settings/reputation]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/group">[[admin/menu:settings/group]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/tags">[[admin/menu:manage/tags]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/post">[[admin/menu:settings/post]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/uploads">[[admin/menu:settings/uploads]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/email">[[admin/menu:settings/email]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/chat">[[admin/menu:settings/chat]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/pagination">[[admin/menu:settings/pagination]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/notifications">[[admin/menu:settings/notifications]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/api">[[admin/menu:settings/api]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/activitypub">[[admin/menu:settings/activitypub]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/cookies">[[admin/menu:settings/cookies]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/web-crawler">[[admin/menu:settings/web-crawler]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/settings/advanced">[[admin/menu:settings/advanced]]</a>
<a class="btn btn-ghost btn-sm text-start" id="settings-general" href="{relative_path}/admin/settings/general">[[admin/menu:section-general]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/navigation">[[admin/menu:settings/navigation]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/user">[[admin/menu:settings/user]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/reputation">[[admin/menu:settings/reputation]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/group">[[admin/menu:settings/group]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/tags">[[admin/menu:manage/tags]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/post">[[admin/menu:settings/post]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/uploads">[[admin/menu:settings/uploads]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/email">[[admin/menu:settings/email]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/chat">[[admin/menu:settings/chat]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/pagination">[[admin/menu:settings/pagination]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/notifications">[[admin/menu:settings/notifications]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/api">[[admin/menu:settings/api]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/activitypub">[[admin/menu:settings/activitypub]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/cookies">[[admin/menu:settings/cookies]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/web-crawler">[[admin/menu:settings/web-crawler]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/advanced">[[admin/menu:settings/advanced]]</a>
</div>
</div>
</div>
@@ -97,16 +97,16 @@
<!-- appearance menu -->
<div class="d-flex flex-column">
<button class="btn-ghost justify-content-start" type="button" data-bs-toggle="collapse" data-bs-target="#collapseAppearance" aria-expanded="true" aria-controls="collapseAppearance">
<button class="btn btn-ghost btn-sm d-flex gap-2 align-items-center" type="button" data-bs-toggle="collapse" data-bs-target="#collapseAppearance" aria-expanded="true" aria-controls="collapseAppearance">
<i class="fa fa-fw fa-paintbrush"></i>
<div class="flex-1 font-serif text-sm fw-semibold">[[admin/menu:section-appearance]]</div>
<div class="flex-1 font-serif text-sm fw-semibold text-start">[[admin/menu:section-appearance]]</div>
</button>
<div id="collapseAppearance" class="accordion-collapse collapse" data-bs-parent="#accordionACP">
<div class="accordion-body p-0">
<a class="btn-ghost-sm justify-content-start text-decoration-none" id="appearance-themes" href="{relative_path}/admin/appearance/themes">[[admin/menu:appearance/themes]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" id="appearance-skins" href="{relative_path}/admin/appearance/skins">[[admin/menu:appearance/skins]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" id="appearance-customise" href="{relative_path}/admin/appearance/customise">[[admin/menu:appearance/customise]]</a>
<div class="accordion-body p-0 d-grid">
<a class="btn btn-ghost btn-sm text-start" id="appearance-themes" href="{relative_path}/admin/appearance/themes">[[admin/menu:appearance/themes]]</a>
<a class="btn btn-ghost btn-sm text-start" id="appearance-skins" href="{relative_path}/admin/appearance/skins">[[admin/menu:appearance/skins]]</a>
<a class="btn btn-ghost btn-sm text-start" id="appearance-customise" href="{relative_path}/admin/appearance/customise">[[admin/menu:appearance/customise]]</a>
</div>
</div>
</div>
@@ -114,16 +114,16 @@
<!-- extend menu -->
<div class="d-flex flex-column">
<button class="btn-ghost justify-content-start" type="button" data-bs-toggle="collapse" data-bs-target="#collapseExtend" aria-expanded="true" aria-controls="collapseExtend">
<button class="btn btn-ghost btn-sm d-flex gap-2 align-items-center" type="button" data-bs-toggle="collapse" data-bs-target="#collapseExtend" aria-expanded="true" aria-controls="collapseExtend">
<i class="fa fa-fw fa-wrench"></i>
<div class="flex-1 font-serif text-sm fw-semibold">[[admin/menu:section-extend]]</div>
<div class="flex-1 font-serif text-sm fw-semibold text-start">[[admin/menu:section-extend]]</div>
</button>
<div id="collapseExtend" class="accordion-collapse collapse" data-bs-parent="#accordionACP">
<div class="accordion-body p-0">
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/extend/plugins">[[admin/menu:extend/plugins]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/extend/widgets">[[admin/menu:extend/widgets]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/extend/rewards">[[admin/menu:extend/rewards]]</a>
<div class="accordion-body p-0 d-grid">
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/extend/plugins">[[admin/menu:extend/plugins]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/extend/widgets">[[admin/menu:extend/widgets]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/extend/rewards">[[admin/menu:extend/rewards]]</a>
</div>
</div>
</div>
@@ -131,26 +131,26 @@
<!-- plugins menu -->
{{{ if plugins.length }}}
<div class="d-flex flex-column">
<button class="btn-ghost justify-content-start" type="button" data-bs-toggle="collapse" data-bs-target="#collapsePlugins" aria-expanded="true" aria-controls="collapsePlugins">
<button class="btn btn-ghost btn-sm d-flex gap-2 align-items-center" type="button" data-bs-toggle="collapse" data-bs-target="#collapsePlugins" aria-expanded="true" aria-controls="collapsePlugins">
<i class="fa fa-fw fa-plug"></i>
<div class="flex-1 font-serif text-sm fw-semibold">[[admin/menu:section-plugins]]</div>
<div class="flex-1 font-serif text-sm fw-semibold text-start">[[admin/menu:section-plugins]]</div>
</button>
<div id="collapsePlugins" class="accordion-collapse collapse" data-bs-parent="#accordionACP">
<div class="accordion-body p-0">
<div class="accordion-body p-0 d-grid">
{{{ each plugins }}}
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin{./route}">{./name}</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin{./route}">{./name}</a>
{{{ end }}}
{{{ if authentication.length }}}
<hr/>
<div class="text-sm ms-4">[[admin/menu:section-social-auth]]</div>
{{{ each authentication }}}
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin{./route}">{./name}</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin{./route}">{./name}</a>
{{{ end }}}
{{{ end }}}
<hr/>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/extend/plugins#download">[[admin/menu:extend/plugins.install]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/extend/plugins#download">[[admin/menu:extend/plugins.install]]</a>
</div>
</div>
</div>
@@ -160,21 +160,21 @@
<!-- advanced menu -->
{{{ if user.privileges.superadmin }}}
<div class="d-flex flex-column">
<button class="btn-ghost justify-content-start" type="button" data-bs-toggle="collapse" data-bs-target="#collapseAdvanced" aria-expanded="true" aria-controls="collapseAdvanced">
<button class="btn btn-ghost btn-sm d-flex gap-2 align-items-center" type="button" data-bs-toggle="collapse" data-bs-target="#collapseAdvanced" aria-expanded="true" aria-controls="collapseAdvanced">
<i class="fa fa-fw fa-superpowers"></i>
<div class="flex-1 font-serif text-sm fw-semibold">[[admin/menu:section-advanced]]</div>
<div class="flex-1 font-serif text-sm fw-semibold text-start">[[admin/menu:section-advanced]]</div>
</button>
<div id="collapseAdvanced" class="accordion-collapse collapse" data-bs-parent="#accordionACP">
<div class="accordion-body p-0">
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/advanced/database">[[admin/menu:advanced/database]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/advanced/events">[[admin/menu:advanced/events]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/advanced/hooks">[[admin/menu:advanced/hooks]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/advanced/cache">[[admin/menu:advanced/cache]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/advanced/errors">[[admin/menu:advanced/errors]]</a>
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/advanced/logs">[[admin/menu:advanced/logs]]</a>
<div class="accordion-body p-0 d-grid">
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/advanced/database">[[admin/menu:advanced/database]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/advanced/events">[[admin/menu:advanced/events]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/advanced/hooks">[[admin/menu:advanced/hooks]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/advanced/cache">[[admin/menu:advanced/cache]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/advanced/errors">[[admin/menu:advanced/errors]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/advanced/logs">[[admin/menu:advanced/logs]]</a>
{{{ if env }}}
<a class="btn-ghost-sm justify-content-start text-decoration-none" href="{relative_path}/admin/development/logger">[[admin/menu:development/logger]]</a>
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/development/logger">[[admin/menu:development/logger]]</a>
{{{ end }}}
</div>
</div>

View File

@@ -2,7 +2,7 @@
<div class="offcanvas-body flex-0 pb-0 overflow-visible d-flex flex-column gap-1 ff-secondary">
<!-- IMPORT admin/partials/quick_actions/alerts.tpl -->
<a href="{config.relative_path}/" class="btn-ghost fw-semibold text-decoration-none justify-content-start"><i class="fa fa-fw fa-home"></i> [[admin/menu:view-forum]]</a>
<a href="{config.relative_path}/" class="btn btn-ghost btn-sm d-flex gap-2 fw-semibold text-decoration-none align-items-center justify-content-start"><i class="fa fa-fw fa-home"></i> [[admin/menu:view-forum]]</a>
<!-- IMPORT admin/partials/search.tpl -->
</div>

View File

@@ -1,7 +1,7 @@
{{{ if user.privileges.superadmin }}}
<button component="rebuild-and-restart" class="btn-ghost fw-semibold text-decoration-none justify-content-start" ><i class="fa fa-fw fa-refresh"></i> [[admin/menu:rebuild-and-restart]]</button>
<button component="rebuild-and-restart" class="btn btn-ghost btn-sm d-flex gap-2 align-items-center fw-semibold text-decoration-none justify-content-start" ><i class="fa fa-fw fa-refresh"></i> [[admin/menu:rebuild-and-restart]]</button>
<button component="restart" class="btn-ghost fw-semibold text-decoration-none justify-content-start" ><i class="fa fa-fw fa-repeat"></i> [[admin/menu:restart]]</button>
<button component="restart" class="btn btn-ghost btn-sm d-flex gap-2 align-items-center fw-semibold text-decoration-none justify-content-start" ><i class="fa fa-fw fa-repeat"></i> [[admin/menu:restart]]</button>
{{{ end }}}
<button component="logout" class="btn-ghost fw-semibold text-decoration-none justify-content-start" ><i class="fa fa-fw fa-sign-out"></i> [[admin/menu:logout]]</button>
<button component="logout" class="btn btn-ghost btn-sm d-flex gap-2 align-items-center fw-semibold text-decoration-none justify-content-start" ><i class="fa fa-fw fa-sign-out"></i> [[admin/menu:logout]]</button>

View File

@@ -3,7 +3,7 @@
<!-- IMPORT admin/partials/quick_actions/alerts.tpl -->
<a href="{config.relative_path}/" class="btn-ghost fw-semibold text-decoration-none justify-content-start"><i class="fa fa-fw fa-home"></i> [[admin/menu:view-forum]]</a>
<a href="{config.relative_path}/" class="btn btn-ghost btn-sm d-flex gap-2 align-items-center fw-semibold text-decoration-none"><i class="fa fa-fw fa-home"></i> [[admin/menu:view-forum]]</a>
<!-- IMPORT admin/partials/search.tpl -->
</div>

View File

@@ -4,7 +4,7 @@
<div class="modal-header d-flex gap-4 justify-content-between">
<div class="fs-6 flex-grow-1 fw-semibold tracking-tight text-truncate text-nowrap" component="chat/room/name" data-icon="{icon}">{{{ if ./roomName }}}<i class="fa {icon} text-muted"></i> {roomName}{{{ else }}}{./chatWithMessage}{{{ end}}}</div>
<div class="d-flex gap-1 align-items-center">
<button type="button" class="btn-ghost-sm d-none d-md-flex" data-action="maximize" title="[[modules:chat.maximize]]" data-bs-toggle="tooltip" data-bs-placement="bottom">
<button type="button" class="btn btn-ghost btn-sm d-none d-md-flex align-self-stretch align-items-center" data-action="maximize" title="[[modules:chat.maximize]]" data-bs-toggle="tooltip" data-bs-placement="bottom">
<i class="fa fa-fw fa-expand text-muted"></i>
</button>

View File

@@ -12,14 +12,14 @@
<div class="d-flex flex-column gap-1">
<div class="d-flex gap-1 align-items-center justify-content-between justify-content-lg-start">
<button class="btn-ghost-sm p-1 order-1 order-lg-0" data-bs-toggle="collapse" data-bs-target="#public-rooms"
<button class="btn btn-ghost btn-sm p-1 order-1 order-lg-0" data-bs-toggle="collapse" data-bs-target="#public-rooms"
onclick="$(this).find('i').toggleClass('fa-rotate-180');"><i class="fa fa-fw fa-chevron-up" style="transition: 0.25s ease;"></i></button>
<label class="text-sm text-muted lh-1">[[modules:chat.public-rooms, {publicRooms.length}]]</label>
</div>
<div id="public-rooms" component="chat/public" class="collapse show">
<div class="d-flex gap-1 flex-column">
{{{ each publicRooms }}}
<div component="chat/public/room" class="btn-ghost-sm ff-sans justify-content-between hover-parent {{{ if ./unread}}}unread{{{ end }}}" data-roomid="{./roomId}">
<div component="chat/public/room" class="btn btn-ghost btn-sm ff-sans d-flex justify-content-between hover-parent {{{ if ./unread}}}unread{{{ end }}}" data-roomid="{./roomId}">
<div class="d-flex gap-1 align-items-center"><i class="fa {./icon} text-muted"></i> {./roomName} <div component="chat/public/room/unread/count" data-count="{./unreadCount}" class="badge border bg-light text-primary {{{ if !./unreadCount }}}hidden{{{ end }}}">{./unreadCountText}</div></div>
<div>
<div component="chat/public/room/sort/handle" class="text-muted {{{ if isAdmin }}}hover-d-block{{{ else }}}d-none{{{ end }}}" style="cursor:grab;"><i class="fa fa-bars"></i></div>
@@ -36,7 +36,7 @@
<div class="d-flex flex-column gap-1 overflow-auto">
{{{ if rooms.length }}}
<div class="d-flex gap-1 align-items-center justify-content-between justify-content-lg-start">
<button class="btn-ghost-sm p-1 order-1 order-lg-0" data-bs-toggle="collapse" data-bs-target="#private-rooms"
<button class="btn btn-ghost btn-sm p-1 order-1 order-lg-0" data-bs-toggle="collapse" data-bs-target="#private-rooms"
onclick="$(this).find('i').toggleClass('fa-rotate-180')"><i class="fa fa-fw fa-chevron-up" style="transition: 0.25s ease;"></i></button>
<label class="text-sm text-muted lh-1">[[modules:chat.private-rooms, {privateRoomCount}]]</label>
</div>

101
src/views/login.tpl Normal file
View File

@@ -0,0 +1,101 @@
<div data-widget-area="header">
{{{each widgets.header}}}
{{widgets.header.html}}
{{{end}}}
</div>
<div class="row login flex-fill">
<div class="d-flex flex-column gap-2 {{{ if widgets.sidebar.length }}}col-lg-9 col-sm-12{{{ else }}}col-lg-12{{{ end }}}">
<h2 class="tracking-tight fw-semibold text-center">[[global:login]]</h2>
<div class="row justify-content-center gap-5">
{{{ if allowLocalLogin }}}
<div class="col-12 col-md-5 col-lg-3 px-md-0">
<div class="login-block">
<form class="d-flex flex-column gap-3" role="form" method="post" id="login-form">
<div class="mb-2 d-flex flex-column gap-2">
<label for="username">{allowLoginWith}</label>
<input class="form-control" type="text" placeholder="{allowLoginWith}" name="username" id="username" autocorrect="off" autocapitalize="off" autocomplete="nickname" value="{username}" aria-required="true"/>
</div>
<div class="mb-2 d-flex flex-column gap-2">
<label for="password">[[user:password]]</label>
<div>
<input class="form-control" type="password" placeholder="[[user:password]]" name="password" id="password" autocomplete="current-password" autocapitalize="off" aria-required="true"/>
<p id="caps-lock-warning" class="text-danger hidden text-sm mb-0 form-text" aria-live="polite" role="alert" aria-atomic="true">
<i class="fa fa-exclamation-triangle"></i> [[login:caps-lock-enabled]]
</p>
</div>
{{{ if allowPasswordReset }}}
<div>
<a id="reset-link" class="text-sm text-reset text-decoration-underline" href="{config.relative_path}/reset">[[login:forgot-password]]</a>
</div>
{{{ end }}}
</div>
{{{ each loginFormEntry }}}
<div class="mb-2 loginFormEntry d-flex flex-column gap-2 {./styleName}">
<label for="{./inputId}">{./label}</label>
<div>{{./html}}</div>
</div>
{{{ end }}}
<input type="hidden" name="_csrf" value="{config.csrf_token}" />
<input type="hidden" name="noscript" id="noscript" value="true" />
<button class="btn btn-primary" id="login" type="submit">[[global:login]]</button>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" name="remember" id="remember" checked />
<label class="form-check-label" for="remember">[[login:remember-me]]</label>
</div>
<div class="alert alert-danger {{{ if !error }}} hidden{{{ end }}}" id="login-error-notify" role="alert" aria-atomic="true">
<strong>[[login:failed-login-attempt]]</strong>
<p class="mb-0">{error}</p>
</div>
<hr/>
{{{ if allowRegistration }}}
<span class="text-sm">[[login:dont-have-account]]</span>
<a class="btn btn-outline-light text-body" href="{config.relative_path}/register">[[register:register]]</a>
{{{ end }}}
</form>
</div>
</div>
{{{ end }}}
{{{ if alternate_logins }}}
<div class="col-12 col-md-5 col-lg-3 px-md-0">
<div class="alt-login-block d-flex flex-column gap-2">
<label>[[login:alternative-logins]]</label>
<ul class="alt-logins list-unstyled">
{{{ each authentication }}}
<li class="{./name} mb-2">
<a class="btn btn-outline-light d-flex align-items-center" rel="nofollow noopener noreferrer" target="_top" href="{config.relative_path}{./url}">
{{{ if ./icons.svg }}}
{./icons.svg}
{{{ else }}}
<i class="flex-shrink-0 {./icons.normal}" style="color:{./color};"></i>
{{{ end }}}
{{{ if ./labels.login }}}
<div class="flex-grow-1 text-body text-sm">{./labels.login}</div>
{{{ end }}}
</a></li>
{{{ end }}}
</ul>
</div>
</div>
{{{ end }}}
</div>
</div>
<div data-widget-area="sidebar" class="col-lg-3 col-sm-12 {{{ if !widgets.sidebar.length }}}hidden{{{ end }}}">
{{{each widgets.sidebar}}}
{{widgets.sidebar.html}}
{{{end}}}
</div>
</div>
<div data-widget-area="footer">
{{{each widgets.footer}}}
{{widgets.footer.html}}
{{{end}}}
</div>

View File

@@ -0,0 +1,41 @@
<button type="button" class="btn btn-ghost btn-sm d-flex align-items-center ff-secondary d-flex gap-2 dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{{ if selectedCategory }}}
<span class="category-item d-inline-flex align-items-center gap-1">
{buildCategoryIcon(selectedCategory, "18px", "rounded-circle")}
<span class="d-none d-md-inline fw-semibold">{selectedCategory.name}</span>
</span>
{{{ else }}}
<i class="fa fa-fw fa-list text-primary"></i>
<span class="d-none d-md-inline fw-semibold">[[unread:all-categories]]</span>{{{ end }}}
</button>
<div component="category-selector-search" class="hidden position-absolute">
<input type="text" class="form-control form-control-sm" placeholder="[[search:type-to-search]]" autocomplete="off">
</div>
<div class="dropdown-menu p-1">
<ul component="category/list" class="list-unstyled mb-0 text-sm category-dropdown-menu ghost-scrollbar" role="menu">
<li role="presentation" class="category" data-cid="all">
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem" href="{{{ if allCategoriesUrl }}}{config.relative_path}/{allCategoriesUrl}{{{ else }}}#{{{ end }}}">
<div class="flex-grow-1">[[unread:all-categories]]</div>
<i component="category/select/icon" class="flex-shrink-0 fa fa-fw fa-check {{{if selectedCategory}}}invisible{{{end}}}"></i>
</a>
</li>
{{{each categoryItems}}}
<li role="presentation" class="category {{{ if ./disabledClass }}}disabled{{{ end }}}" data-cid="{./cid}" data-parent-cid="{./parentCid}" data-name="{./name}">
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2 {{{ if ./disabledClass }}}disabled{{{ end }}}" role="menuitem" href="#">
{./level}
<span component="category-markup" class="flex-grow-1" style="{{{ if ./match }}}font-weight: bold;{{{end}}}">
<div class="category-item d-inline-flex align-items-center gap-1">
{{{ if ./icon }}}
{buildCategoryIcon(@value, "24px", "rounded-circle")}
{{{ end }}}
{./name}
</div>
</span>
<i component="category/select/icon" class="flex-shrink-0 fa fa-fw fa-check {{{ if !./selected }}}invisible{{{ end }}}"></i>
</a>
</li>
{{{end}}}
</ul>
</div>

View File

@@ -0,0 +1,39 @@
<button type="button" class="btn btn-ghost btn-sm ff-secondary d-flex align-items-center gap-2 dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span component="category-selector-selected">
{{{ if (selectedCategory && !showCategorySelectLabel) }}}
<span class="category-item d-inline-flex align-items-center gap-1">
{buildCategoryIcon(selectedCategory, "24px", "rounded-circle")}
<span class="fw-semibold">{selectedCategory.name}</span>
</span>
{{{ else }}}
<i class="fa fa-fw {{{ if selectCategoryIcon }}}{selectCategoryIcon}{{{ else }}}fa-list{{{ end }}} text-primary"></i>
<span class="visible-md-inline visible-lg-inline fw-semibold">{{{ if selectCategoryLabel }}}{selectCategoryLabel}{{{ else }}}[[topic:thread-tools.select-category]]{{{ end }}}</span>
{{{ end }}}
</span>
</button>
<div component="category-selector-search" class="hidden position-absolute">
<input type="text" class="form-control form-control-sm" placeholder="[[search:type-to-search]]" autocomplete="off">
</div>
<div class="dropdown-menu p-1">
<ul component="category/list" class="list-unstyled mb-0 text-sm category-dropdown-menu ghost-scrollbar" role="menu">
<li component="category/no-matches" role="presentation" class="category hidden">
<a class="dropdown-item rounded-1" role="menuitem">[[search:no-matches]]</a>
</li>
{{{ each categoryItems }}}
<li role="presentation" class="category {{{ if ./disabledClass }}}disabled {{{ end }}}" data-cid="{./cid}" data-name="{./name}" data-parent-cid="{./parentCid}">
<a class="dropdown-item rounded-1 {{{ if ./disabledClass }}}disabled{{{ end }}}" role="menuitem" href="#">{./level}
<span component="category-markup" style="{{{ if ./match }}}font-weight: bold;{{{end}}}">
<div class="category-item d-inline-flex align-items-center gap-1">
{{{ if ./icon }}}
{buildCategoryIcon(@value, "24px", "rounded-circle")}
{{{ end }}}
{./name}
</div>
</span>
</a>
</li>
{{{ end }}}
</ul>
</div>

View File

@@ -0,0 +1,39 @@
<div class="btn-group bottom-sheet" component="thread/sort">
<button class="btn btn-ghost btn-sm ff-secondary d-flex gap-2 align-items-center dropdown-toggle" data-bs-toggle="dropdown" type="button" aria-haspopup="true" aria-expanded="false" aria-label="[[aria:topic-sort-option, {sortOptionLabel}]]">
<i class="fa fa-fw fa-arrow-down-wide-short text-primary"></i>
<span class="d-none d-md-inline fw-semibold">{sortOptionLabel}</span>
</button>
<ul class="dropdown-menu p-1 text-sm" role="menu">
<li>
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-sort="recently_replied" role="menuitem">
<span class="flex-grow-1">[[topic:recently-replied]]</span>
<i class="flex-shrink-0 fa fa-fw text-secondary"></i>
</a>
</li>
<li>
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-sort="recently_created" role="menuitem">
<span class="flex-grow-1">[[topic:recently-created]]</span>
<i class="flex-shrink-0 fa fa-fw text-secondary"></i>
</a>
</li>
<li>
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-sort="most_posts" role="menuitem">
<span class="flex-grow-1">[[topic:most-posts]]</span>
<i class="flex-shrink-0 fa fa-fw text-secondary"></i>
</a>
</li>
<li>
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-sort="most_votes" role="menuitem">
<span class="flex-grow-1">[[topic:most-votes]]</span>
<i class="flex-shrink-0 fa fa-fw text-secondary"></i>
</a>
</li>
<li>
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-sort="most_views" role="menuitem">
<span class="flex-grow-1">[[topic:most-views]]</span>
<i class="flex-shrink-0 fa fa-fw text-secondary"></i>
</a>
</li>
</ul>
</div>

View File

@@ -0,0 +1,85 @@
<button class="btn btn-ghost btn-sm ff-secondary d-flex gap-2 align-items-center dropdown-toggle" data-bs-toggle="dropdown" type="button" aria-haspopup="true" aria-expanded="false">
<i class="fa fa-fw fa-gear text-primary"></i>
<span class="visible-md-inline visible-lg-inline fw-semibold">[[topic:thread-tools.title]]</span>
<span component="topic/selected/badge" class="badge rounded-pill bg-secondary"></span>
</button>
<ul class="dropdown-menu p-1 text-sm" role="menu">
<li>
<a component="topic/mark-unread-for-all" href="#" class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem">
<i class="fa fa-fw fa-inbox text-secondary"></i> [[topic:thread-tools.markAsUnreadForAll]]
</a>
</li>
<li>
<a component="topic/pin" href="#" class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem">
<i class="fa fa-fw fa-thumb-tack text-secondary"></i> [[topic:thread-tools.pin]]
</a>
</li>
<li>
<a component="topic/unpin" href="#" class="hidden dropdown-item rounded-1" role="menuitem">
<i class="fa fa-fw fa-thumb-tack fa-rotate-90 text-secondary"></i> [[topic:thread-tools.unpin]]
</a>
</li>
<li>
<a component="topic/lock" href="#" class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem">
<i class="fa fa-fw fa-lock text-secondary"></i> [[topic:thread-tools.lock]]
</a>
</li>
<li>
<a component="topic/unlock" href="#" class="hidden dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem">
<i class="fa fa-fw fa-unlock text-secondary"></i> [[topic:thread-tools.unlock]]
</a>
</li>
<li class="dropdown-divider"></li>
<li>
<a component="topic/move" href="#" class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem">
<i class="fa fa-fw fa-arrows text-secondary"></i> [[topic:thread-tools.move]]
</a>
</li>
{{{if template.category}}}
<li>
<a component="topic/move-all" href="#" class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem">
<i class="fa fa-fw fa-arrows text-secondary"></i> [[topic:thread-tools.move-all]]
</a>
</li>
{{{end}}}
<li>
<a component="topic/merge" href="#" class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem">
<i class="fa fa-fw fa-code-fork text-secondary"></i> [[topic:thread-tools.merge]]
</a>
</li>
<li>
<a component="topic/tag" href="#" class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem">
<i class="fa fa-fw fa-tag text-secondary"></i> [[topic:thread-tools.tag]]
</a>
</li>
<li class="dropdown-divider"></li>
<li>
<a component="topic/delete" href="#" class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem">
<i class="fa fa-fw fa-trash-o text-secondary"></i> [[topic:thread-tools.delete]]
</a>
</li>
<li>
<a component="topic/restore" href="#" class="hidden dropdown-item rounded-1" role="menuitem">
<i class="fa fa-fw fa-history text-secondary"></i> [[topic:thread-tools.restore]]
</a>
</li>
<li>
<a component="topic/purge" href="#" class="hidden dropdown-item rounded-1" role="menuitem">
<i class="fa fa-fw fa-eraser text-secondary"></i> [[topic:thread-tools.purge]]
</a>
</li>
{{{each thread_tools}}}
<li>
<a href="#" class="dropdown-item rounded-1 d-flex align-items-center gap-2 {thread_tools.class}" role="menuitem">
<i class="fa fa-fw {thread_tools.icon} text-secondary"></i>
{thread_tools.title}</a>
</li>
{{{end}}}
</ul>

View File

@@ -0,0 +1,5 @@
{{{ if showTopicTools }}}
<div class="btn-group thread-tools dropdown-left bottom-sheet">
<!-- IMPORT partials/category/tools-dropdown-content.tpl -->
</div>
{{{ end }}}

View File

@@ -0,0 +1,5 @@
{{{ if showTopicTools }}}
<div class="btn-group thread-tools dropdown-right bottom-sheet">
<!-- IMPORT partials/category/tools-dropdown-content.tpl -->
</div>
{{{ end }}}

View File

@@ -0,0 +1,67 @@
{{{ if config.loggedIn }}}
<div class="btn-group bottom-sheet" component="topic/watch">
<button class="btn btn-ghost btn-sm ff-secondary dropdown-toggle" data-bs-toggle="dropdown" type="button" aria-haspopup="true" aria-expanded="false">
<span component="category/watching/menu" class="d-flex gap-2 align-items-center {{{ if !./isWatched }}} hidden{{{ end }}}"><i class="fa fa-fw fa-bell-o text-primary"></i><span class="visible-md-inline visible-lg-inline fw-semibold">[[category:watching]]</span></span>
<span component="category/tracking/menu" class="d-flex gap-2 align-items-center {{{ if !./isTracked }}} hidden{{{ end }}}"><i class="fa fa-fw fa-inbox text-primary"></i><span class="visible-md-inline visible-lg-inline fw-semibold">[[category:tracking]]</span></span>
<span component="category/notwatching/menu" class="d-flex gap-2 align-items-center {{{ if !./isNotWatched }}} hidden{{{ end }}}"><i class="fa fa-fw fa-clock-o text-primary"></i><span class="visible-md-inline visible-lg-inline fw-semibold">[[category:not-watching]]</span></span>
<span component="category/ignoring/menu" class="d-flex gap-2 align-items-center {{{ if !./isIgnored }}} hidden{{{ end }}}"><i class="fa fa-fw fa-eye-slash text-primary"></i><span class="visible-md-inline visible-lg-inline fw-semibold">[[category:ignoring]]</span></span>
</button>
<ul class="dropdown-menu p-1 text-sm {{{ if template.account/categories }}}dropdown-menu-end{{{ end }}}" role="menu">
<li>
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2 p-2" href="#" component="category/watching" data-state="watching" role="menuitem">
<div class="flex-grow-1 d-flex flex-column">
<span class="d-flex align-items-center gap-2">
<i class="flex-shrink-0 fa fa-fw fa-bell-o text-secondary"></i>
<span class="flex-grow-1 fw-semibold">[[category:watching]]</span>
</span>
<div class="help-text text-secondary text-xs">[[category:watching.description]]</div>
</div>
<span class="flex-shrink-0"><i component="category/watching/check" class="fa fa-fw {{{ if ./isWatched }}}fa-check{{{ end }}}"></i></span>
</a>
</li>
<li>
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2 p-2" href="#" component="category/tracking" data-state="tracking" role="menuitem">
<div class="flex-grow-1 d-flex flex-column">
<span class="d-flex align-items-center gap-2">
<i class="flex-shrink-0 fa fa-fw fa-inbox text-secondary"></i>
<span class="flex-grow-1 fw-semibold">[[category:tracking]]</span>
</span>
<div class="help-text text-secondary text-xs">[[category:tracking.description]]</div>
</div>
<span class="flex-shrink-0"><i component="category/tracking/check" class="fa fa-fw {{{ if ./isTracked }}}fa-check{{{ end }}}"></i></span>
</a>
</li>
<li>
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2 p-2" href="#" component="category/notwatching" data-state="notwatching" role="menuitem">
<div class="flex-grow-1 d-flex flex-column">
<span class="d-flex align-items-center gap-2">
<i class="flex-shrink-0 fa fa-fw fa-clock-o text-secondary"></i>
<span class="flex-grow-1 fw-semibold">[[category:not-watching]]</span>
</span>
<div class="help-text text-secondary text-xs">[[category:not-watching.description]]</div>
</div>
<span class="flex-shrink-0"><i component="category/notwatching/check" class="fa fa-fw {{{ if ./isNotWatched }}}fa-check{{{ end }}}"></i></span>
</a>
</li>
<li>
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2 p-2" href="#" component="category/ignoring" data-state="ignoring" role="menuitem">
<div class="flex-grow-1 d-flex flex-column">
<span class="d-flex align-items-center gap-2">
<i class="flex-shrink-0 fa fa-fw fa-eye-slash text-secondary"></i>
<span class="flex-grow-1 fw-semibold">[[category:ignoring]]</span>
</span>
<div class="help-text text-secondary text-xs">[[category:ignoring.description]]</div>
</div>
<span class="flex-shrink-0"><i component="category/ignoring/check" class="fa fa-fw {{{ if ./isIgnored }}}fa-check{{{ end }}}"></i></span>
</a>
</li>
</ul>
</div>
{{{ end }}}

View File

@@ -1,17 +1,17 @@
<div component="chat/composer" class="d-flex flex-column border-top pt-2 align-items-start">
<div component="chat/composer/replying-to" data-tomid="" class="text-sm px-2 mb-1 d-flex gap-2 align-items-center hidden">
<div component="chat/composer/replying-to-text"></div> <button component="chat/composer/replying-to-cancel" class="btn-ghost-sm px-2 py-1"><i class="fa fa-times"></i></button>
<div component="chat/composer/replying-to-text"></div> <button component="chat/composer/replying-to-cancel" class="btn btn-ghost btn-sm px-2 py-1"><i class="fa fa-times"></i></button>
</div>
<div class="w-100 flex-grow-1 flex-nowrap position-relative d-flex rounded-2 border border-secondary p-1 align-items-end">
<button component="chat/upload/button" class="btn-ghost-sm px-2" type="button" title="[[global:upload]]" data-bs-toggle="tooltip"><i class="fa fa-fw fa-upload"></i></button>
<button component="chat/upload/button" class="btn btn-ghost btn-sm d-flex p-2" type="button" title="[[global:upload]]" data-bs-toggle="tooltip"><i class="fa fa-fw fa-upload"></i></button>
<div class="flex-grow-1 align-self-center">
<textarea component="chat/input" placeholder="{{{ if roomName }}}[[modules:chat.placeholder.message-room, {roomName}]]{{{ else }}}[[modules:chat.placeholder.mobile]]{{{ end }}}" class="bg-transparent text-body form-control chat-input mousetrap rounded-0 border-0 shadow-none px-1 py-0" style="min-height: 1.5rem;height:0;max-height:30vh;resize:none;"></textarea>
</div>
<div class="d-flex gap-1">
{{{ each composerActions }}}
<button data-action="{./action}" class="btn-ghost-sm px-2 {./class}" type="button" title="{./title}" data-bs-toggle="tooltip"><i class="fa {./icon}"></i></button>
<button data-action="{./action}" class="btn btn-ghost btn-sm d-flex p-2 {./class}" type="button" title="{./title}" data-bs-toggle="tooltip"><i class="fa {./icon}"></i></button>
{{{ end }}}
<button class="btn-ghost-sm px-2" type="button" data-action="send" title="[[modules:chat.send]]" data-bs-toggle="tooltip"><i class="fa fa-fw fa-paper-plane text-primary"></i></button>
<button class="btn btn-ghost btn-sm d-flex p-2" type="button" data-action="send" title="[[modules:chat.send]]" data-bs-toggle="tooltip"><i class="fa fa-fw fa-paper-plane text-primary"></i></button>
</div>
</div>
<div class="d-flex justify-content-between align-items-center text-xs w-100 px-2 mt-1">

View File

@@ -1,6 +1,6 @@
<div class="d-flex gap-1 align-items-stretch">
<!-- search -->
<button class="btn-ghost-sm" component="chat/room/search/toggle" data-manual-tooltip="1" title="[[global:header.search]]">
<button class="btn btn-ghost btn-sm" component="chat/room/search/toggle" data-manual-tooltip="1" title="[[global:header.search]]">
<i class="fa fa-search text-muted"></i>
</button>
<div component="chat/room/search/container" class="position-relative hidden align-self-center">
@@ -13,7 +13,7 @@
<!-- notification dropdown -->
<div class="dropdown d-flex" data-manual-tooltip="1" title="[[modules:chat.notification-settings]]" component="chat/notification/setting">
<button class="btn-ghost-sm position-relative" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<button class="btn btn-ghost btn-sm position-relative" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fa fa-bell text-muted"></i>
<span class="position-absolute top-0 end-0 text-xs text-muted opacity-50" style="font-size: 10px!important; padding: 1px; line-height: 10px;">
<i component="chat/notification/setting/icon" class="fa {notificationOptionsIcon}"></i>
@@ -43,13 +43,13 @@
</div>
<!-- pinned messages -->
<button component="chat/pinned/messages/btn" class="btn-ghost-sm d-none d-lg-flex flex-nowrap" title="[[modules:chat.pinned-messages]]" data-bs-toggle="tooltip" data-bs-placement="bottom">
<button component="chat/pinned/messages/btn" class="btn btn-ghost btn-sm d-none d-lg-block flex-nowrap" title="[[modules:chat.pinned-messages]]" data-bs-toggle="tooltip" data-bs-placement="bottom">
<i class="fa fa-thumb-tack text-muted"></i>
</button>
<!-- manage/options dropdown -->
<div class="dropdown d-flex" data-manual-tooltip="1" title="[[modules:chat.options]]">
<button component="chat/controlsToggle" class="btn-ghost-sm" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<button component="chat/controlsToggle" class="btn btn-ghost btn-sm" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fa fa-gear text-muted"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end p-1 text-sm" component="chat/controls" role="menu">
@@ -82,7 +82,7 @@
<!-- users toggle -->
{{{ if users.length }}}
<div component="chat/user/list/btn" class="btn-ghost-sm d-none d-lg-flex flex-nowrap gap-3" title="[[modules:chat.view-users-list]]" data-bs-toggle="tooltip" data-bs-placement="bottom">
<div component="chat/user/list/btn" class="btn btn-ghost btn-sm d-none d-lg-flex flex-nowrap gap-3" title="[[modules:chat.view-users-list]]" data-bs-toggle="tooltip" data-bs-placement="bottom">
<div class="d-flex text-nowrap">
{{{ if ./users.0 }}}
<span style="width: 18px; z-index: 3;" class="text-decoration-none" href="{config.relative_path}/user/{./users.0.userslug}">{buildAvatar(./users.0, "24px", true)}</span>

View File

@@ -1,5 +1,5 @@
<div class="d-flex ms-4 mb-2 align-items-center">
<div component="chat/message/parent" data-parent-mid="{messages.parent.mid}" data-uid="{messages.parent.fromuid}" class="btn-ghost-sm ff-secondary align-items-start flex-row w-100">
<div component="chat/message/parent" data-parent-mid="{messages.parent.mid}" data-uid="{messages.parent.fromuid}" class="btn btn-ghost btn-sm d-flex gap-2 ff-secondary text-start flex-row w-100">
<div class="d-flex gap-2 text-sm text-nowrap">
<div><i class="fa fa-sm fa-reply opacity-50"></i></div>
<div class="d-flex flex-nowrap gap-1 align-items-center">

View File

@@ -3,7 +3,7 @@
{{{ end }}}
<div component="chat/recent/room" data-roomid="{./roomId}" data-full="1" class="rounded-1 {{{ if ./unread }}}unread{{{ end }}}">
<div class="d-flex gap-1 justify-content-between">
<div class="chat-room-btn position-relative d-flex flex-grow-1 gap-2 justify-content-start align-items-start btn-ghost-sm ff-sans">
<div class="chat-room-btn position-relative d-flex flex-grow-1 gap-2 justify-content-start align-items-start btn btn-ghost btn-sm ff-sans text-start">
<div class="main-avatar">
{{{ if ./users.length }}}
{{{ if ./groupChat}}}
@@ -35,7 +35,7 @@
</div>
</div>
<div>
<button class="mark-read btn-ghost-sm" style="width: 1.5rem; height: 1.5rem;">
<button class="mark-read btn btn-ghost btn-sm d-flex align-items-center justify-content-center flex-grow-0 flex-shrink-0 p-1" style="width: 1.5rem; height: 1.5rem;">
<i class="unread fa fa-2xs fa-circle text-primary {{{ if !./unread }}}hidden{{{ end }}}" aria-label="[[unread:mark-as-read]]"></i>
<i class="read fa fa-2xs fa-circle-o text-secondary {{{ if ./unread }}}hidden{{{ end }}}" aria-label="[[unread:mark-as-unread]]"></i>
</button>

View File

@@ -1,6 +1,6 @@
<div component="chat/user/list" class="border-start hidden d-flex flex-column gap-1 p-1 overflow-auto ghost-scrollbar" style="min-width:240px; width: 240px;">
{{{ each users }}}
<a data-index="{./index}" data-uid="{./uid}" class="btn-ghost-sm ff-secondary d-flex justify-content-start align-items-center gap-2 {{{ if ./online }}}online{{{ end}}}" href="{config.relative_path}/uid/{./uid}">
<a data-index="{./index}" data-uid="{./uid}" class="btn btn-ghost btn-sm d-flex ff-secondary d-flex justify-content-start align-items-center gap-2 {{{ if ./online }}}online{{{ end}}}" href="{config.relative_path}/uid/{./uid}">
<div>{buildAvatar(users, "24px", true)}</div>
<div class="d-flex gap-1 flex-grow-1 text-nowrap text-truncate">
<span component="chat/user/list/username" class="text-truncate">{./username}</span>

View File

@@ -0,0 +1,25 @@
<div class="dropdown bottom-sheet">
<button type="button" class="btn btn-ghost btn-sm ff-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{{ if selectedGroup }}}
<span class="fw-semibold">{selectedGroup.displayName}</span>
{{{ else }}}
<span class="fw-semibold">[[groups:all-groups]]</span>
{{{ end }}} <span class="caret text-primary opacity-75"></span>
</button>
<ul class="dropdown-menu p-1 text-sm" role="menu">
<li role="presentation" class="user {{{ if !selectedGroup}}}selected{{{end}}}">
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem" href="{config.relative_path}/{allGroupsUrl}">
<div class="flex-grow-1">[[groups:all-groups]]</div>
<i class="flex-shrink-0 fa fa-fw {{{ if !selectedGroup }}}fa-check{{{ end }}}"></i>
</a>
</li>
{{{ each groups }}}
<li role="presentation" class="user {{{ if ./selected}}}selected{{{end}}}">
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem" href="{config.relative_path}/{./url}">
<div class="flex-grow-1 d-inline-flex gap-1 align-items-center">{./displayName}</div>
<i class="flex-shrink-0 fa fa-fw {{{ if ./selected }}}fa-check{{{ end }}}"></i>
</a>
</li>
{{{end}}}
</ul>
</div>

View File

@@ -0,0 +1,38 @@
<button type="button" class="btn btn-ghost btn-sm d-flex align-items-center ff-secondary d-flex gap-2 dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{{ if selectedTag }}}
<span class="d-inline-flex align-items-center gap-1">
<i class="fa fa-fw fa-tags text-primary"></i>
<span class="visible-md-inline visible-lg-inline fw-semibold">{selectedTag.label}</span>
</span>
{{{ else }}}
<i class="fa fa-fw fa-tags text-primary"></i>
<span class="visible-md-inline visible-lg-inline fw-semibold">[[tags:all-tags]]</span>
{{{ end }}}
</button>
<div component="tag/filter/search" class="hidden position-absolute top-0">
<input type="text" class="form-control form-control-sm" placeholder="[[search:type-to-search]]" autocomplete="off">
</div>
<div class="dropdown-menu p-1">
<ul component="tag/filter/list" class="list-unstyled mb-0 text-sm overflow-auto ghost-scrollbar" role="menu" style="max-height: 500px;" role="menu">
<li role="presentation" data-tag="">
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem" href="#">
<span class="flex-grow-1">[[tags:all-tags]]</span>
<i component="tag/select/icon" class="flex-shrink-0 fa fa-fw fa-check {{{if selectedTag }}}invisible{{{ end }}}"></i>
</a>
</li>
{{{ each tagItems }}}
<li role="presentation" data-tag="{./valueEscaped}">
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem" href="#">
<span component="tag-markup" class="flex-grow-1">
<div class="d-inline-flex align-items-center gap-1">
{./valueEscaped}
</div>
</span>
<i component="tag/select/icon" class="flex-shrink-0 fa fa-fw fa-check {{{ if !./selected }}}invisible{{{ end }}}"></i>
</a>
</li>
{{{ end }}}
</ul>
</div>

View File

@@ -1,3 +1,3 @@
<div component="tag/filter" class="dropdown dropdown-right bottom-sheet">
<div component="tag/filter" class="btn-group dropdown dropdown-right bottom-sheet">
<!-- IMPORT partials/tags/filter-dropdown-content.tpl -->
</div>

View File

@@ -0,0 +1,42 @@
{{{ if config.loggedIn }}}
<div class="btn-group bottom-sheet" component="tag/watch">
<button class="btn btn-ghost btn-sm ff-secondary d-flex gap-2 align-items-center dropdown-toggle" data-bs-toggle="dropdown" type="button" aria-haspopup="true" aria-expanded="false">
<span component="tag/following/menu" class="d-flex gap-2 align-items-center{{{ if !isFollowing }}} hidden{{{ end }}}">
<i class="flex-shrink-0 fa fa-fw fa-bell-o text-primary"></i>
<span class="d-none d-md-inline fw-semibold">[[tags:watching]]</span>
</span>
<span component="tag/not-following/menu" class="d-flex gap-2 align-items-center{{{ if isFollowing}}} hidden{{{ end }}}">
<i class="flex-shrink-0 fa fa-fw fa-bell-slash-o text-primary"></i>
<span class="d-none d-md-inline fw-semibold">[[tags:not-watching]]</span>
</span>
</button>
<ul class="dropdown-menu p-1 text-sm" role="menu">
<li>
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2 p-2" href="#" component="tag/following" role="menuitem">
<div class="flex-grow-1 d-flex flex-column">
<span class="d-flex align-items-center gap-2">
<i class="flex-shrink-0 fa fa-fw fa-bell-o"></i>
<span class="flex-grow-1 fw-semibold">[[tags:watching]]</span>
</span>
<div class="help-text text-muted text-xs">[[tags:watching.description]]</div>
</div>
<span class="flex-shrink-0"><i component="tag/following/check" class="fa fa-fw {{{ if isFollowing }}}fa-check{{{ end }}}"></i></span>
</a>
</li>
<li>
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2 p-2" href="#" component="tag/not-following" role="menuitem">
<div class="flex-grow-1 d-flex flex-column">
<span class="d-flex align-items-center gap-2">
<i class="flex-shrink-0 fa fa-fw fa-bell-slash-o"></i>
<span class="flex-grow-1 fw-semibold">[[tags:not-watching]]</span>
</span>
<div class="help-text text-muted text-xs">[[tags:not-watching.description]]</div>
</div>
<span class="flex-shrink-0"><i component="tag/not-following/check" class="fa fa-fw {{{ if !isFollowing }}}fa-check{{{ end }}}"></i></span>
</a>
</li>
</ul>
</div>
{{{ end }}}

View File

View File

@@ -0,0 +1,23 @@
<button type="button" class="btn btn-ghost btn-sm d-flex align-items-center gap-2 ff-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{{ if selectedUser }}}
<span class="fw-semibold">{buildAvatar(selectedUser, "20px", true, "not-responsive")} {selectedUser.username}</span>
{{{ else }}}
<span class="fw-semibold">[[users:all-users]]</span>
{{{ end }}} <span class="caret text-primary opacity-75"></span>
</button>
<ul class="dropdown-menu p-1 text-sm" role="menu">
<li role="presentation" class="user {{{ if !selectedUser}}}selected{{{end}}}">
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem" href="{config.relative_path}/{allUsersUrl}">
<div class="flex-grow-1">[[users:all-users]]</div>
<i class="flex-shrink-0 fa fa-fw {{{ if !selectedUser }}}fa-check{{{ end }}}"></i>
</a>
</li>
{{{ each users }}}
<li role="presentation" class="user {{{ if ./selected}}}selected{{{end}}}">
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" role="menuitem" href="{config.relative_path}/{./url}">
<div class="flex-grow-1 d-inline-flex gap-1 align-items-center">{buildAvatar(@value, "24px", true, "not-responsive")} {./username}</div>
<i class="flex-shrink-0 fa fa-fw {{{ if ./selected }}}fa-check{{{ end }}}"></i>
</a>
</li>
{{{end}}}
</ul>

104
src/views/register.tpl Normal file
View File

@@ -0,0 +1,104 @@
<div data-widget-area="header">
{{{each widgets.header}}}
{{widgets.header.html}}
{{{end}}}
</div>
<div class="row register flex-fill">
<div class="d-flex flex-column gap-2 {{{ if widgets.sidebar.length }}}col-lg-9 col-sm-12{{{ else }}}col-lg-12{{{ end }}}">
<h2 class="tracking-tight fw-semibold text-center">[[global:register]]</h2>
<div class="row justify-content-center gap-5">
<div class="col-12 col-md-5 col-lg-3 px-md-0">
<div class="register-block">
<form component="register/local" class="d-flex flex-column gap-3" role="form" action="{config.relative_path}/register" method="post">
<div class="mb-2 d-flex flex-column gap-2">
<label for="username">[[register:username]]</label>
<div class="d-flex flex-column">
<input class="form-control" type="text" placeholder="[[register:username-placeholder]]" name="username" id="username" autocorrect="off" autocapitalize="off" autocomplete="nickname" aria-required="true" aria-describedby="username-notify"/>
<span class="register-feedback text-xs text-danger" id="username-notify" aria-live="polite"></span>
<span class="form-text text-xs">[[register:help.username-restrictions, {minimumUsernameLength}, {maximumUsernameLength}]]</span>
</div>
</div>
<div class="mb-2 d-flex flex-column gap-2">
<label for="password">[[register:password]]</label>
<div class="d-flex flex-column">
<input class="form-control" type="password" placeholder="[[register:password-placeholder]]" name="password" id="password" autocomplete="new-password" autocapitalize="off" aria-required="true" aria-describedby="password-notify"/>
<span class="register-feedback text-xs text-danger" id="password-notify" aria-live="polite"></span>
<span class="form-text text-xs">[[register:help.minimum-password-length, {minimumPasswordLength}]]</span>
<p id="caps-lock-warning" class="text-danger hidden">
<i class="fa fa-exclamation-triangle"></i> [[login:caps-lock-enabled]]
</p>
</div>
</div>
<div class="mb-2 d-flex flex-column gap-2">
<label for="password-confirm">[[register:confirm-password]]</label>
<div>
<input class="form-control" type="password" placeholder="[[register:confirm-password-placeholder]]" name="password-confirm" id="password-confirm" autocomplete="new-password" autocapitalize="off" aria-required="true" aria-describedby="password-confirm-notify"/>
<span class="register-feedback text-xs text-danger" id="password-confirm-notify" aria-live="polite"></span>
</div>
</div>
{{{ each regFormEntry }}}
<div class="mb-2 regFormEntry d-flex flex-column gap-2 {./styleName}">
<label for="{./inputId}">{./label}</label>
<div>{{./html}}</div>
</div>
{{{ end }}}
<button class="btn btn-primary" id="register" type="submit">[[register:register-now-button]]</button>
<div class="alert alert-danger{{{ if !error }}} hidden{{{ end }}}" id="register-error-notify" role="alert" aria-atomic="true">
<strong>[[error:registration-error]]</strong>
<p class="mb-0">{error}</p>
</div>
<hr/>
<span class="text-sm">[[register:already-have-account]]</span>
<a class="btn btn-outline-light text-body" href="{config.relative_path}/login">[[global:login]]</a>
<input id="token" type="hidden" name="token" value="" />
<input id="noscript" type="hidden" name="noscript" value="true" />
<input type="hidden" name="_csrf" value="{config.csrf_token}" />
</form>
</div>
</div>
{{{ if alternate_logins }}}
<div class="col-12 col-md-5 col-lg-3 px-md-0">
<div class="alt-register-block d-flex flex-column gap-2">
<label>[[register:alternative-registration]]</label>
<ul class="alt-logins list-unstyled">
{{{ each authentication }}}
<li class="{./name} mb-2">
<a class="btn btn-outline-light d-flex align-items-center" rel="nofollow noopener noreferrer" target="_top" href="{config.relative_path}{./url}">
{{{ if ./icons.svg }}}
{./icons.svg}
{{{ else }}}
<i class="flex-shrink-0 {./icons.normal}" style="color:{./color};"></i>
{{{ end }}}
{{{ if ./labels.register }}}
<div class="flex-grow-1 text-body text-sm">{./labels.register}</div>
{{{ end }}}
</a>
</li>
{{{ end }}}
</ul>
</div>
</div>
{{{ end }}}
</div>
</div>
<div data-widget-area="sidebar" class="col-lg-3 col-sm-12 {{{ if !widgets.sidebar.length }}}hidden{{{ end }}}">
{{{each widgets.sidebar}}}
{{widgets.sidebar.html}}
{{{end}}}
</div>
</div>
<div data-widget-area="footer">
{{{each widgets.footer}}}
{{widgets.footer.html}}
{{{end}}}
</div>