feat(review): #90 photo strip — keep/remove, drag-reorder, leftmost=primary, persist
REVIEW-5 / PUBLISH-45: owner edits the stored photo lineup in Review — tap a card to keep/remove, drag to reorder, leftmost kept photo = primary (Woo cover). The kept set must contain a clean calibration + its dimension-overlay copy; publish is blocked until it does. - backend: role column on slab_photos (schema + idempotent _migrate ALTER), role in photo CRUD + new DELETE endpoint, Woo image order by role-rank (clean→overlay→batch) per PUBLISH-45 - frontend: Review photo strip (render from listPhotos, keep/remove, HTML5 drag-reorder, dynamic PRIMARY badge from .primary class), persistLineup() re-seq kept + drop removed before entering Publish - tests: lineup.ts unit, e2e review-photo-strip.spec, backend role + order Refs: #90, REVIEW-5, PUBLISH-45
This commit is contained in:
@@ -80,6 +80,21 @@ _M3_TABLES = [
|
||||
]
|
||||
|
||||
|
||||
def _migrate(conn: sqlite3.Connection) -> None:
|
||||
"""Idempotent column additions for volumes created before a column existed.
|
||||
|
||||
`CREATE TABLE IF NOT EXISTS` in schema.sql is a no-op on an existing table,
|
||||
so new columns must be added here. Each guard is a no-op once the column is
|
||||
present. #90 adds slab_photos.role (lineup kind) for the Review photo strip.
|
||||
"""
|
||||
photo_cols = {r[1] for r in conn.execute("PRAGMA table_info(slab_photos)").fetchall()}
|
||||
if photo_cols and "role" not in photo_cols:
|
||||
conn.execute(
|
||||
"ALTER TABLE slab_photos ADD COLUMN role TEXT NOT NULL DEFAULT 'batch' "
|
||||
"CHECK(role IN ('calibration','overlay','batch'))"
|
||||
)
|
||||
|
||||
|
||||
def init_db(db_path: str | None = None) -> sqlite3.Connection:
|
||||
conn = get_connection(db_path)
|
||||
schema_path = _get_schema_path()
|
||||
@@ -99,6 +114,10 @@ def init_db(db_path: str | None = None) -> sqlite3.Connection:
|
||||
conn.executescript(schema)
|
||||
conn.execute("INSERT OR REPLACE INTO schema_version (version) VALUES (1)")
|
||||
conn.commit()
|
||||
# Safe to run every boot: no-op once the columns exist.
|
||||
with _lock:
|
||||
_migrate(conn)
|
||||
conn.commit()
|
||||
|
||||
return conn
|
||||
|
||||
|
||||
Reference in New Issue
Block a user