1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
use std::collections::HashMap; use serde::ser::SerializeMap; use crate::dsl::schema::DocumentRoot; use crate::dsl::schema::Schema; use crate::dsl::schema::SchemaList; use crate::output::UiObject; use crate::output::UiObjectProperty; use crate::output::UiObjectRoot; use serde::Serialize; use serde::Serializer; use crate::dsl::schema::KeysSchema; use crate::output::UiOptions; use crate::dsl::schema::Annotations; use crate::dsl::schema::Widget; use crate::dsl::schema::object_types::RawObjectType; impl From<DocumentRoot> for UiObjectRoot { fn from(schema: DocumentRoot) -> UiObjectRoot { UiObjectRoot(schema.schema.map(|schema| schema.into())) } } impl From<SchemaList> for UiObject { fn from(list: SchemaList) -> Self { let ui_object_entries: Vec<(String, UiObjectProperty)> = list .entries() .iter() .filter_map(|entry| { let property: UiObjectProperty = entry.schema.clone().into(); if !property.is_empty() { Some((entry.name.clone(), entry.schema.clone().into())) } else { None } }) .collect(); let ui_object_entries: HashMap<String, UiObjectProperty> = ui_object_entries.into_iter().collect(); UiObject(ui_object_entries) } } impl From<Schema> for UiObjectProperty { fn from(schema: Schema) -> Self { let annotations = schema.annotations.clone(); let (help, warning, description) = help_warning_description(&annotations); let widget = widget(&schema); let placeholder = placeholder(&annotations); let readonly = readonly(&annotations); let keys_values = schema.dynamic.map(|keys_values| keys_values.keys); let children = schema.children; let children_ui_objects = children.clone().map(|children| children.into()); let order = children .clone() .map(|list| list.all_names().iter().map(|name| name.to_string()).collect()); let ui_options = ui_options(&annotations); UiObjectProperty { help, warning, description, placeholder, widget, properties: children_ui_objects, keys: keys_values, ui_options, readonly, order, } } } impl Serialize for KeysSchema { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, { let mut map = serializer.serialize_map(None)?; if let Some(title) = &self.title { let mut keys_definition = HashMap::new(); keys_definition.insert("ui:title", title); map.serialize_entry("ui:keys", &keys_definition)?; } map.end() } } fn ui_options(annotations: &Annotations) -> Option<UiOptions> { let default_ui_options = UiOptions::default(); let ui_options = UiOptions { removable: annotations.removable.unwrap_or(default_ui_options.removable), addable: annotations.addable.unwrap_or(default_ui_options.addable), orderable: annotations.orderable.unwrap_or(default_ui_options.orderable), }; if ui_options == default_ui_options { None } else { Some(ui_options) } } fn widget(schema: &Schema) -> Option<Widget> { let annotations = &schema.annotations; if let RawObjectType::Password(_) = schema.object_type.inner_raw() { return Some(Widget::Password); } if annotations.writeonly.unwrap_or(false) { return Some(Widget::Password); } if annotations.hidden.unwrap_or(false) { return Some(Widget::Hidden); } annotations.widget.clone() } fn help_warning_description(annotations: &Annotations) -> (Option<String>, Option<String>, Option<String>) { let help = &annotations.help; let warning = &annotations.warning; let description = &annotations.description; (help.clone(), warning.clone(), description.clone()) } fn placeholder(annotations: &Annotations) -> Option<String> { let placeholder = &annotations.placeholder; placeholder.clone() } fn readonly(annotations: &Annotations) -> Option<bool> { annotations.readonly }