feat(tahuantinsuyu): fase 11 — persistencia de module_configs por carta
Los toggles, sliders y partner pickers de cada overlay (transit,
progression, solar_arc, synastry) ahora persisten por carta en la
tabla SQLite `module_state` (que estaba creada desde fase 1 pero
sin cablear). Cambiar de carta y volver mantiene exactamente el
estado que el usuario dejó.
- shell:
- apply_selection(Chart): tras setear defaults (target_age_years =
edad actual), llama load_persisted_module_states(chart.id) que
mergea sobre los defaults los valores guardados. Luego
sync_panel_from_configs empuja todos los toggles/sliders al
panel para reflejar el estado restaurado. Render al final.
- load_persisted_module_states: lee list_module_states(chart_id),
reconstruye el JSON combinado (mergea `enabled` de la columna
SQL en el config), y lo mergea sobre lo que ya hay en
module_configs. Vacant entries se insertan tal cual; occupied
se patchean field-a-field para no perder defaults no guardados.
- sync_panel_from_configs: itera module_configs, push toggle/slider
al panel por cada key Bool/f64.
- persist_module(module_id): extrae enabled del JSON, deja resto en
config_json, llama upsert_module_state. Invocada desde
on_panel_event "else" tras cada update + desde on_canvas_event
para [T] + tras auto-disable del conflicting module en mutual
exclusion.
- store: nuevo test module_state_roundtrip que cubre upsert/list +
cambio de enabled vía upsert (UPSERT clause de fase 1 vuelve a
validarse).
Flujo de usuario: ajustás el slider de progresión a 42.5 años,
activás synastry, cambiás de carta, volvés — todo está como lo
dejaste. La DB persiste por chart_id, así que distintos sujetos
mantienen estados independientes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -550,7 +550,7 @@ fn now_ms() -> i64 {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use tahuantinsuyu_model::{StoredBirthData, StoredChartConfig};
|
||||
use tahuantinsuyu_model::{ModuleState, StoredBirthData, StoredChartConfig};
|
||||
|
||||
#[test]
|
||||
fn open_and_migrate() {
|
||||
@@ -559,6 +559,80 @@ mod tests {
|
||||
assert!(groups.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn module_state_roundtrip() {
|
||||
let s = Store::in_memory().unwrap();
|
||||
let g = s.create_group(None, "Familia", None).unwrap();
|
||||
let c = s.create_contact(Some(g.id), "Sergio", None).unwrap();
|
||||
let chart = s
|
||||
.create_chart(
|
||||
c.id,
|
||||
ChartKind::Natal,
|
||||
"Natal",
|
||||
&StoredBirthData {
|
||||
year: 1987,
|
||||
month: 3,
|
||||
day: 14,
|
||||
hour: 5,
|
||||
minute: 22,
|
||||
second: 0.0,
|
||||
tz_offset_minutes: -240,
|
||||
latitude_deg: 10.4806,
|
||||
longitude_deg: -66.9036,
|
||||
altitude_m: 900.0,
|
||||
time_certainty: Default::default(),
|
||||
subject_name: None,
|
||||
birthplace_label: None,
|
||||
},
|
||||
&StoredChartConfig::default(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Persistir dos módulos con configs distintos.
|
||||
let state1 = ModuleState {
|
||||
chart_id: chart.id,
|
||||
module_id: "transit".into(),
|
||||
enabled: true,
|
||||
config: serde_json::json!({}),
|
||||
};
|
||||
let state2 = ModuleState {
|
||||
chart_id: chart.id,
|
||||
module_id: "progression".into(),
|
||||
enabled: false,
|
||||
config: serde_json::json!({ "target_age_years": 42.5 }),
|
||||
};
|
||||
s.upsert_module_state(&state1).unwrap();
|
||||
s.upsert_module_state(&state2).unwrap();
|
||||
|
||||
let loaded = s.list_module_states(chart.id).unwrap();
|
||||
assert_eq!(loaded.len(), 2);
|
||||
let by_id: std::collections::HashMap<_, _> =
|
||||
loaded.into_iter().map(|m| (m.module_id.clone(), m)).collect();
|
||||
assert_eq!(by_id["transit"].enabled, true);
|
||||
assert_eq!(by_id["progression"].enabled, false);
|
||||
assert_eq!(
|
||||
by_id["progression"]
|
||||
.config
|
||||
.get("target_age_years")
|
||||
.and_then(|v| v.as_f64()),
|
||||
Some(42.5)
|
||||
);
|
||||
|
||||
// Upsert: cambiar enabled de transit a false.
|
||||
let state1_off = ModuleState {
|
||||
chart_id: chart.id,
|
||||
module_id: "transit".into(),
|
||||
enabled: false,
|
||||
config: serde_json::json!({}),
|
||||
};
|
||||
s.upsert_module_state(&state1_off).unwrap();
|
||||
let loaded = s.list_module_states(chart.id).unwrap();
|
||||
let by_id: std::collections::HashMap<_, _> =
|
||||
loaded.into_iter().map(|m| (m.module_id.clone(), m)).collect();
|
||||
assert_eq!(by_id["transit"].enabled, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn full_hierarchy_roundtrip() {
|
||||
let s = Store::in_memory().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user