display_hint becomes {kind, h_align, v_align} object in API, SQLite
gets alignment columns, SPA widget form gets alignment selects, layout
preview reflects actual alignment instead of hardcoded center
120 lines
3.8 KiB
Rust
120 lines
3.8 KiB
Rust
use crate::error::SqliteConfigError;
|
|
use domain::{DisplayHint, DisplayHintKind, HAlign, KeyMapping, VAlign, WidgetConfig};
|
|
use sqlx::Row;
|
|
use sqlx::sqlite::SqliteRow;
|
|
|
|
pub fn display_hint_kind_to_str(hint: &DisplayHint) -> &'static str {
|
|
match hint.kind {
|
|
DisplayHintKind::IconValue => "icon_value",
|
|
DisplayHintKind::TextBlock => "text_block",
|
|
DisplayHintKind::KeyValue => "key_value",
|
|
}
|
|
}
|
|
|
|
pub fn h_align_to_str(a: HAlign) -> &'static str {
|
|
match a {
|
|
HAlign::Left => "left",
|
|
HAlign::Center => "center",
|
|
HAlign::Right => "right",
|
|
}
|
|
}
|
|
|
|
pub fn v_align_to_str(a: VAlign) -> &'static str {
|
|
match a {
|
|
VAlign::Top => "top",
|
|
VAlign::Middle => "middle",
|
|
VAlign::Bottom => "bottom",
|
|
}
|
|
}
|
|
|
|
fn hint_kind_from_str(s: &str) -> Result<DisplayHintKind, SqliteConfigError> {
|
|
match s {
|
|
"icon_value" => Ok(DisplayHintKind::IconValue),
|
|
"text_block" => Ok(DisplayHintKind::TextBlock),
|
|
"key_value" => Ok(DisplayHintKind::KeyValue),
|
|
_ => Err(SqliteConfigError::Serialization(format!(
|
|
"unknown display hint: {s}"
|
|
))),
|
|
}
|
|
}
|
|
|
|
fn h_align_from_str(s: &str) -> Result<HAlign, SqliteConfigError> {
|
|
match s {
|
|
"left" => Ok(HAlign::Left),
|
|
"center" => Ok(HAlign::Center),
|
|
"right" => Ok(HAlign::Right),
|
|
_ => Err(SqliteConfigError::Serialization(format!(
|
|
"unknown h_align: {s}"
|
|
))),
|
|
}
|
|
}
|
|
|
|
fn v_align_from_str(s: &str) -> Result<VAlign, SqliteConfigError> {
|
|
match s {
|
|
"top" => Ok(VAlign::Top),
|
|
"middle" => Ok(VAlign::Middle),
|
|
"bottom" => Ok(VAlign::Bottom),
|
|
_ => Err(SqliteConfigError::Serialization(format!(
|
|
"unknown v_align: {s}"
|
|
))),
|
|
}
|
|
}
|
|
|
|
pub fn mappings_to_json(mappings: &[KeyMapping]) -> Result<String, SqliteConfigError> {
|
|
let entries: Vec<serde_json::Value> = mappings
|
|
.iter()
|
|
.map(|m| {
|
|
serde_json::json!({
|
|
"source_path": m.source_path,
|
|
"target_key": m.target_key,
|
|
})
|
|
})
|
|
.collect();
|
|
serde_json::to_string(&entries).map_err(|e| SqliteConfigError::Serialization(e.to_string()))
|
|
}
|
|
|
|
fn mappings_from_json(json: &str) -> Result<Vec<KeyMapping>, SqliteConfigError> {
|
|
let entries: Vec<serde_json::Value> =
|
|
serde_json::from_str(json).map_err(|e| SqliteConfigError::Serialization(e.to_string()))?;
|
|
|
|
entries
|
|
.iter()
|
|
.map(|v| {
|
|
Ok(KeyMapping {
|
|
source_path: v["source_path"]
|
|
.as_str()
|
|
.ok_or_else(|| SqliteConfigError::Serialization("missing source_path".into()))?
|
|
.into(),
|
|
target_key: v["target_key"]
|
|
.as_str()
|
|
.ok_or_else(|| SqliteConfigError::Serialization("missing target_key".into()))?
|
|
.into(),
|
|
})
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
pub fn widget_from_row(row: &SqliteRow) -> Result<WidgetConfig, SqliteConfigError> {
|
|
let id: i64 = row.get("id");
|
|
let name: String = row.get("name");
|
|
let hint_str: String = row.get("display_hint");
|
|
let h_align_str: String = row.get("h_align");
|
|
let v_align_str: String = row.get("v_align");
|
|
let ds_id: i64 = row.get("data_source_id");
|
|
let mappings_json: String = row.get("mappings");
|
|
let max_size: i64 = row.get("max_data_size");
|
|
|
|
Ok(WidgetConfig {
|
|
id: id as u16,
|
|
name,
|
|
display_hint: DisplayHint {
|
|
kind: hint_kind_from_str(&hint_str)?,
|
|
h_align: h_align_from_str(&h_align_str)?,
|
|
v_align: v_align_from_str(&v_align_str)?,
|
|
},
|
|
data_source_id: ds_id as u16,
|
|
mappings: mappings_from_json(&mappings_json)?,
|
|
max_data_size: max_size as u16,
|
|
})
|
|
}
|