Initial commit
This commit is contained in:
2
src/components/mod.rs
Normal file
2
src/components/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod task_item;
|
||||
pub mod tasks_list;
|
||||
9
src/components/task_item.rs
Normal file
9
src/components/task_item.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
use contextswitch_types::Task;
|
||||
use sycamore::prelude::*;
|
||||
|
||||
#[component(TaskItem<G>)]
|
||||
pub fn task_item(value: ReadSignal<Task>) -> View<G> {
|
||||
view! {
|
||||
p { (value.get().description) }
|
||||
}
|
||||
}
|
||||
18
src/components/tasks_list.rs
Normal file
18
src/components/tasks_list.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
use crate::components::task_item::TaskItem;
|
||||
use contextswitch_types::Task;
|
||||
use sycamore::prelude::*;
|
||||
|
||||
#[component(TasksList<G>)]
|
||||
pub fn tasks_list(value: ReadSignal<Vec<Task>>) -> View<G> {
|
||||
view! {
|
||||
ul {
|
||||
Keyed(KeyedProps {
|
||||
iterable: value,
|
||||
template: move |task| view! {
|
||||
TaskItem(Signal::new(task).handle()) // TODO : Signal?
|
||||
},
|
||||
key: |task| task.uuid,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
17
src/error_pages.rs
Normal file
17
src/error_pages.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use perseus::{ErrorPages, Html};
|
||||
use sycamore::view;
|
||||
|
||||
pub fn get_error_pages<G: Html>() -> ErrorPages<G> {
|
||||
let mut error_pages = ErrorPages::new(|url, status, err, _| {
|
||||
view! {
|
||||
p { (format!("An error with HTTP code {} occurred at '{}': '{}'.", status, url, err)) }
|
||||
}
|
||||
});
|
||||
error_pages.add_page(404, |_, _, _, _| {
|
||||
view! {
|
||||
p { "Page not found." }
|
||||
}
|
||||
});
|
||||
|
||||
error_pages
|
||||
}
|
||||
17
src/lib.rs
Normal file
17
src/lib.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
mod components;
|
||||
mod error_pages;
|
||||
mod templates;
|
||||
|
||||
use perseus::define_app;
|
||||
|
||||
define_app! {
|
||||
templates: [
|
||||
crate::templates::index::get_template::<G>(),
|
||||
crate::templates::list_tasks::get_template::<G>(),
|
||||
crate::templates::about::get_template::<G>()
|
||||
],
|
||||
error_pages: crate::error_pages::get_error_pages(),
|
||||
static_aliases: {
|
||||
"/test.txt" => "static/test.txt"
|
||||
}
|
||||
}
|
||||
21
src/templates/about.rs
Normal file
21
src/templates/about.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
use perseus::Template;
|
||||
use sycamore::prelude::{component, view, Html, SsrNode, View};
|
||||
|
||||
#[perseus::template(AboutPage)]
|
||||
#[component(AboutPage<G>)]
|
||||
pub fn about_page() -> View<G> {
|
||||
view! {
|
||||
p { "About." }
|
||||
}
|
||||
}
|
||||
|
||||
#[perseus::head]
|
||||
pub fn head() -> View<SsrNode> {
|
||||
view! {
|
||||
title { "About Page | Perseus Example – Basic" }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_template<G: Html>() -> Template<G> {
|
||||
Template::new("about").template(about_page).head(head)
|
||||
}
|
||||
55
src/templates/index.rs
Normal file
55
src/templates/index.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
use perseus::{
|
||||
http::header::{HeaderMap, HeaderName},
|
||||
Html, RenderFnResultWithCause, SsrNode, Template,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sycamore::prelude::{component, view, View};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct IndexPageProps {
|
||||
pub greeting: String,
|
||||
}
|
||||
|
||||
#[perseus::template(IndexPage)]
|
||||
#[component(IndexPage<G>)]
|
||||
pub fn index_page(props: IndexPageProps) -> View<G> {
|
||||
view! {
|
||||
p {(props.greeting)}
|
||||
a(href = "about", id = "about-link") { "About!" }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_template<G: Html>() -> Template<G> {
|
||||
Template::new("index")
|
||||
.build_state_fn(get_build_props)
|
||||
.template(index_page)
|
||||
.head(head)
|
||||
.set_headers_fn(set_headers)
|
||||
}
|
||||
|
||||
#[perseus::head]
|
||||
pub fn head(_props: IndexPageProps) -> View<SsrNode> {
|
||||
view! {
|
||||
title { "Index Page | Perseus Example – Basic" }
|
||||
}
|
||||
}
|
||||
|
||||
#[perseus::autoserde(build_state)]
|
||||
pub async fn get_build_props(
|
||||
_path: String,
|
||||
_locale: String,
|
||||
) -> RenderFnResultWithCause<IndexPageProps> {
|
||||
Ok(IndexPageProps {
|
||||
greeting: "Hello World!".to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
#[perseus::autoserde(set_headers)]
|
||||
pub fn set_headers(props: Option<IndexPageProps>) -> HeaderMap {
|
||||
let mut map = HeaderMap::new();
|
||||
map.insert(
|
||||
HeaderName::from_lowercase(b"x-greeting").unwrap(),
|
||||
props.unwrap().greeting.parse().unwrap(),
|
||||
);
|
||||
map
|
||||
}
|
||||
52
src/templates/list_tasks.rs
Normal file
52
src/templates/list_tasks.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use crate::components::tasks_list::TasksList;
|
||||
use contextswitch_types::Task;
|
||||
use perseus::{Html, RenderFnResultWithCause, Template};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sycamore::prelude::*;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ListTasksProps {
|
||||
tasks: Vec<Task>,
|
||||
}
|
||||
|
||||
#[perseus::template(ListTasksPage)]
|
||||
#[component(ListTasksPage<G>)]
|
||||
pub fn list_tasks_page(ListTasksProps { tasks }: ListTasksProps) -> View<G> {
|
||||
let ltasks: Signal<Vec<Task>> = Signal::new(Vec::new());
|
||||
|
||||
if G::IS_BROWSER {
|
||||
perseus::spawn_local(cloned!(ltasks => async move {
|
||||
let body = reqwasm::http::Request::get("http://localhost:8000/tasks?filter=%2Bwork+test")
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap();
|
||||
ltasks.set(serde_json::from_str(&body).unwrap());
|
||||
}));
|
||||
}
|
||||
|
||||
view! {
|
||||
TasksList(ltasks.handle())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_template<G: Html>() -> Template<G> {
|
||||
Template::new("list_tasks")
|
||||
.build_state_fn(get_build_state)
|
||||
.template(list_tasks_page)
|
||||
}
|
||||
|
||||
#[perseus::autoserde(build_state)]
|
||||
pub async fn get_build_state(
|
||||
_path: String,
|
||||
_locale: String,
|
||||
) -> RenderFnResultWithCause<ListTasksProps> {
|
||||
let body: String = ureq::get("http://localhost:8000/tasks?filter=%2Bwork+test")
|
||||
.call()?
|
||||
.into_string()?;
|
||||
Ok(ListTasksProps {
|
||||
tasks: serde_json::from_str(&body)?,
|
||||
})
|
||||
}
|
||||
3
src/templates/mod.rs
Normal file
3
src/templates/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod about;
|
||||
pub mod index;
|
||||
pub mod list_tasks;
|
||||
Reference in New Issue
Block a user