Use StateHandler in Categories

This commit is contained in:
Jeremy Wall 2022-12-28 14:55:15 -06:00
parent 1888e5328f
commit 4b2563509b
4 changed files with 40 additions and 30 deletions

View File

@ -30,7 +30,7 @@ pub struct AppState {
pub extras: BTreeSet<(String, String)>, pub extras: BTreeSet<(String, String)>,
pub staples: Option<Recipe>, pub staples: Option<Recipe>,
pub recipes: BTreeMap<String, Recipe>, pub recipes: BTreeMap<String, Recipe>,
pub category_map: BTreeMap<String, String>, pub category_map: String,
pub filtered_ingredients: BTreeSet<IngredientKey>, pub filtered_ingredients: BTreeSet<IngredientKey>,
pub modified_amts: BTreeMap<IngredientKey, String>, pub modified_amts: BTreeMap<IngredientKey, String>,
pub auth: Option<UserData>, pub auth: Option<UserData>,
@ -43,7 +43,7 @@ impl AppState {
extras: BTreeSet::new(), extras: BTreeSet::new(),
staples: None, staples: None,
recipes: BTreeMap::new(), recipes: BTreeMap::new(),
category_map: BTreeMap::new(), category_map: String::new(),
filtered_ingredients: BTreeSet::new(), filtered_ingredients: BTreeSet::new(),
modified_amts: BTreeMap::new(), modified_amts: BTreeMap::new(),
auth: None, auth: None,
@ -63,7 +63,8 @@ pub enum Message {
SetRecipe(String, Recipe), SetRecipe(String, Recipe),
RemoveRecipe(String), RemoveRecipe(String),
SetStaples(Option<Recipe>), SetStaples(Option<Recipe>),
SetCategoryMap(BTreeMap<String, String>), SetCategoryMap(String),
UpdateCategories,
InitFilteredIngredient(BTreeSet<IngredientKey>), InitFilteredIngredient(BTreeSet<IngredientKey>),
AddFilteredIngredient(IngredientKey), AddFilteredIngredient(IngredientKey),
RemoveFilteredIngredient(IngredientKey), RemoveFilteredIngredient(IngredientKey),
@ -154,14 +155,7 @@ impl StateMachine {
match store.get_categories().await { match store.get_categories().await {
Ok(Some(categories_content)) => { Ok(Some(categories_content)) => {
debug!(categories=?categories_content); debug!(categories=?categories_content);
match recipes::parse::as_categories(&categories_content) { state.category_map = categories_content;
Ok(category_map) => {
state.category_map = category_map;
}
Err(err) => {
error!(?err)
}
};
} }
Ok(None) => { Ok(None) => {
warn!("There is no category file"); warn!("There is no category file");
@ -233,8 +227,29 @@ impl MessageMapper<Message, AppState> for StateMachine {
Message::RemoveRecipe(id) => { Message::RemoveRecipe(id) => {
original_copy.recipes.remove(&id); original_copy.recipes.remove(&id);
} }
Message::SetCategoryMap(map) => { Message::SetCategoryMap(category_text) => {
original_copy.category_map = map; let store = self.0.clone();
original_copy.category_map = category_text.clone();
spawn_local_scoped(cx, async move {
if let Err(e) = store.save_categories(category_text).await {
error!(?e, "Failed to save categories");
}
});
}
Message::UpdateCategories => {
let store = self.0.clone();
let mut original_copy = original_copy.clone();
spawn_local_scoped(cx, async move {
if let Some(categories) = match store.get_categories().await {
Ok(js) => js,
Err(e) => {
error!(err=?e, "Failed to get categories.");
return;
}
} {
original_copy.category_map = categories;
};
});
} }
Message::InitFilteredIngredient(set) => { Message::InitFilteredIngredient(set) => {
original_copy.filtered_ingredients = set; original_copy.filtered_ingredients = set;

View File

@ -11,14 +11,16 @@
// 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 crate::{
app_state::{Message, StateHandler},
js_lib::get_element_by_id,
};
use sycamore::{futures::spawn_local_scoped, prelude::*}; use sycamore::{futures::spawn_local_scoped, prelude::*};
use tracing::{debug, error, instrument}; use tracing::{debug, error, instrument};
use web_sys::HtmlDialogElement; use web_sys::HtmlDialogElement;
use recipes::parse; use recipes::parse;
use crate::js_lib::get_element_by_id;
fn get_error_dialog() -> HtmlDialogElement { fn get_error_dialog() -> HtmlDialogElement {
get_element_by_id::<HtmlDialogElement>("error-dialog") get_element_by_id::<HtmlDialogElement>("error-dialog")
.expect("error-dialog isn't an html dialog element!") .expect("error-dialog isn't an html dialog element!")
@ -38,9 +40,9 @@ fn check_category_text_parses(unparsed: &str, error_text: &Signal<String>) -> bo
} }
} }
#[instrument] #[instrument(skip_all)]
#[component] #[component]
pub fn Categories<G: Html>(cx: Scope) -> View<G> { pub fn Categories<'ctx, G: Html>(cx: Scope<'ctx>, sh: StateHandler<'ctx>) -> View<G> {
let save_signal = create_signal(cx, ()); let save_signal = create_signal(cx, ());
let error_text = create_signal(cx, String::new()); let error_text = create_signal(cx, String::new());
let category_text: &Signal<String> = create_signal(cx, String::new()); let category_text: &Signal<String> = create_signal(cx, String::new());
@ -65,18 +67,11 @@ pub fn Categories<G: Html>(cx: Scope) -> View<G> {
return; return;
} }
spawn_local_scoped(cx, { spawn_local_scoped(cx, {
let store = crate::api::HttpStore::get_from_context(cx);
async move { async move {
// TODO(jwall): Save the categories. sh.dispatch(
if let Err(e) = store cx,
.save_categories(category_text.get_untracked().as_ref().clone()) Message::SetCategoryMap(category_text.get_untracked().as_ref().clone()),
.await );
{
error!(?e, "Failed to save categories");
error_text.set(format!("{:?}", e));
} else {
dirty.set(false);
}
} }
}); });
}); });

View File

@ -21,6 +21,6 @@ pub fn CategoryPage<'ctx, G: Html>(cx: Scope<'ctx>, sh: StateHandler<'ctx>) -> V
view! {cx, view! {cx,
ManagePage( ManagePage(
selected=Some("Categories".to_owned()), selected=Some("Categories".to_owned()),
) { Categories() } ) { Categories(sh) }
} }
} }

View File

@ -21,8 +21,8 @@ use crate::{api, routing::Handler as RouteHandler};
#[instrument] #[instrument]
#[component] #[component]
pub fn UI<G: Html>(cx: Scope) -> View<G> { pub fn UI<G: Html>(cx: Scope) -> View<G> {
api::HttpStore::provide_context(cx, "/api".to_owned());
// FIXME(jwall): We shouldn't need to get the store from a context anymore. // FIXME(jwall): We shouldn't need to get the store from a context anymore.
api::HttpStore::provide_context(cx, "/api".to_owned());
let store = api::HttpStore::get_from_context(cx).as_ref().clone(); let store = api::HttpStore::get_from_context(cx).as_ref().clone();
info!("Starting UI"); info!("Starting UI");
let app_state = crate::app_state::AppState::new(); let app_state = crate::app_state::AppState::new();