use gloo_net::http::Request; use itertools::Itertools; use wasm_bindgen::*; use web_sys::{EventTarget, HtmlInputElement}; use yew::prelude::*; use lib::lib::*; use yew_router::scope_ext::RouterScopeExt; use crate::Route; #[derive(Properties, Clone, PartialEq, Eq)] pub struct ResultComponentProps { result: IndexedResource, } #[function_component(ResultComponent)] fn result_component(props: &ResultComponentProps) -> Html { html! {
{props.result.url.clone()}{"--"}{props.result.title.clone()}{"----"}{props.result.description.clone()}{format!("PRIO: {}", props.result.priority)}
} } pub struct OSSE { pub search_query: String, pub results: Option>, //TODO: some loading? } #[derive(Properties, PartialEq, Eq)] pub struct OSSEProps { pub api_endpoint: String, pub initial_search_query: Option, } pub enum OSSEMessage { SearchSubmitted, SearchChanged(String), SearchFinished(Vec), } impl Component for OSSE { type Message = OSSEMessage; type Properties = OSSEProps; //TODO: No code duplication for fetching in create() and update() - NEED TO URL ENCODE AND DECODE SEARCH QUERY fn create(ctx: &Context) -> Self { let mut search_query = String::from(""); //we push an update message if inital_search_query is not none if let Some(initial_search_query) = ctx.props().initial_search_query.clone() { search_query = initial_search_query.clone(); let api_endpoint = ctx.props().api_endpoint.clone(); ctx.link().send_future(async move { let endpoint = format!("{}/search/{}", api_endpoint, initial_search_query); let fetched_response = Request::get(endpoint.as_str()).send().await.unwrap(); let fetched_results: Vec = match fetched_response.json().await { Err(e) => panic!("Im panic: {}", e), Ok(json) => json, }; OSSEMessage::SearchFinished(fetched_results) }); } OSSE { search_query, results: None, } } fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { match msg { OSSEMessage::SearchSubmitted => { let api_endpoint = ctx.props().api_endpoint.clone(); let search_query = self.search_query.clone(); let navigator = ctx.link().navigator().unwrap(); navigator.push(&Route::OSSESearch { query: search_query.clone() }); ctx.link().send_future(async move { let endpoint = format!("{}/search/{}", api_endpoint, search_query); let fetched_response = Request::get(endpoint.as_str()).send().await.unwrap(); let fetched_results: Vec = match fetched_response.json().await { Err(e) => panic!("Im panic: {}", e), Ok(json) => json, }; OSSEMessage::SearchFinished(fetched_results) }); false }, OSSEMessage::SearchChanged(search_query) => { self.search_query = search_query; true }, OSSEMessage::SearchFinished(search_results) => { self.results = Some(search_results); true }, } } fn view(&self, ctx: &Context) -> Html { let onsubmit = ctx.link().callback(|event: SubmitEvent| { event.prevent_default(); OSSEMessage::SearchSubmitted }); let oninput = ctx.link().callback(|event: InputEvent| { let target: EventTarget = event .target() .expect("Event should have a target when dispatched"); let input = target.unchecked_into::().value(); OSSEMessage::SearchChanged(input) }); let display_results = |maybe_results: &Option>| -> Html { let maybe_results = maybe_results.as_ref(); if maybe_results.is_none() { return html! {}; } let results = maybe_results.unwrap(); if !results.is_empty() { results .iter() .sorted() .map(|r| { html! {
} }) .collect::() } else { html! {

{"No results!"}

} } }; html! { <>
//SET AT MIDDLE OF VIEWPORT IF NO SEARCHING AND TOP 25% IF SEARCHING
{"OSSE"}

{"Your favorite independent search engine."}

{display_results(&self.results)}
} } } //Your favorite search engine in navbar //Search in middle