tags
This commit is contained in:
1 parent
a9603aa0e8
commit
719f9d51ff
13 files changed
+625
-70
No files matched your search
@@ -73,16 +73,8 @@ export async function openGallery() {
|
||||
if (orphaned.length) {
|
||||
html += `<div class="col-span-full font-pixel text-[10px] text-t-danger flex items-center gap-1.5 pt-2"><i class="ph ph-warning text-xs"></i>orphaned (not used by any card)</div>`;
|
||||
html += orphaned.map(f => `
|
||||
<div class="gallery-item group relative" data-orphan="${f.name}">
|
||||
<div class="gallery-item group relative cursor-pointer" data-orphan="${f.name}">
|
||||
${mediaTile(f.url, 'border-t-danger/30')}
|
||||
<div class="absolute top-1 right-1 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
<button class="w-6 h-6 rounded bg-t-accent text-t-bg flex items-center justify-center text-xs" data-create="${f.url}" title="create card">
|
||||
<i class="ph ph-plus"></i>
|
||||
</button>
|
||||
<button class="w-6 h-6 rounded bg-t-danger text-t-bg flex items-center justify-center text-xs" data-del="${f.name}" title="delete">
|
||||
<i class="ph ph-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="mt-1 font-pixel text-[8px] text-t-dim truncate">${esc(f.name)}</div>
|
||||
</div>`).join('');
|
||||
}
|
||||
@@ -113,27 +105,13 @@ export async function openGallery() {
|
||||
});
|
||||
});
|
||||
|
||||
// Orphan: create card from image
|
||||
grid.querySelectorAll('[data-create]').forEach(btn => {
|
||||
btn.addEventListener('click', async e => {
|
||||
e.stopPropagation();
|
||||
const url = btn.dataset.create;
|
||||
const name = url.split('/').pop().replace(/\.[^.]+$/, '');
|
||||
await api('api/cards', { method: 'POST', body: { title: name, body: ``, color: '#38bdf8', position: -1 } });
|
||||
await window._reloadAll();
|
||||
openGallery(); // refresh
|
||||
});
|
||||
});
|
||||
|
||||
// Orphan: delete
|
||||
grid.querySelectorAll('[data-del]').forEach(btn => {
|
||||
btn.addEventListener('click', async e => {
|
||||
e.stopPropagation();
|
||||
const name = btn.dataset.del;
|
||||
const ok = await showDialog({ title: 'delete_image', message: `"${name}" loeschen?`, danger: true, okLabel: 'delete' });
|
||||
if (!ok) return;
|
||||
await fetch(`api/uploads/${name}`, { method: 'DELETE', headers: { 'X-CSRF-Token': getCsrf() } });
|
||||
openGallery(); // refresh
|
||||
// Orphan: click to enlarge
|
||||
grid.querySelectorAll('[data-orphan]').forEach(item => {
|
||||
item.addEventListener('click', e => {
|
||||
if (e.target.closest('button')) return;
|
||||
const name = item.dataset.orphan;
|
||||
const f = orphaned.find(o => o.name === name);
|
||||
if (f && !isAudio(f.url)) openOrphanLightbox(f);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -141,6 +119,51 @@ export async function openGallery() {
|
||||
el.classList.add('open');
|
||||
}
|
||||
|
||||
function openOrphanLightbox(file) {
|
||||
let overlay = document.querySelector('.orphan-lightbox');
|
||||
if (overlay) overlay.remove();
|
||||
|
||||
overlay = document.createElement('div');
|
||||
overlay.className = 'orphan-lightbox';
|
||||
overlay.style.cssText = 'position:fixed;inset:0;z-index:200;display:flex;align-items:center;justify-content:center;background:rgba(2,6,23,0.92);';
|
||||
overlay.innerHTML = `
|
||||
<img src="${file.url}" style="max-width:min(92vw,1400px);max-height:85vh;object-fit:contain;border:1px solid var(--t-border);box-shadow:0 16px 60px rgba(0,0,0,0.55);">
|
||||
<div style="position:fixed;bottom:24px;left:50%;transform:translateX(-50%);display:flex;gap:8px;">
|
||||
<button class="orphan-lb-create flex items-center gap-1.5 px-3 py-1.5 text-xs border border-t-accent text-t-accent hover:bg-t-accent hover:text-t-bg transition-colors" style="border-radius:4px;">
|
||||
<i class="ph ph-plus text-sm"></i><span class="font-pixel text-[10px]">new card</span>
|
||||
</button>
|
||||
<button class="orphan-lb-delete flex items-center gap-1.5 px-3 py-1.5 text-xs border border-t-danger text-t-danger hover:bg-t-danger hover:text-t-bg transition-colors" style="border-radius:4px;">
|
||||
<i class="ph ph-trash text-sm"></i><span class="font-pixel text-[10px]">delete</span>
|
||||
</button>
|
||||
</div>
|
||||
<button style="position:fixed;top:12px;right:12px;color:rgba(255,255,255,0.6);font-size:20px;background:none;border:none;cursor:pointer;" class="orphan-lb-close">
|
||||
<i class="ph ph-x"></i>
|
||||
</button>
|
||||
`;
|
||||
|
||||
const close = () => overlay.remove();
|
||||
overlay.addEventListener('click', e => { if (e.target === overlay) close(); });
|
||||
overlay.querySelector('.orphan-lb-close').addEventListener('click', close);
|
||||
|
||||
overlay.querySelector('.orphan-lb-create').addEventListener('click', async () => {
|
||||
const name = file.url.split('/').pop().replace(/\.[^.]+$/, '');
|
||||
await api('api/cards', { method: 'POST', body: { title: name, body: ``, color: '#38bdf8', position: -1 } });
|
||||
await window._reloadAll();
|
||||
close();
|
||||
openGallery();
|
||||
});
|
||||
|
||||
overlay.querySelector('.orphan-lb-delete').addEventListener('click', async () => {
|
||||
const ok = await showDialog({ title: 'delete_image', message: `"${file.name}" loeschen?`, danger: true, okLabel: 'delete' });
|
||||
if (!ok) return;
|
||||
await fetch(`api/uploads/${file.name}`, { method: 'DELETE', headers: { 'X-CSRF-Token': getCsrf() } });
|
||||
close();
|
||||
openGallery();
|
||||
});
|
||||
|
||||
document.body.appendChild(overlay);
|
||||
}
|
||||
|
||||
export function closeGallery() {
|
||||
$('gallery')?.classList.remove('open');
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user