Initial commit

This commit is contained in:
2021-12-30 15:54:48 +00:00
commit e6841826f2
16 changed files with 1401 additions and 0 deletions

2
src/components/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod task_item;
pub mod tasks_list;

View 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) }
}
}

View 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
View 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
View 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
View 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
View 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
}

View 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
View File

@@ -0,0 +1,3 @@
pub mod about;
pub mod index;
pub mod list_tasks;