You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
472 lines
32 KiB
472 lines
32 KiB
{% extends "layout.html" %}
|
|
{% block main %}
|
|
|
|
<div class="bg-slate-900 min-h-screen py-8">
|
|
<div class="container mx-auto px-4 max-w-5xl">
|
|
<div class="flex flex-col md:flex-row justify-between items-end gap-4 mb-8">
|
|
<div>
|
|
<h1 class="text-3xl font-bold text-white mb-2">Settings</h1>
|
|
<p class="text-slate-400">Configure your platform credentials and video generation preferences.</p>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<button id="defaultSettingsBtn" type="button" class="btn btn-outline btn-sm text-slate-400 border-slate-700 hover:bg-slate-800">
|
|
Reset Defaults
|
|
</button>
|
|
<button form="settingsForm" type="submit" class="btn btn-indigo btn-sm bg-indigo-600 hover:bg-indigo-500 border-none text-white">
|
|
Save Changes
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<form id="settingsForm" action="/settings" method="post" novalidate>
|
|
<div class="grid grid-cols-1 lg:grid-cols-4 gap-8">
|
|
|
|
<!-- Navigation Tabs -->
|
|
<div class="lg:col-span-1">
|
|
<ul class="menu bg-slate-800/50 rounded-xl p-2 border border-white/5 sticky top-24" id="settingsTabs">
|
|
<li><a class="active flex gap-3 py-3" data-tab="platform"><i data-lucide="layout-template" class="w-4 h-4"></i> Platform</a></li>
|
|
<li><a class="flex gap-3 py-3" data-tab="content"><i data-lucide="file-text" class="w-4 h-4"></i> Content</a></li>
|
|
<li><a class="flex gap-3 py-3" data-tab="visuals"><i data-lucide="palette" class="w-4 h-4"></i> Visuals</a></li>
|
|
<li><a class="flex gap-3 py-3" data-tab="audio"><i data-lucide="volume-2" class="w-4 h-4"></i> Audio</a></li>
|
|
<li><a class="flex gap-3 py-3" data-tab="integration"><i data-lucide="share-2" class="w-4 h-4"></i> Integration</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Tab Content -->
|
|
<div class="lg:col-span-3 space-y-6">
|
|
|
|
<!-- Platform Tab -->
|
|
<div id="tab-platform" class="tab-pane">
|
|
<div class="card bg-slate-800 border border-white/5 shadow-xl">
|
|
<div class="card-body">
|
|
<h2 class="card-title text-white mb-6">Source Configuration</h2>
|
|
|
|
<div class="form-control w-full mb-8">
|
|
<label class="label"><span class="label-text text-slate-300 font-medium">Content Platform</span></label>
|
|
<select name="settings.platform" id="platformSelect" class="select select-bordered bg-slate-900 border-slate-700 focus:border-indigo-500">
|
|
<option value="reddit">Reddit</option>
|
|
<option value="threads">Threads (Meta)</option>
|
|
</select>
|
|
<label class="label"><span class="label-text-alt text-slate-500">Which social media platform to pull content from</span></label>
|
|
</div>
|
|
|
|
<!-- Reddit Section -->
|
|
<div class="platform-section space-y-6" data-platform="reddit">
|
|
<div class="divider text-slate-500 text-xs uppercase tracking-widest">Reddit Credentials</div>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Client ID</span></label>
|
|
<input name="reddit.creds.client_id" value="{{ data['reddit.creds.client_id'] }}" type="text" class="input input-bordered bg-slate-900 border-slate-700" placeholder="Your Client ID">
|
|
</div>
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Client Secret</span></label>
|
|
<input name="reddit.creds.client_secret" value="{{ data['reddit.creds.client_secret'] }}" type="text" class="input input-bordered bg-slate-900 border-slate-700" placeholder="Your Client Secret">
|
|
</div>
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Username</span></label>
|
|
<input name="reddit.creds.username" value="{{ data['reddit.creds.username'] }}" type="text" class="input input-bordered bg-slate-900 border-slate-700" placeholder="Reddit Username">
|
|
</div>
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Password</span></label>
|
|
<input name="reddit.creds.password" value="{{ data['reddit.creds.password'] }}" type="password" class="input input-bordered bg-slate-900 border-slate-700" placeholder="Reddit Password">
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center gap-4 bg-slate-900/50 p-4 rounded-lg border border-white/5">
|
|
<input name="reddit.creds.2fa" type="checkbox" class="toggle toggle-indigo" value="True">
|
|
<span class="text-sm text-slate-300">Enable 2FA Support</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Threads Section -->
|
|
<div class="platform-section space-y-6 hidden" data-platform="threads">
|
|
<div class="divider text-slate-500 text-xs uppercase tracking-widest">Threads Configuration</div>
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Discovery Method</span></label>
|
|
<select name="threads.discovery_method" class="select select-bordered bg-slate-900 border-slate-700">
|
|
<option value="api">API (Your own posts)</option>
|
|
<option value="scrape">Scrape (For You feed)</option>
|
|
</select>
|
|
</div>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Threads Username</span></label>
|
|
<input name="threads.creds.username" value="{{ data['threads.creds.username'] }}" type="text" class="input input-bordered bg-slate-900 border-slate-700" placeholder="Username">
|
|
</div>
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Threads Password</span></label>
|
|
<input name="threads.creds.password" value="{{ data['threads.creds.password'] }}" type="password" class="input input-bordered bg-slate-900 border-slate-700" placeholder="Password">
|
|
</div>
|
|
</div>
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Access Token</span></label>
|
|
<input name="threads.creds.access_token" value="{{ data['threads.creds.access_token'] }}" type="text" class="input input-bordered bg-slate-900 border-slate-700" placeholder="Long-lived Graph API Token">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Content Tab -->
|
|
<div id="tab-content" class="tab-pane hidden">
|
|
<div class="card bg-slate-800 border border-white/5 shadow-xl">
|
|
<div class="card-body space-y-6">
|
|
<h2 class="card-title text-white mb-2">Content Filtering</h2>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<!-- Reddit Options -->
|
|
<div class="platform-section space-y-4" data-platform="reddit">
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Target Subreddit</span></label>
|
|
<input name="reddit.thread.subreddit" value="{{ data['reddit.thread.subreddit'] }}" type="text" class="input input-bordered bg-slate-900 border-slate-700">
|
|
</div>
|
|
<div class="form-control">
|
|
<label class="label"><span class="label-text text-slate-400">Max Comment Length: <span class="val-display font-mono text-indigo-400"></span></span></label>
|
|
<input name="reddit.thread.max_comment_length" type="range" min="100" max="1000" step="50" class="range range-xs range-indigo" value="{{ data['reddit.thread.max_comment_length'] }}">
|
|
</div>
|
|
<div class="form-control">
|
|
<label class="label"><span class="label-text text-slate-400">Min Comments: <span class="val-display font-mono text-indigo-400"></span></span></label>
|
|
<input name="reddit.thread.min_comments" type="range" min="1" max="100" step="1" class="range range-xs range-indigo" value="{{ data['reddit.thread.min_comments'] }}">
|
|
</div>
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Blocked Words</span></label>
|
|
<input name="reddit.thread.blocked_words" value="{{ data['reddit.thread.blocked_words'] }}" type="text" class="input input-bordered bg-slate-900 border-slate-700" placeholder="nsfw, spoiler, politics">
|
|
<label class="label"><span class="label-text-alt text-slate-500">Comma-separated. Posts and comments matching these words are skipped.</span></label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Threads Options -->
|
|
<div class="platform-section hidden space-y-4" data-platform="threads">
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Search Queries</span></label>
|
|
<input name="threads.thread.search_queries" value="{{ data['threads.thread.search_queries'] }}" type="text" class="input input-bordered bg-slate-900 border-slate-700" placeholder="news,viral,stories">
|
|
</div>
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Max Reply Length: <span class="val-display font-mono text-indigo-400"></span></span></label>
|
|
<input name="threads.thread.max_reply_length" type="range" min="100" max="1000" step="50" class="range range-xs range-indigo" value="{{ data['threads.thread.max_reply_length'] }}">
|
|
</div>
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Min Replies: <span class="val-display font-mono text-indigo-400"></span></span></label>
|
|
<input name="threads.thread.min_replies" type="range" min="1" max="50" step="1" class="range range-xs range-indigo" value="{{ data['threads.thread.min_replies'] }}">
|
|
</div>
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Blocked Words</span></label>
|
|
<input name="threads.thread.blocked_words" value="{{ data['threads.thread.blocked_words'] }}" type="text" class="input input-bordered bg-slate-900 border-slate-700" placeholder="nsfw, spoiler, politics">
|
|
<label class="label"><span class="label-text-alt text-slate-500">Comma-separated. Posts and replies matching these words are skipped.</span></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="divider border-white/5">General</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div class="flex items-center gap-4 bg-slate-900/50 p-4 rounded-lg border border-white/5">
|
|
<input name="settings.allow_nsfw" type="checkbox" class="toggle toggle-error" value="True">
|
|
<span class="text-sm text-slate-300">Allow NSFW Content</span>
|
|
</div>
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400 font-medium">Videos to generate: <span class="val-display font-mono text-indigo-400"></span></span></label>
|
|
<input name="settings.times_to_run" type="range" min="1" max="50" step="1" class="range range-xs range-indigo" value="{{ data['settings.times_to_run'] }}">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Visuals Tab -->
|
|
<div id="tab-visuals" class="tab-pane hidden">
|
|
<div class="card bg-slate-800 border border-white/5 shadow-xl">
|
|
<div class="card-body space-y-6">
|
|
<h2 class="card-title text-white">Visual Styling</h2>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div class="form-control">
|
|
<label class="label"><span class="label-text text-slate-400">Screenshot Theme</span></label>
|
|
<select name="settings.theme" class="select select-bordered bg-slate-900 border-slate-700">
|
|
<option value="dark">Dark</option>
|
|
<option value="light">Light</option>
|
|
<option value="transparent">Transparent</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-control">
|
|
<label class="label"><span class="label-text text-slate-400">Comment Opacity: <span class="val-display font-mono text-indigo-400"></span></span></label>
|
|
<input name="settings.opacity" type="range" min="0" max="1" step="0.05" class="range range-xs range-indigo" value="{{ data['settings.opacity'] }}">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="divider border-white/5">Backgrounds</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400 font-medium">Video Background</span></label>
|
|
<select name="settings.background.background_video" class="select select-bordered bg-slate-900 border-slate-700">
|
|
{% for background in checks["settings.background.background_video"]["options"] %}
|
|
<option value="{{background}}">{{ background or 'Random' }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
<label class="label"><a href="/backgrounds" target="_blank" class="label-text-alt text-indigo-400 hover:text-indigo-300">Manage video files →</a></label>
|
|
</div>
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400 font-medium">Audio Track</span></label>
|
|
<select name="settings.background.background_audio" class="select select-bordered bg-slate-900 border-slate-700">
|
|
{% for audio in checks["settings.background.background_audio"]["options"] %}
|
|
<option value="{{audio}}">{{ audio or 'None' }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex items-center gap-4 bg-slate-900/50 p-4 rounded-lg border border-white/5">
|
|
<input name="settings.background.background_thumbnail" type="checkbox" class="toggle toggle-indigo" value="True">
|
|
<span class="text-sm text-slate-300">Generate Thumbnail overlay</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Audio Tab -->
|
|
<div id="tab-audio" class="tab-pane hidden">
|
|
<div class="card bg-slate-800 border border-white/5 shadow-xl">
|
|
<div class="card-body space-y-6">
|
|
<h2 class="card-title text-white">Voice & Speech</h2>
|
|
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400 font-medium">TTS Provider</span></label>
|
|
<select name="settings.tts.voice_choice" id="voiceChoiceSelect" class="select select-bordered bg-slate-900 border-slate-700">
|
|
<option value="streamlabspolly">Streamlabs Polly (Free)</option>
|
|
<option value="tiktok">TikTok</option>
|
|
<option value="googletranslate">Google Translate</option>
|
|
<option value="awspolly">AWS Polly</option>
|
|
<option value="elevenlabs">ElevenLabs</option>
|
|
<option value="OpenAI">OpenAI</option>
|
|
<option value="pyttsx">System Voice (pyttsx)</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div class="form-control">
|
|
<label class="label"><span class="label-text text-slate-400">Silence between comments: <span class="val-display font-mono text-indigo-400"></span>s</span></label>
|
|
<input name="settings.tts.silence_duration" type="range" min="0" max="5" step="0.1" class="range range-xs range-indigo" value="{{ data['settings.tts.silence_duration'] }}">
|
|
</div>
|
|
<div class="flex flex-col gap-3 justify-center">
|
|
<div class="flex items-center gap-4">
|
|
<input name="settings.tts.random_voice" type="checkbox" class="toggle toggle-indigo" value="True">
|
|
<span class="text-sm text-slate-300">Randomize voices</span>
|
|
</div>
|
|
<div class="flex items-center gap-4">
|
|
<input name="settings.tts.no_emojis" type="checkbox" class="toggle toggle-indigo" value="True">
|
|
<span class="text-sm text-slate-300">Strip emojis</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="divider border-white/5">API Credentials</div>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div class="form-control">
|
|
<label class="label"><span class="label-text text-slate-500">ElevenLabs Key</span></label>
|
|
<input name="settings.tts.elevenlabs_api_key" value="{{ data['settings.tts.elevenlabs_api_key'] }}" type="password" class="input input-bordered input-sm bg-slate-900 border-slate-700">
|
|
</div>
|
|
<div class="form-control">
|
|
<label class="label"><span class="label-text text-slate-500">OpenAI Key</span></label>
|
|
<input name="settings.tts.openai_api_key" value="{{ data['settings.tts.openai_api_key'] }}" type="password" class="input input-bordered input-sm bg-slate-900 border-slate-700">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Integration Tab -->
|
|
<div id="tab-integration" class="tab-pane hidden">
|
|
<div class="card bg-slate-800 border border-white/5 shadow-xl">
|
|
<div class="card-body space-y-6">
|
|
<h2 class="card-title text-white">YouTube Integration</h2>
|
|
|
|
<div class="flex items-center gap-4 bg-slate-900/50 p-4 rounded-lg border border-white/5">
|
|
<input name="youtube.enabled" type="checkbox" class="toggle toggle-success" value="True">
|
|
<span class="text-sm text-slate-300 font-medium">Auto-upload after rendering</span>
|
|
</div>
|
|
|
|
<div class="form-control w-full">
|
|
<label class="label"><span class="label-text text-slate-400">Client Secret Path</span></label>
|
|
<input name="youtube.client_secret_path" value="{{ data['youtube.client_secret_path'] }}" type="text" class="input input-bordered bg-slate-900 border-slate-700" placeholder="path/to/secret.json">
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
<div class="form-control">
|
|
<label class="label"><span class="label-text text-slate-400">Privacy</span></label>
|
|
<select name="youtube.privacy" class="select select-bordered bg-slate-900 border-slate-700">
|
|
<option value="public">Public</option>
|
|
<option value="private">Private</option>
|
|
<option value="unlisted">Unlisted</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-control col-span-2">
|
|
<label class="label"><span class="label-text text-slate-400">Tags (comma-separated)</span></label>
|
|
<input name="youtube.tags" value="{{ data['youtube.tags'] }}" type="text" class="input input-bordered bg-slate-900 border-slate-700" placeholder="shorts, reddit, viral">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
const data = {{ data | tojson | safe }};
|
|
const validateChecks = {{ checks | tojson | safe }};
|
|
const form = document.getElementById('settingsForm');
|
|
|
|
// ---- Tab Switching -------------------------------------------------
|
|
const tabs = document.querySelectorAll('#settingsTabs a');
|
|
const panes = document.querySelectorAll('.tab-pane');
|
|
|
|
tabs.forEach(tab => {
|
|
tab.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
const target = tab.dataset.tab;
|
|
|
|
tabs.forEach(t => t.classList.remove('active'));
|
|
tab.classList.add('active');
|
|
|
|
panes.forEach(p => p.classList.toggle('hidden', p.id !== `tab-${target}`));
|
|
});
|
|
});
|
|
|
|
// ---- Form Initialization -------------------------------------------
|
|
// Set values for all inputs based on the flattened data object
|
|
form.querySelectorAll('input, select, textarea').forEach(input => {
|
|
const name = input.name;
|
|
if (data[name] !== undefined) {
|
|
if (input.type === 'checkbox') {
|
|
input.checked = (data[name] === "True" || data[name] === true);
|
|
} else {
|
|
input.value = data[name];
|
|
}
|
|
}
|
|
|
|
// Trigger input events for range displays
|
|
if (input.type === 'range') {
|
|
updateRangeDisplay(input);
|
|
input.addEventListener('input', () => updateRangeDisplay(input));
|
|
}
|
|
});
|
|
|
|
function updateRangeDisplay(input) {
|
|
const display = input.closest('.form-control')?.querySelector('.val-display');
|
|
if (display) display.textContent = input.value;
|
|
}
|
|
|
|
// ---- Platform Visibility -------------------------------------------
|
|
const platformSelect = document.getElementById('platformSelect');
|
|
function applyPlatformVisibility() {
|
|
const current = platformSelect.value || "reddit";
|
|
document.querySelectorAll('.platform-section').forEach(section => {
|
|
const matches = section.dataset.platform === current;
|
|
section.classList.toggle('hidden', !matches);
|
|
section.querySelectorAll('input, select, textarea').forEach(el => el.disabled = !matches);
|
|
});
|
|
}
|
|
platformSelect.addEventListener('change', applyPlatformVisibility);
|
|
applyPlatformVisibility();
|
|
|
|
// ---- Validation ----------------------------------------------------
|
|
function validateInput(input) {
|
|
const check = validateChecks[input.name];
|
|
if (!check) return true;
|
|
|
|
let value = input.value;
|
|
let isValid = true;
|
|
|
|
// Optional/Empty check
|
|
if (value.length === 0) {
|
|
isValid = !!check.optional;
|
|
} else {
|
|
// Type specific checks
|
|
if (check.type === 'int' || check.type === 'float') {
|
|
const num = parseFloat(value);
|
|
if (check.nmin !== undefined && num < check.nmin) isValid = false;
|
|
if (check.nmax !== undefined && num > check.nmax) isValid = false;
|
|
} else {
|
|
if (check.nmin !== undefined && value.length < check.nmin) isValid = false;
|
|
if (check.nmax !== undefined && value.length > check.nmax) isValid = false;
|
|
}
|
|
|
|
// Regex check
|
|
if (isValid && check.regex) {
|
|
const re = new RegExp(check.regex);
|
|
if (!re.test(value)) isValid = false;
|
|
}
|
|
}
|
|
|
|
input.classList.toggle('input-error', !isValid);
|
|
input.classList.toggle('select-error', !isValid && input.tagName === 'SELECT');
|
|
return isValid;
|
|
}
|
|
|
|
form.querySelectorAll('input, select').forEach(input => {
|
|
input.addEventListener('change', () => validateInput(input));
|
|
if (input.tagName === 'INPUT') input.addEventListener('keyup', () => validateInput(input));
|
|
});
|
|
|
|
// ---- Submit Logic --------------------------------------------------
|
|
form.addEventListener('submit', (e) => {
|
|
let formIsValid = true;
|
|
const enabledInputs = form.querySelectorAll('input:not(:disabled), select:not(:disabled)');
|
|
|
|
enabledInputs.forEach(input => {
|
|
if (!validateInput(input)) {
|
|
formIsValid = false;
|
|
// Switch to the tab containing the error
|
|
const pane = input.closest('.tab-pane');
|
|
if (pane) {
|
|
const tabBtn = document.querySelector(`[data-tab="${pane.id.replace('tab-', '')}"]`);
|
|
if (tabBtn) tabBtn.click();
|
|
}
|
|
}
|
|
});
|
|
|
|
if (!formIsValid) {
|
|
e.preventDefault();
|
|
return;
|
|
}
|
|
|
|
// Handle un-checked checkboxes (ensure they submit "False")
|
|
form.querySelectorAll('input[type="checkbox"]:not(:disabled)').forEach(cb => {
|
|
if (!cb.checked) {
|
|
const hidden = document.createElement('input');
|
|
hidden.type = 'hidden';
|
|
hidden.name = cb.name;
|
|
hidden.value = 'False';
|
|
form.appendChild(hidden);
|
|
}
|
|
});
|
|
});
|
|
|
|
// ---- Defaults ------------------------------------------------------
|
|
document.getElementById('defaultSettingsBtn').addEventListener('click', () => {
|
|
if (!confirm('Are you sure you want to reset visible settings to defaults?')) return;
|
|
|
|
form.querySelectorAll('input:not(:disabled), select:not(:disabled)').forEach(input => {
|
|
const check = validateChecks[input.name];
|
|
if (check && check.default !== undefined) {
|
|
if (input.type === 'checkbox') {
|
|
input.checked = (check.default === "True" || check.default === true);
|
|
} else {
|
|
input.value = check.default;
|
|
}
|
|
if (input.type === 'range') updateRangeDisplay(input);
|
|
validateInput(input);
|
|
}
|
|
});
|
|
});
|
|
|
|
lucide.createIcons();
|
|
});
|
|
</script>
|
|
|
|
{% endblock %}
|