feat: switch Dioxus to fullstack, add a form for creating a project

This commit is contained in:
Matouš Volf 2024-08-17 00:30:17 +02:00
parent 283b3965db
commit 57705de44d
13 changed files with 944 additions and 50 deletions

829
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,14 @@ edition = "2021"
[dependencies]
diesel = { version = "2.2.2", features = ["postgres"] }
dioxus = { version = "0.5", features = ["web", "router"] }
dioxus = { version = "0.5", features = ["fullstack", "router"] }
# Debug
dioxus-logger = "0.5.1"
dotenvy = "0.15.7"
serde = "1.0.208"
[features]
default = []
server = ["dioxus/axum"]
web = ["dioxus/web"]

View File

@ -5,7 +5,7 @@ name = "todo-baggins"
# Dioxus App Default Platform
# web, desktop, fullstack
default_platform = "web"
default_platform = "fullstack"
# `build` & `serve` dist path
out_dir = "dist"

View File

@ -14,7 +14,7 @@ stdout_logfile_maxbytes=0
redirect_stderr=true
[program:dx]
command=dx serve --port 8000
command=dx serve
directory=/srv/app
autostart=true
autorestart=true

11
src/components/app.rs Normal file
View File

@ -0,0 +1,11 @@
use crate::route::Route;
use dioxus::core_macro::rsx;
use dioxus::dioxus_core::Element;
use dioxus::prelude::*;
#[component]
pub(crate) fn App() -> Element {
rsx! {
Router::<Route> {}
}
}

View File

@ -0,0 +1,23 @@
use dioxus::core_macro::{component, rsx};
use dioxus::dioxus_core::Element;
use dioxus::prelude::*;
#[component]
pub(crate) fn FormProject(onsubmit: EventHandler<String>) -> Element {
rsx! {
form {
onsubmit: move |event| {
onsubmit(event.values().get("title").unwrap().as_value());
},
input {
r#type: "text",
name: "title",
placeholder: "title"
}
button {
r#type: "submit",
"create"
}
}
}
}

18
src/components/home.rs Normal file
View File

@ -0,0 +1,18 @@
use crate::components::form_project::FormProject;
use crate::server::projects::create_project;
use dioxus::core_macro::rsx;
use dioxus::dioxus_core::Element;
use dioxus::prelude::*;
#[component]
pub(crate) fn Home() -> Element {
rsx! {
FormProject {
onsubmit: move |title| {
spawn(async move {
let _ = create_project(title).await;
});
}
}
}
}

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

@ -0,0 +1,3 @@
pub(crate) mod app;
pub(crate) mod form_project;
pub(crate) mod home;

View File

@ -1,52 +1,22 @@
#![allow(non_snake_case)]
mod components;
mod models;
mod route;
mod schema;
mod server;
use components::app::App;
use dioxus::prelude::*;
use dioxus_logger::tracing::{info, Level};
#[derive(Clone, Routable, Debug, PartialEq)]
enum Route {
#[route("/")]
Home {},
#[route("/blog/:id")]
Blog { id: i32 },
}
fn main() {
// Init logger
dioxus_logger::init(Level::INFO).expect("failed to init logger");
dioxus_logger::init(Level::INFO).expect("failed to initialize logger");
info!("starting app");
launch(App);
}
fn App() -> Element {
rsx! {
Router::<Route> {}
}
}
let cfg = server_only!(
dioxus::fullstack::Config::new().addr(std::net::SocketAddr::from(([0, 0, 0, 0], 8000)))
);
#[component]
fn Blog(id: i32) -> Element {
rsx! {
Link { to: Route::Home {}, "Go to counter" }
"Blog post {id}"
}
}
#[component]
fn Home() -> Element {
let mut count = use_signal(|| 0);
rsx! {
Link {
to: Route::Blog {
id: count()
},
"Go to blog"
}
div {
h1 { "High-Five counter: {count}" }
button { onclick: move |_| count += 1, "Up high!" }
button { onclick: move |_| count -= 1, "Down low!" }
}
}
LaunchBuilder::fullstack().with_cfg(cfg).launch(App);
}

8
src/route/mod.rs Normal file
View File

@ -0,0 +1,8 @@
use crate::components::home::Home;
use dioxus::prelude::*;
#[derive(Clone, Routable, Debug, PartialEq)]
pub(crate) enum Route {
#[route("/")]
Home {},
}

View File

@ -0,0 +1,12 @@
use diesel::pg::PgConnection;
use diesel::prelude::*;
use dotenvy::dotenv;
use std::env;
pub(crate) fn establish_database_connection() -> PgConnection {
dotenv().ok();
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
PgConnection::establish(&database_url)
.unwrap_or_else(|_| panic!("error connecting to {}", database_url))
}

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

@ -0,0 +1,2 @@
mod database_connection;
pub(crate) mod projects;

21
src/server/projects.rs Normal file
View File

@ -0,0 +1,21 @@
use crate::models::project::{NewProject, Project};
use crate::server::database_connection::establish_database_connection;
use diesel::{RunQueryDsl, SelectableHelper};
use dioxus::prelude::*;
#[server]
pub(crate) async fn create_project(title: String) -> Result<Project, ServerFnError> {
use crate::schema::projects;
let mut connection = establish_database_connection();
let new_project = NewProject {
title: title.as_str(),
};
Ok(diesel::insert_into(projects::table)
.values(&new_project)
.returning(Project::as_returning())
.get_result(&mut connection)
.expect("error saving a new project"))
}