From 2f6375e381670e719b1cdd8b8537dbb831b62a1f Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Sat, 4 Feb 2023 12:06:16 -0500 Subject: [PATCH] Sort out recipe saving --- web/src/app_state.rs | 25 +++++++++------- web/src/components/recipe.rs | 50 ++++++++++++------------------- web/src/components/recipe_plan.rs | 3 +- 3 files changed, 34 insertions(+), 44 deletions(-) diff --git a/web/src/app_state.rs b/web/src/app_state.rs index baa44c5..c51b1d4 100644 --- a/web/src/app_state.rs +++ b/web/src/app_state.rs @@ -67,7 +67,6 @@ pub enum Message { RemoveExtra(usize), UpdateExtra(usize, String, String), SaveRecipe(RecipeEntry, Option>), - SetRecipe(String, Recipe), RemoveRecipe(String, Option>), UpdateCategory(String, String, Option>), ResetInventory, @@ -101,9 +100,6 @@ impl Debug for Message { .field(arg2) .finish(), Self::SaveRecipe(arg0, _) => f.debug_tuple("SaveRecipe").field(arg0).finish(), - Self::SetRecipe(arg0, arg1) => { - f.debug_tuple("SetRecipe").field(arg0).field(arg1).finish() - } Self::RemoveRecipe(arg0, _) => f.debug_tuple("SetCategoryMap").field(arg0).finish(), Self::UpdateCategory(i, c, _) => { f.debug_tuple("UpdateCategory").field(i).field(c).finish() @@ -197,7 +193,7 @@ impl StateMachine { entry .category() .cloned() - .unwrap_or_else(|| "Unknown".to_owned()), + .unwrap_or_else(|| "Entree".to_owned()), ) }) .collect::>(); @@ -357,22 +353,29 @@ impl MessageMapper for StateMachine { &original_copy.extras, )) } - Message::SetRecipe(id, recipe) => { - original_copy.recipes.insert(id, recipe); - } Message::SaveRecipe(entry, callback) => { let recipe = parse::as_recipe(entry.recipe_text()).expect("Failed to parse RecipeEntry"); original_copy .recipes .insert(entry.recipe_id().to_owned(), recipe); - original_copy - .recipe_counts - .insert(entry.recipe_id().to_owned(), 0); + if !original_copy.recipe_counts.contains_key(entry.recipe_id()) { + original_copy + .recipe_counts + .insert(entry.recipe_id().to_owned(), 0); + } + if let Some(cat) = entry.category().cloned() { + original_copy + .recipe_categories + .entry(entry.recipe_id().to_owned()) + .and_modify(|c| *c = cat.clone()) + .or_insert(cat); + } let store = self.store.clone(); self.local_store.set_recipe_entry(&entry); spawn_local_scoped(cx, async move { if let Err(e) = store.store_recipes(vec![entry]).await { + // FIXME(jwall): We should have a global way to trigger error messages error!(err=?e, "Unable to save Recipe"); } callback.map(|f| f()); diff --git a/web/src/components/recipe.rs b/web/src/components/recipe.rs index 00bf12d..7a34b47 100644 --- a/web/src/components/recipe.rs +++ b/web/src/components/recipe.rs @@ -72,7 +72,14 @@ pub fn Editor<'ctx, G: Html>(cx: Scope<'ctx>, props: RecipeComponentProps<'ctx>) let id = create_memo(cx, || recipe.get().recipe_id().to_owned()); let dirty = create_signal(cx, false); let ts = create_signal(cx, js_lib::get_ms_timestamp()); - let category = create_signal(cx, recipe.get().category().cloned().unwrap_or_default()); + let category = create_signal( + cx, + recipe + .get() + .category() + .cloned() + .unwrap_or_else(|| "Entree".to_owned()), + ); debug!("creating editor view"); view! {cx, @@ -103,40 +110,21 @@ pub fn Editor<'ctx, G: Html>(cx: Scope<'ctx>, props: RecipeComponentProps<'ctx>) return; } debug!("Recipe text is changed"); - spawn_local_scoped(cx, { - let store = crate::api::HttpStore::get_from_context(cx); - let category = category.get_untracked(); - let category = if category.is_empty() { - None - } else { - Some(category.as_ref().clone()) - }; - async move { - debug!("Attempting to save recipe"); - if let Err(e) = store - .store_recipes(vec![RecipeEntry( + let category = category.get_untracked(); + let category = if category.is_empty() { + None + } else { + Some(category.as_ref().clone()) + }; + let recipe_entry = RecipeEntry( id.get_untracked().as_ref().clone(), text.get_untracked().as_ref().clone(), category, - )]) - .await - { - error!(?e, "Failed to save recipe"); - error_text.set(format!("{:?}", e)); - } else { - // We also need to set recipe in our state - dirty.set(false); - if let Ok(recipe) = recipes::parse::as_recipe(text.get_untracked().as_ref()) { - sh.dispatch( - cx, - Message::SetRecipe(id.get_untracked().as_ref().to_owned(), recipe), - ); - } - }; - } - }); - } else { + ); + sh.dispatch(cx, Message::SaveRecipe(recipe_entry, None)); + dirty.set(false); } + // TODO(jwall): Show error message if trying to save when recipe doesn't parse. }) { "Save" } " " span(role="button", on:click=move |_| { sh.dispatch(cx, Message::RemoveRecipe(id.get_untracked().as_ref().to_owned(), Some(Box::new(|| sycamore_router::navigate("/ui/planning/plan"))))); diff --git a/web/src/components/recipe_plan.rs b/web/src/components/recipe_plan.rs index 94f5f43..7e03ce1 100644 --- a/web/src/components/recipe_plan.rs +++ b/web/src/components/recipe_plan.rs @@ -14,7 +14,6 @@ use std::collections::BTreeMap; // See the License for the specific language governing permissions and // limitations under the License. use recipes::Recipe; -use reqwasm::websocket::State; use sycamore::prelude::*; use tracing::{debug, instrument}; @@ -39,7 +38,7 @@ pub fn CategoryGroup<'ctx, G: Html>( row_size, }: CategoryGroupProps<'ctx>, ) -> View { - let rows = sh.get_selector(cx, move |state| { + let rows = create_signal(cx, { let mut rows = Vec::new(); for row in recipes .iter()