mirror of
https://github.com/Nutomic/ibis.git
synced 2024-11-25 19:01:09 +00:00
cleanup
This commit is contained in:
parent
42d382d19e
commit
db12e5f1e9
4 changed files with 0 additions and 293 deletions
|
@ -98,7 +98,6 @@ pub async fn start(hostname: &str, database_url: &str) -> MyResult<()> {
|
|||
.layer(FederationMiddleware::new(config))
|
||||
.layer(CorsLayer::permissive());
|
||||
|
||||
dbg!(&addr, &hostname);
|
||||
Server::bind(&addr).serve(app.into_make_service()).await?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -12,9 +12,7 @@ pub fn App() -> impl IntoView {
|
|||
provide_meta_context();
|
||||
view! {
|
||||
<>
|
||||
<Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/>
|
||||
<Stylesheet id="leptos" href="/style.css"/>
|
||||
<Meta name="description" content="Leptos implementation of a HackerNews demo."/>
|
||||
<Router>
|
||||
<Nav />
|
||||
<main>
|
||||
|
|
|
@ -1,156 +0,0 @@
|
|||
use crate::api;
|
||||
use leptos::*;
|
||||
use leptos_router::*;
|
||||
|
||||
fn category(from: &str) -> &'static str {
|
||||
match from {
|
||||
"new" => "newest",
|
||||
"show" => "show",
|
||||
"ask" => "ask",
|
||||
"job" => "jobs",
|
||||
_ => "news",
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Stories() -> impl IntoView {
|
||||
let query = use_query_map();
|
||||
let params = use_params_map();
|
||||
let page = move || {
|
||||
query
|
||||
.with(|q| q.get("page").and_then(|page| page.parse::<usize>().ok()))
|
||||
.unwrap_or(1)
|
||||
};
|
||||
let story_type = move || {
|
||||
params
|
||||
.with(|p| p.get("stories").cloned())
|
||||
.unwrap_or_else(|| "top".to_string())
|
||||
};
|
||||
let stories = create_resource(
|
||||
move || (page(), story_type()),
|
||||
move |(page, story_type)| async move {
|
||||
let path = format!("{}?page={}", category(&story_type), page);
|
||||
api::fetch_api::<Vec<api::Story>>(&api::story(&path)).await
|
||||
},
|
||||
);
|
||||
let (pending, set_pending) = create_signal(false);
|
||||
|
||||
let hide_more_link = move || {
|
||||
stories.get().unwrap_or(None).unwrap_or_default().len() < 28
|
||||
|| pending()
|
||||
};
|
||||
|
||||
view! {
|
||||
<div class="news-view">
|
||||
<div class="news-list-nav">
|
||||
<span>
|
||||
{move || if page() > 1 {
|
||||
view! {
|
||||
|
||||
<a class="page-link"
|
||||
href=move || format!("/{}?page={}", story_type(), page() - 1)
|
||||
attr:aria_label="Previous Page"
|
||||
>
|
||||
"< prev"
|
||||
</a>
|
||||
}.into_any()
|
||||
} else {
|
||||
view! {
|
||||
|
||||
<span class="page-link disabled" aria-hidden="true">
|
||||
"< prev"
|
||||
</span>
|
||||
}.into_any()
|
||||
}}
|
||||
</span>
|
||||
<span>"page " {page}</span>
|
||||
<span class="page-link"
|
||||
class:disabled=hide_more_link
|
||||
aria-hidden=hide_more_link
|
||||
>
|
||||
<a href=move || format!("/{}?page={}", story_type(), page() + 1)
|
||||
aria-label="Next Page"
|
||||
>
|
||||
"more >"
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<main class="news-list">
|
||||
<div>
|
||||
<Transition
|
||||
fallback=move || view! { <p>"Loading..."</p> }
|
||||
set_pending
|
||||
>
|
||||
{move || match stories.get() {
|
||||
None => None,
|
||||
Some(None) => Some(view! { <p>"Error loading stories."</p> }.into_any()),
|
||||
Some(Some(stories)) => {
|
||||
Some(view! {
|
||||
<ul>
|
||||
<For
|
||||
each=move || stories.clone()
|
||||
key=|story| story.id
|
||||
let:story
|
||||
>
|
||||
<Story story/>
|
||||
</For>
|
||||
</ul>
|
||||
}.into_any())
|
||||
}
|
||||
}}
|
||||
</Transition>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn Story(story: api::Story) -> impl IntoView {
|
||||
view! {
|
||||
<li class="news-item">
|
||||
<span class="score">{story.points}</span>
|
||||
<span class="title">
|
||||
{if !story.url.starts_with("item?id=") {
|
||||
view! {
|
||||
<span>
|
||||
<a href=story.url target="_blank" rel="noreferrer">
|
||||
{story.title.clone()}
|
||||
</a>
|
||||
<span class="host">"("{story.domain}")"</span>
|
||||
</span>
|
||||
}.into_view()
|
||||
} else {
|
||||
let title = story.title.clone();
|
||||
view! { <A href=format!("/stories/{}", story.id)>{title.clone()}</A> }.into_view()
|
||||
}}
|
||||
</span>
|
||||
<br />
|
||||
<span class="meta">
|
||||
{if story.story_type != "job" {
|
||||
view! {
|
||||
<span>
|
||||
{"by "}
|
||||
{story.user.map(|user| view ! { <A href=format!("/users/{user}")>{user.clone()}</A>})}
|
||||
{format!(" {} | ", story.time_ago)}
|
||||
<A href=format!("/stories/{}", story.id)>
|
||||
{if story.comments_count.unwrap_or_default() > 0 {
|
||||
format!("{} comments", story.comments_count.unwrap_or_default())
|
||||
} else {
|
||||
"discuss".into()
|
||||
}}
|
||||
</A>
|
||||
</span>
|
||||
}.into_view()
|
||||
} else {
|
||||
let title = story.title.clone();
|
||||
view! { <A href=format!("/item/{}", story.id)>{title.clone()}</A> }.into_view()
|
||||
}}
|
||||
</span>
|
||||
{(story.story_type != "link").then(|| view! {
|
||||
" "
|
||||
<span class="label">{story.story_type}</span>
|
||||
})}
|
||||
</li>
|
||||
}
|
||||
}
|
|
@ -2,137 +2,3 @@ pub mod api;
|
|||
pub mod app;
|
||||
pub mod article;
|
||||
pub mod nav;
|
||||
|
||||
use leptos::error::Result;
|
||||
use leptos::*;
|
||||
use log::info;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Cat {
|
||||
url: String,
|
||||
}
|
||||
|
||||
type CatCount = usize;
|
||||
|
||||
async fn fetch_cats(count: CatCount) -> Result<Vec<String>> {
|
||||
if count > 0 {
|
||||
// make the request
|
||||
let res = reqwest::get(&format!(
|
||||
"https://api.thecatapi.com/v1/images/search?limit={count}",
|
||||
))
|
||||
.await?
|
||||
.json::<Vec<Cat>>()
|
||||
.await?
|
||||
// extract the URL field for each cat
|
||||
.into_iter()
|
||||
.take(count)
|
||||
.map(|cat| cat.url)
|
||||
.collect::<Vec<_>>();
|
||||
Ok(res)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: import this from backend somehow
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct DbInstance {
|
||||
pub id: i32,
|
||||
pub ap_id: Url,
|
||||
pub articles_url: Url,
|
||||
pub inbox_url: String,
|
||||
#[serde(skip)]
|
||||
pub public_key: String,
|
||||
#[serde(skip)]
|
||||
pub private_key: Option<String>,
|
||||
pub local: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct InstanceView {
|
||||
pub instance: DbInstance,
|
||||
pub following: Vec<DbInstance>,
|
||||
}
|
||||
|
||||
async fn fetch_instance(url: &str) -> Result<InstanceView> {
|
||||
let res = reqwest::get(url).await?.json::<InstanceView>().await?;
|
||||
info!("{:?}", &res);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn fetch_example() -> impl IntoView {
|
||||
let (cat_count, set_cat_count) = create_signal::<CatCount>(0);
|
||||
|
||||
// we use local_resource here because
|
||||
// 1) our error type isn't serializable/deserializable
|
||||
// 2) we're not doing backend-side rendering in this example anyway
|
||||
// (during SSR, create_resource will begin loading on the backend and resolve on the client)
|
||||
let cats = create_local_resource(move || cat_count.get(), fetch_cats);
|
||||
//let instance = create_local_resource(move || "http://localhost:8131/api/v1/instance", fetch_instance);
|
||||
|
||||
let fallback = move |errors: RwSignal<Errors>| {
|
||||
let error_list = move || {
|
||||
errors.with(|errors| {
|
||||
errors
|
||||
.iter()
|
||||
.map(|(_, e)| view! { <li>{e.to_string()}</li> })
|
||||
.collect_view()
|
||||
})
|
||||
};
|
||||
|
||||
view! {
|
||||
<div class="error">
|
||||
<h2>"Error"</h2>
|
||||
<ul>{error_list}</ul>
|
||||
</div>
|
||||
}
|
||||
};
|
||||
|
||||
// the renderer can handle Option<_> and Result<_> states
|
||||
// by displaying nothing for None if the resource is still loading
|
||||
// and by using the ErrorBoundary fallback to catch Err(_)
|
||||
// so we'll just use `.and_then()` to map over the happy path
|
||||
let cats_view = move || {
|
||||
cats.and_then(|data| {
|
||||
data.iter()
|
||||
.map(|s| view! { <p><img src={s}/></p> })
|
||||
.collect_view()
|
||||
})
|
||||
};
|
||||
|
||||
/*
|
||||
let instance_view = move || {
|
||||
instance.and_then(|data| {
|
||||
view! { <h1>{data.instance.ap_id.to_string()}</h1> }
|
||||
})
|
||||
};
|
||||
*/
|
||||
|
||||
view! {
|
||||
//{instance_view}
|
||||
<div>
|
||||
<label>
|
||||
"How many cats would you like?"
|
||||
<input
|
||||
type="number"
|
||||
prop:value=move || cat_count.get().to_string()
|
||||
on:input=move |ev| {
|
||||
let val = event_target_value(&ev).parse::<CatCount>().unwrap_or(0);
|
||||
set_cat_count.set(val);
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
<Transition fallback=move || {
|
||||
view! { <div>"Loading (Suspense Fallback)..."</div> }
|
||||
}>
|
||||
<ErrorBoundary fallback>
|
||||
<div>
|
||||
{cats_view}
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
</Transition>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue