feat: begin implementation of value display
This commit is contained in:
1 parent
f10f01534c
commit
04ba0ff1ea
5 files changed
+325
-54
No files matched your search
+2
-1
@@ -8,8 +8,9 @@ mod user;
|
||||
mod value_type;
|
||||
pub mod animations;
|
||||
mod tab_info;
|
||||
mod schema_node;
|
||||
|
||||
pub use self::{
|
||||
comparison::*, date_info::*, expandable_info::*, form_params::*, form_schema::*,
|
||||
submit_status::*, user::*, value_type::*, tab_info::*,
|
||||
submit_status::*, user::*, value_type::*, tab_info::*, schema_node::*,
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
use std::collections::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum SchemaType {
|
||||
String,
|
||||
Number,
|
||||
List,
|
||||
Map
|
||||
}
|
||||
|
||||
/// # Schema Node
|
||||
///
|
||||
/// This is used to create a schema that is used in the [`ValueDisplay`] component. It stores all
|
||||
/// required information for the display, specifically where to find the data and how to display it.
|
||||
/// It covers all `ValueType` variants, however for data storage and DX it uses a `SchemaType`
|
||||
/// instead.
|
||||
///
|
||||
/// Some examples are as follows, using the fluent builder notation:
|
||||
/// - Displaying a single `ValueType::String` from the data map at the key `example_one`:
|
||||
/// ```
|
||||
/// SchemaNode::new(SchemaType::String).header("The example string")
|
||||
/// ```
|
||||
/// - Displaying a `ValueType::List` which contains only `ValueType::String` entries:
|
||||
/// ```
|
||||
/// SchemaNode::new(SchemaType::List)
|
||||
/// .header("The example list")
|
||||
/// .item_template(SchemaNode::new(SchemaType::String).header(""))
|
||||
/// ```
|
||||
/// - Displaying a `ValueType::Map` which contains a name and age:
|
||||
/// ```
|
||||
/// SchemaType::new(SchemaType::Map)
|
||||
/// .header("The example map")
|
||||
/// .child("first_name", SchemaNode::new(SchemaType::String).header("First Name:"))
|
||||
/// .child("age", SchemaNode::new(SchemaType::Number).header("Age:"))
|
||||
/// ```
|
||||
/// - Put it all together: a `ValueType::List` which contains `ValueType::Map` entries, each of
|
||||
/// which also contains the name and age from the previous example:
|
||||
/// ```
|
||||
/// SchemaNode::new(SchemaType::List)
|
||||
/// .header("The example map list")
|
||||
/// .item_template(
|
||||
/// SchemaNode::new(SchemaType::Map)
|
||||
/// .header("The example map from earlier")
|
||||
/// .child("first_name", SchemaNode::new(SchemaType::String).header("First Name:"))
|
||||
/// .child("age", SchemaNode::new(SchemaType::Number).header("Age:"))
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// This schema allows for definitive typing and styling for every level of the data display.
|
||||
///
|
||||
/// ## Important Notes
|
||||
///
|
||||
/// This schema does not currently support display of a single nested member, like a single map
|
||||
/// within a list. This means that you will have to display any listed or mapped information as a
|
||||
/// list. Consider this when designing the data.
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub struct SchemaNode {
|
||||
/// The datatype of the data found using the `data_member` key.
|
||||
pub data_type: SchemaType,
|
||||
/// The header of this display.
|
||||
pub header: String,
|
||||
/// When used with a SchemaType::List, this determines the datatype and children for every entry
|
||||
/// in the list. Some examples include a list of maps, where we use the `item_template` to define
|
||||
/// the SchemaType::Map, and all its children. This is then mapped across all entries in the list,
|
||||
/// where any entries that do not match the template are skipped.
|
||||
pub item_template: Option<Box<SchemaNode>>,
|
||||
/// When used with a SchemaType::Map, this determines what children from the map are displayed
|
||||
/// and how. It is ignored with all other SchemaType variants.
|
||||
pub children: HashMap<String, SchemaNode>,
|
||||
}
|
||||
|
||||
impl SchemaNode {
|
||||
pub fn new(data_type: SchemaType) -> Self {
|
||||
SchemaNode {
|
||||
data_type,
|
||||
header: "".to_string(),
|
||||
item_template: None,
|
||||
children: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn header(mut self, header: impl Into<String>) -> Self {
|
||||
self.header = header.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn child(mut self, data_member: impl Into<String>, node: SchemaNode) -> Self {
|
||||
self.children.insert(data_member.into(), node);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn item_template(mut self, node: SchemaNode) -> Self {
|
||||
self.item_template = Some(Box::new(node));
|
||||
self
|
||||
}
|
||||
}
|
||||
@@ -105,8 +105,8 @@ impl Default for ValueType {
|
||||
impl Display for ValueType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let str = match self {
|
||||
ValueType::String(s) => s.clone().unwrap_or("".to_owned()),
|
||||
ValueType::Number(n) => n.clone().unwrap_or("".to_owned()),
|
||||
ValueType::String(s) => s.clone().unwrap_or_default(),
|
||||
ValueType::Number(n) => n.clone().unwrap_or_default(),
|
||||
ValueType::List(l) => format!("{l:?}"),
|
||||
ValueType::Map(m) => format!("{m:?}"),
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user