edc-web-ui 0.3.1

A Rust Web interface with patternfly-yew client for EDC
use super::ToggleTheme;
use crate::configuration::Configuration;
use patternfly_yew::prelude::*;
use wasm_cookies::CookieOptions;
use web_sys::SubmitEvent;
use yew::platform::spawn_local;
use yew::prelude::*;

#[derive(Properties, PartialEq, Clone)]
pub struct LoginComponentProps {
  pub onconfiguration: Callback<Configuration>,
}

#[component]
pub fn LoginComponent(props: &LoginComponentProps) -> Html {
  let management_url = use_state(|| {
    if let Some(Ok(management_url)) = wasm_cookies::get("EDC_CONNECTOR_MANAGEMENT_URL") {
      management_url
    } else {
      "".to_string()
    }
  });

  let api_key = use_state(|| {
    if let Some(Ok(api_key)) = wasm_cookies::get("EDC_CONNECTOR_API_KEY") {
      api_key
    } else {
      "".to_string()
    }
  });

  let client_id = use_state(|| {
    if let Some(Ok(client_id)) = wasm_cookies::get("EDC_CONNECTOR_CLIENT_ID") {
      client_id
    } else {
      "".to_string()
    }
  });

  let openid_issuer_url = use_state(|| {
    if let Some(Ok(openid_issuer_url)) = wasm_cookies::get("EDC_CONNECTOR_OPENID_ISSUER_URL") {
      openid_issuer_url
    } else {
      "".to_string()
    }
  });

  use_effect_with(props.onconfiguration.clone(), move |onconfiguration| {
    let onconfiguration = onconfiguration.clone();

    spawn_local(async move {
      let server_url = web_sys::window().unwrap().location().origin().unwrap();

      if let Ok(response) = reqwest::get(format!("{server_url}/configuration.json")).await {
        if let Ok(configuration) = response.json::<Configuration>().await {
          onconfiguration.emit(configuration);
        }
      }
    });
  });

  let onchange_management_url =
    use_callback(management_url.setter(), |value: String, management_url| {
      management_url.set(value);
    });

  let onchange_api_key = use_callback(api_key.setter(), |value: String, api_key| {
    api_key.set(value);
  });

  let onchange_client_id = use_callback(client_id.setter(), |value: String, client_id| {
    client_id.set(value);
  });

  let onchange_openid_issuer_url = use_callback(
    openid_issuer_url.setter(),
    |value: String, openid_issuer_url| {
      openid_issuer_url.set(value);
    },
  );

  let onsubmit = use_callback(
    (
      management_url.clone(),
      api_key.clone(),
      props.onconfiguration.clone(),
    ),
    |event: SubmitEvent, (management_url, api_key, onconfiguration)| {
      event.prevent_default();

      wasm_cookies::set(
        "EDC_CONNECTOR_MANAGEMENT_URL",
        &**management_url,
        &CookieOptions::default().with_path("/"),
      );

      wasm_cookies::set(
        "EDC_CONNECTOR_API_KEY",
        &**api_key,
        &CookieOptions::default().with_path("/"),
      );

      onconfiguration.emit(Configuration {
        management_url: (**management_url).clone(),
        api_key: Some((**api_key).clone()),
        client_id: None,
        openid_issuer_url: None,
      });
    },
  );

  let openid_onsubmit = use_callback(
    (
      management_url.clone(),
      client_id.clone(),
      openid_issuer_url.clone(),
      props.onconfiguration.clone(),
    ),
    |event: SubmitEvent, (management_url, client_id, openid_issuer_url, onconfiguration)| {
      event.prevent_default();
      wasm_cookies::set(
        "EDC_CONNECTOR_MANAGEMENT_URL",
        &**management_url,
        &CookieOptions::default().with_path("/"),
      );

      wasm_cookies::set(
        "EDC_CONNECTOR_CLIENT_ID",
        &**client_id,
        &CookieOptions::default().with_path("/"),
      );

      wasm_cookies::set(
        "EDC_CONNECTOR_OPENID_ISSUER_URL",
        &**openid_issuer_url,
        &CookieOptions::default().with_path("/"),
      );

      onconfiguration.emit(Configuration {
        management_url: (**management_url).clone(),
        api_key: None,
        client_id: Some((**client_id).clone()),
        openid_issuer_url: Some((**openid_issuer_url).clone()),
      });
    },
  );

  let selected = use_state_eq(|| TabIndex::OpenID);
  let onselect = use_callback(selected.clone(), |index, selected| selected.set(index));

  #[derive(Clone, Copy, PartialEq, Eq)]
  enum TabIndex {
    ApiToken,
    OpenID,
  }

  html!(
    <>
      <Background
        style="logo.png"
        additional_style="background-size: 200px 200px; background-position: calc(100vw - 220px) calc(100vh - 220px); background-color: var(--pf-t--global--background--color--secondary--default);"
      />
      <Login>
        <Card>
          <CardHeader>
            <Title level={Level::H3} size={Size::XXLarge}>{ "EDC Connector Management" }</Title>
          </CardHeader>
          <CardBody>
            <Tabs<TabIndex> {onselect} selected={*selected} r#box=true>
              <Tab<TabIndex> index={TabIndex::ApiToken} title="API Token">
                <Form {onsubmit}>
                  <FormGroup label="Management URL" required=true>
                    <TextInput
                      required=true
                      value={(*management_url).to_string()}
                      onchange={onchange_management_url.clone()}
                    />
                  </FormGroup>
                  <FormGroup label="API Key">
                    <TextInput
                      value={(*api_key).to_string()}
                      onchange={onchange_api_key}
                      r#type={TextInputType::Password}
                    />
                  </FormGroup>
                  <ActionGroup>
                    <Button
                      variant={ButtonVariant::Primary}
                      label="Submit"
                      r#type={ButtonType::Submit}
                    />
                    <Button
                      variant={ButtonVariant::Secondary}
                      label="Reset"
                      r#type={ButtonType::Reset}
                    />
                  </ActionGroup>
                </Form>
              </Tab<TabIndex>>
              <Tab<TabIndex> index={TabIndex::OpenID} title="Open ID">
                <Form onsubmit={openid_onsubmit}>
                  <FormGroup label="Management URL" required=true>
                    <TextInput
                      required=true
                      value={(*management_url).to_string()}
                      onchange={onchange_management_url}
                    />
                  </FormGroup>
                  <FormGroup label="Client ID">
                    <TextInput
                      value={(*client_id).to_string()}
                      onchange={onchange_client_id}
                      r#type={TextInputType::Password}
                    />
                  </FormGroup>
                  <FormGroup label="Open ID Issuer URL">
                    <TextInput
                      value={(*openid_issuer_url).to_string()}
                      onchange={onchange_openid_issuer_url}
                      r#type={TextInputType::Password}
                    />
                  </FormGroup>
                  <ActionGroup>
                    <Button
                      variant={ButtonVariant::Primary}
                      label="Submit"
                      r#type={ButtonType::Submit}
                    />
                    <Button
                      variant={ButtonVariant::Secondary}
                      label="Reset"
                      r#type={ButtonType::Reset}
                    />
                  </ActionGroup>
                </Form>
              </Tab<TabIndex>>
            </Tabs<TabIndex>>
          </CardBody>
          <CardFooter>
            <Bullseye>
              <ToggleTheme />
            </Bullseye>
          </CardFooter>
        </Card>
      </Login>
    </>
  )
}