reworked settings page
This commit is contained in:
211
web/settings.js
211
web/settings.js
@@ -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));
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user