mirror of
https://github.com/Nutomic/ibis.git
synced 2024-11-29 10:01:10 +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(FederationMiddleware::new(config))
|
||||||
.layer(CorsLayer::permissive());
|
.layer(CorsLayer::permissive());
|
||||||
|
|
||||||
dbg!(&addr, &hostname);
|
|
||||||
Server::bind(&addr).serve(app.into_make_service()).await?;
|
Server::bind(&addr).serve(app.into_make_service()).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -12,9 +12,7 @@ pub fn App() -> impl IntoView {
|
||||||
provide_meta_context();
|
provide_meta_context();
|
||||||
view! {
|
view! {
|
||||||
<>
|
<>
|
||||||
<Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/>
|
|
||||||
<Stylesheet id="leptos" href="/style.css"/>
|
<Stylesheet id="leptos" href="/style.css"/>
|
||||||
<Meta name="description" content="Leptos implementation of a HackerNews demo."/>
|
|
||||||
<Router>
|
<Router>
|
||||||
<Nav />
|
<Nav />
|
||||||
<main>
|
<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 app;
|
||||||
pub mod article;
|
pub mod article;
|
||||||
pub mod nav;
|
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