summaryrefslogtreecommitdiff
path: root/webapp/src/components/app_context_provider.rs
blob: 4cf233bd8b87d86e5d14908b58abe7a614a0999b (plain)
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
use gloo_net::http::Request;
use protocol::UserInfo;
use std::rc::Rc;
use yew::prelude::*;

#[derive(Properties, Clone, PartialEq, Debug)]
pub struct ErrorInfoProperties {
    pub message: String,
}

#[derive(Clone, Debug, PartialEq, Default)]
pub struct AppContext {
    pub error: Option<ErrorInfoProperties>,
    pub user: Option<UserInfo>,
}

#[derive(Properties, Clone, PartialEq)]
pub struct Props {
    pub children: Children,
}

async fn initialize_user_info() -> Result<UserInfo, anyhow::Error> {
    let response = Request::get("/api/user/info").send().await?;
    if response.status() == 401 {
        web_sys::window()
            .unwrap()
            .location()
            .assign("/api/login")
            .unwrap();
    };
    let user_info = response.json().await?;
    Ok(user_info)
}

#[function_component(AppContextProvider)]
pub fn app_context_provider(props: &Props) -> Html {
    let context: UseStateHandle<Option<Rc<AppContext>>> = use_state(|| None);

    {
        let context = context.clone();
        use_effect_with_deps(
            move |_| {
                wasm_bindgen_futures::spawn_local(async move {
                    let previous_context: AppContext = context
                        .as_ref()
                        .map_or(Default::default(), |c| (**c).clone());
                    context.set(Some(Rc::new(match initialize_user_info().await {
                        Ok(user_info) => AppContext {
                            user: Some(user_info),
                            ..previous_context
                        },
                        Err(e) => AppContext {
                            error: Some(ErrorInfoProperties {
                                message: format!("Could not contact server"),
                            }),
			    ..previous_context
                        },
                    })));
                });
                || ()
            },
            (),
        );
    }

    match &*context {
        None => html! {
            <p>{ "Loading app..." }</p>
        },
        Some(context) => html! {
            <ContextProvider<Rc<AppContext>> {context}>
                { for props.children.iter() }
            </ContextProvider<Rc<AppContext>>>
        },
    }
}