reverseproxy

This commit is contained in:
2026-09-07 12:46:58 +02:00
parent 93051f791d
commit cbe4726c07
16 changed files with 519 additions and 32 deletions

View File

@@ -1,5 +1,6 @@
let friends = [];
let shareTargetId = null;
let settings = { publicBaseUrl: '' };
async function checkSession() {
const res = await fetch('/api/session');
@@ -9,6 +10,37 @@ async function checkSession() {
}
}
async function loadSettings() {
const res = await fetch('/api/settings');
if (!res.ok) return;
const data = await res.json();
settings = data.settings || { publicBaseUrl: '' };
document.getElementById('publicBaseUrl').value = settings.publicBaseUrl || '';
}
document.getElementById('saveSettingsBtn').addEventListener('click', async () => {
const publicBaseUrl = document.getElementById('publicBaseUrl').value.trim();
const res = await fetch('/api/settings', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ publicBaseUrl }),
});
const data = await res.json();
if (res.ok) {
settings = data.settings;
const msg = document.getElementById('settingsSaved');
msg.textContent = 'Gespeichert ✓';
msg.classList.add('show');
setTimeout(() => msg.classList.remove('show'), 1800);
}
});
function baseUrl() {
return settings.publicBaseUrl && settings.publicBaseUrl.length
? settings.publicBaseUrl
: window.location.origin;
}
async function loadFriends() {
const res = await fetch('/api/friends');
if (res.status === 401) { window.location.href = '/'; return; }
@@ -37,6 +69,7 @@ function renderFriends() {
<div class="friend-actions">
<a class="btn" href="/friend/${f.id}">✏️ Bearbeiten</a>
<button class="secondary" data-share="${f.id}">🔗 Freigabe</button>
<button class="secondary" data-export="${f.id}">⬇️ Export</button>
<button class="danger" data-delete="${f.id}">🗑️</button>
</div>
`;
@@ -49,6 +82,9 @@ function renderFriends() {
grid.querySelectorAll('[data-delete]').forEach((btn) => {
btn.addEventListener('click', () => deleteFriend(btn.dataset.delete));
});
grid.querySelectorAll('[data-export]').forEach((btn) => {
btn.addEventListener('click', () => window.location.href = `/api/friends/${btn.dataset.export}/export`);
});
}
// wir brauchen den vollen Ordnernamen für Bild-URLs; da wir ihn nicht separat liefern,
@@ -101,7 +137,7 @@ function openShareModal(id) {
const linkBox = document.getElementById('shareLinkBox');
if (f && f.shareEnabled) {
linkBox.style.display = 'block';
document.getElementById('shareLinkInput').value = `${window.location.origin}/share/${id}`;
document.getElementById('shareLinkInput').value = `${baseUrl()}/share/${id}`;
} else {
linkBox.style.display = 'none';
}
@@ -127,7 +163,7 @@ document.getElementById('shareEnableBtn').addEventListener('click', async () =>
return;
}
document.getElementById('shareLinkBox').style.display = 'block';
document.getElementById('shareLinkInput').value = `${window.location.origin}/share/${shareTargetId}`;
document.getElementById('shareLinkInput').value = `${baseUrl()}/share/${shareTargetId}`;
await loadFriends();
});
@@ -154,5 +190,56 @@ document.getElementById('logoutBtn').addEventListener('click', async () => {
window.location.href = '/';
});
// --- Sichern & Wiederherstellen ---
function showTransferMsg(text, isError) {
const box = document.getElementById('transferMsg');
box.innerHTML = isError ? `<p class="error-msg">${text}</p>` : `<p class="saved-msg2 show">${text}</p>`;
}
document.getElementById('bookExportBtn').addEventListener('click', () => {
window.location.href = '/api/book/export';
});
document.getElementById('bookImportBtn').addEventListener('click', async () => {
const fileInput = document.getElementById('bookImportFile');
const file = fileInput.files[0];
if (!file) { showTransferMsg('Bitte zuerst eine ZIP-Datei auswählen.', true); return; }
const replaceAll = document.getElementById('bookImportReplace').checked;
if (replaceAll && !confirm('Wirklich ALLE bestehenden Freunde vor dem Import löschen?')) return;
const fd = new FormData();
fd.append('file', file);
fd.append('replaceAll', replaceAll ? 'true' : 'false');
showTransferMsg('Importiere...', false);
const res = await fetch('/api/book/import', { method: 'POST', body: fd });
const data = await res.json();
if (res.ok) {
showTransferMsg(`${data.imported.length} Freund(e) importiert: ${data.imported.join(', ') || ''}`, false);
fileInput.value = '';
loadFriends();
} else {
showTransferMsg(data.error || 'Import fehlgeschlagen.', true);
}
});
document.getElementById('friendImportBtn').addEventListener('click', async () => {
const fileInput = document.getElementById('friendImportFile');
const file = fileInput.files[0];
if (!file) { showTransferMsg('Bitte zuerst eine ZIP-Datei auswählen.', true); return; }
const fd = new FormData();
fd.append('file', file);
showTransferMsg('Importiere...', false);
const res = await fetch('/api/friends/import', { method: 'POST', body: fd });
const data = await res.json();
if (res.ok) {
showTransferMsg(`"${data.friend.name}" wurde importiert.`, false);
fileInput.value = '';
loadFriends();
} else {
showTransferMsg(data.error || 'Import fehlgeschlagen.', true);
}
});
checkSession();
loadSettings();
loadFriends();