use crate::{
api::Response,
route::RouterTarget,
service::{
cookie::CookieService,
session_timer::{self, SessionTimerAgent},
uikit::{NotificationStatus, UIkitService},
},
string::{REQUEST_ERROR, RESPONSE_ERROR, TEXT_CONTENT, TEXT_LOGOUT},
SESSION_COOKIE,
};
use log::{error, info, warn};
use webapp::{
protocol::{model::Session, request, response},
API_URL_LOGOUT,
};
use yew::{agent::Bridged, format::Cbor, html, prelude::*, services::fetch::FetchTask};
use yew_router::{self, RouterAgent};
pub struct ContentComponent {
component_link: ComponentLink<ContentComponent>,
cookie_service: CookieService,
fetch_task: Option<FetchTask>,
logout_button_disabled: bool,
router_agent: Box<Bridge<RouterAgent<()>>>,
session_timer_agent: Box<Bridge<SessionTimerAgent>>,
uikit_service: UIkitService,
}
pub enum Message {
Fetch(Response<response::Logout>),
Ignore,
LogoutRequest,
}
impl Component for ContentComponent {
type Message = Message;
type Properties = ();
fn create(_: Self::Properties, mut link: ComponentLink<Self>) -> Self {
let mut router_agent = RouterAgent::bridge(link.send_back(|_| Message::Ignore));
let cookie_service = CookieService::new();
let mut session_timer_agent =
SessionTimerAgent::bridge(link.send_back(|_| Message::Ignore));
if cookie_service.get(SESSION_COOKIE).is_err() {
info!("No session token found, routing back to login");
router_agent.send(yew_router::Request::ChangeRoute(RouterTarget::Login.into()));
} else {
session_timer_agent.send(session_timer::Request::Start);
}
Self {
component_link: link,
cookie_service,
fetch_task: None,
logout_button_disabled: false,
router_agent,
session_timer_agent,
uikit_service: UIkitService::new(),
}
}
fn change(&mut self, _: Self::Properties) -> ShouldRender {
true
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Message::LogoutRequest => {
if let Ok(token) = self.cookie_service.get(SESSION_COOKIE) {
self.fetch_task = fetch! {
request::Logout(Session::new(token)) => API_URL_LOGOUT,
self.component_link, Message::Fetch,
|| {
self.logout_button_disabled = true;
},
|| {
error!("Unable to create logout request");
self.uikit_service
.notify(REQUEST_ERROR, &NotificationStatus::Danger);
}
};
} else {
error!("No session cookie found");
self.router_agent
.send(yew_router::Request::ChangeRoute(RouterTarget::Login.into()));
}
}
Message::Fetch(response) => {
let (meta, Cbor(body)) = response.into_parts();
if meta.status.is_success() {
match body {
Ok(response::Logout) => info!("Got valid logout response"),
_ => {
warn!("Got wrong logout response");
self.uikit_service
.notify(RESPONSE_ERROR, &NotificationStatus::Danger);
}
}
} else {
warn!("Logout failed with status: {}", meta.status);
}
self.cookie_service.remove(SESSION_COOKIE);
self.session_timer_agent.send(session_timer::Request::Stop);
self.router_agent
.send(yew_router::Request::ChangeRoute(RouterTarget::Login.into()));
self.logout_button_disabled = true;
self.fetch_task = None;
}
Message::Ignore => {}
}
true
}
}
impl Renderable<ContentComponent> for ContentComponent {
fn view(&self) -> Html<Self> {
html! {
<div class="uk-card uk-card-default uk-card-body uk-width-1-3@s uk-position-center",>
<h1 class="uk-card-title",>{TEXT_CONTENT}</h1>
<button disabled=self.logout_button_disabled,
class="uk-button uk-button-default",
onclick=|_| Message::LogoutRequest,>{TEXT_LOGOUT}</button>
</div>
}
}
}