use serde_json::{Map, Value};
use super::spend::Figure;
use super::{fields, spend};
pub(crate) const KIND: &str = "board";
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Board {
pub rows: Vec<BoardRow>,
pub fleet: Vec<Fleet>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BoardRow {
pub id: String,
pub column: String,
pub state: String,
pub title: String,
pub priority: i64,
pub project: String,
pub workspace: Option<String>,
pub claimant: Option<String>,
pub parent: Option<String>,
pub gates: Vec<Gate>,
pub drones: Vec<Drone>,
pub spend: Option<Figure>,
pub rollup: Option<Figure>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Gate {
pub id: String,
pub title: String,
pub mints: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Drone {
pub root_id: String,
pub name: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Fleet {
pub workspace: String,
pub project: String,
pub cap: u64,
pub count: u64,
pub room: bool,
pub ceiling: Option<String>,
pub label: String,
}
pub(crate) fn board(obj: &Map<String, Value>) -> Result<Board, String> {
Ok(Board {
rows: fields::rows(obj, row)?,
fleet: match obj.get("fleet") {
None => Vec::new(),
Some(_) => fields::list(obj, "fleet", fleet)?,
},
})
}
fn row(value: &Value) -> Result<BoardRow, String> {
let obj: &Map<String, Value> = value.as_object().ok_or("board row: not an object")?;
Ok(BoardRow {
id: fields::text(obj, "id")?,
column: fields::text(obj, "column")?,
state: fields::text(obj, "state")?,
title: fields::text(obj, "title")?,
priority: fields::secs(obj, "priority")?,
project: fields::text(obj, "project")?,
workspace: fields::opt_text(obj, "workspace")?,
claimant: fields::opt_text(obj, "claimant")?,
parent: fields::opt_text(obj, "parent")?,
gates: fields::list(obj, "gates", gate)?,
drones: fields::list(obj, "drones", drone)?,
spend: obj.get("spend").map(spend::figure).transpose()?,
rollup: obj.get("rollup").map(spend::figure).transpose()?,
})
}
fn gate(value: &Value) -> Result<Gate, String> {
let obj: &Map<String, Value> = value.as_object().ok_or("board gate: not an object")?;
Ok(Gate {
id: fields::text(obj, "id")?,
title: fields::text(obj, "title")?,
mints: fields::text(obj, "mints")?,
})
}
fn drone(value: &Value) -> Result<Drone, String> {
let obj: &Map<String, Value> = value.as_object().ok_or("board drone: not an object")?;
Ok(Drone {
root_id: fields::text(obj, "root_id")?,
name: fields::text(obj, "name")?,
})
}
fn fleet(value: &Value) -> Result<Fleet, String> {
let obj: &Map<String, Value> = value.as_object().ok_or("fleet facts: not an object")?;
Ok(Fleet {
workspace: fields::text(obj, "workspace")?,
project: fields::text(obj, "project")?,
cap: fields::count(obj, "cap")?,
count: fields::count(obj, "count")?,
room: fields::flag(obj, "room")?,
ceiling: fields::opt_text(obj, "ceiling")?,
label: fields::text(obj, "label")?,
})
}
#[cfg(test)]
mod tests;