ads
This commit is contained in:
@@ -99,13 +99,12 @@ export async function loadList(resource){
|
||||
|
||||
const prevBtn = `<button class='btn' data-preview='${resource}:${item.id}'>Vorschau</button>`;
|
||||
const delBtn = `<button class='btn btn-danger' data-del='${resource}:${item.id}' data-name='${name}'>Löschen</button>`;
|
||||
const debugBtn= `<a class='btn' href='api.php?resource=${resource}&action=get&id=${item.id}' target='_blank' rel='noopener'>GET</a>`;
|
||||
|
||||
return `<div class='p-3 flex items-center gap-3'>
|
||||
<div class='min-w-48 font-medium truncate' title="${name}">${name || '(ohne Name)'}</div>
|
||||
<div class='text-xs text-gray-500'>#${item.id}</div>
|
||||
<div class='text-xs'>${parentBadge(resource,item)}</div>
|
||||
<div class='ms-auto flex gap-2'>${[openBtn, editBtn, prevBtn, delBtn, debugBtn].filter(Boolean).join('')}</div>
|
||||
<div class='ms-auto flex gap-2'>${[openBtn, editBtn, prevBtn, delBtn].filter(Boolean).join('')}</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
// assets/js/ui-tools.js
|
||||
// Öffnet API-Health (JSON), DB-Doctor (Iframe) & beliebige JSON-GETs im Popup,
|
||||
// ohne die Seite zu verlassen. Links bleiben als Fallback nutzbar.
|
||||
|
||||
(function () {
|
||||
const dlg = document.getElementById('toolsDialog');
|
||||
if (!dlg) return;
|
||||
|
||||
const title = document.getElementById('toolsTitle');
|
||||
const btnX = document.getElementById('toolsClose');
|
||||
const btnCopy = document.getElementById('toolsCopy');
|
||||
const btnDl = document.getElementById('toolsDownload');
|
||||
|
||||
const jsonWrap = document.getElementById('toolsJsonWrap');
|
||||
const jsonPre = document.getElementById('toolsJsonPre');
|
||||
const frame = document.getElementById('toolsFrame');
|
||||
|
||||
function showJson(obj, ttl) {
|
||||
title.textContent = ttl || 'Antwort (JSON)';
|
||||
const txt = (typeof obj === 'string') ? obj : JSON.stringify(obj, null, 2);
|
||||
jsonPre.textContent = txt;
|
||||
jsonWrap.classList.remove('hidden');
|
||||
frame.classList.add('hidden');
|
||||
btnCopy.classList.remove('hidden');
|
||||
btnDl.classList.remove('hidden');
|
||||
try { dlg.showModal(); } catch {}
|
||||
}
|
||||
|
||||
function showFrame(url, ttl) {
|
||||
title.textContent = ttl || 'Werkzeug';
|
||||
frame.src = url + (url.includes('?') ? '&' : '?') + 't=' + Date.now();
|
||||
frame.classList.remove('hidden');
|
||||
jsonWrap.classList.add('hidden');
|
||||
btnCopy.classList.add('hidden');
|
||||
btnDl.classList.add('hidden');
|
||||
try { dlg.showModal(); } catch {}
|
||||
}
|
||||
|
||||
btnX?.addEventListener('click', () => {
|
||||
try { dlg.close(); } catch {}
|
||||
frame.src = 'about:blank';
|
||||
});
|
||||
|
||||
btnCopy?.addEventListener('click', async () => {
|
||||
const txt = jsonPre.textContent || '';
|
||||
try {
|
||||
await navigator.clipboard.writeText(txt);
|
||||
// optional: kleines Feedback
|
||||
(window.Toast?.show || window.toast || (()=>{}))('In Zwischenablage kopiert');
|
||||
} catch {}
|
||||
});
|
||||
|
||||
btnDl?.addEventListener('click', () => {
|
||||
const blob = new Blob([jsonPre.textContent || ''], { type:'application/json;charset=utf-8' });
|
||||
const a = document.createElement('a');
|
||||
a.href = URL.createObjectURL(blob);
|
||||
const stamp = new Date().toISOString().replace(/[:.]/g,'-');
|
||||
a.download = `response-${stamp}.json`;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
setTimeout(()=>{ URL.revokeObjectURL(a.href); a.remove(); }, 0);
|
||||
});
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// 1) Offizieller Weg: Links mit data-popup="json" | "frame"
|
||||
// ------------------------------------------------------------
|
||||
document.addEventListener('click', async (ev) => {
|
||||
const a = ev.target.closest('a[data-popup]');
|
||||
if (!a) return;
|
||||
|
||||
const mode = (a.getAttribute('data-popup') || '').toLowerCase();
|
||||
const href = a.getAttribute('href') || '#';
|
||||
const ttl = a.getAttribute('data-title') || a.textContent.trim() || 'Werkzeug';
|
||||
|
||||
if (!/^json|frame$/.test(mode)) return;
|
||||
// Cmd/Strg-Klick & Mittelklick respektieren (neuer Tab)
|
||||
if (ev.metaKey || ev.ctrlKey || ev.button === 1) return;
|
||||
|
||||
ev.preventDefault();
|
||||
|
||||
if (mode === 'frame') {
|
||||
showFrame(href, ttl);
|
||||
return;
|
||||
}
|
||||
|
||||
// mode === 'json'
|
||||
try {
|
||||
const r = await fetch(href, { credentials: 'include' });
|
||||
const txt = await r.text();
|
||||
let data = null;
|
||||
try { data = JSON.parse(txt); } catch { data = txt; }
|
||||
showJson(data, ttl);
|
||||
} catch (e) {
|
||||
showJson({ ok:false, error: String(e) }, ttl);
|
||||
}
|
||||
});
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// 2) Fallback: *alle* API-GET-Links (action=get) ohne data-popup
|
||||
// -> automatisch im JSON-Popup öffnen
|
||||
// ------------------------------------------------------------
|
||||
document.addEventListener('click', async (ev) => {
|
||||
const a = ev.target.closest('a');
|
||||
if (!a) return;
|
||||
// bereits oben behandelt
|
||||
if (a.hasAttribute('data-popup')) return;
|
||||
|
||||
const href = a.getAttribute('href') || '';
|
||||
// nur api.php-GET-Routen mit action=get abfangen
|
||||
if (!/api\.php/i.test(href) || !/[?&]action=get(&|$)/i.test(href)) return;
|
||||
|
||||
// Cmd/Strg/Mittelklick respektieren
|
||||
if (ev.metaKey || ev.ctrlKey || ev.button === 1) return;
|
||||
|
||||
ev.preventDefault();
|
||||
|
||||
const makeTitle = () => {
|
||||
try {
|
||||
const u = new URL(href, location.href);
|
||||
const res = u.searchParams.get('resource') || 'resource';
|
||||
const id = u.searchParams.get('id') || '';
|
||||
// Optional: Name aus data-title wenn vorhanden
|
||||
const custom = a.getAttribute('data-title');
|
||||
return custom || `GET ${res}${id ? ` #${id}` : ''}`;
|
||||
} catch { return 'GET'; }
|
||||
};
|
||||
|
||||
const title = makeTitle();
|
||||
|
||||
// Popup öffnen (wie oben)
|
||||
try {
|
||||
const r = await fetch(href, { credentials: 'include' });
|
||||
const txt = await r.text();
|
||||
let data = null;
|
||||
try { data = JSON.parse(txt); } catch { data = txt; }
|
||||
showJson(data, title);
|
||||
} catch (e) {
|
||||
showJson({ ok:false, error: String(e) }, title);
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Utility: Öffnen aus Code
|
||||
window.AdminTools = {
|
||||
openJson(url, title) {
|
||||
fetch(url, { credentials: 'include' })
|
||||
.then(r => r.text())
|
||||
.then(txt => {
|
||||
try { showJson(JSON.parse(txt), title); }
|
||||
catch { showJson(txt, title); }
|
||||
})
|
||||
.catch(err => showJson({ ok:false, error:String(err) }, title));
|
||||
},
|
||||
openFrame(url, title) {
|
||||
showFrame(url, title);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user