diff --git a/rust/js/app.js b/rust/js/app.js index 2435022..f59befa 100644 --- a/rust/js/app.js +++ b/rust/js/app.js @@ -1,5 +1,11 @@ window.onload = function() { document.body.addEventListener('htmx:responseError', function(evt) { - console.log(evt.detail); + console.log(evt.detail); }); + + document.dispatchEvent(new Event("loaded")); }; + +function is_positive_integer(val) { + return /^\d+$/.test(val); +} diff --git a/rust/rebuild-schema-data.sh b/rust/rebuild-schema-data.sh index 072ccee..cc8bbac 100755 --- a/rust/rebuild-schema-data.sh +++ b/rust/rebuild-schema-data.sh @@ -4,4 +4,4 @@ export DATABASE_URL="sqlite://${db}" cargo sqlx database create cargo sqlx migrate run -cargo sqlx prepare +cargo sqlx prepare -- --color=always diff --git a/rust/sqlx-data.json b/rust/sqlx-data.json index e1e966a..2b7c0ad 100644 --- a/rust/sqlx-data.json +++ b/rust/sqlx-data.json @@ -86,6 +86,30 @@ }, "query": "\n SELECT\n type.id as id,\n type.name as name,\n inner.id IS NOT NULL AS active\n FROM trips_types AS type\n LEFT JOIN (\n SELECT type.id as id, type.name as name\n FROM trips as trip\n INNER JOIN trips_to_trips_types as ttt\n ON ttt.trip_id = trip.id\n INNER JOIN trips_types AS type\n ON type.id == ttt.trip_type_id\n WHERE trip.id = ?\n ) AS inner\n ON inner.id = type.id\n " }, + "4caaa7a80a3c66bb6525bd8ed226a446e131fb19f643b447b4c24824b9561e55": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "name", + "ordinal": 1, + "type_info": "Text" + } + ], + "nullable": [ + false, + false + ], + "parameters": { + "Right": 0 + } + }, + "query": "SELECT\n id,\n name\n FROM trips_types" + }, "4d377bb01af6bbbca637d8c61326c84e8b05b1e570199c464b593bdc81b3dba6": { "describe": { "columns": [], @@ -96,6 +120,16 @@ }, "query": "INSERT INTO trips_to_trips_types\n (trip_id, trip_type_id) VALUES (?, ?)" }, + "68304c19a0bee12c0b3ce9740d53389620b20e47973b41975678dbd13bd30c7f": { + "describe": { + "columns": [], + "nullable": [], + "parameters": { + "Right": 2 + } + }, + "query": "UPDATE trips_types\n SET name = ?\n WHERE id = ?" + }, "6973cceeb5499216475136b320b25e1355974e1213829d931abdd6b7a1448a87": { "describe": { "columns": [ @@ -392,6 +426,16 @@ }, "query": "SELECT * FROM inventory_items AS item\n WHERE item.id = ?" }, + "ded3be1c8894a64e3b5f749461db7261d9224abb8a54da980db8262733d08205": { + "describe": { + "columns": [], + "nullable": [], + "parameters": { + "Right": 2 + } + }, + "query": "INSERT INTO trips_types\n (id, name)\n VALUES\n (?, ?)" + }, "f2038d75ff5ff10d4baeb30b9dc4cc1c991da1facdb1f05e16f271372eee0c7a": { "describe": { "columns": [], @@ -479,5 +523,23 @@ } }, "query": "\n SELECT\n category.id as category_id,\n category.name as category_name,\n category.description AS category_description,\n inner.trip_id AS trip_id,\n inner.item_id AS item_id,\n inner.item_name AS item_name,\n inner.item_description AS item_description,\n inner.item_weight AS item_weight,\n inner.item_is_picked AS item_is_picked,\n inner.item_is_packed AS item_is_packed,\n inner.item_is_new AS item_is_new\n FROM inventory_items_categories AS category\n LEFT JOIN (\n SELECT\n trip.trip_id AS trip_id,\n category.id as category_id,\n category.name as category_name,\n category.description as category_description,\n item.id as item_id,\n item.name as item_name,\n item.description as item_description,\n item.weight as item_weight,\n trip.pick as item_is_picked,\n trip.pack as item_is_packed,\n trip.new as item_is_new\n FROM trips_items as trip\n INNER JOIN inventory_items as item\n ON item.id = trip.item_id\n INNER JOIN inventory_items_categories as category\n ON category.id = item.category_id\n WHERE trip.trip_id = ?\n ) AS inner\n ON inner.category_id = category.id\n " + }, + "ff260eef6f95a3c1f8e2f822808ac250925dc0971b9bddd9015b8b24643357c9": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Text" + } + ], + "nullable": [ + false + ], + "parameters": { + "Right": 1 + } + }, + "query": "SELECT id\n FROM inventory_items\n WHERE name = ?" } } \ No newline at end of file diff --git a/rust/src/components/inventory.rs b/rust/src/components/inventory.rs index 27e64af..b037587 100644 --- a/rust/src/components/inventory.rs +++ b/rust/src/components/inventory.rs @@ -323,9 +323,11 @@ impl InventoryNewItemFormName { ."justify-items-center" ."items-center" hx-post="/inventory/item/name/validate" - hx-trigger="input delay:1s, every 5s" + hx-trigger="input delay:1s, loaded from:document" + hx-params="new-item-name" hx-swap="outerHTML" + #abc { label for="name" .font-bold { "Name" } input diff --git a/rust/src/components/mod.rs b/rust/src/components/mod.rs index 15a9a52..3cdf5bd 100644 --- a/rust/src/components/mod.rs +++ b/rust/src/components/mod.rs @@ -1,4 +1,4 @@ -use maud::{html, Markup, DOCTYPE}; +use maud::{html, Markup, PreEscaped, DOCTYPE}; pub mod home; pub mod inventory; @@ -29,7 +29,7 @@ impl Root { script src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.js" defer {} link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"; link rel="shortcut icon" type="image/svg+xml" href="/favicon.svg"; - script { (include_str!(concat!(env!("CARGO_MANIFEST_DIR"),"/js/app.js"))) } + script { (PreEscaped(include_str!(concat!(env!("CARGO_MANIFEST_DIR"),"/js/app.js")))) } } body hx-boost="true" diff --git a/rust/src/main.rs b/rust/src/main.rs index 440e04e..0d1a697 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -394,7 +394,38 @@ async fn inventory_item_delete( ) .execute(&state.database_pool) .await - .map_err(|e| (StatusCode::BAD_REQUEST, e.to_string()))?; + .map_err(|error| match error { + sqlx::Error::Database(ref error) => { + let sqlite_error = error.downcast_ref::(); + if let Some(code) = sqlite_error.code() { + match &*code { + "787" => { + // SQLITE_CONSTRAINT_FOREIGNKEY + ( + StatusCode::BAD_REQUEST, + // TODO: this is not perfect, as both foreign keys + // may be responsible for the error. how can we tell + // which one? + format!("item {} cannot be deleted because it's on use in trips. instead, archive it", code.to_string()), + ) + } + _ => ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("got error with unknown code: {}", sqlite_error.to_string()), + ), + } + } else { + ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("got error without code: {}", sqlite_error.to_string()), + ) + } + } + _ => ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("got unknown error: {}", error.to_string()), + ), + })?; if results.rows_affected() == 0 { Err((