use crate::{ components::{ delete_user_attribute::DeleteUserAttribute, router::{AppRoute, Link}, }, convert_attribute_type, infra::{ common_component::{CommonComponent, CommonComponentParts}, schema::AttributeType, }, }; use anyhow::{anyhow, Error, Result}; use gloo_console::log; use graphql_client::GraphQLQuery; use yew::prelude::*; #[derive(GraphQLQuery)] #[graphql( schema_path = "../schema.graphql", query_path = "queries/get_user_attributes_schema.graphql", response_derives = "Debug,Clone,PartialEq,Eq", custom_scalars_module = "crate::infra::graphql" )] pub struct GetUserAttributesSchema; use get_user_attributes_schema::ResponseData; pub type Attribute = get_user_attributes_schema::GetUserAttributesSchemaSchemaUserSchemaAttributes; convert_attribute_type!(get_user_attributes_schema::AttributeType); #[derive(yew::Properties, Clone, PartialEq, Eq)] pub struct Props { pub hardcoded: bool, } pub struct UserSchemaTable { common: CommonComponentParts, attributes: Option>, } pub enum Msg { ListAttributesResponse(Result), OnAttributeDeleted(String), OnError(Error), } impl CommonComponent for UserSchemaTable { fn handle_msg(&mut self, _: &Context, msg: ::Message) -> Result { match msg { Msg::ListAttributesResponse(schema) => { self.attributes = Some(schema?.schema.user_schema.attributes.into_iter().collect()); Ok(true) } Msg::OnError(e) => Err(e), Msg::OnAttributeDeleted(attribute_name) => { match self.attributes { None => { log!(format!("Attribute {attribute_name} was deleted but component has no attributes")); Err(anyhow!("invalid state")) } Some(_) => { self.attributes .as_mut() .unwrap() .retain(|a| a.name != attribute_name); Ok(true) } } } } } fn mut_common(&mut self) -> &mut CommonComponentParts { &mut self.common } } impl Component for UserSchemaTable { type Message = Msg; type Properties = Props; fn create(ctx: &Context) -> Self { let mut table = UserSchemaTable { common: CommonComponentParts::::create(), attributes: None, }; table.common.call_graphql::( ctx, get_user_attributes_schema::Variables {}, Msg::ListAttributesResponse, "Error trying to fetch user schema", ); table } fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { CommonComponentParts::::update(self, ctx, msg) } fn view(&self, ctx: &Context) -> Html { html! {
{self.view_attributes(ctx)} {self.view_errors()}
} } } impl UserSchemaTable { fn view_attributes(&self, ctx: &Context) -> Html { let hardcoded = ctx.props().hardcoded; let make_table = |attributes: &Vec| { html! {

{if hardcoded {"Hardcoded"} else {"User-defined"}}{" attributes"}

{if hardcoded {html!{}} else {html!{}}} {attributes.iter().map(|u| self.view_attribute(ctx, u)).collect::>()}
{"Attribute name"} {"Type"} {"Editable"} {"Visible"}{"Delete"}
} }; match &self.attributes { None => html! {{"Loading..."}}, Some(attributes) => { let mut attributes = attributes.clone(); attributes.retain(|attribute| attribute.is_hardcoded == ctx.props().hardcoded); make_table(&attributes) } } } fn view_attribute(&self, ctx: &Context, attribute: &Attribute) -> Html { let link = ctx.link(); let attribute_type = AttributeType::from(attribute.attribute_type.clone()); let checkmark = html! { }; let hardcoded = ctx.props().hardcoded; html! { {&attribute.name} {if attribute.is_list { format!("List<{attribute_type}>")} else {attribute_type.to_string()}} {if attribute.is_editable {checkmark.clone()} else {html!{}}} {if attribute.is_visible {checkmark.clone()} else {html!{}}} { if hardcoded { html!{} } else { html!{ } } } } } fn view_errors(&self) -> Html { match &self.common.error { None => html! {}, Some(e) => html! {
{"Error: "}{e.to_string()}
}, } } } #[function_component(ListUserSchema)] pub fn list_user_schema() -> Html { html! {
{"Create an attribute"}
} }