Add support for disabling broken profiles
This commit is contained in:
176
web/settings.js
176
web/settings.js
@@ -52,10 +52,13 @@ const AI_AUTO_COMMENT_RATE_LIMIT_DEFAULTS = Object.freeze({
|
||||
active_hours_start: '',
|
||||
active_hours_end: ''
|
||||
});
|
||||
const MAX_PROFILES = 5;
|
||||
const DEFAULT_ACTIVE_PROFILES = Array.from({ length: MAX_PROFILES }, (_unused, index) => index + 1);
|
||||
|
||||
let credentials = [];
|
||||
let currentSettings = null;
|
||||
let hiddenSettings = { auto_purge_enabled: true, retention_days: 90 };
|
||||
let profileSettings = { active_profiles: [...DEFAULT_ACTIVE_PROFILES], max_target_count: MAX_PROFILES };
|
||||
const SPORT_WEIGHT_FIELDS = [
|
||||
{ key: 'scoreline', id: 'sportWeightScoreline' },
|
||||
{ key: 'scoreEmoji', id: 'sportWeightScoreEmoji' },
|
||||
@@ -1229,7 +1232,7 @@ async function testComment() {
|
||||
try {
|
||||
const data = JSON.parse(lastTest);
|
||||
document.getElementById('testPostText').value = data.postText || '';
|
||||
document.getElementById('testProfileNumber').value = data.profileNumber || '1';
|
||||
renderTestProfileOptions(data.profileNumber || profileSettings.active_profiles[0] || 1);
|
||||
} catch (e) {
|
||||
console.error('Failed to load last test comment:', e);
|
||||
}
|
||||
@@ -1313,6 +1316,7 @@ async function saveAllSettings(event) {
|
||||
|
||||
const results = await Promise.all([
|
||||
saveSettings(null, { silent: true }),
|
||||
saveProfileSettings(null, { silent: true }),
|
||||
saveHiddenSettings(null, { silent: true }),
|
||||
saveModerationSettings(null, { silent: true }),
|
||||
saveSimilaritySettings(null, { silent: true }),
|
||||
@@ -1343,6 +1347,146 @@ async function saveAllSettings(event) {
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeActiveProfileNumbers(values) {
|
||||
if (!Array.isArray(values)) {
|
||||
return [...DEFAULT_ACTIVE_PROFILES];
|
||||
}
|
||||
|
||||
const seen = new Set();
|
||||
const normalized = values
|
||||
.map((value) => parseInt(value, 10))
|
||||
.filter((value) => Number.isInteger(value) && value >= 1 && value <= MAX_PROFILES && !seen.has(value) && seen.add(value))
|
||||
.sort((a, b) => a - b);
|
||||
|
||||
return normalized.length ? normalized : [...DEFAULT_ACTIVE_PROFILES];
|
||||
}
|
||||
|
||||
function collectActiveProfilesFromInputs() {
|
||||
return Array.from(document.querySelectorAll('.profile-activation-checkbox:checked'))
|
||||
.map((input) => parseInt(input.value, 10))
|
||||
.filter((value) => Number.isInteger(value) && value >= 1 && value <= MAX_PROFILES)
|
||||
.sort((a, b) => a - b);
|
||||
}
|
||||
|
||||
function renderTestProfileOptions(selectedValue = null) {
|
||||
const select = document.getElementById('testProfileNumber');
|
||||
if (!select) {
|
||||
return;
|
||||
}
|
||||
|
||||
const activeProfiles = normalizeActiveProfileNumbers(profileSettings.active_profiles);
|
||||
const fallbackValue = activeProfiles[0] || 1;
|
||||
const normalizedSelected = activeProfiles.includes(parseInt(selectedValue, 10))
|
||||
? parseInt(selectedValue, 10)
|
||||
: fallbackValue;
|
||||
|
||||
select.innerHTML = activeProfiles.map((profileNumber) => (
|
||||
`<option value="${profileNumber}">Profil ${profileNumber}</option>`
|
||||
)).join('');
|
||||
select.value = String(normalizedSelected);
|
||||
}
|
||||
|
||||
function updateProfileActivationSummary() {
|
||||
const summary = document.getElementById('profileActivationSummary');
|
||||
if (!summary) {
|
||||
return;
|
||||
}
|
||||
|
||||
const activeProfiles = collectActiveProfilesFromInputs();
|
||||
summary.textContent = `Aktiv: ${activeProfiles.length} von ${MAX_PROFILES}. Max. benötigte Profile: ${Math.max(1, activeProfiles.length)}.`;
|
||||
}
|
||||
|
||||
function renderProfileActivationList() {
|
||||
const container = document.getElementById('profileActivationList');
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
const activeProfiles = normalizeActiveProfileNumbers(profileSettings.active_profiles);
|
||||
container.innerHTML = DEFAULT_ACTIVE_PROFILES.map((profileNumber) => {
|
||||
const checked = activeProfiles.includes(profileNumber);
|
||||
return `
|
||||
<label class="profile-activation-item">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="form-checkbox profile-activation-checkbox"
|
||||
value="${profileNumber}"
|
||||
${checked ? 'checked' : ''}
|
||||
>
|
||||
<span class="profile-activation-item__copy">
|
||||
<span class="profile-activation-item__title">Profil ${profileNumber}</span>
|
||||
<span class="profile-activation-item__hint">${checked ? 'Aktiv im Bestätigungsfluss' : 'Wird übersprungen'}</span>
|
||||
</span>
|
||||
</label>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
container.querySelectorAll('.profile-activation-checkbox').forEach((checkbox) => {
|
||||
checkbox.addEventListener('change', (event) => {
|
||||
const checkedProfiles = collectActiveProfilesFromInputs();
|
||||
if (!checkedProfiles.length) {
|
||||
event.target.checked = true;
|
||||
showError('❌ Mindestens ein Profil muss aktiv bleiben');
|
||||
return;
|
||||
}
|
||||
updateProfileActivationSummary();
|
||||
renderTestProfileOptions(document.getElementById('testProfileNumber')?.value || checkedProfiles[0]);
|
||||
});
|
||||
});
|
||||
|
||||
updateProfileActivationSummary();
|
||||
renderTestProfileOptions(document.getElementById('testProfileNumber')?.value || activeProfiles[0] || 1);
|
||||
}
|
||||
|
||||
async function loadProfileSettings() {
|
||||
const res = await apiFetch(`${API_URL}/profile-settings`);
|
||||
if (!res.ok) throw new Error('Failed to load profile settings');
|
||||
profileSettings = await res.json();
|
||||
profileSettings.active_profiles = normalizeActiveProfileNumbers(profileSettings.active_profiles);
|
||||
renderProfileActivationList();
|
||||
}
|
||||
|
||||
async function saveProfileSettings(event, { silent = false } = {}) {
|
||||
if (event && typeof event.preventDefault === 'function') {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
try {
|
||||
const activeProfiles = collectActiveProfilesFromInputs();
|
||||
if (!activeProfiles.length) {
|
||||
throw new Error('Mindestens ein Profil muss aktiv bleiben');
|
||||
}
|
||||
|
||||
const res = await apiFetch(`${API_URL}/profile-settings`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ active_profiles: activeProfiles })
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => null);
|
||||
throw new Error((err && err.error) || 'Fehler beim Speichern');
|
||||
}
|
||||
|
||||
profileSettings = await res.json();
|
||||
profileSettings.active_profiles = normalizeActiveProfileNumbers(profileSettings.active_profiles);
|
||||
renderProfileActivationList();
|
||||
if (!silent) {
|
||||
await loadProfileFriends();
|
||||
}
|
||||
window.dispatchEvent(new CustomEvent('profile-settings-updated', { detail: profileSettings }));
|
||||
if (!silent) {
|
||||
showSuccess('✅ Aktive Profile gespeichert');
|
||||
}
|
||||
return true;
|
||||
} catch (err) {
|
||||
if (!silent) {
|
||||
showError('❌ ' + err.message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// PROFILE FRIENDS
|
||||
// ============================================================================
|
||||
@@ -1353,10 +1497,11 @@ async function loadProfileFriends() {
|
||||
const list = document.getElementById('profileFriendsList');
|
||||
list.innerHTML = '';
|
||||
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
for (let i = 1; i <= MAX_PROFILES; i++) {
|
||||
const res = await apiFetch(`${API_URL}/profile-friends/${i}`);
|
||||
const data = await res.json();
|
||||
profileFriends[i] = data.friend_names || '';
|
||||
const isActive = normalizeActiveProfileNumbers(profileSettings.active_profiles).includes(i);
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.className = 'form-group';
|
||||
@@ -1365,7 +1510,7 @@ async function loadProfileFriends() {
|
||||
<input type="text" id="friends${i}" class="form-input"
|
||||
placeholder="z.B. Anna, Max, Lisa"
|
||||
value="${escapeHtml(profileFriends[i])}">
|
||||
<p class="form-help">Kommagetrennte Liste von Freundesnamen für Profil ${i}</p>
|
||||
<p class="form-help">Kommagetrennte Liste von Freundesnamen für Profil ${i}${isActive ? '' : ' (derzeit deaktiviert)'}</p>
|
||||
`;
|
||||
list.appendChild(div);
|
||||
|
||||
@@ -1406,7 +1551,7 @@ async function saveFriends(profileNumber, friendNames, { silent = false } = {})
|
||||
|
||||
async function saveAllFriends({ silent = false } = {}) {
|
||||
let success = true;
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
for (let i = 1; i <= MAX_PROFILES; i++) {
|
||||
const input = document.getElementById(`friends${i}`);
|
||||
if (!input) {
|
||||
continue;
|
||||
@@ -1533,12 +1678,19 @@ if (similarityForm) {
|
||||
}
|
||||
|
||||
// Initialize
|
||||
Promise.all([
|
||||
loadCredentials(),
|
||||
loadSettings(),
|
||||
loadHiddenSettings(),
|
||||
loadModerationSettings(),
|
||||
loadSimilaritySettings(),
|
||||
loadProfileFriends()
|
||||
]).catch(err => showError(err.message));
|
||||
(async () => {
|
||||
try {
|
||||
await Promise.all([
|
||||
loadCredentials(),
|
||||
loadSettings(),
|
||||
loadProfileSettings(),
|
||||
loadHiddenSettings(),
|
||||
loadModerationSettings(),
|
||||
loadSimilaritySettings()
|
||||
]);
|
||||
await loadProfileFriends();
|
||||
} catch (err) {
|
||||
showError(err.message);
|
||||
}
|
||||
})();
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user