mirror of
https://github.com/zaphar/kitchen.git
synced 2025-07-22 19:40:14 -04:00
fix: Turns out that indexed db doesn't support Map
Had to modify the wasm-bindgen serialization to use objects instead of the Map type.
This commit is contained in:
parent
548f336e1a
commit
9126d434d5
149
web/src/api.rs
149
web/src/api.rs
@ -24,11 +24,16 @@ use tracing::{debug, error, field::debug, instrument};
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use client_api::*;
|
use client_api::*;
|
||||||
use recipes::{IngredientKey, RecipeEntry};
|
use recipes::{IngredientKey, RecipeEntry};
|
||||||
use serde_wasm_bindgen::{from_value, to_value};
|
use serde_wasm_bindgen::{from_value, Serializer};
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
use web_sys::Storage;
|
|
||||||
// TODO(jwall): Remove this when we have gone a few migrations past.
|
// TODO(jwall): Remove this when we have gone a few migrations past.
|
||||||
//use web_sys::Storage;
|
use web_sys::{window, Storage};
|
||||||
|
|
||||||
|
fn to_js<T: serde::ser::Serialize>(value: T) -> Result<JsValue, serde_wasm_bindgen::Error>
|
||||||
|
{
|
||||||
|
let s = Serializer::new().serialize_maps_as_objects(true);
|
||||||
|
value.serialize(&s)
|
||||||
|
}
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app_state::{parse_recipes, AppState},
|
app_state::{parse_recipes, AppState},
|
||||||
@ -85,6 +90,16 @@ fn token68(user: String, pass: String) -> String {
|
|||||||
base64::engine::general_purpose::STANDARD.encode(format!("{}:{}", user, pass))
|
base64::engine::general_purpose::STANDARD.encode(format!("{}:{}", user, pass))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn convert_to_io_error<V, E>(res: Result<V, E>) -> Result<V, std::io::Error>
|
||||||
|
where
|
||||||
|
E: Into<Box<dyn std::error::Error>> + std::fmt::Debug,
|
||||||
|
{
|
||||||
|
match res {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(e) => Err(std::io::Error::new(std::io::ErrorKind::Other, format!("{:?}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct LocalStore {
|
pub struct LocalStore {
|
||||||
// TODO(zaphar): Remove this when it's safe to delete the migration
|
// TODO(zaphar): Remove this when it's safe to delete the migration
|
||||||
@ -105,7 +120,7 @@ impl LocalStore {
|
|||||||
|
|
||||||
pub async fn migrate(&self) {
|
pub async fn migrate(&self) {
|
||||||
// 1. migrate app-state from localstore to indexeddb
|
// 1. migrate app-state from localstore to indexeddb
|
||||||
debug("Peforming localstorage migration");
|
debug!("Peforming localstorage migration");
|
||||||
if let Ok(Some(v)) = self.old_store.get("app_state") {
|
if let Ok(Some(v)) = self.old_store.get("app_state") {
|
||||||
if let Ok(Some(local_state)) = from_str::<Option<AppState>>(&v) {
|
if let Ok(Some(local_state)) = from_str::<Option<AppState>>(&v) {
|
||||||
self.store_app_state(&local_state).await;
|
self.store_app_state(&local_state).await;
|
||||||
@ -138,43 +153,37 @@ impl LocalStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip_all)]
|
||||||
pub async fn store_app_state(&self, state: &AppState) {
|
pub async fn store_app_state(&self, state: &AppState) {
|
||||||
//self.migrate_local_store().await;
|
let state = match to_js(state) {
|
||||||
let state = match to_value(state) {
|
|
||||||
Ok(state) => state,
|
Ok(state) => state,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(?err, ?state, "Error deserializing app_state");
|
error!(?err, ?state, "Error deserializing app_state");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let key = to_value(APP_STATE_KEY).expect("Failed to serialize key");
|
web_sys::console::log_1(&state);
|
||||||
|
let key = to_js(APP_STATE_KEY).expect("Failed to serialize key");
|
||||||
self.store
|
self.store
|
||||||
.rw_transaction(&[js_lib::STATE_STORE_NAME], |trx| async move {
|
.rw_transaction(&[js_lib::STATE_STORE_NAME], |trx| async move {
|
||||||
let object_store = trx
|
let object_store = trx.object_store(js_lib::STATE_STORE_NAME)?;
|
||||||
.object_store(js_lib::STATE_STORE_NAME)
|
object_store.put_kv(&key, &state).await?;
|
||||||
.expect("Failed to get object store");
|
|
||||||
object_store
|
|
||||||
.put_kv(&key, &state)
|
|
||||||
.await
|
|
||||||
.expect("Failed to write to object store");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("Failed to store app-state");
|
.expect("Failed to store app-state");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
pub async fn fetch_app_state(&self) -> Option<AppState> {
|
pub async fn fetch_app_state(&self) -> Option<AppState> {
|
||||||
debug!("Loading state from local store");
|
debug!("Loading state from local store");
|
||||||
let recipes = parse_recipes(&self.get_recipes().await).expect("Failed to parse recipes");
|
let recipes = parse_recipes(&self.get_recipes().await).expect("Failed to parse recipes");
|
||||||
self.store
|
self.store
|
||||||
.ro_transaction(&[js_lib::STATE_STORE_NAME], |trx| async move {
|
.ro_transaction(&[js_lib::STATE_STORE_NAME], |trx| async move {
|
||||||
let key = to_value(APP_STATE_KEY).expect("Failed to serialize key");
|
let key = convert_to_io_error(to_js(APP_STATE_KEY))?;
|
||||||
let object_store = trx
|
let object_store = trx.object_store(js_lib::STATE_STORE_NAME)?;
|
||||||
.object_store(js_lib::STATE_STORE_NAME)
|
let mut app_state: AppState = match object_store.get(&key).await? {
|
||||||
.expect("Failed to get object store");
|
Some(s) => convert_to_io_error(from_value(s))?,
|
||||||
let mut app_state: AppState =
|
|
||||||
match object_store.get(&key).await.expect("Failed to read from") {
|
|
||||||
Some(s) => from_value(s).expect("Failed to deserialize app state"),
|
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -191,20 +200,19 @@ impl LocalStore {
|
|||||||
.expect("Failed to fetch app-state")
|
.expect("Failed to fetch app-state")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
/// Gets user data from local storage.
|
/// Gets user data from local storage.
|
||||||
pub async fn get_user_data(&self) -> Option<UserData> {
|
pub async fn get_user_data(&self) -> Option<UserData> {
|
||||||
self.store
|
self.store
|
||||||
.ro_transaction(&[js_lib::STATE_STORE_NAME], |trx| async move {
|
.ro_transaction(&[js_lib::STATE_STORE_NAME], |trx| async move {
|
||||||
let key = to_value(USER_DATA_KEY).expect("Failed to serialize key");
|
let key = to_js(USER_DATA_KEY).expect("Failed to serialize key");
|
||||||
let object_store = trx
|
let object_store = trx
|
||||||
.object_store(js_lib::STATE_STORE_NAME)
|
.object_store(js_lib::STATE_STORE_NAME)?;
|
||||||
.expect("Failed to get object store");
|
|
||||||
let user_data: UserData = match object_store
|
let user_data: UserData = match object_store
|
||||||
.get(&key)
|
.get(&key)
|
||||||
.await
|
.await?
|
||||||
.expect("Failed to read from object store")
|
|
||||||
{
|
{
|
||||||
Some(s) => from_value(s).expect("Failed to deserialize app state"),
|
Some(s) => convert_to_io_error(from_value(s))?,
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
Ok(Some(user_data))
|
Ok(Some(user_data))
|
||||||
@ -213,23 +221,22 @@ impl LocalStore {
|
|||||||
.expect("Failed to fetch user_data")
|
.expect("Failed to fetch user_data")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
// Set's user data to local storage.
|
// Set's user data to local storage.
|
||||||
pub async fn set_user_data(&self, data: Option<&UserData>) {
|
pub async fn set_user_data(&self, data: Option<&UserData>) {
|
||||||
let key = to_value(USER_DATA_KEY).expect("Failed to serialize key");
|
let key = to_js(USER_DATA_KEY).expect("Failed to serialize key");
|
||||||
if let Some(data) = data {
|
if let Some(data) = data {
|
||||||
let data = data.clone();
|
let data = data.clone();
|
||||||
self.store
|
self.store
|
||||||
.rw_transaction(&[js_lib::STATE_STORE_NAME], |trx| async move {
|
.rw_transaction(&[js_lib::STATE_STORE_NAME], |trx| async move {
|
||||||
let object_store = trx
|
let object_store = trx
|
||||||
.object_store(js_lib::STATE_STORE_NAME)
|
.object_store(js_lib::STATE_STORE_NAME)?;
|
||||||
.expect("Failed to get object store");
|
|
||||||
object_store
|
object_store
|
||||||
.put_kv(
|
.put_kv(
|
||||||
&key,
|
&key,
|
||||||
&to_value(&data).expect("failed to serialize UserData"),
|
&convert_to_io_error(to_js(&data))?,
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
.expect("Failed to store user_data");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
@ -238,12 +245,10 @@ impl LocalStore {
|
|||||||
self.store
|
self.store
|
||||||
.rw_transaction(&[js_lib::STATE_STORE_NAME], |trx| async move {
|
.rw_transaction(&[js_lib::STATE_STORE_NAME], |trx| async move {
|
||||||
let object_store = trx
|
let object_store = trx
|
||||||
.object_store(js_lib::STATE_STORE_NAME)
|
.object_store(js_lib::STATE_STORE_NAME)?;
|
||||||
.expect("Failed to get object store");
|
|
||||||
object_store
|
object_store
|
||||||
.delete(&key)
|
.delete(&key)
|
||||||
.await
|
.await?;
|
||||||
.expect("Failed to delete user_data");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
@ -251,17 +256,16 @@ impl LocalStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
async fn get_recipe_keys(&self) -> impl Iterator<Item = String> {
|
async fn get_recipe_keys(&self) -> impl Iterator<Item = String> {
|
||||||
self.store
|
self.store
|
||||||
.ro_transaction(&[js_lib::RECIPE_STORE_NAME], |trx| async move {
|
.ro_transaction(&[js_lib::RECIPE_STORE_NAME], |trx| async move {
|
||||||
let mut keys = Vec::new();
|
let mut keys = Vec::new();
|
||||||
let object_store = trx
|
let object_store = trx
|
||||||
.object_store(js_lib::RECIPE_STORE_NAME)
|
.object_store(js_lib::RECIPE_STORE_NAME)?;
|
||||||
.expect("Failed to get object store");
|
|
||||||
let key_vec = object_store
|
let key_vec = object_store
|
||||||
.get_all_keys(None)
|
.get_all_keys(None)
|
||||||
.await
|
.await?;
|
||||||
.expect("Failed to get keys from object_store");
|
|
||||||
for k in key_vec {
|
for k in key_vec {
|
||||||
if let Ok(v) = from_value(k) {
|
if let Ok(v) = from_value(k) {
|
||||||
keys.push(v);
|
keys.push(v);
|
||||||
@ -274,22 +278,22 @@ impl LocalStore {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
/// Gets all the recipes from local storage.
|
/// Gets all the recipes from local storage.
|
||||||
pub async fn get_recipes(&self) -> Option<Vec<RecipeEntry>> {
|
pub async fn get_recipes(&self) -> Option<Vec<RecipeEntry>> {
|
||||||
self.store
|
self.store
|
||||||
.ro_transaction(&[js_lib::RECIPE_STORE_NAME], |trx| async move {
|
.ro_transaction(&[js_lib::RECIPE_STORE_NAME], |trx| async move {
|
||||||
let mut recipe_list = Vec::new();
|
let mut recipe_list = Vec::new();
|
||||||
let object_store = trx
|
let object_store = trx
|
||||||
.object_store(js_lib::RECIPE_STORE_NAME)
|
.object_store(js_lib::RECIPE_STORE_NAME)?;
|
||||||
.expect("Failed to get object store");
|
|
||||||
let mut c = object_store
|
let mut c = object_store
|
||||||
.cursor()
|
.cursor()
|
||||||
.open()
|
.open()
|
||||||
.await
|
.await?;
|
||||||
.expect("Failed to open recipe cursor");
|
|
||||||
while let Some(value) = c.value() {
|
while let Some(value) = c.value() {
|
||||||
recipe_list.push(from_value(value).expect("Failed to deserialize entry"));
|
recipe_list.push(convert_to_io_error(from_value(value))?);
|
||||||
c.advance(1).await.expect("Failed to advance cursor for recipes");
|
c.advance(1)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
if recipe_list.is_empty() {
|
if recipe_list.is_empty() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@ -300,19 +304,18 @@ impl LocalStore {
|
|||||||
.expect("Failed to get recipes")
|
.expect("Failed to get recipes")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
pub async fn get_recipe_entry(&self, id: &str) -> Option<RecipeEntry> {
|
pub async fn get_recipe_entry(&self, id: &str) -> Option<RecipeEntry> {
|
||||||
let key = to_value(id).expect("Failed to serialize key");
|
let key = to_js(id).expect("Failed to serialize key");
|
||||||
self.store
|
self.store
|
||||||
.ro_transaction(&[js_lib::RECIPE_STORE_NAME], |trx| async move {
|
.ro_transaction(&[js_lib::RECIPE_STORE_NAME], |trx| async move {
|
||||||
let object_store = trx
|
let object_store = trx
|
||||||
.object_store(js_lib::RECIPE_STORE_NAME)
|
.object_store(js_lib::RECIPE_STORE_NAME)?;
|
||||||
.expect("Failed to get object store");
|
|
||||||
let entry: Option<RecipeEntry> = match object_store
|
let entry: Option<RecipeEntry> = match object_store
|
||||||
.get(&key)
|
.get(&key)
|
||||||
.await
|
.await?
|
||||||
.expect("Failed to get recipe from key")
|
|
||||||
{
|
{
|
||||||
Some(v) => from_value(v).expect("Failed to deserialize entry"),
|
Some(v) => convert_to_io_error(from_value(v))?,
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
Ok(entry)
|
Ok(entry)
|
||||||
@ -321,20 +324,19 @@ impl LocalStore {
|
|||||||
.expect("Failed to get recipes")
|
.expect("Failed to get recipes")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
/// Sets the set of recipes to the entries passed in. Deletes any recipes not
|
/// Sets the set of recipes to the entries passed in. Deletes any recipes not
|
||||||
/// in the list.
|
/// in the list.
|
||||||
pub async fn set_all_recipes(&self, entries: &Vec<RecipeEntry>) {
|
pub async fn set_all_recipes(&self, entries: &Vec<RecipeEntry>) {
|
||||||
for recipe_key in self.get_recipe_keys().await {
|
for recipe_key in self.get_recipe_keys().await {
|
||||||
let key = to_value(&recipe_key).expect("Failed to serialize key");
|
let key = to_js(&recipe_key).expect("Failed to serialize key");
|
||||||
self.store
|
self.store
|
||||||
.rw_transaction(&[js_lib::STATE_STORE_NAME], |trx| async move {
|
.rw_transaction(&[js_lib::STATE_STORE_NAME], |trx| async move {
|
||||||
let object_store = trx
|
let object_store = trx
|
||||||
.object_store(js_lib::STATE_STORE_NAME)
|
.object_store(js_lib::STATE_STORE_NAME)?;
|
||||||
.expect("Failed to get object store");
|
|
||||||
object_store
|
object_store
|
||||||
.delete(&key)
|
.delete(&key)
|
||||||
.await
|
.await?;
|
||||||
.expect("Failed to delete user_data");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
@ -342,20 +344,17 @@ impl LocalStore {
|
|||||||
}
|
}
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
let entry = entry.clone();
|
let entry = entry.clone();
|
||||||
let key =
|
let key = to_js(entry.recipe_id()).expect("Failed to serialize recipe key");
|
||||||
to_value(entry.recipe_id()).expect("Failed to serialize recipe key");
|
|
||||||
self.store
|
self.store
|
||||||
.rw_transaction(&[js_lib::RECIPE_STORE_NAME], |trx| async move {
|
.rw_transaction(&[js_lib::RECIPE_STORE_NAME], |trx| async move {
|
||||||
let object_store = trx
|
let object_store = trx
|
||||||
.object_store(js_lib::RECIPE_STORE_NAME)
|
.object_store(js_lib::RECIPE_STORE_NAME)?;
|
||||||
.expect("Failed to get object store");
|
|
||||||
object_store
|
object_store
|
||||||
.put_kv(
|
.put_kv(
|
||||||
&key,
|
&key,
|
||||||
&to_value(&entry).expect("Failed to serialize recipe entry"),
|
&convert_to_io_error(to_js(&entry))?,
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
.expect("Failed to store recipe_entry");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
@ -363,40 +362,38 @@ impl LocalStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
/// Set recipe entry in local storage.
|
/// Set recipe entry in local storage.
|
||||||
pub async fn set_recipe_entry(&self, entry: &RecipeEntry) {
|
pub async fn set_recipe_entry(&self, entry: &RecipeEntry) {
|
||||||
let entry = entry.clone();
|
let entry = entry.clone();
|
||||||
let key = to_value(entry.recipe_id()).expect("Failed to serialize recipe key");
|
let key = to_js(entry.recipe_id()).expect("Failed to serialize recipe key");
|
||||||
self.store
|
self.store
|
||||||
.rw_transaction(&[js_lib::RECIPE_STORE_NAME], |trx| async move {
|
.rw_transaction(&[js_lib::RECIPE_STORE_NAME], |trx| async move {
|
||||||
let object_store = trx
|
let object_store = trx
|
||||||
.object_store(js_lib::RECIPE_STORE_NAME)
|
.object_store(js_lib::RECIPE_STORE_NAME)?;
|
||||||
.expect("Failed to get object store");
|
|
||||||
object_store
|
object_store
|
||||||
.put_kv(
|
.put_kv(
|
||||||
&key,
|
&key,
|
||||||
&to_value(&entry).expect("Failed to serialize recipe entry"),
|
&convert_to_io_error(to_js(&entry))?,
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
.expect("Failed to store recipe_entry");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("Failed to store recipe entry");
|
.expect("Failed to store recipe entry");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
/// Delete recipe entry from local storage.
|
/// Delete recipe entry from local storage.
|
||||||
pub async fn delete_recipe_entry(&self, recipe_id: &str) {
|
pub async fn delete_recipe_entry(&self, recipe_id: &str) {
|
||||||
let key = to_value(recipe_id).expect("Failed to serialize key");
|
let key = to_js(recipe_id).expect("Failed to serialize key");
|
||||||
self.store
|
self.store
|
||||||
.rw_transaction(&[js_lib::RECIPE_STORE_NAME], |trx| async move {
|
.rw_transaction(&[js_lib::RECIPE_STORE_NAME], |trx| async move {
|
||||||
let object_store = trx
|
let object_store = trx
|
||||||
.object_store(js_lib::RECIPE_STORE_NAME)
|
.object_store(js_lib::RECIPE_STORE_NAME)?;
|
||||||
.expect("Failed to get object store");
|
|
||||||
object_store
|
object_store
|
||||||
.delete(&key)
|
.delete(&key)
|
||||||
.await
|
.await?;
|
||||||
.expect("Failed to delete user_data");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -37,7 +37,7 @@ fn bool_true() -> bool {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
pub recipe_counts: BTreeMap<String, usize>,
|
pub recipe_counts: BTreeMap<String, u32>,
|
||||||
pub recipe_categories: BTreeMap<String, String>,
|
pub recipe_categories: BTreeMap<String, String>,
|
||||||
pub extras: Vec<(String, String)>,
|
pub extras: Vec<(String, String)>,
|
||||||
// FIXME(jwall): This should really be storable I think?
|
// FIXME(jwall): This should really be storable I think?
|
||||||
@ -77,7 +77,7 @@ impl AppState {
|
|||||||
|
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
ResetRecipeCounts,
|
ResetRecipeCounts,
|
||||||
UpdateRecipeCount(String, usize),
|
UpdateRecipeCount(String, u32),
|
||||||
AddExtra(String, String),
|
AddExtra(String, String),
|
||||||
RemoveExtra(usize),
|
RemoveExtra(usize),
|
||||||
UpdateExtra(usize, String, String),
|
UpdateExtra(usize, String, String),
|
||||||
@ -171,6 +171,7 @@ impl StateMachine {
|
|||||||
Self { store, local_store }
|
Self { store, local_store }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip_all)]
|
||||||
async fn load_state(
|
async fn load_state(
|
||||||
store: &HttpStore,
|
store: &HttpStore,
|
||||||
local_store: &LocalStore,
|
local_store: &LocalStore,
|
||||||
@ -238,7 +239,7 @@ impl StateMachine {
|
|||||||
// set the counts.
|
// set the counts.
|
||||||
let mut plan_map = BTreeMap::new();
|
let mut plan_map = BTreeMap::new();
|
||||||
for (id, count) in plan {
|
for (id, count) in plan {
|
||||||
plan_map.insert(id, count as usize);
|
plan_map.insert(id, count as u32);
|
||||||
}
|
}
|
||||||
state.recipe_counts = plan_map;
|
state.recipe_counts = plan_map;
|
||||||
for (id, _) in state.recipes.iter() {
|
for (id, _) in state.recipes.iter() {
|
||||||
@ -470,7 +471,7 @@ impl MessageMapper<Message, AppState> for StateMachine {
|
|||||||
// Note(jwall): This is a little unusual but because this
|
// Note(jwall): This is a little unusual but because this
|
||||||
// is async code we can't rely on the set below.
|
// is async code we can't rely on the set below.
|
||||||
original_copy.recipe_counts =
|
original_copy.recipe_counts =
|
||||||
BTreeMap::from_iter(plan.drain(0..).map(|(k, v)| (k, v as usize)));
|
BTreeMap::from_iter(plan.drain(0..).map(|(k, v)| (k, v as u32)));
|
||||||
}
|
}
|
||||||
let (filtered, modified, extras) = store
|
let (filtered, modified, extras) = store
|
||||||
.fetch_inventory_for_date(&date)
|
.fetch_inventory_for_date(&date)
|
||||||
|
@ -68,7 +68,7 @@ pub fn RecipeSelection<'ctx, G: Html>(
|
|||||||
label(for=for_id, class="flex-item-grow") { a(href=href) { (*title) } }
|
label(for=for_id, class="flex-item-grow") { a(href=href) { (*title) } }
|
||||||
NumberField(name=name, class="flex-item-shrink".to_string(), counter=count, min=0.0, on_change=Some(move |_| {
|
NumberField(name=name, class="flex-item-shrink".to_string(), counter=count, min=0.0, on_change=Some(move |_| {
|
||||||
debug!(idx=%id, count=%(*count.get_untracked()), "setting recipe count");
|
debug!(idx=%id, count=%(*count.get_untracked()), "setting recipe count");
|
||||||
sh.dispatch(cx, Message::UpdateRecipeCount(id.as_ref().clone(), *count.get_untracked() as usize));
|
sh.dispatch(cx, Message::UpdateRecipeCount(id.as_ref().clone(), *count.get_untracked() as u32));
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user