Skip to main content

flowsurface_data/layout/
dashboard.rs

1use serde::{Deserialize, Deserializer, Serialize};
2use serde_json::Value;
3
4use crate::chart::kline::ChartSettings;
5
6use super::{WindowSpec, pane::Pane};
7
8#[derive(Debug, Clone, Deserialize, Serialize, Default)]
9pub struct Dashboard {
10    #[serde(deserialize_with = "deserialize_pane", default)]
11    pub pane: Pane,
12    #[serde(deserialize_with = "deserialize_popouts", default)]
13    pub popout: Vec<(Pane, WindowSpec)>,
14    #[serde(default)]
15    pub chart_settings: ChartSettings,
16}
17
18fn deserialize_pane<'de, D>(deserializer: D) -> Result<Pane, D::Error>
19where
20    D: Deserializer<'de>,
21{
22    let value = Value::deserialize(deserializer)?;
23    deserialize_normalized_pane(normalize_pane(value)).map_err(serde::de::Error::custom)
24}
25
26fn deserialize_popouts<'de, D>(deserializer: D) -> Result<Vec<(Pane, WindowSpec)>, D::Error>
27where
28    D: Deserializer<'de>,
29{
30    let popouts = Vec::<(Value, WindowSpec)>::deserialize(deserializer)?;
31
32    popouts
33        .into_iter()
34        .map(|(pane, window)| {
35            deserialize_normalized_pane(normalize_pane(pane))
36                .map(|pane| (pane, window))
37                .map_err(serde::de::Error::custom)
38        })
39        .collect()
40}
41
42fn normalize_pane(mut value: Value) -> Value {
43    if let Some(split) = value.get_mut("Split").and_then(Value::as_object_mut) {
44        for child_name in ["a", "b"] {
45            if let Some(child) = split.remove(child_name) {
46                split.insert(child_name.to_string(), normalize_pane(child));
47            }
48        }
49    }
50
51    if serde_json::from_value::<Pane>(value.clone()).is_ok() {
52        value
53    } else {
54        starter_pane(&value)
55    }
56}
57
58fn deserialize_normalized_pane(value: Value) -> Result<Pane, serde_json::Error> {
59    serde_json::from_value(value)
60}
61
62fn starter_pane(value: &Value) -> Value {
63    let link_group = value
64        .as_object()
65        .and_then(|object| object.values().next())
66        .and_then(Value::as_object)
67        .and_then(|payload| payload.get("link_group"))
68        .cloned()
69        .unwrap_or(Value::Null);
70
71    serde_json::json!({
72        "Starter": {
73            "link_group": link_group,
74        }
75    })
76}