Compare commits

...

3 Commits

Author SHA1 Message Date
4230eabcae fix: Unsafe recursive object use 2024-02-20 17:12:16 -05:00
40ff02bb46 Alloy models for browser_state 2024-01-28 16:56:36 -05:00
8de0307e44 Add some models 2024-01-28 15:09:24 -05:00
5 changed files with 209 additions and 30 deletions

51
models/browser_state.als Normal file
View File

@ -0,0 +1,51 @@
sig Id {}
sig Text {}
sig Recipe {
, id: one Id
, text: one Text
}
fact {
no r1, r2: Recipe | (r1.id = r2.id) and (r1.text != r2.text)
no r1, r2: Recipe | (r1 != r2) and (r1.id = r2.id)
}
sig Ingredient {}
sig Modifier {}
sig Amt {}
sig ModifiedInventory {
, ingredient: one Ingredient
, modifier: lone Modifier
, amt: one Amt
}
fact {
no mi1, mi2: ModifiedInventory | mi1 != mi2 && (mi1.ingredient = mi2.ingredient) and (mi1.modifier = mi2.modifier)
}
sig DeletedInventory {
, ingredient: one Ingredient
, modifier: lone Modifier
}
fact {
no mi1, mi2: DeletedInventory | mi1 != mi2 && (mi1.ingredient = mi2.ingredient) and (mi1.modifier = mi2.modifier)
}
sig ExtraItems {
, ingredient: one Ingredient
, amt: one Amt
}
sig State {
, recipes: some Recipe
, modified: set ModifiedInventory
, deleted: set DeletedInventory
, extras: set ExtraItems
} {
no rs: Recipe | rs not in recipes
}
run { } for 3 but exactly 2 State, 2 Modifier, exactly 3 ModifiedInventory, exactly 9 Ingredient

17
models/planning.d2 Normal file
View File

@ -0,0 +1,17 @@
Meal Planning: {
shape: sequence_diagram
user: Cook; client: Kitchen frontend; kitchen: Kitchen backend
user -> client: Start new meal Plan
client -> kitchen: new plan created
user -> client: Add recipe to meal plan
client -> kitchen: Update meal plan with recipe
client -> client: cache updated meal plan
user -> client: Do inventory
client -> kitchen: Store inventory mutations
client -> client: cache inventory mutations
user -> client: Undo mutation
client -> kitchen: Store inventory mutations
client -> client: cache inventory mutations
user -> user: Cook recipes
}

125
models/planning.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 94 KiB

View File

@ -56,6 +56,7 @@ features = [
"Event",
"InputEvent",
"CustomEvent",
"CustomEventInit",
"EventTarget",
"History",
"HtmlAnchorElement",

View File

@ -14,9 +14,9 @@
use maud::html;
use sycamore::prelude::*;
use tracing::{debug, error};
use wasm_bindgen::JsCast;
use wasm_bindgen::{JsCast, JsValue};
use wasm_web_component::{web_component, WebComponentBinding};
use web_sys::{window, CustomEvent, Event, HtmlElement, InputEvent, ShadowRoot};
use web_sys::{window, CustomEvent, CustomEventInit, Event, HtmlElement, InputEvent, ShadowRoot};
use crate::js_lib::LogFailures;
@ -135,11 +135,10 @@ impl WebComponentBinding for NumberSpinner {
return;
}
};
let mut eventDict = CustomEventInit::new();
eventDict.detail(&JsValue::from_f64(self.value as f64));
element
.set_attribute("val", &format!("{}", self.value))
.swallow_and_log();
element
.dispatch_event(&CustomEvent::new("updated").unwrap())
.dispatch_event(&CustomEvent::new_with_event_init_dict("updated", &eventDict).unwrap())
.unwrap();
debug!("Dispatched updated event");
}
@ -147,9 +146,9 @@ impl WebComponentBinding for NumberSpinner {
fn attribute_changed_mut(
&mut self,
_element: &web_sys::HtmlElement,
name: wasm_bindgen::JsValue,
old_value: wasm_bindgen::JsValue,
new_value: wasm_bindgen::JsValue,
name: JsValue,
old_value: JsValue,
new_value: JsValue,
) {
let nval_el = self.get_input_el();
let name = name.as_string().unwrap();
@ -213,7 +212,7 @@ impl WebComponentBinding for NumberSpinner {
#[derive(Props)]
pub struct NumberProps<'ctx, F>
where
F: Fn(Event),
F: Fn(CustomEvent),
{
name: String,
class: String,
@ -225,7 +224,7 @@ where
#[component]
pub fn NumberField<'ctx, F, G: Html>(cx: Scope<'ctx>, props: NumberProps<'ctx, F>) -> View<G>
where
F: Fn(web_sys::Event) + 'ctx,
F: Fn(CustomEvent) + 'ctx,
{
let NumberProps {
name,
@ -238,27 +237,13 @@ where
// TODO(jwall): I'm pretty sure this triggers: https://github.com/sycamore-rs/sycamore/issues/602
// Which means I probably have to wait till v0.9.0 drops or switch to leptos.
let id = name.clone();
create_effect(cx, move || {
let new_count = *counter.get();
debug!(new_count, "COUNTS: Updating spinner with new value");
if let Some(el) = window()
.unwrap()
.document()
.unwrap()
.get_element_by_id(id.as_str())
{
debug!("COUNTS: found element");
el.set_attribute("val", new_count.to_string().as_str())
.unwrap();
}
});
let id = name.clone();
let initial_count = *counter.get();
view! {cx,
number-spinner(id=id, class=(class), val=*counter.get(), min=min, on:updated=move |evt: Event| {
let target: HtmlElement = evt.target().unwrap().dyn_into().unwrap();
let val: f64 = target.get_attribute("val").unwrap().parse().unwrap();
number-spinner(id=id, class=(class), val=(initial_count), min=min, on:updated=move |evt: Event| {
let event = evt.unchecked_into::<CustomEvent>();
let val: f64 = event.detail().as_f64().unwrap();
counter.set(val);
on_change.as_ref().map(|f| f(evt));
on_change.as_ref().map(|f| f(event));
debug!(counter=%(counter.get_untracked()), "set counter to new value");
})
}