refactor crud
This commit is contained in:
@@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "UPDATE trip_todos\n SET description = ?\n WHERE \n id = ? \n AND trip_id = ?\n AND EXISTS(SELECT 1 FROM trips WHERE trip_id = ? AND user_id = ?)\n RETURNING\n id,\n description,\n done\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "description",
|
|
||||||
"ordinal": 1,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "done",
|
|
||||||
"ordinal": 2,
|
|
||||||
"type_info": "Bool"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 5
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "33cba5d1fbcfb492f8f8443782c45f9326e3fa966b3f8e864b3e01d4fe7b25b8"
|
|
||||||
}
|
|
||||||
12
.sqlx/query-4b087f9afbc94acbdf09a04c934b158668704d4497c2f7fef327d56559c5ee8a.json
generated
Normal file
12
.sqlx/query-4b087f9afbc94acbdf09a04c934b158668704d4497c2f7fef327d56559c5ee8a.json
generated
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n INSERT INTO trip_todos\n (id, description, done, trip_id)\n SELECT ?, ?, false, id as trip_id\n FROM trips\n WHERE trip_id = ? AND EXISTS(SELECT 1 FROM trips WHERE id = ? and user_id = ?)\n LIMIT 1\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 5
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "4b087f9afbc94acbdf09a04c934b158668704d4497c2f7fef327d56559c5ee8a"
|
||||||
|
}
|
||||||
32
.sqlx/query-4f9e7f676f42a548c8993a0182313fb3beebb547e658ea80302490953205a4c5.json
generated
Normal file
32
.sqlx/query-4f9e7f676f42a548c8993a0182313fb3beebb547e658ea80302490953205a4c5.json
generated
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n UPDATE trip_todos\n SET description = ?\n WHERE \n id = ? \n AND trip_id = ?\n AND EXISTS(SELECT 1 FROM trips WHERE trip_id = ? AND user_id = ?)\n RETURNING\n id,\n description,\n done\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "description",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "done",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 5
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "4f9e7f676f42a548c8993a0182313fb3beebb547e658ea80302490953205a4c5"
|
||||||
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "DELETE FROM trip_todos\n WHERE \n id = ?\n AND EXISTS (SELECT 1 FROM trips WHERE trip_id = ? AND user_id = ?)",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 3
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "5ac0e60ed79f626300f0dfde880f92d4eae3aa4281eafc2ac29fdb83525e0536"
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "INSERT INTO trip_todos\n (id, description, done, trip_id)\n SELECT ?, ?, false, id as trip_id\n FROM trips\n WHERE trip_id = ? AND EXISTS(SELECT 1 FROM trips WHERE id = ? and user_id = ?)\n LIMIT 1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 5
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "9784595191d25448b2a24c856288d8fa3ba73c423cafcaa555c6f0a588b622a3"
|
|
||||||
}
|
|
||||||
32
.sqlx/query-d20992191e5fd34a3b03a117abf5e95f04eedf2875afa5b2d687b893fee5fbbb.json
generated
Normal file
32
.sqlx/query-d20992191e5fd34a3b03a117abf5e95f04eedf2875afa5b2d687b893fee5fbbb.json
generated
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n UPDATE trip_todos\n SET done = ?\n WHERE trip_id = ?\n AND id = ?\n AND EXISTS(SELECT 1 FROM trips WHERE id = ? AND user_id = ?)\n RETURNING\n id,\n description,\n done\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "description",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "done",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 5
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "d20992191e5fd34a3b03a117abf5e95f04eedf2875afa5b2d687b893fee5fbbb"
|
||||||
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n UPDATE trip_todos\n SET done = ?\n WHERE trip_id = ?\n AND id = ?\n AND EXISTS(SELECT 1 FROM trips WHERE id = ? AND user_id = ?)",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 5
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "d29d72b5c9dbf34d672aa271823b3b87f29e85ccdf67dc40f9ce372d5db9727d"
|
|
||||||
}
|
|
||||||
12
.sqlx/query-d47bf74e8aaecdeb3730edab4d267f61ab03356497e777e55493c4f188e14a25.json
generated
Normal file
12
.sqlx/query-d47bf74e8aaecdeb3730edab4d267f61ab03356497e777e55493c4f188e14a25.json
generated
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n DELETE FROM trip_todos\n WHERE \n id = ?\n AND EXISTS (SELECT 1 FROM trips WHERE trip_id = ? AND user_id = ?)\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 3
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "d47bf74e8aaecdeb3730edab4d267f61ab03356497e777e55493c4f188e14a25"
|
||||||
|
}
|
||||||
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1428,6 +1428,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
|||||||
name = "packager"
|
name = "packager"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
"axum-prometheus",
|
"axum-prometheus",
|
||||||
"base64 0.21.4",
|
"base64 0.21.4",
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ default = ["jaeger", "prometheus", "tokio-console"]
|
|||||||
opt-level = 0
|
opt-level = 0
|
||||||
lto = "off"
|
lto = "off"
|
||||||
|
|
||||||
|
[dependencies.async-trait]
|
||||||
|
version = "0.1"
|
||||||
|
|
||||||
[dependencies.opentelemetry]
|
[dependencies.opentelemetry]
|
||||||
version = "0.20"
|
version = "0.20"
|
||||||
optional = true
|
optional = true
|
||||||
|
|||||||
89
src/components/mod.rs
Normal file
89
src/components/mod.rs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
pub mod crud {
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use crate::{models::Error, sqlite, Context};
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait Create: Sized {
|
||||||
|
type Id;
|
||||||
|
type Filter;
|
||||||
|
type Info;
|
||||||
|
|
||||||
|
async fn create(
|
||||||
|
ctx: &Context,
|
||||||
|
pool: &sqlite::Pool,
|
||||||
|
filter: Self::Filter,
|
||||||
|
info: Self::Info,
|
||||||
|
) -> Result<Self::Id, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait Read: Sized {
|
||||||
|
type Filter;
|
||||||
|
type Id;
|
||||||
|
|
||||||
|
async fn findall(
|
||||||
|
ctx: &Context,
|
||||||
|
pool: &sqlite::Pool,
|
||||||
|
filter: Self::Filter,
|
||||||
|
) -> Result<Vec<Self>, Error>;
|
||||||
|
|
||||||
|
async fn find(
|
||||||
|
ctx: &Context,
|
||||||
|
pool: &sqlite::Pool,
|
||||||
|
filter: Self::Filter,
|
||||||
|
id: Self::Id,
|
||||||
|
) -> Result<Option<Self>, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait Update: Sized {
|
||||||
|
type Id;
|
||||||
|
type Filter;
|
||||||
|
type Update;
|
||||||
|
|
||||||
|
async fn update(
|
||||||
|
ctx: &Context,
|
||||||
|
pool: &sqlite::Pool,
|
||||||
|
filter: Self::Filter,
|
||||||
|
id: Self::Id,
|
||||||
|
update: Self::Update,
|
||||||
|
) -> Result<Option<Self>, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait Delete: Sized {
|
||||||
|
type Id;
|
||||||
|
type Filter;
|
||||||
|
|
||||||
|
async fn delete(
|
||||||
|
ctx: &Context,
|
||||||
|
pool: impl sqlx::Acquire,
|
||||||
|
filter: Self::Filter,
|
||||||
|
id: Self::Id,
|
||||||
|
) -> Result<bool, Error>;
|
||||||
|
|
||||||
|
async fn delete_all(
|
||||||
|
ctx: &Context,
|
||||||
|
pool: &sqlite::Pool,
|
||||||
|
filter: Self::Filter,
|
||||||
|
ids: Vec<Self::Id>,
|
||||||
|
) -> Result<bool, Error> {
|
||||||
|
let mut transaction = pool.begin().await?;
|
||||||
|
|
||||||
|
for id in ids {
|
||||||
|
Self::delete(ctx, &mut transaction, filter, id).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod view {
|
||||||
|
use maud::Markup;
|
||||||
|
|
||||||
|
pub trait View {
|
||||||
|
type Input;
|
||||||
|
|
||||||
|
fn build(&self, input: Self::Input) -> Markup;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ use std::fmt;
|
|||||||
|
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
|
pub mod components;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod htmx;
|
pub mod htmx;
|
||||||
pub mod models;
|
pub mod models;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use crate::components::crud::*;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
consts,
|
consts,
|
||||||
error::{DatabaseError, Error, QueryError},
|
error::{DatabaseError, Error, QueryError},
|
||||||
@@ -1019,7 +1021,8 @@ impl Trip {
|
|||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
pub async fn load_todos(&mut self, ctx: &Context, pool: &sqlite::Pool) -> Result<(), Error> {
|
pub async fn load_todos(&mut self, ctx: &Context, pool: &sqlite::Pool) -> Result<(), Error> {
|
||||||
self.todos = Some(todos::Todo::load(ctx, pool, self.id).await?);
|
self.todos =
|
||||||
|
Some(todos::Todo::findall(ctx, pool, todos::TodoFilter { trip_id: self.id }).await?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
use maud::{html, Markup};
|
use maud::{html, Markup};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::components::crud;
|
||||||
models::{Error, QueryError},
|
use crate::components::view::{self, *};
|
||||||
sqlite, Context,
|
|
||||||
};
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use crate::{models::Error, sqlite, Context};
|
||||||
|
|
||||||
use super::Trip;
|
use super::Trip;
|
||||||
|
|
||||||
@@ -58,17 +60,28 @@ impl TryFrom<TodoRow> for Todo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TodoFilter {
|
||||||
|
pub trip_id: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
impl Todo {
|
impl Todo {
|
||||||
pub fn is_done(&self) -> bool {
|
pub fn is_done(&self) -> bool {
|
||||||
self.state == State::Done
|
self.state == State::Done
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn load(
|
#[async_trait]
|
||||||
|
impl crud::Read for Todo {
|
||||||
|
type Filter = TodoFilter;
|
||||||
|
type Id = Uuid;
|
||||||
|
|
||||||
|
async fn findall(
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
pool: &sqlite::Pool,
|
pool: &sqlite::Pool,
|
||||||
trip_id: Uuid,
|
filter: TodoFilter,
|
||||||
) -> Result<Vec<Self>, Error> {
|
) -> Result<Vec<Self>, Error> {
|
||||||
let trip_id_param = trip_id.to_string();
|
let trip_id_param = filter.trip_id.to_string();
|
||||||
let user_id = ctx.user.id.to_string();
|
let user_id = ctx.user.id.to_string();
|
||||||
|
|
||||||
let todos: Vec<Todo> = crate::query_all!(
|
let todos: Vec<Todo> = crate::query_all!(
|
||||||
@@ -100,13 +113,13 @@ impl Todo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
pub async fn find(
|
async fn find(
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
pool: &sqlite::Pool,
|
pool: &sqlite::Pool,
|
||||||
trip_id: Uuid,
|
filter: TodoFilter,
|
||||||
todo_id: Uuid,
|
todo_id: Uuid,
|
||||||
) -> Result<Option<Self>, Error> {
|
) -> Result<Option<Self>, Error> {
|
||||||
let trip_id_param = trip_id.to_string();
|
let trip_id_param = filter.trip_id.to_string();
|
||||||
let todo_id_param = todo_id.to_string();
|
let todo_id_param = todo_id.to_string();
|
||||||
let user_id = ctx.user.id.to_string();
|
let user_id = ctx.user.id.to_string();
|
||||||
crate::query_one!(
|
crate::query_one!(
|
||||||
@@ -136,72 +149,45 @@ impl Todo {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
|
||||||
pub async fn set_state(
|
|
||||||
ctx: &Context,
|
|
||||||
pool: &sqlite::Pool,
|
|
||||||
trip_id: Uuid,
|
|
||||||
todo_id: Uuid,
|
|
||||||
state: State,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let user_id = ctx.user.id.to_string();
|
|
||||||
let trip_id_param = trip_id.to_string();
|
|
||||||
let todo_id_param = todo_id.to_string();
|
|
||||||
let done = state == State::Done;
|
|
||||||
|
|
||||||
let result = crate::execute!(
|
|
||||||
&sqlite::QueryClassification {
|
|
||||||
query_type: sqlite::QueryType::Update,
|
|
||||||
component: sqlite::Component::Trips,
|
|
||||||
},
|
|
||||||
pool,
|
|
||||||
r#"
|
|
||||||
UPDATE trip_todos
|
|
||||||
SET done = ?
|
|
||||||
WHERE trip_id = ?
|
|
||||||
AND id = ?
|
|
||||||
AND EXISTS(SELECT 1 FROM trips WHERE id = ? AND user_id = ?)"#,
|
|
||||||
done,
|
|
||||||
trip_id_param,
|
|
||||||
todo_id_param,
|
|
||||||
trip_id_param,
|
|
||||||
user_id
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
(result.rows_affected() != 0).then_some(()).ok_or_else(|| {
|
|
||||||
Error::Query(QueryError::NotFound {
|
|
||||||
description: format!("todo {todo_id} not found for trip {trip_id}"),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn new(
|
pub struct TodoNew {
|
||||||
|
pub description: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl crud::Create for Todo {
|
||||||
|
type Id = Uuid;
|
||||||
|
type Filter = TodoFilter;
|
||||||
|
type Info = TodoNew;
|
||||||
|
|
||||||
|
async fn create(
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
pool: &sqlite::Pool,
|
pool: &sqlite::Pool,
|
||||||
trip_id: Uuid,
|
filter: Self::Filter,
|
||||||
description: String,
|
info: Self::Info,
|
||||||
) -> Result<Uuid, Error> {
|
) -> Result<Self::Id, Error> {
|
||||||
let user_id = ctx.user.id.to_string();
|
let user_id = ctx.user.id.to_string();
|
||||||
let id = Uuid::new_v4();
|
let id = Uuid::new_v4();
|
||||||
tracing::info!("adding new todo with id {id}");
|
tracing::info!("adding new todo with id {id}");
|
||||||
let id_param = id.to_string();
|
let id_param = id.to_string();
|
||||||
let trip_id_param = trip_id.to_string();
|
let trip_id_param = filter.trip_id.to_string();
|
||||||
crate::execute!(
|
crate::execute!(
|
||||||
&sqlite::QueryClassification {
|
&sqlite::QueryClassification {
|
||||||
query_type: sqlite::QueryType::Insert,
|
query_type: sqlite::QueryType::Insert,
|
||||||
component: sqlite::Component::Todo,
|
component: sqlite::Component::Todo,
|
||||||
},
|
},
|
||||||
pool,
|
pool,
|
||||||
"INSERT INTO trip_todos
|
r#"
|
||||||
|
INSERT INTO trip_todos
|
||||||
(id, description, done, trip_id)
|
(id, description, done, trip_id)
|
||||||
SELECT ?, ?, false, id as trip_id
|
SELECT ?, ?, false, id as trip_id
|
||||||
FROM trips
|
FROM trips
|
||||||
WHERE trip_id = ? AND EXISTS(SELECT 1 FROM trips WHERE id = ? and user_id = ?)
|
WHERE trip_id = ? AND EXISTS(SELECT 1 FROM trips WHERE id = ? and user_id = ?)
|
||||||
LIMIT 1",
|
LIMIT 1
|
||||||
|
"#,
|
||||||
id_param,
|
id_param,
|
||||||
description,
|
info.description,
|
||||||
trip_id_param,
|
trip_id_param,
|
||||||
trip_id_param,
|
trip_id_param,
|
||||||
user_id,
|
user_id,
|
||||||
@@ -210,27 +196,130 @@ impl Todo {
|
|||||||
|
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum TodoUpdate {
|
||||||
|
State(State),
|
||||||
|
Description(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl crud::Update for Todo {
|
||||||
|
type Id = Uuid;
|
||||||
|
type Filter = TodoFilter;
|
||||||
|
type Update = TodoUpdate;
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
pub async fn delete(
|
async fn update(
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
pool: &sqlite::Pool,
|
pool: &sqlite::Pool,
|
||||||
trip_id: Uuid,
|
filter: Self::Filter,
|
||||||
|
id: Self::Id,
|
||||||
|
update: Self::Update,
|
||||||
|
) -> 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 {
|
||||||
|
TodoUpdate::State(state) => {
|
||||||
|
let done = state == State::Done;
|
||||||
|
|
||||||
|
let result = crate::query_one!(
|
||||||
|
&sqlite::QueryClassification {
|
||||||
|
query_type: sqlite::QueryType::Update,
|
||||||
|
component: sqlite::Component::Trips,
|
||||||
|
},
|
||||||
|
pool,
|
||||||
|
TodoRow,
|
||||||
|
Todo,
|
||||||
|
r#"
|
||||||
|
UPDATE trip_todos
|
||||||
|
SET done = ?
|
||||||
|
WHERE trip_id = ?
|
||||||
|
AND id = ?
|
||||||
|
AND EXISTS(SELECT 1 FROM trips WHERE id = ? AND user_id = ?)
|
||||||
|
RETURNING
|
||||||
|
id,
|
||||||
|
description,
|
||||||
|
done
|
||||||
|
"#,
|
||||||
|
done,
|
||||||
|
trip_id_param,
|
||||||
|
todo_id_param,
|
||||||
|
trip_id_param,
|
||||||
|
user_id
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
TodoUpdate::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();
|
||||||
|
|
||||||
|
let result = crate::query_one!(
|
||||||
|
&sqlite::QueryClassification {
|
||||||
|
query_type: sqlite::QueryType::Update,
|
||||||
|
component: sqlite::Component::Todo,
|
||||||
|
},
|
||||||
|
pool,
|
||||||
|
TodoRow,
|
||||||
|
Todo,
|
||||||
|
r#"
|
||||||
|
UPDATE trip_todos
|
||||||
|
SET description = ?
|
||||||
|
WHERE
|
||||||
|
id = ?
|
||||||
|
AND trip_id = ?
|
||||||
|
AND EXISTS(SELECT 1 FROM trips WHERE trip_id = ? AND user_id = ?)
|
||||||
|
RETURNING
|
||||||
|
id,
|
||||||
|
description,
|
||||||
|
done
|
||||||
|
"#,
|
||||||
|
new_description,
|
||||||
|
todo_id_param,
|
||||||
|
trip_id_param,
|
||||||
|
trip_id_param,
|
||||||
|
user_id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl crud::Delete for Todo {
|
||||||
|
type Id = Uuid;
|
||||||
|
type Filter = TodoFilter;
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
async fn delete(
|
||||||
|
ctx: &Context,
|
||||||
|
pool: &sqlite::Pool,
|
||||||
|
filter: TodoFilter,
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
) -> Result<bool, Error> {
|
) -> Result<bool, Error> {
|
||||||
let id_param = id.to_string();
|
let id_param = id.to_string();
|
||||||
let user_id = ctx.user.id.to_string();
|
let user_id = ctx.user.id.to_string();
|
||||||
let trip_id_param = trip_id.to_string();
|
let trip_id_param = filter.trip_id.to_string();
|
||||||
let results = crate::execute!(
|
let results = crate::execute!(
|
||||||
&sqlite::QueryClassification {
|
&sqlite::QueryClassification {
|
||||||
query_type: sqlite::QueryType::Delete,
|
query_type: sqlite::QueryType::Delete,
|
||||||
component: sqlite::Component::Todo,
|
component: sqlite::Component::Todo,
|
||||||
},
|
},
|
||||||
pool,
|
pool,
|
||||||
"DELETE FROM trip_todos
|
r#"
|
||||||
|
DELETE FROM trip_todos
|
||||||
WHERE
|
WHERE
|
||||||
id = ?
|
id = ?
|
||||||
AND EXISTS (SELECT 1 FROM trips WHERE trip_id = ? AND user_id = ?)",
|
AND EXISTS (SELECT 1 FROM trips WHERE trip_id = ? AND user_id = ?)
|
||||||
|
"#,
|
||||||
id_param,
|
id_param,
|
||||||
trip_id_param,
|
trip_id_param,
|
||||||
user_id,
|
user_id,
|
||||||
@@ -247,9 +336,17 @@ pub enum TodoUiState {
|
|||||||
Edit,
|
Edit,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Todo {
|
#[derive(Debug)]
|
||||||
|
pub struct TodoBuildInput {
|
||||||
|
pub trip_id: Uuid,
|
||||||
|
pub state: TodoUiState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl view::View for Todo {
|
||||||
|
type Input = TodoBuildInput;
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
pub fn build(&self, trip_id: &Uuid, state: TodoUiState) -> Markup {
|
fn build(&self, input: Self::Input) -> Markup {
|
||||||
let done = self.is_done();
|
let done = self.is_done();
|
||||||
html!(
|
html!(
|
||||||
li
|
li
|
||||||
@@ -261,19 +358,19 @@ impl Todo {
|
|||||||
."bg-red-50"[!done]
|
."bg-red-50"[!done]
|
||||||
."h-full"
|
."h-full"
|
||||||
{
|
{
|
||||||
@if state == TodoUiState::Edit {
|
@if input.state == TodoUiState::Edit {
|
||||||
form
|
form
|
||||||
name="edit-todo"
|
name="edit-todo"
|
||||||
id="edit-todo"
|
id="edit-todo"
|
||||||
action={
|
action={
|
||||||
"/trips/" (trip_id)
|
"/trips/" (input.trip_id)
|
||||||
"/todo/" (self.id)
|
"/todo/" (self.id)
|
||||||
"/edit/save"
|
"/edit/save"
|
||||||
}
|
}
|
||||||
target="_self"
|
target="_self"
|
||||||
method="post"
|
method="post"
|
||||||
hx-post={
|
hx-post={
|
||||||
"/trips/" (trip_id)
|
"/trips/" (input.trip_id)
|
||||||
"/todo/" (self.id)
|
"/todo/" (self.id)
|
||||||
"/edit/save"
|
"/edit/save"
|
||||||
}
|
}
|
||||||
@@ -325,7 +422,7 @@ impl Todo {
|
|||||||
a
|
a
|
||||||
href="."
|
href="."
|
||||||
hx-post={
|
hx-post={
|
||||||
"/trips/" (trip_id)
|
"/trips/" (input.trip_id)
|
||||||
"/todo/" (self.id)
|
"/todo/" (self.id)
|
||||||
"/edit/cancel"
|
"/edit/cancel"
|
||||||
}
|
}
|
||||||
@@ -352,12 +449,12 @@ impl Todo {
|
|||||||
."aspect-square"
|
."aspect-square"
|
||||||
."hover:bg-red-50"
|
."hover:bg-red-50"
|
||||||
href={
|
href={
|
||||||
"/trips/" (trip_id)
|
"/trips/" (input.trip_id)
|
||||||
"/todo/" (self.id)
|
"/todo/" (self.id)
|
||||||
"/undone"
|
"/undone"
|
||||||
}
|
}
|
||||||
hx-post={
|
hx-post={
|
||||||
"/trips/" (trip_id)
|
"/trips/" (input.trip_id)
|
||||||
"/todo/" (self.id)
|
"/todo/" (self.id)
|
||||||
"/undone"
|
"/undone"
|
||||||
}
|
}
|
||||||
@@ -378,12 +475,12 @@ impl Todo {
|
|||||||
."aspect-square"
|
."aspect-square"
|
||||||
."hover:bg-green-50"
|
."hover:bg-green-50"
|
||||||
href={
|
href={
|
||||||
"/trips/" (trip_id)
|
"/trips/" (input.trip_id)
|
||||||
"/todo/" (self.id)
|
"/todo/" (self.id)
|
||||||
"/done"
|
"/done"
|
||||||
}
|
}
|
||||||
hx-post={
|
hx-post={
|
||||||
"/trips/" (trip_id)
|
"/trips/" (input.trip_id)
|
||||||
"/todo/" (self.id)
|
"/todo/" (self.id)
|
||||||
"/done"
|
"/done"
|
||||||
}
|
}
|
||||||
@@ -412,7 +509,7 @@ impl Todo {
|
|||||||
."hover:bg-blue-400"
|
."hover:bg-blue-400"
|
||||||
href=(format!("?edit_todo={id}", id = self.id))
|
href=(format!("?edit_todo={id}", id = self.id))
|
||||||
hx-post={
|
hx-post={
|
||||||
"/trips/" (trip_id)
|
"/trips/" (input.trip_id)
|
||||||
"/todo/" (self.id)
|
"/todo/" (self.id)
|
||||||
"/edit"
|
"/edit"
|
||||||
}
|
}
|
||||||
@@ -429,7 +526,7 @@ impl Todo {
|
|||||||
."hover:bg-red-200"
|
."hover:bg-red-200"
|
||||||
href=(format!("?delete_todo={id}", id = self.id))
|
href=(format!("?delete_todo={id}", id = self.id))
|
||||||
hx-post={
|
hx-post={
|
||||||
"/trips/" (trip_id)
|
"/trips/" (input.trip_id)
|
||||||
"/todo/" (self.id)
|
"/todo/" (self.id)
|
||||||
"/delete"
|
"/delete"
|
||||||
}
|
}
|
||||||
@@ -442,48 +539,6 @@ impl Todo {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
|
||||||
pub async fn set_description(
|
|
||||||
ctx: &Context,
|
|
||||||
pool: &sqlite::Pool,
|
|
||||||
trip_id: Uuid,
|
|
||||||
todo_id: Uuid,
|
|
||||||
new_description: String,
|
|
||||||
) -> Result<Option<Self>, Error> {
|
|
||||||
let user_id = ctx.user.id.to_string();
|
|
||||||
let trip_id_param = trip_id.to_string();
|
|
||||||
let todo_id_param = todo_id.to_string();
|
|
||||||
|
|
||||||
let result = crate::query_one!(
|
|
||||||
&sqlite::QueryClassification {
|
|
||||||
query_type: sqlite::QueryType::Update,
|
|
||||||
component: sqlite::Component::Todo,
|
|
||||||
},
|
|
||||||
pool,
|
|
||||||
TodoRow,
|
|
||||||
Todo,
|
|
||||||
"UPDATE trip_todos
|
|
||||||
SET description = ?
|
|
||||||
WHERE
|
|
||||||
id = ?
|
|
||||||
AND trip_id = ?
|
|
||||||
AND EXISTS(SELECT 1 FROM trips WHERE trip_id = ? AND user_id = ?)
|
|
||||||
RETURNING
|
|
||||||
id,
|
|
||||||
description,
|
|
||||||
done
|
|
||||||
",
|
|
||||||
new_description,
|
|
||||||
todo_id_param,
|
|
||||||
trip_id_param,
|
|
||||||
trip_id_param,
|
|
||||||
user_id,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NewTodo;
|
pub struct NewTodo;
|
||||||
@@ -573,7 +628,7 @@ impl<'a> TodoList<'a> {
|
|||||||
} else {
|
} else {
|
||||||
TodoUiState::Default
|
TodoUiState::Default
|
||||||
}).unwrap_or(TodoUiState::Default);
|
}).unwrap_or(TodoUiState::Default);
|
||||||
(todo.build(&self.trip.id, state))
|
(todo.build(TodoBuildInput{trip_id:self.trip.id, state}))
|
||||||
}
|
}
|
||||||
(NewTodo::build(&self.trip.id))
|
(NewTodo::build(&self.trip.id))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ use axum::{
|
|||||||
Form,
|
Form,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::components::crud::*;
|
||||||
|
use crate::components::view::*;
|
||||||
|
use crate::models::trips::todos::{TodoBuildInput, TodoFilter, TodoNew, TodoUpdate};
|
||||||
|
|
||||||
use crate::view::Component;
|
use crate::view::Component;
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
@@ -433,8 +437,13 @@ pub async fn trip(
|
|||||||
state.client_state.active_category_id = trip_query.category;
|
state.client_state.active_category_id = trip_query.category;
|
||||||
|
|
||||||
if let Some(delete_todo) = trip_query.delete_todo {
|
if let Some(delete_todo) = trip_query.delete_todo {
|
||||||
let deleted =
|
let deleted = models::trips::todos::Todo::delete(
|
||||||
models::trips::todos::Todo::delete(&ctx, &state.database_pool, id, delete_todo).await?;
|
&ctx,
|
||||||
|
&state.database_pool,
|
||||||
|
TodoFilter { trip_id: id },
|
||||||
|
delete_todo,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
return if deleted {
|
return if deleted {
|
||||||
Ok(Redirect::to(get_referer(&headers)?).into_response())
|
Ok(Redirect::to(get_referer(&headers)?).into_response())
|
||||||
@@ -1266,16 +1275,21 @@ pub async fn trip_todo_done_htmx(
|
|||||||
Path((trip_id, todo_id)): Path<(Uuid, Uuid)>,
|
Path((trip_id, todo_id)): Path<(Uuid, Uuid)>,
|
||||||
) -> Result<impl IntoResponse, Error> {
|
) -> Result<impl IntoResponse, Error> {
|
||||||
let ctx = Context::build(current_user);
|
let ctx = Context::build(current_user);
|
||||||
models::trips::todos::Todo::set_state(
|
models::trips::todos::Todo::update(
|
||||||
&ctx,
|
&ctx,
|
||||||
&state.database_pool,
|
&state.database_pool,
|
||||||
trip_id,
|
TodoFilter { trip_id },
|
||||||
todo_id,
|
todo_id,
|
||||||
models::trips::todos::State::Done,
|
TodoUpdate::State(models::trips::todos::State::Done),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let todo_item = models::trips::todos::Todo::find(&ctx, &state.database_pool, trip_id, todo_id)
|
let todo_item = models::trips::todos::Todo::find(
|
||||||
|
&ctx,
|
||||||
|
&state.database_pool,
|
||||||
|
TodoFilter { trip_id },
|
||||||
|
todo_id,
|
||||||
|
)
|
||||||
.await?
|
.await?
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
Error::Request(RequestError::NotFound {
|
Error::Request(RequestError::NotFound {
|
||||||
@@ -1283,7 +1297,10 @@ pub async fn trip_todo_done_htmx(
|
|||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(todo_item.build(&trip_id, models::trips::todos::TodoUiState::Default))
|
Ok(todo_item.build(TodoBuildInput {
|
||||||
|
trip_id,
|
||||||
|
state: models::trips::todos::TodoUiState::Default,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
@@ -1294,12 +1311,12 @@ pub async fn trip_todo_done(
|
|||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
) -> Result<impl IntoResponse, Error> {
|
) -> Result<impl IntoResponse, Error> {
|
||||||
let ctx = Context::build(current_user);
|
let ctx = Context::build(current_user);
|
||||||
models::trips::todos::Todo::set_state(
|
models::trips::todos::Todo::update(
|
||||||
&ctx,
|
&ctx,
|
||||||
&state.database_pool,
|
&state.database_pool,
|
||||||
trip_id,
|
TodoFilter { trip_id },
|
||||||
todo_id,
|
todo_id,
|
||||||
models::trips::todos::State::Done,
|
TodoUpdate::State(models::trips::todos::State::Done),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -1313,16 +1330,21 @@ pub async fn trip_todo_undone_htmx(
|
|||||||
Path((trip_id, todo_id)): Path<(Uuid, Uuid)>,
|
Path((trip_id, todo_id)): Path<(Uuid, Uuid)>,
|
||||||
) -> Result<impl IntoResponse, Error> {
|
) -> Result<impl IntoResponse, Error> {
|
||||||
let ctx = Context::build(current_user);
|
let ctx = Context::build(current_user);
|
||||||
models::trips::todos::Todo::set_state(
|
models::trips::todos::Todo::update(
|
||||||
&ctx,
|
&ctx,
|
||||||
&state.database_pool,
|
&state.database_pool,
|
||||||
trip_id,
|
TodoFilter { trip_id },
|
||||||
todo_id,
|
todo_id,
|
||||||
models::trips::todos::State::Todo,
|
TodoUpdate::State(models::trips::todos::State::Todo),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let todo_item = models::trips::todos::Todo::find(&ctx, &state.database_pool, trip_id, todo_id)
|
let todo_item = models::trips::todos::Todo::find(
|
||||||
|
&ctx,
|
||||||
|
&state.database_pool,
|
||||||
|
TodoFilter { trip_id },
|
||||||
|
todo_id,
|
||||||
|
)
|
||||||
.await?
|
.await?
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
Error::Request(RequestError::NotFound {
|
Error::Request(RequestError::NotFound {
|
||||||
@@ -1330,7 +1352,10 @@ pub async fn trip_todo_undone_htmx(
|
|||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(todo_item.build(&trip_id, models::trips::todos::TodoUiState::Default))
|
Ok(todo_item.build(TodoBuildInput {
|
||||||
|
trip_id,
|
||||||
|
state: models::trips::todos::TodoUiState::Default,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
@@ -1341,12 +1366,12 @@ pub async fn trip_todo_undone(
|
|||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
) -> Result<impl IntoResponse, Error> {
|
) -> Result<impl IntoResponse, Error> {
|
||||||
let ctx = Context::build(current_user);
|
let ctx = Context::build(current_user);
|
||||||
models::trips::todos::Todo::set_state(
|
models::trips::todos::Todo::update(
|
||||||
&ctx,
|
&ctx,
|
||||||
&state.database_pool,
|
&state.database_pool,
|
||||||
trip_id,
|
TodoFilter { trip_id },
|
||||||
todo_id,
|
todo_id,
|
||||||
models::trips::todos::State::Todo,
|
TodoUpdate::State(models::trips::todos::State::Todo),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -1368,15 +1393,23 @@ pub async fn trip_todo_edit(
|
|||||||
Path((trip_id, todo_id)): Path<(Uuid, Uuid)>,
|
Path((trip_id, todo_id)): Path<(Uuid, Uuid)>,
|
||||||
) -> Result<impl IntoResponse, Error> {
|
) -> Result<impl IntoResponse, Error> {
|
||||||
let ctx = Context::build(current_user);
|
let ctx = Context::build(current_user);
|
||||||
let todo_item =
|
let todo_item = models::trips::todos::Todo::find(
|
||||||
models::trips::todos::Todo::find(&ctx, &state.database_pool, trip_id, todo_id).await?;
|
&ctx,
|
||||||
|
&state.database_pool,
|
||||||
|
TodoFilter { trip_id },
|
||||||
|
todo_id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
match todo_item {
|
match todo_item {
|
||||||
None => Err(Error::Request(RequestError::NotFound {
|
None => Err(Error::Request(RequestError::NotFound {
|
||||||
message: format!("todo with id {todo_id} not found"),
|
message: format!("todo with id {todo_id} not found"),
|
||||||
})),
|
})),
|
||||||
Some(todo_item) => Ok(todo_item
|
Some(todo_item) => Ok(todo_item
|
||||||
.build(&trip_id, models::trips::todos::TodoUiState::Edit)
|
.build(TodoBuildInput {
|
||||||
|
trip_id,
|
||||||
|
state: models::trips::todos::TodoUiState::Edit,
|
||||||
|
})
|
||||||
.into_response()),
|
.into_response()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1390,12 +1423,12 @@ pub async fn trip_todo_edit_save(
|
|||||||
Form(form): Form<TripTodoDescription>,
|
Form(form): Form<TripTodoDescription>,
|
||||||
) -> Result<impl IntoResponse, Error> {
|
) -> Result<impl IntoResponse, Error> {
|
||||||
let ctx = Context::build(current_user);
|
let ctx = Context::build(current_user);
|
||||||
let todo_item = models::trips::todos::Todo::set_description(
|
let todo_item = models::trips::todos::Todo::update(
|
||||||
&ctx,
|
&ctx,
|
||||||
&state.database_pool,
|
&state.database_pool,
|
||||||
trip_id,
|
TodoFilter { trip_id },
|
||||||
todo_id,
|
todo_id,
|
||||||
form.description,
|
TodoUpdate::Description(form.description),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -1406,7 +1439,10 @@ pub async fn trip_todo_edit_save(
|
|||||||
Some(todo_item) => {
|
Some(todo_item) => {
|
||||||
if htmx::is_htmx(&headers) {
|
if htmx::is_htmx(&headers) {
|
||||||
Ok(todo_item
|
Ok(todo_item
|
||||||
.build(&trip_id, models::trips::todos::TodoUiState::Default)
|
.build(TodoBuildInput {
|
||||||
|
trip_id,
|
||||||
|
state: models::trips::todos::TodoUiState::Default,
|
||||||
|
})
|
||||||
.into_response())
|
.into_response())
|
||||||
} else {
|
} else {
|
||||||
Ok(Redirect::to(&format!("/trips/{trip_id}/")).into_response())
|
Ok(Redirect::to(&format!("/trips/{trip_id}/")).into_response())
|
||||||
@@ -1423,15 +1459,23 @@ pub async fn trip_todo_edit_cancel(
|
|||||||
Path((trip_id, todo_id)): Path<(Uuid, Uuid)>,
|
Path((trip_id, todo_id)): Path<(Uuid, Uuid)>,
|
||||||
) -> Result<impl IntoResponse, Error> {
|
) -> Result<impl IntoResponse, Error> {
|
||||||
let ctx = Context::build(current_user);
|
let ctx = Context::build(current_user);
|
||||||
let todo_item =
|
let todo_item = models::trips::todos::Todo::find(
|
||||||
models::trips::todos::Todo::find(&ctx, &state.database_pool, trip_id, todo_id).await?;
|
&ctx,
|
||||||
|
&state.database_pool,
|
||||||
|
TodoFilter { trip_id },
|
||||||
|
todo_id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
match todo_item {
|
match todo_item {
|
||||||
None => Err(Error::Request(RequestError::NotFound {
|
None => Err(Error::Request(RequestError::NotFound {
|
||||||
message: format!("todo with id {todo_id} not found"),
|
message: format!("todo with id {todo_id} not found"),
|
||||||
})),
|
})),
|
||||||
Some(todo_item) => Ok(todo_item
|
Some(todo_item) => Ok(todo_item
|
||||||
.build(&trip_id, models::trips::todos::TodoUiState::Default)
|
.build(TodoBuildInput {
|
||||||
|
trip_id,
|
||||||
|
state: models::trips::todos::TodoUiState::Default,
|
||||||
|
})
|
||||||
.into_response()),
|
.into_response()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1453,8 +1497,14 @@ pub async fn trip_todo_new(
|
|||||||
) -> Result<impl IntoResponse, Error> {
|
) -> Result<impl IntoResponse, Error> {
|
||||||
let ctx = Context::build(current_user);
|
let ctx = Context::build(current_user);
|
||||||
// method output is not required as we reload the whole trip todos anyway
|
// method output is not required as we reload the whole trip todos anyway
|
||||||
let _todo_item =
|
let _todo_item = models::trips::todos::Todo::create(
|
||||||
models::trips::todos::Todo::new(&ctx, &state.database_pool, trip_id, form.description)
|
&ctx,
|
||||||
|
&state.database_pool,
|
||||||
|
TodoFilter { trip_id },
|
||||||
|
TodoNew {
|
||||||
|
description: form.description,
|
||||||
|
},
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if htmx::is_htmx(&headers) {
|
if htmx::is_htmx(&headers) {
|
||||||
@@ -1486,8 +1536,13 @@ pub async fn trip_todo_delete(
|
|||||||
Path((trip_id, todo_id)): Path<(Uuid, Uuid)>,
|
Path((trip_id, todo_id)): Path<(Uuid, Uuid)>,
|
||||||
) -> Result<impl IntoResponse, Error> {
|
) -> Result<impl IntoResponse, Error> {
|
||||||
let ctx = Context::build(current_user);
|
let ctx = Context::build(current_user);
|
||||||
let deleted =
|
let deleted = models::trips::todos::Todo::delete(
|
||||||
models::trips::todos::Todo::delete(&ctx, &state.database_pool, trip_id, todo_id).await?;
|
&ctx,
|
||||||
|
&state.database_pool,
|
||||||
|
TodoFilter { trip_id },
|
||||||
|
todo_id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
if !deleted {
|
if !deleted {
|
||||||
return Err(Error::Request(RequestError::NotFound {
|
return Err(Error::Request(RequestError::NotFound {
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ fn get_jaeger_layer<
|
|||||||
// mentioned earlier.
|
// mentioned earlier.
|
||||||
let tracer = opentelemetry_jaeger::new_agent_pipeline()
|
let tracer = opentelemetry_jaeger::new_agent_pipeline()
|
||||||
.with_service_name(env!("CARGO_PKG_NAME"))
|
.with_service_name(env!("CARGO_PKG_NAME"))
|
||||||
.with_max_packet_size(20_000)
|
.with_max_packet_size(50_000)
|
||||||
.with_auto_split_batch(true)
|
.with_auto_split_batch(true)
|
||||||
.install_batch(Tokio)
|
.install_batch(Tokio)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user