works, lets do updates now

This commit is contained in:
2023-09-17 15:45:02 +02:00
parent 849798f7cb
commit 8c0a4c53b8
6 changed files with 97 additions and 54 deletions

13
Cargo.lock generated
View File

@@ -132,6 +132,7 @@ checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
dependencies = [
"async-trait",
"axum-core",
"axum-macros",
"bitflags 1.3.2",
"bytes",
"futures-util",
@@ -174,6 +175,18 @@ dependencies = [
"tower-service",
]
[[package]]
name = "axum-macros"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdca6a10ecad987bda04e95606ef85a5417dcaac1a78455242d72e031e2b6b62"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.35",
]
[[package]]
name = "axum-prometheus"
version = "0.4.0"

View File

@@ -51,7 +51,7 @@ features = ["derive"]
[dependencies.axum]
version = "0.6"
features = ["headers"]
features = ["headers", "macros"]
[dependencies.tokio]
version = "1"

View File

@@ -7,9 +7,9 @@ pub mod crud {
#[async_trait]
pub trait Create: Sized {
type Id;
type Filter;
type Info;
type Id: Sized + Send + Sync + 'static;
type Filter: Sized + Send + Sync + 'static;
type Info: Sized + Send + Sync + 'static;
async fn create(
ctx: &Context,
@@ -42,14 +42,14 @@ pub mod crud {
pub trait Update: Sized {
type Id;
type Filter;
type Update;
type UpdateElement;
async fn update(
ctx: &Context,
pool: &sqlite::Pool,
filter: Self::Filter,
id: Self::Id,
update: Self::Update,
update: Self::UpdateElement,
) -> Result<Option<Self>, Error>;
}
@@ -116,7 +116,7 @@ pub mod route {
use crate::AppState;
use axum::{
body::BoxBody,
body::{BoxBody, HttpBody},
extract::{Path, Query, State},
http::HeaderMap,
response::Response,
@@ -132,7 +132,6 @@ pub mod route {
pub trait Create: super::crud::Create {
type Form: Send + Sync + 'static;
type ParentUrlParams: Send + Sync + 'static;
type UrlParams: Send + Sync + 'static;
const URL: &'static str;
@@ -141,13 +140,9 @@ pub mod route {
user: Extension<crate::models::user::User>,
state: State<AppState>,
headers: HeaderMap,
path: Path<(Self::ParentUrlParams, Self::UrlParams)>,
path: Path<Self::UrlParams>,
form: Form<Self::Form>,
) -> Result<Response<BoxBody>, crate::Error>;
fn with_prefix(prefix: &'static str) -> String {
format!("{}{}", prefix, Self::URL)
}
}
#[async_trait]
@@ -164,15 +159,40 @@ pub mod route {
query: Query<Self::QueryParams>,
path: Path<Self::UrlParams>,
) -> Result<Response<BoxBody>, crate::Error>;
fn with_prefix(prefix: &'static str) -> String {
format!("{}{}", prefix, Self::URL)
}
#[async_trait]
pub trait Update: super::crud::Update {
type UrlParams: Send + Sync + 'static;
type UpdateForm: Send + Sync + 'static;
const URL: &'static str;
async fn start(
user: Extension<crate::models::user::User>,
state: State<AppState>,
headers: HeaderMap,
path: Path<Self::UrlParams>,
) -> Result<Response<BoxBody>, crate::Error>;
async fn save(
user: Extension<crate::models::user::User>,
state: State<AppState>,
headers: HeaderMap,
path: Path<Self::UrlParams>,
form: Form<Self::UpdateForm>,
) -> Result<Response<BoxBody>, crate::Error>;
async fn cancel(
user: Extension<crate::models::user::User>,
state: State<AppState>,
headers: HeaderMap,
path: Path<Self::UrlParams>,
) -> Result<Response<BoxBody>, crate::Error>;
}
#[async_trait]
pub trait Delete: super::crud::Delete {
type ParentUrlParams: Send + Sync + 'static;
type UrlParams: Send + Sync + 'static;
const URL: &'static str;
@@ -181,11 +201,15 @@ pub mod route {
user: Extension<crate::models::user::User>,
state: State<AppState>,
headers: HeaderMap,
path: Path<(Self::ParentUrlParams, Self::UrlParams)>,
path: Path<Self::UrlParams>,
) -> Result<Response<BoxBody>, crate::Error>;
}
fn with_prefix(prefix: &'static str) -> String {
format!("{}{}", prefix, Self::URL)
}
pub trait Router: Create + Delete {
fn get<B>() -> axum::Router<AppState, B>
where
B: HttpBody + Send + 'static,
<B as HttpBody>::Data: Send,
<B as HttpBody>::Error: std::error::Error + Sync + Send;
}
}

View File

@@ -2,7 +2,7 @@ pub mod list;
pub use list::List;
use axum::{
body::BoxBody,
body::{BoxBody, HttpBody},
extract::{Form, Path},
http::HeaderMap,
response::{IntoResponse, Redirect, Response},
@@ -215,7 +215,7 @@ impl crud::Create for Todo {
}
#[derive(Debug)]
pub enum Update {
pub enum UpdateElement {
State(State),
Description(String),
}
@@ -224,7 +224,7 @@ pub enum Update {
impl crud::Update for Todo {
type Id = Uuid;
type Filter = Filter;
type Update = Update;
type UpdateElement = UpdateElement;
#[tracing::instrument]
async fn update(
@@ -232,13 +232,13 @@ impl crud::Update for Todo {
pool: &sqlite::Pool,
filter: Self::Filter,
id: Self::Id,
update: Self::Update,
update_element: Self::UpdateElement,
) -> Result<Option<Self>, Error> {
let user_id = ctx.user.id.to_string();
let trip_id_param = filter.trip_id.to_string();
let todo_id_param = id.to_string();
match update {
Update::State(state) => {
match update_element {
UpdateElement::State(state) => {
let done = state == State::Done;
let result = crate::query_one!(
@@ -270,7 +270,7 @@ impl crud::Update for Todo {
Ok(result)
}
Update::Description(new_description) => {
UpdateElement::Description(new_description) => {
let user_id = ctx.user.id.to_string();
let trip_id_param = filter.trip_id.to_string();
let todo_id_param = id.to_string();
@@ -566,17 +566,16 @@ pub struct TripTodoNew {
#[async_trait]
impl route::Create for Todo {
type Form = TripTodoNew;
type ParentUrlParams = (Uuid,);
type UrlParams = ();
type UrlParams = (Uuid,);
const URL: &'static str = "/new";
const URL: &'static str = "/:id/todo/new";
#[tracing::instrument]
async fn create(
Extension(current_user): Extension<crate::models::user::User>,
axum::extract::State(state): axum::extract::State<AppState>,
headers: HeaderMap,
Path(((trip_id,), ())): Path<(Self::ParentUrlParams, Self::UrlParams)>,
Path((trip_id,)): Path<Self::UrlParams>,
Form(form): Form<Self::Form>,
) -> Result<Response<BoxBody>, crate::Error> {
let ctx = Context::build(current_user);
@@ -615,17 +614,16 @@ impl route::Create for Todo {
#[async_trait]
impl route::Delete for Todo {
type ParentUrlParams = (Uuid,);
type UrlParams = (Uuid,);
type UrlParams = (Uuid, Uuid);
const URL: &'static str = "/:id/delete";
const URL: &'static str = "/:id/todo/:id/delete";
#[tracing::instrument]
async fn delete(
Extension(current_user): Extension<crate::models::user::User>,
axum::extract::State(state): axum::extract::State<AppState>,
_headers: HeaderMap,
Path(((trip_id,), (todo_id,))): Path<(Self::ParentUrlParams, Self::UrlParams)>,
Path((trip_id, todo_id)): Path<Self::UrlParams>,
) -> Result<Response<BoxBody>, crate::Error> {
let ctx = Context::build(current_user);
let deleted = <Self as crud::Delete>::delete(
@@ -659,3 +657,19 @@ impl route::Delete for Todo {
}
}
}
impl route::Router for Todo {
fn get<B>() -> axum::Router<AppState, B>
where
B: HttpBody + Send + 'static,
<B as HttpBody>::Data: Send,
<B as HttpBody>::Error: std::error::Error + Sync + Send,
{
axum::Router::new()
.route("/new", axum::routing::post(<Self as route::Create>::create))
.route(
"/:id/delete",
axum::routing::post(<Self as route::Delete>::delete),
)
}
}

View File

@@ -12,7 +12,10 @@ use uuid::Uuid;
use std::{fmt, time::Duration};
use tower::{timeout::TimeoutLayer, ServiceBuilder};
use crate::{components::route, AppState, Error, RequestError, TopLevelPage};
use crate::{
components::{self, route::Router as _},
AppState, Error, RequestError, TopLevelPage,
};
use super::auth;
@@ -151,18 +154,7 @@ pub fn router(state: AppState) -> Router {
.route("/:id/todo/:id/edit", post(trip_todo_edit))
.route("/:id/todo/:id/edit/save", post(trip_todo_edit_save))
.route("/:id/todo/:id/edit/cancel", post(trip_todo_edit_cancel))
.route(
&<crate::components::trips::todos::Todo as route::Create>::with_prefix(
"/:id/todo",
),
post(<crate::components::trips::todos::Todo as route::Create>::create),
)
.route(
&<crate::components::trips::todos::Todo as route::Delete>::with_prefix(
"/:id/todo",
),
post(<crate::components::trips::todos::Todo as route::Delete>::delete),
),
.nest("/:id/todo/", components::trips::todos::Todo::get()),
)
.nest(
(&TopLevelPage::Inventory.path()).into(),

View File

@@ -1281,7 +1281,7 @@ pub async fn trip_todo_done_htmx(
&state.database_pool,
todos::Filter { trip_id },
todo_id,
todos::Update::State(components::trips::todos::State::Done),
todos::UpdateElement::State(components::trips::todos::State::Done),
)
.await?;
@@ -1317,7 +1317,7 @@ pub async fn trip_todo_done(
&state.database_pool,
todos::Filter { trip_id },
todo_id,
todos::Update::State(components::trips::todos::State::Done),
todos::UpdateElement::State(components::trips::todos::State::Done),
)
.await?;
@@ -1336,7 +1336,7 @@ pub async fn trip_todo_undone_htmx(
&state.database_pool,
todos::Filter { trip_id },
todo_id,
todos::Update::State(components::trips::todos::State::Todo),
todos::UpdateElement::State(components::trips::todos::State::Todo),
)
.await?;
@@ -1372,7 +1372,7 @@ pub async fn trip_todo_undone(
&state.database_pool,
todos::Filter { trip_id },
todo_id,
todos::Update::State(components::trips::todos::State::Todo),
todos::UpdateElement::State(components::trips::todos::State::Todo),
)
.await?;
@@ -1429,7 +1429,7 @@ pub async fn trip_todo_edit_save(
&state.database_pool,
todos::Filter { trip_id },
todo_id,
todos::Update::Description(form.description),
todos::UpdateElement::Description(form.description),
)
.await?;