feat: add atomic state management (TripState, Photo, Group)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import json
|
||||
import os
|
||||
from dataclasses import dataclass, field, asdict
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from flask import current_app
|
||||
|
||||
|
||||
@dataclass
|
||||
class Photo:
|
||||
id: str
|
||||
original_filename: str
|
||||
local_datetime: str
|
||||
tag: str = "untagged" # untagged | journal | story | skip
|
||||
order: int = 0
|
||||
|
||||
|
||||
@dataclass
|
||||
class Group:
|
||||
id: str
|
||||
photo_ids: list = field(default_factory=list)
|
||||
entry_type: str = "journal" # journal | story
|
||||
title: str = ""
|
||||
body: str = ""
|
||||
location_city: str = ""
|
||||
location_country: str = ""
|
||||
date: str = ""
|
||||
hero_photo_id: Optional[str] = None
|
||||
shortcode_hints: str = ""
|
||||
status: str = "draft" # draft | written | skipped | exported
|
||||
|
||||
|
||||
@dataclass
|
||||
class TripState:
|
||||
album_id: str
|
||||
album_name: str
|
||||
grav_trip_slug: str
|
||||
phase: str = "triage"
|
||||
phases_completed: list = field(default_factory=list)
|
||||
phase_stale: list = field(default_factory=list)
|
||||
photos: list = field(default_factory=list)
|
||||
groups: list = field(default_factory=list)
|
||||
notes: str = ""
|
||||
|
||||
|
||||
def _state_path(album_id: str, app) -> Path:
|
||||
return Path(app.config["STATE_DIR"]) / f"{album_id}.json"
|
||||
|
||||
|
||||
def load_state(album_id: str, app) -> Optional[TripState]:
|
||||
path = _state_path(album_id, app)
|
||||
if not path.exists():
|
||||
return None
|
||||
with open(path) as f:
|
||||
data = json.load(f)
|
||||
photos = [Photo(**p) for p in data.pop("photos", [])]
|
||||
groups = [Group(**g) for g in data.pop("groups", [])]
|
||||
return TripState(photos=photos, groups=groups, **data)
|
||||
|
||||
|
||||
def save_state(state: TripState, app) -> None:
|
||||
path = _state_path(state.album_id, app)
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
tmp = path.with_suffix(".tmp")
|
||||
with open(tmp, "w") as f:
|
||||
json.dump(asdict(state), f, indent=2)
|
||||
os.rename(tmp, path)
|
||||
Reference in New Issue
Block a user