added standard-theme function
This commit is contained in:
parent
a027cf8c1c
commit
b5f0146cc4
@ -6,7 +6,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
from flask import Blueprint, render_template, request, jsonify, redirect, url_for, current_app
|
from flask import Blueprint, render_template, request, jsonify, redirect, url_for, current_app
|
||||||
from app.state import current_config
|
from app.state import current_config
|
||||||
from app.utils.helpers import load_configs, load_default_sounds, load_soundboard_configs
|
from app.utils.helpers import load_configs, load_default_sounds, load_soundboard_configs, write_default_theme
|
||||||
|
|
||||||
admin_bp = Blueprint('admin', __name__)
|
admin_bp = Blueprint('admin', __name__)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -210,8 +210,23 @@ def admin_create_theme():
|
|||||||
}
|
}
|
||||||
with open(path, 'w', encoding='utf-8') as f:
|
with open(path, 'w', encoding='utf-8') as f:
|
||||||
json.dump(template, f, ensure_ascii=False, indent=2)
|
json.dump(template, f, ensure_ascii=False, indent=2)
|
||||||
logger.info(f"Neues Theme angelegt: {os.path.relpath(path, base_dir)}")
|
logger.info(f"Neues Theme angelegt: {os.path.relpath(path, base_dir)}")
|
||||||
return jsonify({"success": True, "path": os.path.relpath(path, base_dir)})
|
return jsonify({"success": True, "path": os.path.relpath(path, base_dir)})
|
||||||
|
|
||||||
|
|
||||||
|
@admin_bp.route('/set_default_theme', methods=['POST'])
|
||||||
|
def admin_set_default_theme():
|
||||||
|
data = request.get_json(force=True, silent=True) or {}
|
||||||
|
filename = data.get('filename')
|
||||||
|
if not filename:
|
||||||
|
return jsonify({"success": False, "message": "filename fehlt"}), 400
|
||||||
|
try:
|
||||||
|
write_default_theme(current_app.config['DEFAULT_THEME_FILE'], filename)
|
||||||
|
logger.info(f"Default-Theme gesetzt: {filename}")
|
||||||
|
return jsonify({"success": True, "filename": filename})
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception("Default-Theme setzen fehlgeschlagen")
|
||||||
|
return jsonify({"success": False, "message": str(e)}), 500
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception("create_theme fehlgeschlagen")
|
logger.exception("create_theme fehlgeschlagen")
|
||||||
return jsonify({"success": False, "message": str(e)}), 500
|
return jsonify({"success": False, "message": str(e)}), 500
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from flask import Blueprint, jsonify, request, current_app
|
|||||||
|
|
||||||
import app.state as state
|
import app.state as state
|
||||||
from app.bluetooth.manager import MouldKing, advertiser, tracer
|
from app.bluetooth.manager import MouldKing, advertiser, tracer
|
||||||
from app.utils.helpers import load_default_sounds, load_soundboard_configs, load_soundboard_config
|
from app.utils.helpers import load_default_sounds, load_soundboard_configs, load_soundboard_config, read_default_theme
|
||||||
from config import Config
|
from config import Config
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -451,6 +451,26 @@ def api_soundboard_load():
|
|||||||
return jsonify({"success": False, "message": str(e)}), 500
|
return jsonify({"success": False, "message": str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
|
@api_bp.route('/soundboard/load_default', methods=['POST'])
|
||||||
|
def api_soundboard_load_default():
|
||||||
|
# Lädt das Standard-Theme, falls gesetzt und noch kein Soundboard aktiv ist
|
||||||
|
try:
|
||||||
|
if state.current_soundboard:
|
||||||
|
return jsonify({"success": True, "soundboard": state.current_soundboard, "already_loaded": True})
|
||||||
|
default_file = read_default_theme(Config.DEFAULT_THEME_FILE)
|
||||||
|
if not default_file:
|
||||||
|
return jsonify({"success": False, "message": "Kein Standard-Theme gesetzt"}), 404
|
||||||
|
sb = load_soundboard_config(default_file,
|
||||||
|
current_app.config['SOUNDBOARD_CONFIG_DIR'],
|
||||||
|
current_app.config['SOUNDS_DIR'])
|
||||||
|
state.current_soundboard = sb
|
||||||
|
logger.info(f"Standard-Soundboard geladen: {default_file}")
|
||||||
|
return jsonify({"success": True, "soundboard": sb, "default_loaded": True})
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception("Standard-Soundboard laden fehlgeschlagen")
|
||||||
|
return jsonify({"success": False, "message": str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
@api_bp.route('/soundboard/play_random', methods=['POST'])
|
@api_bp.route('/soundboard/play_random', methods=['POST'])
|
||||||
def api_soundboard_play_random():
|
def api_soundboard_play_random():
|
||||||
if state.current_soundboard is None:
|
if state.current_soundboard is None:
|
||||||
|
|||||||
@ -144,3 +144,20 @@ def load_soundboard_config(filename, config_dir, sounds_dir=None):
|
|||||||
for item in data[key]:
|
for item in data[key]:
|
||||||
item.setdefault('base_path', base_sound_dir)
|
item.setdefault('base_path', base_sound_dir)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def read_default_theme(path):
|
||||||
|
try:
|
||||||
|
if not os.path.exists(path):
|
||||||
|
return None
|
||||||
|
with open(path, 'r', encoding='utf-8') as f:
|
||||||
|
val = f.read().strip()
|
||||||
|
return val or None
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def write_default_theme(path, filename):
|
||||||
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||||
|
with open(path, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(filename)
|
||||||
|
|||||||
@ -13,6 +13,7 @@ class Config:
|
|||||||
LOG_DIR = os.path.join(BASE_DIR, 'logs')
|
LOG_DIR = os.path.join(BASE_DIR, 'logs')
|
||||||
SOUNDS_DIR = os.path.join(BASE_DIR, 'sounds')
|
SOUNDS_DIR = os.path.join(BASE_DIR, 'sounds')
|
||||||
SOUNDBOARD_CONFIG_DIR = os.path.join(BASE_DIR, 'soundboards')
|
SOUNDBOARD_CONFIG_DIR = os.path.join(BASE_DIR, 'soundboards')
|
||||||
|
DEFAULT_THEME_FILE = os.path.join(SOUNDBOARD_CONFIG_DIR, 'default_theme.txt')
|
||||||
|
|
||||||
# Audio-Parameter (für pygame.mixer)
|
# Audio-Parameter (für pygame.mixer)
|
||||||
AUDIO_FREQ = 44100
|
AUDIO_FREQ = 44100
|
||||||
|
|||||||
@ -84,6 +84,10 @@
|
|||||||
class="btn btn-sm btn-primary">
|
class="btn btn-sm btn-primary">
|
||||||
<i class="bi bi-pencil"></i> Bearbeiten
|
<i class="bi bi-pencil"></i> Bearbeiten
|
||||||
</a>
|
</a>
|
||||||
|
<button class="btn btn-sm btn-outline-success set-default-theme-btn"
|
||||||
|
data-filename="{{ sb.filename }}">
|
||||||
|
Als Standard setzen
|
||||||
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -252,5 +256,26 @@
|
|||||||
alert('Fehler: ' + e.message);
|
alert('Fehler: ' + e.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Standard-Theme setzen
|
||||||
|
document.querySelectorAll('.set-default-theme-btn').forEach(btn => {
|
||||||
|
btn.addEventListener('click', async () => {
|
||||||
|
const filename = btn.dataset.filename;
|
||||||
|
try {
|
||||||
|
const res = await fetch('/admin/set_default_theme', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ filename })
|
||||||
|
});
|
||||||
|
const text = await res.text();
|
||||||
|
let json;
|
||||||
|
try { json = JSON.parse(text); } catch (_) { throw new Error('Serverantwort ist kein JSON:\n'+text); }
|
||||||
|
if (!json.success) throw new Error(json.message || 'Fehler');
|
||||||
|
alert('Standard-Theme gesetzt: ' + filename);
|
||||||
|
} catch (e) {
|
||||||
|
alert('Fehler: ' + e.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@ -288,14 +288,18 @@
|
|||||||
// Reihenfolge: Status prüfen, dann ggf. Theme laden
|
// Reihenfolge: Status prüfen, dann ggf. Theme laden
|
||||||
(async () => {
|
(async () => {
|
||||||
await updateAutoStatus();
|
await updateAutoStatus();
|
||||||
|
// Wenn noch kein Theme aktiv ist, versuche Standard-Theme zu laden
|
||||||
|
const statusRes = await fetch('/api/soundboard/status');
|
||||||
|
const statusData = await statusRes.json();
|
||||||
|
if (!statusData.active && !statusData.current_theme) {
|
||||||
|
await fetch('/api/soundboard/load_default', { method: 'POST' });
|
||||||
|
}
|
||||||
if (selectEl && selectEl.value) {
|
if (selectEl && selectEl.value) {
|
||||||
// Wenn bereits ein Theme aktiv ist, nicht erneut laden (würde Auto stoppen)
|
const statusRes2 = await fetch('/api/soundboard/status');
|
||||||
const statusRes = await fetch('/api/soundboard/status');
|
const statusData2 = await statusRes2.json();
|
||||||
const statusData = await statusRes.json();
|
if (!statusData2.active || statusData2.current_theme !== selectEl.value) {
|
||||||
if (!statusData.active || statusData.current_theme !== selectEl.value) {
|
|
||||||
loadSoundboard(selectEl.value);
|
loadSoundboard(selectEl.value);
|
||||||
} else {
|
} else {
|
||||||
// Theme-Daten nachladen ohne Auto zu stoppen
|
|
||||||
const cur = await fetch('/api/soundboard/current');
|
const cur = await fetch('/api/soundboard/current');
|
||||||
const curData = await cur.json();
|
const curData = await cur.json();
|
||||||
if (curData.soundboard) {
|
if (curData.soundboard) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user