from __future__ import annotations import json from copy import deepcopy from pathlib import Path from typing import Any ALLOWED_COMPONENTS = { "task-list", "overview-summary", "task-progress-grid", "task-header", "today-record", "metric-progress", "activity-heatmap", "task-settings", } FALLBACKS = { "home": { "schemaVersion": 1, "page": "home", "regions": { "sidebar": [{"component": "task-list"}], "main": [{"component": "overview-summary"}, {"component": "task-progress-grid"}], }, }, "task-detail": { "schemaVersion": 1, "page": "task-detail", "regions": { "sidebar": [{"component": "task-list"}], "main": [ {"component": "task-header"}, {"component": "today-record"}, {"component": "metric-progress"}, {"component": "activity-heatmap"}, {"component": "task-settings"}, ], }, }, } def validate_layout(layout: Any, expected_page: str) -> bool: if not isinstance(layout, dict): return False if layout.get("schemaVersion") != 1 or layout.get("page") != expected_page: return False regions = layout.get("regions") if not isinstance(regions, dict) or set(regions) - {"sidebar", "main"}: return False for items in regions.values(): if not isinstance(items, list): return False for item in items: if not isinstance(item, dict) or set(item) - {"component", "options"}: return False if item.get("component") not in ALLOWED_COMPONENTS: return False if "options" in item and not isinstance(item["options"], dict): return False return True def load_layout(layout_dir: Path, page: str) -> dict[str, Any]: if page not in FALLBACKS: raise KeyError(page) try: with (layout_dir / f"{page}.json").open("r", encoding="utf-8") as handle: layout = json.load(handle) if validate_layout(layout, page): return layout except (OSError, json.JSONDecodeError): pass return deepcopy(FALLBACKS[page])