reworked settings page

This commit is contained in:
2025-11-21 14:33:34 +01:00
parent 23a5714119
commit 2e4a6ae7c4
4 changed files with 403 additions and 29 deletions

View File

@@ -43,6 +43,7 @@ const PROVIDER_INFO = {
let credentials = [];
let currentSettings = null;
let hiddenSettings = { auto_purge_enabled: true, retention_days: 90 };
function apiFetch(url, options = {}) {
return fetch(url, {...options, credentials: 'include'});
@@ -52,7 +53,7 @@ function showToast(message, type = 'info') {
const toast = document.createElement('div');
toast.style.cssText = `
position: fixed;
bottom: 24px;
bottom: 84px;
right: 24px;
background: ${type === 'error' ? '#e74c3c' : type === 'success' ? '#42b72a' : '#1877f2'};
color: white;
@@ -64,6 +65,7 @@ function showToast(message, type = 'info') {
z-index: 999999;
max-width: 350px;
animation: slideIn 0.3s ease-out;
pointer-events: none;
`;
toast.textContent = message;
@@ -124,6 +126,93 @@ async function loadSettings() {
'Schreibe einen freundlichen, authentischen Kommentar auf Deutsch zu folgendem Facebook-Post. Der Kommentar soll natürlich wirken und maximal 2-3 Sätze lang sein:\n\n';
}
async function loadHiddenSettings() {
const res = await apiFetch(`${API_URL}/hidden-settings`);
if (!res.ok) throw new Error('Failed to load hidden settings');
hiddenSettings = await res.json();
applyHiddenSettingsUI();
}
function applyHiddenSettingsUI() {
const autoToggle = document.getElementById('autoPurgeHiddenToggle');
const retentionInput = document.getElementById('hiddenRetentionDays');
if (autoToggle) {
autoToggle.checked = !!hiddenSettings.auto_purge_enabled;
}
if (retentionInput) {
retentionInput.value = hiddenSettings.retention_days || 90;
retentionInput.disabled = !autoToggle?.checked;
}
}
function normalizeRetentionInput(value) {
const parsed = parseInt(value, 10);
if (Number.isNaN(parsed) || parsed <= 0) {
return 90;
}
return Math.min(365, Math.max(1, parsed));
}
async function saveHiddenSettings(event, { silent = false } = {}) {
if (event && typeof event.preventDefault === 'function') {
event.preventDefault();
}
const autoToggle = document.getElementById('autoPurgeHiddenToggle');
const retentionInput = document.getElementById('hiddenRetentionDays');
const autoEnabled = autoToggle ? autoToggle.checked : true;
const retention = normalizeRetentionInput(retentionInput ? retentionInput.value : hiddenSettings.retention_days);
try {
const res = await apiFetch(`${API_URL}/hidden-settings`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
auto_purge_enabled: autoEnabled,
retention_days: retention
})
});
if (!res.ok) {
const err = await res.json();
throw new Error(err.error || 'Fehler beim Speichern');
}
hiddenSettings = await res.json();
applyHiddenSettingsUI();
if (!silent) {
showSuccess('✅ Einstellungen für versteckte Beiträge gespeichert');
}
return true;
} catch (err) {
if (!silent) {
showError('❌ ' + err.message);
}
return false;
}
}
async function purgeHiddenNow() {
const btn = document.getElementById('purgeHiddenNowBtn');
const originalText = btn ? btn.textContent : '';
if (btn) {
btn.disabled = true;
btn.textContent = 'Bereinige...';
}
try {
const res = await apiFetch(`${API_URL}/search-posts`, { method: 'DELETE' });
if (!res.ok) {
const err = await res.json();
throw new Error(err.error || 'Fehler beim Bereinigen');
}
showSuccess('🧹 Versteckte Beiträge wurden zurückgesetzt');
} catch (err) {
showError('❌ ' + err.message);
} finally {
if (btn) {
btn.disabled = false;
btn.textContent = originalText || 'Jetzt bereinigen';
}
}
}
function shorten(text, maxLength = 80) {
if (typeof text !== 'string') {
return '';
@@ -626,8 +715,10 @@ async function saveCredentialOrder() {
}
}
async function saveSettings(e) {
e.preventDefault();
async function saveSettings(e, { silent = false } = {}) {
if (e && typeof e.preventDefault === 'function') {
e.preventDefault();
}
try {
const data = {
@@ -648,9 +739,15 @@ async function saveSettings(e) {
}
currentSettings = await res.json();
showSuccess('✅ Einstellungen erfolgreich gespeichert');
if (!silent) {
showSuccess('✅ Einstellungen erfolgreich gespeichert');
}
return true;
} catch (err) {
showError('❌ ' + err.message);
if (!silent) {
showError('❌ ' + err.message);
}
return false;
}
}
@@ -720,6 +817,64 @@ function escapeHtml(text) {
return div.innerHTML;
}
async function saveAllSettings(event) {
if (event && typeof event.preventDefault === 'function') {
event.preventDefault();
}
const saveBtn = document.getElementById('saveAllFloatingBtn');
const labelEl = saveBtn ? saveBtn.querySelector('.label') : null;
const spinnerEl = saveBtn ? saveBtn.querySelector('.spinner') : null;
const defaultLabel = saveBtn
? (saveBtn.dataset.defaultLabel || (labelEl && labelEl.textContent.trim()) || 'Einstellungen speichern')
: 'Einstellungen speichern';
if (saveBtn) {
saveBtn.dataset.defaultLabel = defaultLabel;
}
if (saveBtn) {
saveBtn.disabled = true;
saveBtn.classList.add('is-saving');
if (labelEl) {
labelEl.textContent = 'Speichern...';
} else {
saveBtn.textContent = 'Speichern...';
}
if (spinnerEl) {
spinnerEl.style.display = 'inline-block';
spinnerEl.classList.add('spin');
}
}
const results = await Promise.all([
saveSettings(null, { silent: true }),
saveHiddenSettings(null, { silent: true }),
saveAllFriends({ silent: true })
]);
const allOk = results.every(Boolean);
if (allOk) {
showSuccess('Gespeichert');
} else {
showError('❌ Nicht alle Einstellungen konnten gespeichert werden');
}
if (saveBtn) {
saveBtn.disabled = false;
saveBtn.classList.remove('is-saving');
const label = saveBtn.querySelector('.label');
const spinner = saveBtn.querySelector('.spinner');
if (label) {
label.textContent = saveBtn.dataset.defaultLabel || 'Einstellungen speichern';
} else {
saveBtn.textContent = 'Einstellungen speichern';
}
if (spinner) {
spinner.style.display = 'none';
spinner.classList.remove('spin');
}
}
}
// ============================================================================
// PROFILE FRIENDS
// ============================================================================
@@ -755,7 +910,7 @@ async function loadProfileFriends() {
}
}
async function saveFriends(profileNumber, friendNames) {
async function saveFriends(profileNumber, friendNames, { silent = false } = {}) {
try {
const res = await apiFetch(`${API_URL}/profile-friends/${profileNumber}`, {
method: 'PUT',
@@ -769,12 +924,34 @@ async function saveFriends(profileNumber, friendNames) {
}
profileFriends[profileNumber] = friendNames;
showSuccess(`✅ Freunde für Profil ${profileNumber} gespeichert`);
if (!silent) {
showSuccess(`✅ Freunde für Profil ${profileNumber} gespeichert`);
}
return true;
} catch (err) {
showError('❌ ' + err.message);
if (!silent) {
showError('❌ ' + err.message);
}
return false;
}
}
async function saveAllFriends({ silent = false } = {}) {
let success = true;
for (let i = 1; i <= 5; i++) {
const input = document.getElementById(`friends${i}`);
if (!input) {
continue;
}
const newValue = input.value.trim();
if (newValue !== profileFriends[i]) {
const result = await saveFriends(i, newValue, { silent });
success = success && result;
}
}
return success;
}
// Event listeners
document.getElementById('addCredentialBtn').addEventListener('click', () => openCredentialModal());
document.getElementById('credentialModalClose').addEventListener('click', closeCredentialModal);
@@ -785,14 +962,22 @@ document.getElementById('aiSettingsForm').addEventListener('submit', (e) => {
e.preventDefault();
saveSettings(e);
});
document.getElementById('saveAllBtn').addEventListener('click', (e) => {
e.preventDefault();
saveSettings(e);
});
document.getElementById('testBtn').addEventListener('click', testComment);
document.getElementById('testModalClose').addEventListener('click', () => document.getElementById('testModal').setAttribute('hidden', ''));
document.getElementById('generateTestComment').addEventListener('click', generateTest);
document.getElementById('purgeHiddenNowBtn').addEventListener('click', purgeHiddenNow);
document.getElementById('saveAllFloatingBtn').addEventListener('click', saveAllSettings);
const autoPurgeHiddenToggle = document.getElementById('autoPurgeHiddenToggle');
if (autoPurgeHiddenToggle) {
autoPurgeHiddenToggle.addEventListener('change', () => {
const retentionInput = document.getElementById('hiddenRetentionDays');
if (retentionInput) {
retentionInput.disabled = !autoPurgeHiddenToggle.checked;
}
});
}
// Initialize
Promise.all([loadCredentials(), loadSettings(), loadProfileFriends()]).catch(err => showError(err.message));
Promise.all([loadCredentials(), loadSettings(), loadHiddenSettings(), loadProfileFriends()]).catch(err => showError(err.message));
})();