gioser

tawasuyu/brahman

Rust 326TOML 123JSON 14Markdown 114554 Definiciones

⎇ 61044844980dd4f8505d9ba94600d9b92a85423e crates/modules/ui_engine/libs/meta-runtime/src/format.rs Rust · 116 líneas · 4.2 KB Historia Quién tocó qué crudo

refactor(yahweh): Fase 2 — extraer helpers puros a yahweh-meta-runtime 610448449 · Sergio ·

1//! Helpers de presentación humana para records y values.
2//!
3//! Sin GPUI: devuelven `String`s. El widget renderer los wrap-ea
4//! en `div().child(...)` o equivalente.
5
6use serde_json::Value;
7use uuid::Uuid;
8
9/// Etiqueta humana para representar un record en el selector de
10/// EntityRef. Heurística: prefiere campos comunes en este orden:
11/// `name`, `label`, `title`, `sku`, `sku_id`. Fallback al UUID corto.
12pub fn human_label_for_record(value: &Value, id: &Uuid) -> String {
13    for key in ["name", "label", "title", "sku", "sku_id"] {
14        if let Some(v) = value.get(key).and_then(Value::as_str) {
15            if !v.is_empty() {
16                return format!("{} ({})", v, short_uuid(id));
17            }
18        }
19    }
20    short_uuid(id)
21}
22
23/// Render legible de un `Value` arbitrario para mostrar en una celda
24/// de lista. Strings van pelados; bools como ✓/✗; el resto via
25/// `Display`.
26pub fn render_value(v: Option<&Value>) -> String {
27    match v {
28        None | Some(Value::Null) => String::new(),
29        Some(Value::String(s)) => s.clone(),
30        Some(Value::Bool(b)) => if *b { "✓" } else { "✗" }.to_string(),
31        Some(Value::Number(n)) => n.to_string(),
32        Some(other) => other.to_string(),
33    }
34}
35
36/// Conversión inversa a `parse_field_value`: del JSON al texto raw
37/// que un input puede tomar y volver a parsearse igual al submit.
38/// Usado para pre-llenar inputs en modo edit.
39pub fn value_to_input_text(v: &Value) -> String {
40    match v {
41        Value::Null => String::new(),
42        Value::String(s) => s.clone(),
43        Value::Bool(b) => if *b { "true" } else { "false" }.to_string(),
44        Value::Number(n) => n.to_string(),
45        other => other.to_string(),
46    }
47}
48
49/// Primeros 8 chars del UUID en forma canónica. Útil para logs y UI
50/// donde el UUID full es ruido visual.
51pub fn short_uuid(id: &Uuid) -> String {
52    id.to_string().chars().take(8).collect()
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58    use serde_json::json;
59
60    #[test]
61    fn human_label_prefers_name_over_id() {
62        let id = Uuid::new_v4();
63        let v = json!({"name": "Acme S.A.", "email": "x@y.z"});
64        let label = human_label_for_record(&v, &id);
65        assert!(label.starts_with("Acme S.A."));
66        assert!(label.contains(&short_uuid(&id)));
67    }
68
69    #[test]
70    fn human_label_falls_back_through_label_title_sku() {
71        let id = Uuid::new_v4();
72        let only_label = json!({"label": "X"});
73        assert!(human_label_for_record(&only_label, &id).starts_with("X "));
74        let only_title = json!({"title": "Y"});
75        assert!(human_label_for_record(&only_title, &id).starts_with("Y "));
76        let only_sku = json!({"sku": "Z"});
77        assert!(human_label_for_record(&only_sku, &id).starts_with("Z "));
78        let only_sku_id = json!({"sku_id": "W"});
79        assert!(human_label_for_record(&only_sku_id, &id).starts_with("W "));
80    }
81
82    #[test]
83    fn human_label_falls_back_to_short_uuid_when_no_keys_match() {
84        let id = Uuid::new_v4();
85        let v = json!({"random": "field"});
86        assert_eq!(human_label_for_record(&v, &id), short_uuid(&id));
87    }
88
89    #[test]
90    fn render_value_handles_basic_kinds() {
91        assert_eq!(render_value(None), "");
92        assert_eq!(render_value(Some(&Value::Null)), "");
93        assert_eq!(render_value(Some(&json!("hola"))), "hola");
94        assert_eq!(render_value(Some(&json!(true))), "✓");
95        assert_eq!(render_value(Some(&json!(false))), "✗");
96        assert_eq!(render_value(Some(&json!(42))), "42");
97    }
98
99    #[test]
100    fn value_to_input_text_round_trip_with_strings_and_numbers() {
101        assert_eq!(value_to_input_text(&Value::Null), "");
102        assert_eq!(value_to_input_text(&json!("x")), "x");
103        assert_eq!(value_to_input_text(&json!(true)), "true");
104        assert_eq!(value_to_input_text(&json!(false)), "false");
105        assert_eq!(value_to_input_text(&json!(42)), "42");
106    }
107
108    #[test]
109    fn short_uuid_returns_first_8_chars() {
110        let id = Uuid::parse_str("01ARZ3ND-EKTS-V4RR-FFQ6-9G5FAV000000").ok();
111        // Si el parse falla, usamos uno fresco — el invariant es la
112        // longitud, no el contenido.
113        let id = id.unwrap_or_else(Uuid::new_v4);
114        assert_eq!(short_uuid(&id).len(), 8);
115    }
116}