alotta good shit
This commit is contained in:
+122
-1
@@ -35,10 +35,37 @@
|
||||
@endif
|
||||
</ul>
|
||||
<hr style="margin: 20px 0; border: 0; border-top: 1px solid rgba(255,255,255,0.1);">
|
||||
|
||||
|
||||
<!-- 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 2 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>
|
||||
</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>
|
||||
@@ -199,6 +226,100 @@
|
||||
btn.textContent = 'Regenerate All';
|
||||
}
|
||||
}
|
||||
|
||||
async function uploadBrandImage(input) {
|
||||
const file = input.files[0];
|
||||
if (!file) return;
|
||||
|
||||
const status = document.getElementById('brand-status');
|
||||
const removeBtn = document.getElementById('brand-remove-btn');
|
||||
status.textContent = 'Uploading…';
|
||||
status.style.color = 'var(--accent)';
|
||||
|
||||
const csrfToken = (window.f0ckSession && window.f0ckSession.csrf_token) || '{{ csrf_token }}';
|
||||
const fd = new FormData();
|
||||
fd.append('file', file);
|
||||
|
||||
try {
|
||||
const res = await fetch('/admin/brand_image/upload', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'X-CSRF-Token': csrfToken
|
||||
},
|
||||
body: fd
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!data.success) throw new Error(data.msg || 'Upload failed');
|
||||
|
||||
status.textContent = '✓ Brand image updated!';
|
||||
status.style.color = '#28a745';
|
||||
|
||||
// Update preview
|
||||
const wrap = document.getElementById('brand-preview-wrap');
|
||||
let preview = document.getElementById('brand-preview');
|
||||
if (!preview || preview.tagName !== 'IMG') {
|
||||
wrap.innerHTML = '';
|
||||
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;
|
||||
|
||||
// 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) {
|
||||
status.textContent = 'Error: ' + err.message;
|
||||
status.style.color = '#d9534f';
|
||||
} finally {
|
||||
input.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
async function removeBrandImage() {
|
||||
const status = document.getElementById('brand-status');
|
||||
const removeBtn = document.getElementById('brand-remove-btn');
|
||||
|
||||
if (!confirm('Remove the custom brand image? The navbar will revert to text.')) return;
|
||||
|
||||
status.textContent = 'Removing…';
|
||||
status.style.color = 'var(--accent)';
|
||||
|
||||
const csrfToken = (window.f0ckSession && window.f0ckSession.csrf_token) || '{{ csrf_token }}';
|
||||
|
||||
try {
|
||||
const res = await fetch('/admin/brand_image/delete', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'X-CSRF-Token': csrfToken
|
||||
}
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!data.success) throw new Error(data.msg || 'Remove failed');
|
||||
|
||||
status.textContent = '✓ Brand image removed.';
|
||||
status.style.color = '#28a745';
|
||||
|
||||
// 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>';
|
||||
|
||||
// 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) {
|
||||
status.textContent = 'Error: ' + err.message;
|
||||
status.style.color = '#d9534f';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user