use crate::{ components::{ delete_user_attribute::DeleteUserAttribute, fragments::attribute_schema::render_attribute_name, router::{AppRoute, Link}, }, infra::{ attributes::user, common_component::{CommonComponent, CommonComponentParts}, schema::AttributeType, }, }; use anyhow::{Error, Result, anyhow}; 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", extern_enums("AttributeType") )] pub struct GetUserAttributesSchema; use get_user_attributes_schema::ResponseData; pub type Attribute = get_user_attributes_schema::GetUserAttributesSchemaSchemaUserSchemaAttributes; #[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 = attribute.attribute_type; let checkmark = html! { }; let hardcoded = ctx.props().hardcoded; let desc = user::resolve_user_attribute_description_or_default(&attribute.name); html! { {render_attribute_name(hardcoded, &desc)} {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"}
} }