mirror of
https://github.com/zaphar/kitchen.git
synced 2025-07-22 19:40:14 -04:00
Fix inventory api serialization issues
This commit is contained in:
parent
2a1180dd94
commit
a1b7f953bb
@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"db": "SQLite",
|
"db": "SQLite",
|
||||||
"0e06f6e072e2c55769feda0d5f998509139097fee640caf8fb38c7087669bee4": {
|
"07f619ff4474e9eb5f4d56497abb724e6952b4e43d681ba5ecd61490cf990ae9": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
"nullable": [],
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 4
|
"Right": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"query": "insert into filtered_ingredients(user_id, name, form, measure_type)\n values (?, ?, ?, ?)"
|
"query": "delete from filtered_ingredients where user_id = ?"
|
||||||
},
|
},
|
||||||
"104f07472670436d3eee1733578bbf0c92dc4f965d3d13f9bf4bfbc92958c5b6": {
|
"104f07472670436d3eee1733578bbf0c92dc4f965d3d13f9bf4bfbc92958c5b6": {
|
||||||
"describe": {
|
"describe": {
|
||||||
@ -92,16 +92,6 @@
|
|||||||
},
|
},
|
||||||
"query": "insert into recipes (user_id, recipe_id, recipe_text) values (?, ?, ?)\n on conflict(user_id, recipe_id) do update set recipe_text=excluded.recipe_text"
|
"query": "insert into recipes (user_id, recipe_id, recipe_text) values (?, ?, ?)\n on conflict(user_id, recipe_id) do update set recipe_text=excluded.recipe_text"
|
||||||
},
|
},
|
||||||
"512003bd6ef47567b243bbcaefcbd220acf36efab4cbd43b1a8debe59593577c": {
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"nullable": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"query": "insert into modified_amts(user_id, name, form, measure_type, amt)\n values (?, ?, ?, ?, ?)"
|
|
||||||
},
|
|
||||||
"5d743897fb0d8fd54c3708f1b1c6e416346201faa9e28823c1ba5a421472b1fa": {
|
"5d743897fb0d8fd54c3708f1b1c6e416346201faa9e28823c1ba5a421472b1fa": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
@ -184,6 +174,16 @@
|
|||||||
},
|
},
|
||||||
"query": "insert into sessions (id, session_value) values (?, ?)"
|
"query": "insert into sessions (id, session_value) values (?, ?)"
|
||||||
},
|
},
|
||||||
|
"9e24ed2ea4d235e3a036025a0a0b5ea685546a81d7f2469a59a2fc1fc88798dc": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "delete from modified_amts where user_id = ?"
|
||||||
|
},
|
||||||
"ad3408cd773dd8f9308255ec2800171638a1aeda9817c57fb8360f97115f8e97": {
|
"ad3408cd773dd8f9308255ec2800171638a1aeda9817c57fb8360f97115f8e97": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
@ -282,6 +282,16 @@
|
|||||||
},
|
},
|
||||||
"query": "delete from sessions"
|
"query": "delete from sessions"
|
||||||
},
|
},
|
||||||
|
"f510d7f8dcb79907abd8b17bd52127af1699b3b79d2737c7729972d6bd5a0693": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "insert into filtered_ingredients(user_id, name, form, measure_type)\n values (?, ?, ?, ?) on conflict(user_id, name, form, measure_type) DO NOTHING"
|
||||||
|
},
|
||||||
"fc294739374d2a791214f747095e0bf9378989d1ff07d96a5431dbb208f21951": {
|
"fc294739374d2a791214f747095e0bf9378989d1ff07d96a5431dbb208f21951": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
@ -317,5 +327,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"query": "select name, form, measure_type, amt from modified_amts where user_id = ?;"
|
"query": "select name, form, measure_type, amt from modified_amts where user_id = ?;"
|
||||||
|
},
|
||||||
|
"fc9d3f8ce9d0b42f34307aeb31c128cc3267e77613d6f2e170c95e83d6e361df": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "insert into modified_amts(user_id, name, form, measure_type, amt)\n values (?, ?, ?, ?, ?) on conflict (user_id, name, form, measure_type) do update set amt=excluded.amt"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,3 @@
|
|||||||
use std::collections::BTreeMap;
|
|
||||||
// Copyright 2022 Jeremy Wall
|
// Copyright 2022 Jeremy Wall
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -12,9 +11,9 @@ use std::collections::BTreeMap;
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
use std::net::SocketAddr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{collections::BTreeSet, net::SocketAddr};
|
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
body::{boxed, Full},
|
body::{boxed, Full},
|
||||||
@ -289,12 +288,14 @@ async fn api_save_inventory(
|
|||||||
Extension(app_store): Extension<Arc<storage::SqliteStore>>,
|
Extension(app_store): Extension<Arc<storage::SqliteStore>>,
|
||||||
session: storage::UserIdFromSession,
|
session: storage::UserIdFromSession,
|
||||||
Json((filtered_ingredients, modified_amts)): Json<(
|
Json((filtered_ingredients, modified_amts)): Json<(
|
||||||
BTreeSet<IngredientKey>,
|
Vec<IngredientKey>,
|
||||||
BTreeMap<IngredientKey, String>,
|
Vec<(IngredientKey, String)>,
|
||||||
)>,
|
)>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
use storage::{UserId, UserIdFromSession::FoundUserId};
|
use storage::{UserId, UserIdFromSession::FoundUserId};
|
||||||
if let FoundUserId(UserId(id)) = session {
|
if let FoundUserId(UserId(id)) = session {
|
||||||
|
let filtered_ingredients = filtered_ingredients.into_iter().collect();
|
||||||
|
let modified_amts = modified_amts.into_iter().collect();
|
||||||
if let Err(e) = app_store
|
if let Err(e) = app_store
|
||||||
.save_inventory_data(id, filtered_ingredients, modified_amts)
|
.save_inventory_data(id, filtered_ingredients, modified_amts)
|
||||||
.await
|
.await
|
||||||
|
@ -124,7 +124,7 @@ pub trait APIStore {
|
|||||||
async fn fetch_inventory_data<S: AsRef<str> + Send>(
|
async fn fetch_inventory_data<S: AsRef<str> + Send>(
|
||||||
&self,
|
&self,
|
||||||
user_id: S,
|
user_id: S,
|
||||||
) -> Result<(BTreeSet<IngredientKey>, BTreeMap<IngredientKey, String>)>;
|
) -> Result<(Vec<IngredientKey>, Vec<(IngredientKey, String)>)>;
|
||||||
|
|
||||||
async fn save_inventory_data<S: AsRef<str> + Send>(
|
async fn save_inventory_data<S: AsRef<str> + Send>(
|
||||||
&self,
|
&self,
|
||||||
@ -496,7 +496,7 @@ impl APIStore for SqliteStore {
|
|||||||
async fn fetch_inventory_data<S: AsRef<str> + Send>(
|
async fn fetch_inventory_data<S: AsRef<str> + Send>(
|
||||||
&self,
|
&self,
|
||||||
user_id: S,
|
user_id: S,
|
||||||
) -> Result<(BTreeSet<IngredientKey>, BTreeMap<IngredientKey, String>)> {
|
) -> Result<(Vec<IngredientKey>, Vec<(IngredientKey, String)>)> {
|
||||||
let user_id = user_id.as_ref();
|
let user_id = user_id.as_ref();
|
||||||
struct FilteredIngredientRow {
|
struct FilteredIngredientRow {
|
||||||
name: String,
|
name: String,
|
||||||
@ -510,9 +510,9 @@ impl APIStore for SqliteStore {
|
|||||||
)
|
)
|
||||||
.fetch_all(self.pool.as_ref())
|
.fetch_all(self.pool.as_ref())
|
||||||
.await?;
|
.await?;
|
||||||
let mut filtered_ingredients = BTreeSet::new();
|
let mut filtered_ingredients = Vec::new();
|
||||||
for row in filtered_ingredient_rows {
|
for row in filtered_ingredient_rows {
|
||||||
filtered_ingredients.insert(IngredientKey::new(
|
filtered_ingredients.push(IngredientKey::new(
|
||||||
row.name,
|
row.name,
|
||||||
if row.form.is_empty() {
|
if row.form.is_empty() {
|
||||||
None
|
None
|
||||||
@ -535,9 +535,9 @@ impl APIStore for SqliteStore {
|
|||||||
)
|
)
|
||||||
.fetch_all(self.pool.as_ref())
|
.fetch_all(self.pool.as_ref())
|
||||||
.await?;
|
.await?;
|
||||||
let mut modified_amts = BTreeMap::new();
|
let mut modified_amts = Vec::new();
|
||||||
for row in modified_amt_rows {
|
for row in modified_amt_rows {
|
||||||
modified_amts.insert(
|
modified_amts.push((
|
||||||
IngredientKey::new(
|
IngredientKey::new(
|
||||||
row.name,
|
row.name,
|
||||||
if row.form.is_empty() {
|
if row.form.is_empty() {
|
||||||
@ -548,7 +548,7 @@ impl APIStore for SqliteStore {
|
|||||||
row.measure_type,
|
row.measure_type,
|
||||||
),
|
),
|
||||||
row.amt,
|
row.amt,
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
Ok((filtered_ingredients, modified_amts))
|
Ok((filtered_ingredients, modified_amts))
|
||||||
}
|
}
|
||||||
@ -561,6 +561,15 @@ impl APIStore for SqliteStore {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let user_id = user_id.as_ref();
|
let user_id = user_id.as_ref();
|
||||||
let mut transaction = self.pool.as_ref().begin().await?;
|
let mut transaction = self.pool.as_ref().begin().await?;
|
||||||
|
sqlx::query!(
|
||||||
|
"delete from filtered_ingredients where user_id = ?",
|
||||||
|
user_id
|
||||||
|
)
|
||||||
|
.execute(&mut transaction)
|
||||||
|
.await?;
|
||||||
|
sqlx::query!("delete from modified_amts where user_id = ?", user_id)
|
||||||
|
.execute(&mut transaction)
|
||||||
|
.await?;
|
||||||
for key in filtered_ingredients {
|
for key in filtered_ingredients {
|
||||||
let name = key.name();
|
let name = key.name();
|
||||||
let form = key.form();
|
let form = key.form();
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
insert into filtered_ingredients(user_id, name, form, measure_type)
|
insert into filtered_ingredients(user_id, name, form, measure_type)
|
||||||
values (?, ?, ?, ?)
|
values (?, ?, ?, ?) on conflict(user_id, name, form, measure_type) DO NOTHING
|
@ -1,2 +1,2 @@
|
|||||||
insert into modified_amts(user_id, name, form, measure_type, amt)
|
insert into modified_amts(user_id, name, form, measure_type, amt)
|
||||||
values (?, ?, ?, ?, ?)
|
values (?, ?, ?, ?, ?) on conflict (user_id, name, form, measure_type) do update set amt=excluded.amt
|
@ -392,8 +392,14 @@ impl HttpStore {
|
|||||||
Err(format!("Status: {}", resp.status()).into())
|
Err(format!("Status: {}", resp.status()).into())
|
||||||
} else {
|
} else {
|
||||||
debug!("We got a valid response back");
|
debug!("We got a valid response back");
|
||||||
let inventory = resp.json().await.map_err(|e| format!("{}", e))?;
|
let (filtered_ingredients, modified_amts): (
|
||||||
Ok(inventory)
|
Vec<IngredientKey>,
|
||||||
|
Vec<(IngredientKey, String)>,
|
||||||
|
) = resp.json().await.map_err(|e| format!("{}", e))?;
|
||||||
|
Ok((
|
||||||
|
filtered_ingredients.into_iter().collect(),
|
||||||
|
modified_amts.into_iter().collect(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,6 +409,8 @@ impl HttpStore {
|
|||||||
modified_amts: BTreeMap<IngredientKey, String>,
|
modified_amts: BTreeMap<IngredientKey, String>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut path = self.root.clone();
|
let mut path = self.root.clone();
|
||||||
|
let filtered_ingredients: Vec<IngredientKey> = filtered_ingredients.into_iter().collect();
|
||||||
|
let modified_amts: Vec<(IngredientKey, String)> = modified_amts.into_iter().collect();
|
||||||
let serialized_inventory = to_string(&(filtered_ingredients, modified_amts))
|
let serialized_inventory = to_string(&(filtered_ingredients, modified_amts))
|
||||||
.expect("Unable to encode plan as json");
|
.expect("Unable to encode plan as json");
|
||||||
path.push_str("/inventory");
|
path.push_str("/inventory");
|
||||||
|
@ -15,7 +15,7 @@ use std::collections::{BTreeMap, BTreeSet};
|
|||||||
|
|
||||||
use recipes::{Ingredient, IngredientKey};
|
use recipes::{Ingredient, IngredientKey};
|
||||||
use sycamore::{futures::spawn_local_scoped, prelude::*};
|
use sycamore::{futures::spawn_local_scoped, prelude::*};
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, info, instrument};
|
||||||
|
|
||||||
fn make_ingredients_rows<'ctx, G: Html>(
|
fn make_ingredients_rows<'ctx, G: Html>(
|
||||||
cx: Scope<'ctx>,
|
cx: Scope<'ctx>,
|
||||||
@ -187,15 +187,20 @@ pub fn ShoppingList<G: Html>(cx: Scope) -> View<G> {
|
|||||||
});
|
});
|
||||||
create_effect(cx, move || {
|
create_effect(cx, move || {
|
||||||
save_click.track();
|
save_click.track();
|
||||||
|
info!("Registering save request for inventory");
|
||||||
spawn_local_scoped(cx, {
|
spawn_local_scoped(cx, {
|
||||||
let state = crate::app_state::State::get_from_context(cx);
|
let state = crate::app_state::State::get_from_context(cx);
|
||||||
let store = crate::api::HttpStore::get_from_context(cx);
|
let store = crate::api::HttpStore::get_from_context(cx);
|
||||||
|
let filtered_ingredients = state.filtered_ingredients.get_untracked().as_ref().clone();
|
||||||
|
let modified_amts = state.get_current_modified_amts();
|
||||||
async move {
|
async move {
|
||||||
|
debug!(
|
||||||
|
?filtered_ingredients,
|
||||||
|
?modified_amts,
|
||||||
|
"Attempting save for inventory"
|
||||||
|
);
|
||||||
store
|
store
|
||||||
.save_inventory_data(
|
.save_inventory_data(filtered_ingredients, modified_amts)
|
||||||
state.filtered_ingredients.get_untracked().as_ref().clone(),
|
|
||||||
state.get_current_modified_amts(),
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
.expect("Unable to save inventory data");
|
.expect("Unable to save inventory data");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user