feat: add web dashboard with slide-in drawer navigation

- Flask backend with 23 API routes (entertainment, telegram, docker, system)
- Alpine.js + Tailwind CSS dark-mode SPA with 4 tabs
- pos-dashboard CLI tool with port/config management
- Mobile slide-in drawer with swipe-to-close
- Sticky header stays pinned on scroll
- Tab completion fixes for category-less tools
- POST /api/telegram/commands endpoint for adding commands
This commit is contained in:
Your Name
2026-08-18 11:54:41 -04:00
parent 06b077db40
commit 99085adc76
63 changed files with 5905 additions and 122852 deletions
+20 -8
View File
@@ -34,20 +34,21 @@ config_value() {
}
write_config_key() {
local key="$1" val="$2" tmp
local key="$1" val="$2" tmp _esc_key
val="${val//$'\r'/}"
val="${val%%$'\n'*}"
_esc_key="$(printf '%s' "$key" | sed 's/[.[\*^$()+?{|]/\\&/g')"
mkdir -p "$CONFIG_DIR"
if [ "$val" = "-" ]; then
[ -f "$CONFIG_FILE" ] || return 0
tmp="$(mktemp)"
grep -v "^${key}=" "$CONFIG_FILE" >"$tmp" || true
grep -v "^${_esc_key}=" "$CONFIG_FILE" >"$tmp" || true
mv "$tmp" "$CONFIG_FILE"
chmod 600 "$CONFIG_FILE"
return 0
fi
tmp="$(mktemp)"
grep -v "^${key}=" "$CONFIG_FILE" 2>/dev/null >"$tmp" || true
grep -v "^${_esc_key}=" "$CONFIG_FILE" 2>/dev/null >"$tmp" || true
printf '%s="%s"\n' "$key" "$val" >>"$tmp"
mv "$tmp" "$CONFIG_FILE"
chmod 600 "$CONFIG_FILE"
@@ -164,7 +165,12 @@ parse_enabled() {
[ -n "$cur" ] && ENABLED_ENTRIES+=("$cur")
cur="$token"
elif [ -n "$cur" ]; then
cur="$cur,$token"
# Token is not a plugin name — check if it looks like a valid interval
if [[ "$token" =~ ^[0-9]+[mhd]$ ]] || [[ "$token" =~ ^(hourly|daily|weekly)$ ]]; then
cur="$cur,$token"
else
warn "skipping unknown token '$token' in ENABLED (not a plugin or interval)"
fi
fi
done
[ -n "$cur" ] && ENABLED_ENTRIES+=("$cur")
@@ -187,7 +193,7 @@ enabled_upsert() {
local plugin="$1" interval="${2:-}" raw entry p
raw="$(config_value ENABLED)"
local -a out=() found=0
[ -n "$raw" ] && parse_enabled "$raw"
parse_enabled "$raw"
for entry in "${ENABLED_ENTRIES[@]}"; do
p="${entry%%,*}"
if [ "$p" = "$plugin" ]; then
@@ -209,13 +215,19 @@ enabled_remove() {
local plugin="$1" raw entry p
raw="$(config_value ENABLED)"
local -a out=()
[ -n "$raw" ] && parse_enabled "$raw"
parse_enabled "$raw"
for entry in "${ENABLED_ENTRIES[@]}"; do
p="${entry%%,*}"
[ "$p" = "$plugin" ] && continue
out+=("$entry")
done
write_config_key ENABLED "$(render_enabled "${out[@]}")"
local result
result="$(render_enabled "${out[@]}")"
if [ -n "$result" ]; then
write_config_key ENABLED "$result"
else
write_config_key ENABLED "-"
fi
}
# ── systemd user timers ───────────────────────────────────────────
@@ -232,7 +244,7 @@ sync_timers() {
# ── Backend: systemd user timers ─────────────────────────────────
sync_systemd() {
local raw entry plugin oncal
local raw entry plugin oncal interval
raw="$(config_value ENABLED)"
parse_enabled "$raw"