works, lets do updates now
This commit is contained in:
13
Cargo.lock
generated
13
Cargo.lock
generated
@@ -132,6 +132,7 @@ checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum-core",
|
"axum-core",
|
||||||
|
"axum-macros",
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@@ -174,6 +175,18 @@ dependencies = [
|
|||||||
"tower-service",
|
"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]]
|
[[package]]
|
||||||
name = "axum-prometheus"
|
name = "axum-prometheus"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ features = ["derive"]
|
|||||||
|
|
||||||
[dependencies.axum]
|
[dependencies.axum]
|
||||||
version = "0.6"
|
version = "0.6"
|
||||||
features = ["headers"]
|
features = ["headers", "macros"]
|
||||||
|
|
||||||
[dependencies.tokio]
|
[dependencies.tokio]
|
||||||
version = "1"
|
version = "1"
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ pub mod crud {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Create: Sized {
|
pub trait Create: Sized {
|
||||||
type Id;
|
type Id: Sized + Send + Sync + 'static;
|
||||||
type Filter;
|
type Filter: Sized + Send + Sync + 'static;
|
||||||
type Info;
|
type Info: Sized + Send + Sync + 'static;
|
||||||
|
|
||||||
async fn create(
|
async fn create(
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
@@ -42,14 +42,14 @@ pub mod crud {
|
|||||||
pub trait Update: Sized {
|
pub trait Update: Sized {
|
||||||
type Id;
|
type Id;
|
||||||
type Filter;
|
type Filter;
|
||||||
type Update;
|
type UpdateElement;
|
||||||
|
|
||||||
async fn update(
|
async fn update(
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
pool: &sqlite::Pool,
|
pool: &sqlite::Pool,
|
||||||
filter: Self::Filter,
|
filter: Self::Filter,
|
||||||
id: Self::Id,
|
id: Self::Id,
|
||||||
update: Self::Update,
|
update: Self::UpdateElement,
|
||||||
) -> Result<Option<Self>, Error>;
|
) -> Result<Option<Self>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ pub mod route {
|
|||||||
|
|
||||||
use crate::AppState;
|
use crate::AppState;
|
||||||
use axum::{
|
use axum::{
|
||||||
body::BoxBody,
|
body::{BoxBody, HttpBody},
|
||||||
extract::{Path, Query, State},
|
extract::{Path, Query, State},
|
||||||
http::HeaderMap,
|
http::HeaderMap,
|
||||||
response::Response,
|
response::Response,
|
||||||
@@ -132,7 +132,6 @@ pub mod route {
|
|||||||
pub trait Create: super::crud::Create {
|
pub trait Create: super::crud::Create {
|
||||||
type Form: Send + Sync + 'static;
|
type Form: Send + Sync + 'static;
|
||||||
|
|
||||||
type ParentUrlParams: Send + Sync + 'static;
|
|
||||||
type UrlParams: Send + Sync + 'static;
|
type UrlParams: Send + Sync + 'static;
|
||||||
|
|
||||||
const URL: &'static str;
|
const URL: &'static str;
|
||||||
@@ -141,13 +140,9 @@ pub mod route {
|
|||||||
user: Extension<crate::models::user::User>,
|
user: Extension<crate::models::user::User>,
|
||||||
state: State<AppState>,
|
state: State<AppState>,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
path: Path<(Self::ParentUrlParams, Self::UrlParams)>,
|
path: Path<Self::UrlParams>,
|
||||||
form: Form<Self::Form>,
|
form: Form<Self::Form>,
|
||||||
) -> Result<Response<BoxBody>, crate::Error>;
|
) -> Result<Response<BoxBody>, crate::Error>;
|
||||||
|
|
||||||
fn with_prefix(prefix: &'static str) -> String {
|
|
||||||
format!("{}{}", prefix, Self::URL)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@@ -164,15 +159,40 @@ pub mod route {
|
|||||||
query: Query<Self::QueryParams>,
|
query: Query<Self::QueryParams>,
|
||||||
path: Path<Self::UrlParams>,
|
path: Path<Self::UrlParams>,
|
||||||
) -> Result<Response<BoxBody>, crate::Error>;
|
) -> 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]
|
#[async_trait]
|
||||||
pub trait Delete: super::crud::Delete {
|
pub trait Delete: super::crud::Delete {
|
||||||
type ParentUrlParams: Send + Sync + 'static;
|
|
||||||
type UrlParams: Send + Sync + 'static;
|
type UrlParams: Send + Sync + 'static;
|
||||||
|
|
||||||
const URL: &'static str;
|
const URL: &'static str;
|
||||||
@@ -181,11 +201,15 @@ pub mod route {
|
|||||||
user: Extension<crate::models::user::User>,
|
user: Extension<crate::models::user::User>,
|
||||||
state: State<AppState>,
|
state: State<AppState>,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
path: Path<(Self::ParentUrlParams, Self::UrlParams)>,
|
path: Path<Self::UrlParams>,
|
||||||
) -> Result<Response<BoxBody>, crate::Error>;
|
) -> 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ pub mod list;
|
|||||||
pub use list::List;
|
pub use list::List;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
body::BoxBody,
|
body::{BoxBody, HttpBody},
|
||||||
extract::{Form, Path},
|
extract::{Form, Path},
|
||||||
http::HeaderMap,
|
http::HeaderMap,
|
||||||
response::{IntoResponse, Redirect, Response},
|
response::{IntoResponse, Redirect, Response},
|
||||||
@@ -215,7 +215,7 @@ impl crud::Create for Todo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Update {
|
pub enum UpdateElement {
|
||||||
State(State),
|
State(State),
|
||||||
Description(String),
|
Description(String),
|
||||||
}
|
}
|
||||||
@@ -224,7 +224,7 @@ pub enum Update {
|
|||||||
impl crud::Update for Todo {
|
impl crud::Update for Todo {
|
||||||
type Id = Uuid;
|
type Id = Uuid;
|
||||||
type Filter = Filter;
|
type Filter = Filter;
|
||||||
type Update = Update;
|
type UpdateElement = UpdateElement;
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
async fn update(
|
async fn update(
|
||||||
@@ -232,13 +232,13 @@ impl crud::Update for Todo {
|
|||||||
pool: &sqlite::Pool,
|
pool: &sqlite::Pool,
|
||||||
filter: Self::Filter,
|
filter: Self::Filter,
|
||||||
id: Self::Id,
|
id: Self::Id,
|
||||||
update: Self::Update,
|
update_element: Self::UpdateElement,
|
||||||
) -> Result<Option<Self>, Error> {
|
) -> Result<Option<Self>, Error> {
|
||||||
let user_id = ctx.user.id.to_string();
|
let user_id = ctx.user.id.to_string();
|
||||||
let trip_id_param = filter.trip_id.to_string();
|
let trip_id_param = filter.trip_id.to_string();
|
||||||
let todo_id_param = id.to_string();
|
let todo_id_param = id.to_string();
|
||||||
match update {
|
match update_element {
|
||||||
Update::State(state) => {
|
UpdateElement::State(state) => {
|
||||||
let done = state == State::Done;
|
let done = state == State::Done;
|
||||||
|
|
||||||
let result = crate::query_one!(
|
let result = crate::query_one!(
|
||||||
@@ -270,7 +270,7 @@ impl crud::Update for Todo {
|
|||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
Update::Description(new_description) => {
|
UpdateElement::Description(new_description) => {
|
||||||
let user_id = ctx.user.id.to_string();
|
let user_id = ctx.user.id.to_string();
|
||||||
let trip_id_param = filter.trip_id.to_string();
|
let trip_id_param = filter.trip_id.to_string();
|
||||||
let todo_id_param = id.to_string();
|
let todo_id_param = id.to_string();
|
||||||
@@ -566,17 +566,16 @@ pub struct TripTodoNew {
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl route::Create for Todo {
|
impl route::Create for Todo {
|
||||||
type Form = TripTodoNew;
|
type Form = TripTodoNew;
|
||||||
type ParentUrlParams = (Uuid,);
|
type UrlParams = (Uuid,);
|
||||||
type UrlParams = ();
|
|
||||||
|
|
||||||
const URL: &'static str = "/new";
|
const URL: &'static str = "/:id/todo/new";
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
async fn create(
|
async fn create(
|
||||||
Extension(current_user): Extension<crate::models::user::User>,
|
Extension(current_user): Extension<crate::models::user::User>,
|
||||||
axum::extract::State(state): axum::extract::State<AppState>,
|
axum::extract::State(state): axum::extract::State<AppState>,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
Path(((trip_id,), ())): Path<(Self::ParentUrlParams, Self::UrlParams)>,
|
Path((trip_id,)): Path<Self::UrlParams>,
|
||||||
Form(form): Form<Self::Form>,
|
Form(form): Form<Self::Form>,
|
||||||
) -> Result<Response<BoxBody>, crate::Error> {
|
) -> Result<Response<BoxBody>, crate::Error> {
|
||||||
let ctx = Context::build(current_user);
|
let ctx = Context::build(current_user);
|
||||||
@@ -615,17 +614,16 @@ impl route::Create for Todo {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl route::Delete for Todo {
|
impl route::Delete for Todo {
|
||||||
type ParentUrlParams = (Uuid,);
|
type UrlParams = (Uuid, Uuid);
|
||||||
type UrlParams = (Uuid,);
|
|
||||||
|
|
||||||
const URL: &'static str = "/:id/delete";
|
const URL: &'static str = "/:id/todo/:id/delete";
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
async fn delete(
|
async fn delete(
|
||||||
Extension(current_user): Extension<crate::models::user::User>,
|
Extension(current_user): Extension<crate::models::user::User>,
|
||||||
axum::extract::State(state): axum::extract::State<AppState>,
|
axum::extract::State(state): axum::extract::State<AppState>,
|
||||||
_headers: HeaderMap,
|
_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> {
|
) -> Result<Response<BoxBody>, crate::Error> {
|
||||||
let ctx = Context::build(current_user);
|
let ctx = Context::build(current_user);
|
||||||
let deleted = <Self as crud::Delete>::delete(
|
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),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ use uuid::Uuid;
|
|||||||
use std::{fmt, time::Duration};
|
use std::{fmt, time::Duration};
|
||||||
use tower::{timeout::TimeoutLayer, ServiceBuilder};
|
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;
|
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", post(trip_todo_edit))
|
||||||
.route("/:id/todo/:id/edit/save", post(trip_todo_edit_save))
|
.route("/:id/todo/:id/edit/save", post(trip_todo_edit_save))
|
||||||
.route("/:id/todo/:id/edit/cancel", post(trip_todo_edit_cancel))
|
.route("/:id/todo/:id/edit/cancel", post(trip_todo_edit_cancel))
|
||||||
.route(
|
.nest("/:id/todo/", components::trips::todos::Todo::get()),
|
||||||
&<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(
|
.nest(
|
||||||
(&TopLevelPage::Inventory.path()).into(),
|
(&TopLevelPage::Inventory.path()).into(),
|
||||||
|
|||||||
@@ -1281,7 +1281,7 @@ pub async fn trip_todo_done_htmx(
|
|||||||
&state.database_pool,
|
&state.database_pool,
|
||||||
todos::Filter { trip_id },
|
todos::Filter { trip_id },
|
||||||
todo_id,
|
todo_id,
|
||||||
todos::Update::State(components::trips::todos::State::Done),
|
todos::UpdateElement::State(components::trips::todos::State::Done),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -1317,7 +1317,7 @@ pub async fn trip_todo_done(
|
|||||||
&state.database_pool,
|
&state.database_pool,
|
||||||
todos::Filter { trip_id },
|
todos::Filter { trip_id },
|
||||||
todo_id,
|
todo_id,
|
||||||
todos::Update::State(components::trips::todos::State::Done),
|
todos::UpdateElement::State(components::trips::todos::State::Done),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -1336,7 +1336,7 @@ pub async fn trip_todo_undone_htmx(
|
|||||||
&state.database_pool,
|
&state.database_pool,
|
||||||
todos::Filter { trip_id },
|
todos::Filter { trip_id },
|
||||||
todo_id,
|
todo_id,
|
||||||
todos::Update::State(components::trips::todos::State::Todo),
|
todos::UpdateElement::State(components::trips::todos::State::Todo),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -1372,7 +1372,7 @@ pub async fn trip_todo_undone(
|
|||||||
&state.database_pool,
|
&state.database_pool,
|
||||||
todos::Filter { trip_id },
|
todos::Filter { trip_id },
|
||||||
todo_id,
|
todo_id,
|
||||||
todos::Update::State(components::trips::todos::State::Todo),
|
todos::UpdateElement::State(components::trips::todos::State::Todo),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -1429,7 +1429,7 @@ pub async fn trip_todo_edit_save(
|
|||||||
&state.database_pool,
|
&state.database_pool,
|
||||||
todos::Filter { trip_id },
|
todos::Filter { trip_id },
|
||||||
todo_id,
|
todo_id,
|
||||||
todos::Update::Description(form.description),
|
todos::UpdateElement::Description(form.description),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user