slette lister

This commit is contained in:
2026-04-19 13:43:11 +02:00
parent bf26ff6377
commit e149fb3ce2
5 changed files with 80 additions and 32 deletions

View File

@@ -71,11 +71,12 @@ class PlaylistData(BaseModel):
songs: list[PlaylistSongData] = []
class PushPayload(BaseModel):
songs: list[SongData] = []
dances: list[DanceData] = []
song_dances: list[SongDanceData] = []
song_alts: list[SongAltDanceData] = []
playlists: list[PlaylistData] = []
songs: list[SongData] = []
dances: list[DanceData] = []
song_dances: list[SongDanceData] = []
song_alts: list[SongAltDanceData] = []
playlists: list[PlaylistData] = []
deleted_playlists: list[str] = [] # navne på slettede playlister
# ── Push ──────────────────────────────────────────────────────────────────────
@@ -206,8 +207,9 @@ def push(
if existing:
existing.description = pl.description
existing.visibility = pl.visibility
# Slet og geninsert sange
db.query(ProjectSong).filter_by(project_id=existing.id).delete()
# Opdater kun sange hvis push faktisk har sange med
if pl.songs:
db.query(ProjectSong).filter_by(project_id=existing.id).delete()
project = existing
else:
project = Project(
@@ -238,6 +240,13 @@ def push(
)
db.add(proj_song)
# ── Slet playlister der er fjernet lokalt ─────────────────────────────────
for name in payload.deleted_playlists:
proj = db.query(Project).filter_by(owner_id=me.id, name=name).first()
if proj:
db.query(ProjectSong).filter_by(project_id=proj.id).delete()
db.delete(proj)
db.commit()
return {

View File

@@ -301,6 +301,14 @@ MIGRATIONS: dict[int, list[str]] = {
"INSERT INTO dance_levels (sort_order, name, description) VALUES (90, 'High Intermediate', 'Stærk intermediate')",
"INSERT INTO dance_levels (sort_order, name, description) VALUES (99, 'Advanced', 'Fuld beherskelse af trin og teknik')",
],
12: [
# Tabel til at huske slettede playlister — til sync med serveren
"""CREATE TABLE IF NOT EXISTS deleted_playlists (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
deleted_at TEXT NOT NULL DEFAULT (datetime('now'))
)""",
],
}

View File

@@ -57,6 +57,12 @@ class SyncManager:
logger.info(f"Push OK: {len(payload['songs'])} sange")
result = self._post("/sync/push", payload)
self._save_playlist_ids(result.get("playlist_id_map", {}))
# Ryd deleted_playlists nu de er sendt til serveren
if payload.get("deleted_playlists"):
conn = sqlite3.connect(self._db_path)
conn.execute("DELETE FROM deleted_playlists")
conn.commit()
conn.close()
logger.info(f"Push OK: {result.get('songs_synced', '?')} sange synkroniseret")
if on_done:
on_done(result)
@@ -99,19 +105,24 @@ class SyncManager:
threading.Thread(target=_run, daemon=True).start()
def push_and_pull(self, on_done=None, on_error=None):
"""Push og derefter pull i samme tråd."""
"""Pull FØR push — server er sandhed for playlister."""
def _run():
try:
# 1. Pull FØR push — hent server-data ned lokalt
pull_result = self._get("/sync/pull")
self._apply_pull(pull_result)
# 2. Push lokal data op (sange, danse, dans-tags)
# — playlister der kom fra serveren pushes IKKE
payload = self._build_push_payload()
push_result = self._post("/sync/push", payload)
pull_result = self._get("/sync/pull")
pl_count = len(pull_result.get("my_playlists", []))
logger.info(
f"Sync OK — {len(payload['songs'])} sange, "
f"{len(payload['playlists'])} playlister, "
f"{pl_count} server-playlister"
)
self._apply_pull(pull_result)
if on_done:
on_done({"push": push_result, "pull": pull_result})
except Exception as e:
@@ -190,11 +201,11 @@ class SyncManager:
"note": row["note"] or "",
})
# Playlister (kun navngivne — ikke __aktiv__)
# Playlister (kun lokalt oprettede — IKKE dem der kom fra serveren)
playlists = []
for pl in conn.execute(
"SELECT id, name, description, tags FROM playlists "
"WHERE name != '__aktiv__'"
"SELECT id, name, description, tags, api_project_id FROM playlists "
"WHERE name != '__aktiv__' AND (api_project_id IS NULL OR api_project_id = '')"
).fetchall():
pl_songs = []
for ps in conn.execute("""
@@ -222,13 +233,21 @@ class SyncManager:
"songs": pl_songs,
})
# Slettede playlister — skal fjernes fra serveren
deleted = [
row["name"] for row in conn.execute(
"SELECT name FROM deleted_playlists"
).fetchall()
]
conn.close()
return {
"songs": songs,
"dances": dances,
"song_dances": song_dances,
"song_alts": song_alts,
"playlists": playlists,
"songs": songs,
"dances": dances,
"song_dances": song_dances,
"song_alts": song_alts,
"playlists": playlists,
"deleted_playlists": deleted,
}
# ── Anvend pull ───────────────────────────────────────────────────────────
@@ -255,42 +274,44 @@ class SyncManager:
""", (d.get("choreographer",""), d.get("video_url",""),
d.get("stepsheet_url",""), existing["id"]))
# Importer egne playlister fra server hvis de ikke findes lokalt
# Importer/opdater egne playlister fra server — server er sandhed
for pl in data.get("my_playlists", []):
server_id = pl.get("server_id")
name = pl.get("name", "")
if not server_id or not name:
continue
# Tjek om listen allerede eksisterer lokalt
existing = conn.execute(
"SELECT id FROM playlists WHERE api_project_id=?", (server_id,)
).fetchone()
if existing:
continue # Allerede importeret — spring over
pl_id = existing["id"]
# Opdater navn hvis det er ændret på serveren
conn.execute(
"UPDATE playlists SET name=? WHERE id=?", (name, pl_id)
)
else:
cur = conn.execute(
"INSERT INTO playlists (name, description, api_project_id, is_linked, server_permission) "
"VALUES (?,?,?,1,'edit')",
(name, pl.get("description",""), server_id)
)
pl_id = cur.lastrowid
# Opret liste
cur = conn.execute(
"INSERT INTO playlists (name, description, api_project_id, is_linked, server_permission) "
"VALUES (?,?,?,1,'edit')",
(name, pl.get("description",""), server_id)
)
pl_id = cur.lastrowid
# Indsæt sange — opret dem lokalt hvis de ikke findes endnu
# Genindlæs sange fra serveren — server er sandhed
conn.execute("DELETE FROM playlist_songs WHERE playlist_id=?", (pl_id,))
position = 1
for song_data in pl.get("songs", []):
title = song_data.get("title", "")
artist = song_data.get("artist", "")
if not title:
continue
# Find sangen lokalt
local = conn.execute(
"SELECT id FROM songs WHERE title=? AND artist=? LIMIT 1",
(title, artist)
).fetchone()
if not local:
# Opret som file_missing=1 — kobles til rigtig fil ved næste scan
import uuid
new_id = str(uuid.uuid4())
conn.execute(

View File

@@ -372,6 +372,12 @@ class MainWindow(QMainWindow):
self._sync_debounce.setInterval(5000)
self._sync_debounce.timeout.connect(self._auto_sync)
# Periodisk sync — kører hvert 10. minut
self._sync_periodic = QTimer(self)
self._sync_periodic.setInterval(10 * 60 * 1000)
self._sync_periodic.timeout.connect(self._manual_sync)
self._sync_periodic.start()
self._library_panel = LibraryPanel()
self._library_panel.set_preview_player(self._preview_player)

View File

@@ -180,6 +180,10 @@ class PlaylistManagerDialog(QDialog):
try:
from local.local_db import get_db
with get_db() as conn:
conn.execute(
"INSERT INTO deleted_playlists (name) "
"SELECT name FROM playlists WHERE id=?", (pl["id"],)
)
conn.execute("DELETE FROM playlists WHERE id=?", (pl["id"],))
self._load_saved_playlists()
except Exception as e: