feat(web): Library Management — manual album import (drag-and-drop)
Second Library Management feature. An "Add album" button on the Library page opens a modal: drag-drop (or pick) the audio files (+ optional cover image), enter artist/album/year, and Lyra writes the album into the library. - POST /api/library/import (auth-gated, multipart): sanitizes the folder name like the worker's safe_name, assembles into a sibling ".importing" temp dir then renames into place (never a half-written album), writes a cover.jpg from any image, and records a source="manual" LibraryItem with the on-disk trackNames + a rough quality class from the extension (a later Scan re-probes / MB-resolves for cover art + hi-res detection). Guards: 400 (missing artist/album or no audio), 409 (folder exists / already in library). - Library page: ImportAlbum drop-zone modal wired to refresh the grid. web 161 tests (write-to-disk + trackNames + guards + filename sanitization). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Also: DELETE now prunes an emptied artist folder (best-effort).
This commit is contained in:
@@ -204,6 +204,12 @@ nav.contents .sep { flex: 1; }
|
||||
font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase;
|
||||
color: var(--graphite); margin: 0 0 10px;
|
||||
}
|
||||
.import-form { display: flex; flex-direction: column; gap: 6px; }
|
||||
.dropzone {
|
||||
border: 1.5px dashed var(--rule-2); padding: 28px 20px; text-align: center; cursor: pointer;
|
||||
font-family: var(--mono); font-size: 0.8rem; color: var(--graphite); margin-bottom: 8px;
|
||||
}
|
||||
.dropzone:hover, .dropzone.over { border-color: var(--accent); color: var(--accent); }
|
||||
|
||||
/* ── Phase 2: page headers, list rows, tools ──────────── */
|
||||
.page-head { margin: 6px 0 26px; }
|
||||
|
||||
Reference in New Issue
Block a user