esifawafwu
This commit is contained in:
+211
-123
@@ -1,136 +1,230 @@
|
||||
@include(snippets/header)
|
||||
<div class="pagewrapper">
|
||||
<div id="main">
|
||||
<div class="container">
|
||||
<h1>ADMINBEREICH</h1>
|
||||
<h5>Hallo, {{ session.user }}</h5>
|
||||
<span>Hier entsteht eine Internetpräsenz!</span><br>
|
||||
<hr>
|
||||
<p>f0ck stats: @if(typeof totals !== "undefined")total: {{ totals.total }} | tagged: {{ totals.tagged }} | untagged: {{ totals.untagged }} | sfw: {{ totals.sfw }} | nsfw: {{ totals.nsfw }}@endif</p>
|
||||
<hr>
|
||||
<div class="admintools">
|
||||
<p>Adminwerkzeuge</p>
|
||||
<ul>
|
||||
<li><a href="/mod/audit">Audit Log</a></li>
|
||||
<li><a href="/admin/approve">Approval Queue</a></li>
|
||||
<li><a href="/admin/sessions">Sessions</a></li>
|
||||
<li><a href="/admin/tokens">Invite Tokens</a></li>
|
||||
<li><a href="/admin/users">User Manager</a></li>
|
||||
<li><a href="/admin/bans">Ban & Fingerprint Manager</a></li>
|
||||
<li><a href="/admin/emojis">Emoji Manager</a></li>
|
||||
<li><a href="/admin/memes">Meme Manager</a></li>
|
||||
<li><a href="/admin/koepfe">Köpfe Manager</a></li>
|
||||
<li><a href="/admin/halls">Hall Manager</a></li>
|
||||
<li><a href="/admin/motd">MOTD Manager</a></li>
|
||||
<li><a href="/admin/wordfilter">Wordfilter Manager</a></li>
|
||||
<li><a href="/admin/nsfp">NSFP Tag Manager</a></li>
|
||||
<div class="container adm">
|
||||
|
||||
<!-- Header -->
|
||||
<header class="adm-header">
|
||||
<div>
|
||||
<h1 class="adm-title">Admin</h1>
|
||||
<div class="adm-subtitle">Signed in as <strong>{{ session.user }}</strong></div>
|
||||
</div>
|
||||
<a href="/mod" class="adm-btn adm-btn-ghost"><i class="fa-solid fa-gavel"></i> Moderator panel</a>
|
||||
</header>
|
||||
|
||||
<!-- Overview -->
|
||||
<section class="adm-section">
|
||||
<h2 class="adm-section-title"><i class="fa-solid fa-chart-simple"></i> Overview</h2>
|
||||
@if(typeof totals !== "undefined")
|
||||
<div class="adm-stats">
|
||||
<div class="adm-stat"><span class="adm-stat-num">{{ totals.total }}</span><span class="adm-stat-label">Posts</span></div>
|
||||
<div class="adm-stat"><span class="adm-stat-num">{{ totals.sfw }}</span><span class="adm-stat-label">SFW</span></div>
|
||||
<div class="adm-stat"><span class="adm-stat-num">{{ totals.nsfw }}</span><span class="adm-stat-label">NSFW</span></div>
|
||||
@if(enable_nsfl)
|
||||
<div class="adm-stat"><span class="adm-stat-num">{{ totals.nsfl }}</span><span class="adm-stat-label">NSFL</span></div>
|
||||
@endif
|
||||
<div class="adm-stat"><span class="adm-stat-num">{{ totals.untagged }}</span><span class="adm-stat-label">Untagged</span></div>
|
||||
<a href="/admin/approve" class="adm-stat adm-stat-link @if(totals.pending > 0) is-hot @endif"><span class="adm-stat-num">{{ totals.pending }}</span><span class="adm-stat-label">Pending approval</span></a>
|
||||
<a href="/mod/trash" class="adm-stat adm-stat-link"><span class="adm-stat-num">{{ dash.trash }}</span><span class="adm-stat-label">Soft deleted</span></a>
|
||||
<a href="/mod/reports" class="adm-stat adm-stat-link @if(dash.open_reports > 0) is-hot @endif"><span class="adm-stat-num">{{ dash.open_reports }}</span><span class="adm-stat-label">Open reports</span></a>
|
||||
<a href="/admin/users" class="adm-stat adm-stat-link"><span class="adm-stat-num">{{ dash.users }}</span><span class="adm-stat-label">Users <small>+{{ dash.anon_users }} anon</small></span></a>
|
||||
</div>
|
||||
@endif
|
||||
</section>
|
||||
|
||||
<!-- Tools -->
|
||||
<section class="adm-section">
|
||||
<h2 class="adm-section-title"><i class="fa-solid fa-screwdriver-wrench"></i> Tools</h2>
|
||||
|
||||
<h3 class="adm-group-title">Moderation</h3>
|
||||
<div class="adm-tools">
|
||||
<a href="/admin/approve" class="adm-tool">
|
||||
<i class="fa-solid fa-clock"></i>
|
||||
<span class="adm-tool-text"><strong>Approval Queue @if(totals.pending > 0)<span class="adm-count">{{ totals.pending }}</span>@endif</strong><span>Review uploads waiting for approval</span></span>
|
||||
</a>
|
||||
<a href="/mod/trash" class="adm-tool">
|
||||
<i class="fa-solid fa-trash-can"></i>
|
||||
<span class="adm-tool-text"><strong>Soft Deleted @if(dash.trash > 0)<span class="adm-count">{{ dash.trash }}</span>@endif</strong><span>Restore or permanently purge removed items</span></span>
|
||||
</a>
|
||||
<a href="/mod/reports" class="adm-tool">
|
||||
<i class="fa-solid fa-flag"></i>
|
||||
<span class="adm-tool-text"><strong>User Reports @if(dash.open_reports > 0)<span class="adm-count">{{ dash.open_reports }}</span>@endif</strong><span>Reported posts, comments and users</span></span>
|
||||
</a>
|
||||
<a href="/mod/audit" class="adm-tool">
|
||||
<i class="fa-solid fa-scroll"></i>
|
||||
<span class="adm-tool-text"><strong>Audit Log</strong><span>Every moderation and admin action</span></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h3 class="adm-group-title">Users & access</h3>
|
||||
<div class="adm-tools">
|
||||
<a href="/admin/users" class="adm-tool">
|
||||
<i class="fa-solid fa-users"></i>
|
||||
<span class="adm-tool-text"><strong>User Manager</strong><span>Accounts, roles and groups</span></span>
|
||||
</a>
|
||||
<a href="/admin/bans" class="adm-tool">
|
||||
<i class="fa-solid fa-ban"></i>
|
||||
<span class="adm-tool-text"><strong>Bans & Fingerprints</strong><span>IP, hardware and passkey bans</span></span>
|
||||
</a>
|
||||
<a href="/admin/sessions" class="adm-tool">
|
||||
<i class="fa-solid fa-key"></i>
|
||||
<span class="adm-tool-text"><strong>Sessions</strong><span>Active logins across all users</span></span>
|
||||
</a>
|
||||
<a href="/admin/tokens" class="adm-tool">
|
||||
<i class="fa-solid fa-ticket"></i>
|
||||
<span class="adm-tool-text"><strong>Invite Tokens</strong><span>Create and revoke invites</span></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h3 class="adm-group-title">Content</h3>
|
||||
<div class="adm-tools">
|
||||
<a href="/admin/halls" class="adm-tool">
|
||||
<i class="fa-solid fa-layer-group"></i>
|
||||
<span class="adm-tool-text"><strong>Halls</strong><span>Curated collections</span></span>
|
||||
</a>
|
||||
<a href="/admin/emojis" class="adm-tool">
|
||||
<i class="fa-solid fa-face-smile"></i>
|
||||
<span class="adm-tool-text"><strong>Emojis</strong><span>Custom emojis and sticker packs</span></span>
|
||||
</a>
|
||||
<a href="/admin/memes" class="adm-tool">
|
||||
<i class="fa-regular fa-image"></i>
|
||||
<span class="adm-tool-text"><strong>Memes</strong><span>Meme creator templates</span></span>
|
||||
</a>
|
||||
<a href="/admin/koepfe" class="adm-tool">
|
||||
<i class="fa-solid fa-masks-theater"></i>
|
||||
<span class="adm-tool-text"><strong>Köpfe</strong><span>Floating head images</span></span>
|
||||
</a>
|
||||
<a href="/admin/nsfp" class="adm-tool">
|
||||
<i class="fa-solid fa-eye-slash"></i>
|
||||
<span class="adm-tool-text"><strong>NSFP Tags</strong><span>Tags hidden from the public</span></span>
|
||||
</a>
|
||||
<a href="/admin/wordfilter" class="adm-tool">
|
||||
<i class="fa-solid fa-filter"></i>
|
||||
<span class="adm-tool-text"><strong>Wordfilter</strong><span>Replace words in comments</span></span>
|
||||
</a>
|
||||
@if(enable_cleanup)
|
||||
<li><a href="/admin/cleanup">Cleanup Manager</a></li>
|
||||
<a href="/admin/cleanup" class="adm-tool">
|
||||
<i class="fa-solid fa-broom"></i>
|
||||
<span class="adm-tool-text"><strong>Cleanup</strong><span>Remove old unengaged uploads</span></span>
|
||||
</a>
|
||||
@endif
|
||||
<li><a href="/admin/about">About Page</a></li>
|
||||
<li><a href="/admin/rules">Rules Page</a></li>
|
||||
<li><a href="/admin/terms">ToS Page</a></li>
|
||||
</div>
|
||||
|
||||
<h3 class="adm-group-title">Site</h3>
|
||||
<div class="adm-tools">
|
||||
<a href="/admin/motd" class="adm-tool">
|
||||
<i class="fa-solid fa-bullhorn"></i>
|
||||
<span class="adm-tool-text"><strong>MOTD</strong><span>Message of the day banner</span></span>
|
||||
</a>
|
||||
<a href="/admin/about" class="adm-tool">
|
||||
<i class="fa-solid fa-circle-info"></i>
|
||||
<span class="adm-tool-text"><strong>About Page</strong><span>Edit /about</span></span>
|
||||
</a>
|
||||
<a href="/admin/rules" class="adm-tool">
|
||||
<i class="fa-solid fa-list-check"></i>
|
||||
<span class="adm-tool-text"><strong>Rules Page</strong><span>Edit /rules</span></span>
|
||||
</a>
|
||||
<a href="/admin/terms" class="adm-tool">
|
||||
<i class="fa-solid fa-file-contract"></i>
|
||||
<span class="adm-tool-text"><strong>ToS Page</strong><span>Edit /terms</span></span>
|
||||
</a>
|
||||
@if(enable_global_chat)
|
||||
<li><a href="/admin/chat">Global Chat Manager</a></li>
|
||||
<a href="/admin/chat" class="adm-tool">
|
||||
<i class="fa-solid fa-comments"></i>
|
||||
<span class="adm-tool-text"><strong>Global Chat</strong><span>Moderate the site chat</span></span>
|
||||
</a>
|
||||
@endif
|
||||
</ul>
|
||||
<hr style="margin: 20px 0; border: 0; border-top: 1px solid rgba(255,255,255,0.1);">
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Navbar Brand Image -->
|
||||
<div class="settings-item" id="brand-image-section" style="background: rgba(0,0,0,0.2); padding: 15px; border-radius: 4px; margin-top: 10px;">
|
||||
<label style="display: block; font-weight: bold; color: var(--accent); margin-bottom: 8px;">Navbar Brand Image</label>
|
||||
<p style="margin: 0 0 12px 0; font-size: 0.8em; color: #aaa;">Upload a logo to display in the site navbar instead of plain text. Accepted: gif, jpg, png, webp, svg — max 5 MB.</p>
|
||||
|
||||
<div style="display: flex; align-items: center; gap: 16px; flex-wrap: wrap;">
|
||||
<!-- Preview -->
|
||||
<div id="brand-preview-wrap" style="width: 160px; height: 54px; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.12); border-radius: 4px; display: flex; align-items: center; justify-content: center; overflow: hidden; flex-shrink: 0;">
|
||||
@if(current_brand_image)
|
||||
<img id="brand-preview" src="{{ current_brand_image }}" alt="current brand" style="max-height: 48px; max-width: 150px; object-fit: contain;">
|
||||
@else
|
||||
<span id="brand-preview" style="font-size: 0.75em; color: #666; font-style: italic;">No image set</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Controls -->
|
||||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||||
<label for="brand-file-input" style="display: inline-block; background: var(--accent); color: #000; padding: 7px 16px; border-radius: 4px; cursor: pointer; font-size: 0.82em; font-weight: bold; transition: opacity 0.2s;"
|
||||
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">Choose Image</label>
|
||||
<input type="file" id="brand-file-input" accept="image/gif,image/jpeg,image/png,image/webp,image/svg+xml" style="display:none;" onchange="uploadBrandImage(this)">
|
||||
<button id="brand-remove-btn" onclick="removeBrandImage()" style="background: rgba(220,53,69,0.15); border: 1px solid rgba(220,53,69,0.4); color: #dc3545; padding: 7px 16px; border-radius: 4px; cursor: pointer; font-size: 0.82em; font-weight: bold; transition: background 0.2s;"
|
||||
onmouseover="this.style.background='rgba(220,53,69,0.3)'" onmouseout="this.style.background='rgba(220,53,69,0.15)'"@if(!current_brand_image) disabled style="background: rgba(220,53,69,0.05); border: 1px solid rgba(220,53,69,0.15); color: #884040; padding: 7px 16px; border-radius: 4px; cursor: not-allowed; font-size: 0.82em; font-weight: bold;"@endif>Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
<span id="brand-status" style="display: block; margin-top: 10px; font-size: 0.8em; font-weight: bold;"></span>
|
||||
<!-- Settings -->
|
||||
<section class="adm-section">
|
||||
<div class="adm-section-head">
|
||||
<h2 class="adm-section-title"><i class="fa-solid fa-sliders"></i> Settings</h2>
|
||||
<span id="settings-status" class="adm-status"></span>
|
||||
</div>
|
||||
|
||||
<hr style="margin: 20px 0; border: 0; border-top: 1px solid rgba(255,255,255,0.1);">
|
||||
|
||||
|
||||
<div class="settings-toggle" style="background: rgba(0,0,0,0.2); padding: 15px; border-radius: 4px; display: flex; align-items: center; justify-content: space-between;">
|
||||
<div>
|
||||
<label style="display: block; font-weight: bold; color: var(--accent);">Manual Upload Approval</label>
|
||||
<p style="margin: 2px 0 0 0; font-size: 0.8em; color: #aaa;">If enabled, mods must approve every upload.</p>
|
||||
<h3 class="adm-group-title">Uploads</h3>
|
||||
<div class="adm-panel">
|
||||
<div class="adm-row">
|
||||
<div class="adm-row-text">
|
||||
<label for="manual_approval_toggle">Manual upload approval</label>
|
||||
<p>If enabled, mods must approve every upload.</p>
|
||||
</div>
|
||||
<label class="adm-switch">
|
||||
<input type="checkbox" id="manual_approval_toggle" {{ manual_approval ? 'checked' : '' }} onchange="saveAdminSettings()">
|
||||
<span class="adm-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="adm-row">
|
||||
<div class="adm-row-text">
|
||||
<label for="min_tags_input">Minimum tags</label>
|
||||
<p>Minimum number of tags required per upload.</p>
|
||||
</div>
|
||||
<input type="number" id="min_tags_input" class="adm-number" value="{{ min_tags }}" min="0" max="20" onchange="saveAdminSettings()">
|
||||
</div>
|
||||
<div class="adm-row">
|
||||
<div class="adm-row-text">
|
||||
<label for="trusted_uploads_input">Trusted upload threshold</label>
|
||||
<p>Users with fewer approved uploads than this still need manual approval, even if the toggle above is off. 0 disables it.</p>
|
||||
</div>
|
||||
<input type="number" id="trusted_uploads_input" class="adm-number" value="{{ trusted_uploads }}" min="0" max="999" onchange="saveAdminSettings()">
|
||||
</div>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="manual_approval_toggle" {{ manual_approval ? 'checked' : '' }} onchange="saveAdminSettings()">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@if(registration_web_toggle_enabled)
|
||||
<div class="settings-toggle" style="background: rgba(0,0,0,0.2); padding: 15px; border-radius: 4px; display: flex; align-items: center; justify-content: space-between; margin-top: 10px;">
|
||||
<div>
|
||||
<label style="display: block; font-weight: bold; color: var(--accent);">Open Registration</label>
|
||||
<p style="margin: 2px 0 0 0; font-size: 0.8em; color: #aaa;">Allow registration without invite tokens. Requires email activation.</p>
|
||||
<h3 class="adm-group-title">Registration</h3>
|
||||
<div class="adm-panel">
|
||||
<div class="adm-row">
|
||||
<div class="adm-row-text">
|
||||
<label for="registration_open_toggle">Open registration</label>
|
||||
<p>Allow registration without invite tokens. Requires email activation.</p>
|
||||
</div>
|
||||
<label class="adm-switch">
|
||||
<input type="checkbox" id="registration_open_toggle" {{ registration_open ? 'checked' : '' }} onchange="saveAdminSettings()">
|
||||
<span class="adm-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="registration_open_toggle" {{ registration_open ? 'checked' : '' }} onchange="saveAdminSettings()">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="settings-item" style="background: rgba(0,0,0,0.2); padding: 15px; border-radius: 4px; display: flex; align-items: center; justify-content: space-between; margin-top: 10px;">
|
||||
<div>
|
||||
<label style="display: block; font-weight: bold; color: var(--accent);">Minimum Tags</label>
|
||||
<p style="margin: 2px 0 0 0; font-size: 0.8em; color: #aaa;">Minimum number of tags required per upload.</p>
|
||||
<h3 class="adm-group-title">Branding</h3>
|
||||
<div class="adm-panel" id="brand-image-section">
|
||||
<div class="adm-row adm-row-wrap">
|
||||
<div class="adm-row-text">
|
||||
<label>Navbar brand image</label>
|
||||
<p>Shown in the navbar instead of the site name. gif, jpg, png, webp or svg, max 5 MB.</p>
|
||||
</div>
|
||||
<div class="adm-brand">
|
||||
<div id="brand-preview-wrap" class="adm-brand-preview">
|
||||
@if(current_brand_image)
|
||||
<img id="brand-preview" src="{{ current_brand_image }}" alt="current brand">
|
||||
@else
|
||||
<span id="brand-preview" class="adm-muted">No image set</span>
|
||||
@endif
|
||||
</div>
|
||||
<label for="brand-file-input" class="adm-btn adm-btn-primary">Choose image</label>
|
||||
<input type="file" id="brand-file-input" accept="image/gif,image/jpeg,image/png,image/webp,image/svg+xml" hidden onchange="uploadBrandImage(this)">
|
||||
<button type="button" id="brand-remove-btn" class="adm-btn adm-btn-danger" onclick="removeBrandImage()" @if(!current_brand_image) disabled @endif>Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
<input type="number" id="min_tags_input" value="{{ min_tags }}" min="0" max="20" style="width: 60px; background: #333; border: 1px solid #444; color: #fff; padding: 5px; border-radius: 4px; text-align: center;" onchange="saveAdminSettings()">
|
||||
<span id="brand-status" class="adm-status adm-status-row"></span>
|
||||
</div>
|
||||
|
||||
<div class="settings-item" style="background: rgba(0,0,0,0.2); padding: 15px; border-radius: 4px; display: flex; align-items: center; justify-content: space-between; margin-top: 10px;">
|
||||
<div>
|
||||
<label style="display: block; font-weight: bold; color: var(--accent);">Trusted Upload Threshold</label>
|
||||
<p style="margin: 2px 0 0 0; font-size: 0.8em; color: #aaa;">New users with fewer than this many approved uploads must still go through manual approval, even if the global toggle is off. Set to 0 to disable.</p>
|
||||
<h3 class="adm-group-title">Maintenance</h3>
|
||||
<div class="adm-panel">
|
||||
<div class="adm-row">
|
||||
<div class="adm-row-text">
|
||||
<label>Tag image cache</label>
|
||||
<p>Regenerate thumbnails for the /tags page. Runs in the background and may take a while.</p>
|
||||
</div>
|
||||
<button type="button" onclick="regenerateTagImages()" id="regen_tag_btn" class="adm-btn adm-btn-ghost">Regenerate all</button>
|
||||
</div>
|
||||
<input type="number" id="trusted_uploads_input" value="{{ trusted_uploads }}" min="0" max="999" style="width: 60px; background: #333; border: 1px solid #444; color: #fff; padding: 5px; border-radius: 4px; text-align: center;" onchange="saveAdminSettings()">
|
||||
</div>
|
||||
|
||||
|
||||
<div class="settings-item" style="background: rgba(0,0,0,0.2); padding: 15px; border-radius: 4px; display: flex; align-items: center; justify-content: space-between; margin-top: 10px;">
|
||||
<div>
|
||||
<label style="display: block; font-weight: bold; color: var(--accent);">Tag Image Cache</label>
|
||||
<p style="margin: 2px 0 0 0; font-size: 0.8em; color: #aaa;">Regenerate thumbnails for the /tags page. This may take a while.</p>
|
||||
</div>
|
||||
<button onclick="regenerateTagImages()" id="regen_tag_btn" style="background: #007bff; border: 0; color: #fff; padding: 8px 16px; border-radius: 4px; cursor: pointer; font-size: 0.8em; font-weight: bold;">Regenerate All</button>
|
||||
</div>
|
||||
|
||||
|
||||
<span id="settings-status" style="display: block; margin-top: 10px; font-size: 0.8em; font-weight: bold; text-align: right;"></span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.switch { position: relative; display: inline-block; width: 50px; height: 26px; }
|
||||
.switch input { opacity: 0; width: 0; height: 0; }
|
||||
.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #333; transition: .4s; border-radius: 34px; }
|
||||
.slider:before { position: absolute; content: ""; height: 18px; width: 18px; left: 4px; bottom: 4px; background-color: white; transition: .4s; border-radius: 50%; }
|
||||
input:checked + .slider { background-color: var(--accent); }
|
||||
input:checked + .slider:before { transform: translateX(24px); background-color: #000; }
|
||||
</style>
|
||||
@include(snippets/adm-dashboard-style)
|
||||
|
||||
<script>
|
||||
|
||||
@@ -166,14 +260,14 @@
|
||||
csrf_token: csrfToken
|
||||
}).toString()
|
||||
});
|
||||
|
||||
|
||||
if (!res.ok) {
|
||||
if (res.status === 403) {
|
||||
throw new Error('CSRF validation failed or session expired. Please reload the page.');
|
||||
}
|
||||
throw new Error('Server returned ' + res.status);
|
||||
}
|
||||
|
||||
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
status.textContent = 'Saved!';
|
||||
@@ -192,7 +286,7 @@
|
||||
async function regenerateTagImages() {
|
||||
const btn = document.getElementById('regen_tag_btn');
|
||||
const status = document.getElementById('settings-status');
|
||||
|
||||
|
||||
if (!confirm('Are you sure you want to trigger a full regeneration of all tag images? This will run in the background.')) return;
|
||||
|
||||
btn.disabled = true;
|
||||
@@ -205,14 +299,14 @@
|
||||
headers: { 'X-Requested-With': 'XMLHttpRequest' }
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
|
||||
if (data.success) {
|
||||
status.textContent = data.message;
|
||||
status.style.color = '#28a745';
|
||||
btn.textContent = 'Started!';
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'Regenerate All';
|
||||
btn.textContent = 'Regenerate all';
|
||||
status.textContent = '';
|
||||
}, 5000);
|
||||
} else {
|
||||
@@ -223,7 +317,7 @@
|
||||
status.textContent = 'Error: ' + err.message;
|
||||
status.style.color = '#d9534f';
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'Regenerate All';
|
||||
btn.textContent = 'Regenerate all';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +357,6 @@
|
||||
preview = document.createElement('img');
|
||||
preview.id = 'brand-preview';
|
||||
preview.alt = 'current brand';
|
||||
preview.style.cssText = 'max-height:48px;max-width:150px;object-fit:contain;';
|
||||
wrap.appendChild(preview);
|
||||
}
|
||||
preview.src = data.url;
|
||||
@@ -271,9 +364,7 @@
|
||||
// Immediately update navbar brand logo
|
||||
if (window.updateBrandImage) window.updateBrandImage(data.url);
|
||||
|
||||
// Enable remove button
|
||||
removeBtn.disabled = false;
|
||||
removeBtn.style.cssText = 'background:rgba(220,53,69,0.15);border:1px solid rgba(220,53,69,0.4);color:#dc3545;padding:7px 16px;border-radius:4px;cursor:pointer;font-size:0.82em;font-weight:bold;transition:background 0.2s;';
|
||||
|
||||
setTimeout(() => { status.textContent = ''; }, 3000);
|
||||
} catch (err) {
|
||||
@@ -311,14 +402,12 @@
|
||||
|
||||
// Reset preview
|
||||
const wrap = document.getElementById('brand-preview-wrap');
|
||||
wrap.innerHTML = '<span id="brand-preview" style="font-size:0.75em;color:#666;font-style:italic;">No image set</span>';
|
||||
wrap.innerHTML = '<span id="brand-preview" class="adm-muted">No image set</span>';
|
||||
|
||||
// Immediately update navbar brand logo (revert to text)
|
||||
if (window.updateBrandImage) window.updateBrandImage(null);
|
||||
|
||||
// Disable remove button
|
||||
removeBtn.disabled = true;
|
||||
removeBtn.style.cssText = 'background:rgba(220,53,69,0.05);border:1px solid rgba(220,53,69,0.15);color:#884040;padding:7px 16px;border-radius:4px;cursor:not-allowed;font-size:0.82em;font-weight:bold;';
|
||||
|
||||
setTimeout(() => { status.textContent = ''; }, 3000);
|
||||
} catch (err) {
|
||||
@@ -326,9 +415,8 @@
|
||||
status.style.color = '#d9534f';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
@include(snippets/footer)
|
||||
@include(snippets/footer)
|
||||
|
||||
Reference in New Issue
Block a user