use std::sync::Arc;
use serde::Serialize;
use crate::runtime::handle::ExtensionHandle;
use crate::runtime::state::OverviewHandler;
use crate::runtime::handlers::SingleEntryContext;
use crate::error::Error;
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct OverviewField {
id: String,
label: String,
#[serde(skip)]
handler: OverviewHandler,
}
impl OverviewField {
pub fn new<F, Fut>(id: impl Into<String>, label: impl Into<String>, handler: F) -> Self
where
F: Fn(SingleEntryContext, ExtensionHandle) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<Option<String>, Error>> + Send + 'static,
{
Self {
id: id.into(),
label: label.into(),
handler: Arc::new(move |ctx, handle| {
let fut = handler(ctx, handle);
Box::pin(async move { fut.await.map_err(Error::into_jrpc) })
}),
}
}
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct OverviewSection {
label: String,
children: Vec<OverviewNode>,
}
impl OverviewSection {
pub fn new(label: impl Into<String>) -> Self {
Self {
label: label.into(),
children: Vec::new()
}
}
pub fn with_children(mut self, children: &mut Vec<OverviewNode>) -> Self {
self.children.append(children);
self
}
pub fn with_child(mut self, child: OverviewNode) -> Self {
self.children.push(child);
self
}
}
#[derive(Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum OverviewNode {
Section(OverviewSection),
Field(OverviewField),
}
impl From<OverviewField> for OverviewNode {
fn from(field: OverviewField) -> Self {
OverviewNode::Field(field)
}
}
impl From<OverviewSection> for OverviewNode {
fn from(section: OverviewSection) -> Self {
OverviewNode::Section(section)
}
}
impl OverviewNode {
pub(crate) fn extract_handlers(&self) -> Vec<(String, OverviewHandler)> {
match self {
Self::Field(field) => vec![(field.id.clone(), Arc::clone(&field.handler))],
Self::Section(section) => section
.children
.iter()
.flat_map(|child| child.extract_handlers())
.collect(),
}
}
}