Næste version

This commit is contained in:
2026-04-12 10:25:41 +02:00
parent b678787236
commit 57f3c913b4
18 changed files with 2690 additions and 458 deletions

View File

@@ -232,6 +232,25 @@ MIGRATIONS: dict[int, list[str]] = {
SELECT DISTINCT dance_name, level_id, 'local'
FROM song_dances WHERE dance_name IS NOT NULL AND dance_name != ''""",
],
3: [
"ALTER TABLE playlists ADD COLUMN tags TEXT NOT NULL DEFAULT ''",
],
4: [
"ALTER TABLE dances ADD COLUMN choreographer TEXT NOT NULL DEFAULT ''",
"ALTER TABLE dances ADD COLUMN video_url TEXT NOT NULL DEFAULT ''",
"ALTER TABLE dances ADD COLUMN stepsheet_url TEXT NOT NULL DEFAULT ''",
"ALTER TABLE dances ADD COLUMN notes TEXT NOT NULL DEFAULT ''",
],
5: [
# Workshop-markering på sang+dans kombination (ikke dans alene)
"""ALTER TABLE song_dances ADD COLUMN is_workshop INTEGER NOT NULL DEFAULT 0""",
"""ALTER TABLE song_alt_dances ADD COLUMN is_workshop INTEGER NOT NULL DEFAULT 0""",
],
6: [
# Workshop og dans-valg på selve playlist-sangen
"""ALTER TABLE playlist_songs ADD COLUMN is_workshop INTEGER NOT NULL DEFAULT 0""",
"""ALTER TABLE playlist_songs ADD COLUMN dance_override TEXT NOT NULL DEFAULT ''""",
],
}
@@ -283,11 +302,12 @@ def get_libraries(active_only: bool = True) -> list[sqlite3.Row]:
def remove_library(library_id: int):
with get_db() as conn:
# Marker sange som manglende
# Marker sange som manglende og løsriv dem fra biblioteket
conn.execute(
"UPDATE songs SET file_missing=1 WHERE library_id=?", (library_id,)
"UPDATE songs SET file_missing=1, library_id=NULL WHERE library_id=?",
(library_id,)
)
# Slet biblioteket helt
# Nu kan biblioteket slettes uden FK-konflikt
conn.execute("DELETE FROM libraries WHERE id=?", (library_id,))
@@ -452,20 +472,70 @@ def get_all_song_paths_for_library(library_id: int) -> dict[str, str]:
# ── Afspilningslister ─────────────────────────────────────────────────────────
def create_playlist(name: str, description: str = "") -> int:
def create_playlist(name: str, description: str = "", tags: str = "") -> int:
with get_db() as conn:
cur = conn.execute(
"INSERT INTO playlists (name, description) VALUES (?,?)",
(name, description)
"INSERT INTO playlists (name, description, tags) VALUES (?,?,?)",
(name, description, tags)
)
return cur.lastrowid
def get_playlists() -> list[sqlite3.Row]:
def update_playlist_tags(playlist_id: int, tags: str):
with get_db() as conn:
return conn.execute(
"SELECT * FROM playlists ORDER BY created_at DESC"
conn.execute(
"UPDATE playlists SET tags=? WHERE id=?",
(tags, playlist_id)
)
def get_all_playlist_tags() -> list[str]:
"""Returnerer alle unikke tags på tværs af alle playlists, sorteret alfabetisk."""
with get_db() as conn:
rows = conn.execute(
"SELECT tags FROM playlists WHERE tags != '' AND name != ?",
("__aktiv__",)
).fetchall()
tags = set()
for row in rows:
for tag in row["tags"].split(","):
t = tag.strip().lower()
if t:
tags.add(t)
return sorted(tags)
def get_playlists(tag_filter: str | None = None) -> list[sqlite3.Row]:
"""Hent alle navngivne playlists med sang-antal. Filtrer på tag hvis angivet."""
with get_db() as conn:
if tag_filter:
rows = conn.execute("""
SELECT p.*, COUNT(ps.id) as song_count
FROM playlists p
LEFT JOIN playlist_songs ps ON ps.playlist_id = p.id
WHERE p.name != ? AND (
p.tags LIKE ? OR p.tags LIKE ? OR
p.tags LIKE ? OR p.tags = ?
)
GROUP BY p.id
ORDER BY p.created_at DESC
""", (
"__aktiv__",
f"{tag_filter},%",
f"%, {tag_filter},%",
f"%, {tag_filter}",
tag_filter,
)).fetchall()
else:
rows = conn.execute("""
SELECT p.*, COUNT(ps.id) as song_count
FROM playlists p
LEFT JOIN playlist_songs ps ON ps.playlist_id = p.id
WHERE p.name != ?
GROUP BY p.id
ORDER BY p.created_at DESC
""", ("__aktiv__",)).fetchall()
return rows
def add_song_to_playlist(playlist_id: int, song_id: str, position: int | None = None) -> int:
@@ -554,6 +624,29 @@ def clear_event_state():
# ── Dans-entitet funktioner ───────────────────────────────────────────────────
def get_dance(dance_id: int) -> sqlite3.Row | None:
with get_db() as conn:
return conn.execute(
"SELECT * FROM dances WHERE id=?", (dance_id,)
).fetchone()
def update_dance_info(dance_id: int, choreographer: str = "",
video_url: str = "", stepsheet_url: str = "",
notes: str = ""):
with get_db() as conn:
conn.execute("""
UPDATE dances SET
choreographer = ?,
video_url = ?,
stepsheet_url = ?,
notes = ?
WHERE id = ?
""", (choreographer.strip(), video_url.strip(),
stepsheet_url.strip(), notes.strip(), dance_id))
def get_or_create_dance(name: str, level_id: int | None,
conn=None) -> int:
"""Find eller opret en dans (name + level_id kombination).
@@ -605,11 +698,12 @@ def get_dance_suggestions(prefix: str, limit: int = 20) -> list[dict]:
def get_dances_for_song(song_id: str) -> list[dict]:
"""Hent hoveddanse for en sang med niveau-info."""
"""Hent hoveddanse for en sang med niveau-info og workshop-flag."""
with get_db() as conn:
rows = conn.execute("""
SELECT d.id as dance_id, d.name, d.level_id,
dl.name as level_name, sd.dance_order, sd.id as song_dance_id
dl.name as level_name, sd.dance_order,
sd.id as song_dance_id, sd.is_workshop
FROM song_dances sd
JOIN dances d ON d.id = sd.dance_id
LEFT JOIN dance_levels dl ON dl.id = d.level_id