Gunnar

mikronova/kyokkou

src/data_graphs.rs

use crate::common::{Scene, ValidationStatus, render_button, show_validation};

#[derive(Debug, Clone, PartialEq)]
pub enum DataSource {
    FalkorDB,
    Neo4jDump,
    PropertyGraphJson,
}

pub struct DataGraphs {
    pub source: DataSource,
    pub connection_string: String,
    pub node_size_property: String,
    pub emission_property: String,
    pub edge_weight_property: String,
    pub node_count: usize,
    pub edge_count: usize,
}

impl Default for DataGraphs {
    fn default() -> Self {
        Self {
            source: DataSource::FalkorDB,
            connection_string: "localhost:6379".into(),
            node_size_property: "value".into(),
            emission_property: "load".into(),
            edge_weight_property: "weight".into(),
            node_count: 0,
            edge_count: 0,
        }
    }
}

impl Scene for DataGraphs {
    fn name(&self) -> &str {
        "Data graphs"
    }

    fn validate(&self) -> Vec<ValidationStatus> {
        let mut v = vec![];
        if self.node_count > 50 {
            v.push(ValidationStatus::Warning(
                "Glass caustics > 50 nodes — render time will be high".into(),
            ));
        }
        if self.edge_count > 200 {
            v.push(ValidationStatus::Warning(
                "Edge count > 200 — volumetric beams will be batched".into(),
            ));
        }
        if self.connection_string.is_empty() {
            v.push(ValidationStatus::Error("Connection string required".into()));
        }
        if v.is_empty() {
            v.push(ValidationStatus::Ok);
        }
        v
    }

    fn show(&mut self, ui: &mut egui::Ui) -> Option<String> {
        ui.heading("Data graphs");
        ui.separator();

        ui.horizontal(|ui| {
            ui.label("Source:");
            egui::ComboBox::from_id_salt("data_source")
                .selected_text(format!("{:?}", self.source))
                .show_ui(ui, |ui| {
                    ui.selectable_value(&mut self.source, DataSource::FalkorDB, "FalkorDB");
                    ui.selectable_value(&mut self.source, DataSource::Neo4jDump, "Neo4j dump");
                    ui.selectable_value(&mut self.source, DataSource::PropertyGraphJson, "Property graph JSON");
                });
        });

        ui.horizontal(|ui| {
            ui.label("Connection:");
            ui.text_edit_singleline(&mut self.connection_string);
            if ui.button("Connect").clicked() {
                // TODO: query and populate node_count / edge_count
            }
        });

        ui.separator();
        ui.label("Value → visual mapping");
        ui.horizontal(|ui| {
            ui.label("Node size property:");
            ui.text_edit_singleline(&mut self.node_size_property);
        });
        ui.horizontal(|ui| {
            ui.label("Emission property:");
            ui.text_edit_singleline(&mut self.emission_property);
        });
        ui.horizontal(|ui| {
            ui.label("Edge weight property:");
            ui.text_edit_singleline(&mut self.edge_weight_property);
        });

        ui.separator();
        let statuses = self.validate();
        show_validation(ui, &statuses);
        ui.separator();
        if render_button(ui, self.is_renderable()) {
            // TODO: to_yaml() for data graphs
        }
        None
    }
}