diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..f4e8c00 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "wasm32-unknown-unknown" diff --git a/Cargo.lock b/Cargo.lock index 594aa1e..883e5ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,26 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - [[package]] name = "aho-corasick" version = "1.0.1" @@ -32,45 +12,16 @@ dependencies = [ ] [[package]] -name = "android_system_properties" -version = "0.1.5" +name = "anymap" +version = "1.0.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] +checksum = "8f1f8f5a6f3d50d89e3797d7593a50f96bb2aaa20ca0cc7be1fb673232c91d72" [[package]] -name = "anyhow" -version = "1.0.71" +name = "anymap2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" - -[[package]] -name = "async-channel" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-lock" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-task" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" +checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" [[package]] name = "async-trait" @@ -80,15 +31,9 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] -[[package]] -name = "atomic-waker" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" - [[package]] name = "autocfg" version = "1.1.0" @@ -96,147 +41,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] -name = "bitflags" -version = "1.3.2" +name = "bincode" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitmaps" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ - "typenum", -] - -[[package]] -name = "blocking" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" -dependencies = [ - "async-channel", - "async-lock", - "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "log", -] - -[[package]] -name = "bstr" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" -dependencies = [ - "memchr", "serde", ] +[[package]] +name = "boolinator" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" + [[package]] name = "bumpalo" version = "3.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b" -[[package]] -name = "bumpslab" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5816c875b50b9866d759fa24d46159dccab0d7942c0ccbfd700b4f45dd961e" -dependencies = [ - "bumpalo", -] - -[[package]] -name = "camino" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-platform" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" - -[[package]] -name = "cfg-expr" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bbc13bf6290a6b202cc3efb36f7ec2b739a80634215630c8053a313edf6abef" -dependencies = [ - "smallvec", -] - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chrono" -version = "0.4.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-integer", - "num-traits", - "time", - "wasm-bindgen", - "winapi", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - -[[package]] -name = "concurrent-queue" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -247,80 +77,11 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "cxx" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn 2.0.15", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] - [[package]] name = "darling" -version = "0.20.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" dependencies = [ "darling_core", "darling_macro", @@ -328,280 +89,29 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8bfa2e259f8ee1ce5e97824a3c55ec4404a0d772ca7fa96bf19f0752a046eb" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "syn 2.0.15", + "strsim", + "syn 1.0.109", ] [[package]] name = "darling_macro" -version = "0.20.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", - "syn 2.0.15", -] - -[[package]] -name = "dioxus" -version = "0.3.2" -source = "git+https://github.com/dioxuslabs/dioxus.git#b476c6e8a73bd6591ec4827c6f9b196d7c270c3d" -dependencies = [ - "dioxus-core", - "dioxus-core-macro", - "dioxus-hooks", - "dioxus-hot-reload", - "dioxus-html", - "dioxus-rsx", -] - -[[package]] -name = "dioxus-core" -version = "0.3.3" -source = "git+https://github.com/dioxuslabs/dioxus.git#b476c6e8a73bd6591ec4827c6f9b196d7c270c3d" -dependencies = [ - "bumpalo", - "bumpslab", - "futures-channel", - "futures-util", - "indexmap", - "log", - "longest-increasing-subsequence", - "rustc-hash", - "serde", - "slab", - "smallbox", -] - -[[package]] -name = "dioxus-core-macro" -version = "0.3.0" -source = "git+https://github.com/dioxuslabs/dioxus.git#b476c6e8a73bd6591ec4827c6f9b196d7c270c3d" -dependencies = [ - "dioxus-rsx", - "proc-macro2", - "quote", "syn 1.0.109", ] -[[package]] -name = "dioxus-hooks" -version = "0.3.1" -source = "git+https://github.com/dioxuslabs/dioxus.git#b476c6e8a73bd6591ec4827c6f9b196d7c270c3d" -dependencies = [ - "dioxus-core", - "futures-channel", - "log", -] - -[[package]] -name = "dioxus-hot-reload" -version = "0.1.1" -source = "git+https://github.com/dioxuslabs/dioxus.git#b476c6e8a73bd6591ec4827c6f9b196d7c270c3d" -dependencies = [ - "chrono", - "dioxus-core", - "dioxus-html", - "dioxus-rsx", - "execute", - "ignore", - "interprocess", - "notify", - "once_cell", - "serde", - "serde_json", -] - -[[package]] -name = "dioxus-html" -version = "0.3.1" -source = "git+https://github.com/dioxuslabs/dioxus.git#b476c6e8a73bd6591ec4827c6f9b196d7c270c3d" -dependencies = [ - "async-trait", - "dioxus-core", - "dioxus-rsx", - "enumset", - "euclid", - "keyboard-types", - "serde", - "serde-value", - "serde_repr", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "dioxus-interpreter-js" -version = "0.3.1" -source = "git+https://github.com/dioxuslabs/dioxus.git#b476c6e8a73bd6591ec4827c6f9b196d7c270c3d" -dependencies = [ - "js-sys", - "sledgehammer_bindgen", - "sledgehammer_utils", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "dioxus-rsx" -version = "0.0.3" -source = "git+https://github.com/dioxuslabs/dioxus.git#b476c6e8a73bd6591ec4827c6f9b196d7c270c3d" -dependencies = [ - "dioxus-core", - "internment", - "krates", - "proc-macro2", - "quote", - "serde", - "syn 1.0.109", -] - -[[package]] -name = "dioxus-web" -version = "0.3.2" -source = "git+https://github.com/dioxuslabs/dioxus.git#b476c6e8a73bd6591ec4827c6f9b196d7c270c3d" -dependencies = [ - "anyhow", - "async-trait", - "console_error_panic_hook", - "dioxus-core", - "dioxus-html", - "dioxus-interpreter-js", - "futures-channel", - "futures-util", - "gloo-timers", - "js-sys", - "log", - "once_cell", - "rustc-hash", - "serde", - "serde-wasm-bindgen", - "serde_json", - "smallstr", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "enumset" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e875f1719c16de097dee81ed675e2d9bb63096823ed3f0ca827b7dea3028bbbb" -dependencies = [ - "enumset_derive", -] - -[[package]] -name = "enumset_derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.15", -] - -[[package]] -name = "euclid" -version = "0.22.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f253bc5c813ca05792837a0ff4b3a580336b224512d48f7eda1d7dd9210787" -dependencies = [ - "num-traits", - "serde", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "execute" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d9a9ea4c04632c16bc5c71a2fcc63d308481f7fc67eb1a1ce6315c44a426ae" -dependencies = [ - "execute-command-macro", - "execute-command-tokens", - "generic-array", -] - -[[package]] -name = "execute-command-macro" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5fbc65a0cf735106743f4c38c9a3671c1e734b5c2c20d21a3c93c696daa3157" -dependencies = [ - "execute-command-macro-impl", -] - -[[package]] -name = "execute-command-macro-impl" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55a9a55d1dab3b07854648d48e366f684aefe2ac78ae28cec3bf65e3cd53d9a3" -dependencies = [ - "execute-command-tokens", - "quote", - "syn 2.0.15", -] - -[[package]] -name = "execute-command-tokens" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba569491c70ec8471e34aa7e9c0b9e82bb5d2464c0398442d17d3c4af814e5a" - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fermi" -version = "0.3.0" -source = "git+https://github.com/dioxuslabs/dioxus.git#b476c6e8a73bd6591ec4827c6f9b196d7c270c3d" -dependencies = [ - "dioxus-core", - "im-rc", - "log", -] - -[[package]] -name = "filetime" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "windows-sys 0.48.0", -] - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - [[package]] name = "fnv" version = "1.0.7" @@ -609,12 +119,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "fsevent-sys" -version = "4.1.0" +name = "form_urlencoded" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "libc", + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", ] [[package]] @@ -624,6 +148,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -638,21 +163,6 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - [[package]] name = "futures-macro" version = "0.3.28" @@ -661,9 +171,15 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + [[package]] name = "futures-task" version = "0.3.28" @@ -676,24 +192,18 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ + "futures-channel", "futures-core", + "futures-io", "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", "slab", ] -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "getrandom" version = "0.2.9" @@ -701,21 +211,135 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" dependencies = [ "cfg-if", + "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", + "wasm-bindgen", ] [[package]] -name = "globset" -version = "0.4.10" +name = "gloo" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "3a4bef6b277b3ab073253d4bca60761240cf8d6998f4bd142211957b69a61b20" dependencies = [ - "aho-corasick 0.7.20", - "bstr", - "fnv", - "log", - "regex", + "gloo-console", + "gloo-dialogs", + "gloo-events", + "gloo-file", + "gloo-history", + "gloo-net", + "gloo-render", + "gloo-storage", + "gloo-timers", + "gloo-utils", + "gloo-worker", +] + +[[package]] +name = "gloo-console" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b7ce3c05debe147233596904981848862b068862e9ec3e34be446077190d3f" +dependencies = [ + "gloo-utils", + "js-sys", + "serde", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-dialogs" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67062364ac72d27f08445a46cab428188e2e224ec9e37efdba48ae8c289002e6" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-events" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b107f8abed8105e4182de63845afcc7b69c098b7852a813ea7462a320992fc" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-file" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d5564e570a38b43d78bdc063374a0c3098c4f0d64005b12f9bbe87e869b6d7" +dependencies = [ + "gloo-events", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-history" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd451019e0b7a2b8a7a7b23e74916601abf1135c54664e57ff71dcc26dfcdeb7" +dependencies = [ + "gloo-events", + "gloo-utils", + "serde", + "serde-wasm-bindgen", + "serde_urlencoded", + "thiserror", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-net" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9902a044653b26b99f7e3693a42f171312d9be8b26b5697bd1e43ad1f8a35e10" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-render" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd9306aef67cfd4449823aadcd14e3958e0800aa2183955a309112a84ec7764" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-storage" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6ab60bf5dbfd6f0ed1f7843da31b41010515c745735c970e821945ca91e480" +dependencies = [ + "gloo-utils", + "js-sys", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "web-sys", ] [[package]] @@ -724,43 +348,53 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" dependencies = [ - "futures-channel", - "futures-core", "js-sys", "wasm-bindgen", ] +[[package]] +name = "gloo-utils" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8e8fc851e9c7b9852508bc6e3f690f452f474417e8545ec9857b7f7377036b5" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-worker" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13471584da78061a28306d1359dd0178d8d6fc1c7c80e5e35d27260346e0516a" +dependencies = [ + "anymap2", + "bincode", + "gloo-console", + "gloo-utils", + "js-sys", + "serde", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", -] [[package]] -name = "iana-time-zone" -version = "0.1.56" +name = "hermit-abi" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" -dependencies = [ - "cxx", - "cxx-build", + "libc", ] [[package]] @@ -770,35 +404,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] -name = "ignore" -version = "0.4.20" +name = "implicit-clone" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +checksum = "40fc102e70475c320b185cd18c1e48bba2d7210b63970a4d581ef903e4368ef7" dependencies = [ - "globset", - "lazy_static", - "log", - "memchr", - "regex", - "same-file", - "thread_local", - "walkdir", - "winapi-util", -] - -[[package]] -name = "im-rc" -version = "15.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" -dependencies = [ - "bitmaps", - "rand_core", - "rand_xoshiro", - "serde", - "sized-chunks", - "typenum", - "version_check", + "indexmap", ] [[package]] @@ -811,71 +422,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "inotify" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" -dependencies = [ - "bitflags", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "internment" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a798d7677f07d6f1e77be484ea8626ddb1566194de399f1206306820c406371" -dependencies = [ - "hashbrown", - "parking_lot", -] - -[[package]] -name = "interprocess" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81f2533f3be42fffe3b5e63b71aeca416c1c3bc33e4e27be018521e76b1f38fb" -dependencies = [ - "blocking", - "cfg-if", - "futures-core", - "futures-io", - "intmap", - "libc", - "once_cell", - "rustc_version", - "spinning", - "thiserror", - "to_method", - "winapi", -] - -[[package]] -name = "intmap" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae52f28f45ac2bc96edb7714de995cffc174a395fb0abf5bff453587c980d7b9" - [[package]] name = "itoa" version = "1.0.6" @@ -884,56 +430,13 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "js-sys" -version = "0.3.62" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68c16e1bfd491478ab155fd8b4896b86f9ede344949b641e61501e07c2b8b4d5" +checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" dependencies = [ "wasm-bindgen", ] -[[package]] -name = "keyboard-types" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7668b7cff6a51fe61cdde64cd27c8a220786f399501b57ebe36f7d8112fd68" -dependencies = [ - "bitflags", - "serde", - "unicode-segmentation", -] - -[[package]] -name = "kqueue" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" -dependencies = [ - "bitflags", - "libc", -] - -[[package]] -name = "krates" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942c43a6cba1c201dfe81a943c89fa5c9140b34993e0c027f542c80b92e319a7" -dependencies = [ - "cargo_metadata", - "cfg-expr", - "petgraph", - "semver", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -946,25 +449,6 @@ version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" -[[package]] -name = "link-cplusplus" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" -dependencies = [ - "cc", -] - -[[package]] -name = "lock_api" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "log" version = "0.4.17" @@ -974,21 +458,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "longest-increasing-subsequence" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" - -[[package]] -name = "lru" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" -dependencies = [ - "hashbrown", -] - [[package]] name = "memchr" version = "2.5.0" @@ -996,52 +465,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] -name = "mio" -version = "0.8.6" +name = "num_cpus" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ + "hermit-abi", "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", -] - -[[package]] -name = "notify" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9" -dependencies = [ - "bitflags", - "crossbeam-channel", - "filetime", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "mio", - "walkdir", - "windows-sys 0.42.0", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", ] [[package]] @@ -1051,51 +481,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] -name = "ordered-float" -version = "2.10.0" +name = "percent-encoding" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pin-project" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" dependencies = [ - "num-traits", + "pin-project-internal", ] [[package]] -name = "parking" -version = "2.1.0" +name = "pin-project-internal" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-sys 0.45.0", -] - -[[package]] -name = "petgraph" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" -dependencies = [ - "fixedbitset", - "indexmap", + "proc-macro2", + "quote", + "syn 2.0.16", ] [[package]] @@ -1110,28 +518,100 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pinned" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a829027bd95e54cfe13e3e258a1ae7b645960553fb82b75ff852c29688ee595b" +dependencies = [ + "futures", + "rustversion", + "thiserror", +] + [[package]] name = "plate-tool" version = "0.1.0" dependencies = [ - "dioxus", - "dioxus-web", - "fermi", "lazy_static", "log", "regex", + "serde", + "uuid", + "wasm-bindgen", + "wasm-bindgen-test", "wasm-logger", + "web-sys", + "yew", + "yewdux", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", ] [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" dependencies = [ "unicode-ident", ] +[[package]] +name = "prokio" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b55e106e5791fa5a13abd13c85d6127312e8e09098059ca2bc9b03ca4cf488" +dependencies = [ + "futures", + "gloo", + "num_cpus", + "once_cell", + "pin-project", + "pinned", + "tokio", + "tokio-stream", + "wasm-bindgen-futures", +] + [[package]] name = "quote" version = "1.0.27" @@ -1142,27 +622,33 @@ dependencies = [ ] [[package]] -name = "rand_core" -version = "0.6.4" +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - -[[package]] -name = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", + "rand_chacha", "rand_core", ] [[package]] -name = "redox_syscall" -version = "0.2.16" +name = "rand_chacha" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ - "bitflags", + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", ] [[package]] @@ -1171,7 +657,7 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" dependencies = [ - "aho-corasick 1.0.1", + "aho-corasick", "memchr", "regex-syntax", ] @@ -1183,19 +669,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" [[package]] -name = "rustc-hash" -version = "1.1.0" +name = "rustversion" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" [[package]] name = "ryu" @@ -1204,34 +681,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] -name = "same-file" -version = "1.0.6" +name = "scoped-tls" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "scratch" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" - -[[package]] -name = "semver" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" -dependencies = [ - "serde", -] +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "serde" @@ -1242,16 +695,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-value" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" -dependencies = [ - "ordered-float", - "serde", -] - [[package]] name = "serde-wasm-bindgen" version = "0.4.5" @@ -1271,7 +714,7 @@ checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -1286,24 +729,15 @@ dependencies = [ ] [[package]] -name = "serde_repr" -version = "0.1.12" +name = "serde_urlencoded" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] - -[[package]] -name = "sized-chunks" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" -dependencies = [ - "bitmaps", - "typenum", + "form_urlencoded", + "itoa", + "ryu", + "serde", ] [[package]] @@ -1316,56 +750,10 @@ dependencies = [ ] [[package]] -name = "sledgehammer_bindgen" -version = "0.2.2" +name = "strsim" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a2ff7338d75d086ba25c3958e3673282b1d986c466532bd7a731fe63e8c5e" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "sledgehammer_utils" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "095fd5332b21763203248070746b86b98c6167fc620af73d4cb2bc2d7d9cd815" -dependencies = [ - "lru", - "once_cell", - "rustc-hash", - "ux", -] - -[[package]] -name = "smallbox" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4679d6eef28b85020158619fc09769de89e90886c5de7157587d87cb72648faa" - -[[package]] -name = "smallstr" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e922794d168678729ffc7e07182721a14219c65814e66e91b839a272fe5ae4f" -dependencies = [ - "smallvec", -] - -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - -[[package]] -name = "spinning" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d4f0e86297cad2658d92a707320d87bf4e6ae1050287f51d19b67ef3f153a7b" -dependencies = [ - "lock_api", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" @@ -1380,24 +768,15 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - [[package]] name = "thiserror" version = "1.0.40" @@ -1415,42 +794,63 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] -name = "thread_local" -version = "1.1.7" +name = "tokio" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" +dependencies = [ + "autocfg", + "pin-project-lite", + "windows-sys", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.16", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ "once_cell", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "to_method" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8" - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - [[package]] name = "unicode-ident" version = "1.0.8" @@ -1458,22 +858,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] -name = "unicode-segmentation" -version = "1.10.1" +name = "uuid" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" +dependencies = [ + "getrandom", + "rand", + "serde", + "uuid-macro-internal", + "wasm-bindgen", +] [[package]] -name = "unicode-width" -version = "0.1.10" +name = "uuid-macro-internal" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "ux" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb3ff47e36907a6267572c1e398ff32ef78ac5131de8aa272e53846592c207e" +checksum = "3f67b459f42af2e6e1ee213cb9da4dbd022d3320788c3fb3e1b893093f1e45da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.16", +] [[package]] name = "version_check" @@ -1481,28 +887,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "walkdir" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1511,9 +895,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.85" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b6cb788c4e39112fbe1822277ef6fb3c55cd86b95cb3d3c4c1c9597e4ac74b4" +checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1521,24 +905,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.85" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e522ed4105a9d626d885b35d62501b30d9666283a5c8be12c14a8bdafe7822" +checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.35" +version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "083abe15c5d88556b77bdf7aef403625be9e327ad37c62c4e4129af740168163" +checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" dependencies = [ "cfg-if", "js-sys", @@ -1548,9 +932,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.85" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "358a79a0cb89d21db8120cbfb91392335913e4890665b1a7981d9e956903b434" +checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1558,22 +942,46 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.85" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4783ce29f09b9d93134d41297aded3a712b7b979e9c6f28c32cb88c973a94869" +checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.85" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a901d592cafaa4d711bc324edfaff879ac700b19c3dfd60058d2b445be2691eb" +checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e636f3a428ff62b3742ebc3c70e254dfe12b8c2b469d688ea59cdd4abcf502" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f18c1fad2f7c4958e7bcce014fa212f59a65d5e3721d0f77e6c0b27ede936ba3" +dependencies = [ + "proc-macro2", + "quote", +] [[package]] name = "wasm-logger" @@ -1588,100 +996,21 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.62" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b5f940c7edfdc6d12126d98c9ef4d1b3d470011c47c76a6581df47ad9ba721" +checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" dependencies = [ "js-sys", "wasm-bindgen", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets", ] [[package]] @@ -1690,95 +1019,125 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "yew" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dbecfe44343b70cc2932c3eb445425969ae21754a8ab3a0966981c1cf7af1cc" +dependencies = [ + "console_error_panic_hook", + "futures", + "gloo", + "implicit-clone", + "indexmap", + "js-sys", + "prokio", + "rustversion", + "serde", + "slab", + "thiserror", + "tokio", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "yew-macro", +] + +[[package]] +name = "yew-macro" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b64c253c1d401f1ea868ca9988db63958cfa15a69f739101f338d6f05eea8301" +dependencies = [ + "boolinator", + "once_cell", + "prettyplease", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "yewdux" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653ba356bc60d1804c28ec6cc8ddac2741c686bde2a65074d07faba735914464" +dependencies = [ + "anymap", + "async-trait", + "log", + "serde", + "serde_json", + "slab", + "thiserror", + "wasm-bindgen", + "web-sys", + "yew", + "yewdux-macros", +] + +[[package]] +name = "yewdux-macros" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25bcd923aceaa85cb4affad8657cc36e3d6b6932740e711574182f7817492739" +dependencies = [ + "darling", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] diff --git a/Cargo.toml b/Cargo.toml index f954095..7a037b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,10 +6,16 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -dioxus = { git = "https://github.com/dioxuslabs/dioxus.git" } -dioxus-web = { git = "https://github.com/dioxuslabs/dioxus.git" } -fermi = { git = "https://github.com/dioxuslabs/dioxus" } # Yikes +yew = { version = "0.20.0", features = ["csr"] } +yewdux = "0.9" +wasm-bindgen = "0.2" +web-sys = { version = "0.3", features = ["FormData", "HtmlFormElement", "HtmlDialogElement"] } log = "0.4" wasm-logger = "0.2" regex = "1" lazy_static = "1.4" +uuid = { version = "1.3", features = ["v4", "fast-rng", "macro-diagnostics", "js", "serde"] } +serde = { version = "1.0", features = ["derive"] } + +[dev-dependencies] +wasm-bindgen-test = "0.3.0" diff --git a/Dioxus.toml b/Dioxus.toml deleted file mode 100644 index aa4f7b1..0000000 --- a/Dioxus.toml +++ /dev/null @@ -1,46 +0,0 @@ -[application] - -# dioxus project name -name = "Plate Tool" - -# default platfrom -# you can also use `dioxus serve/build --platform XXX` to use other platform -# value: web | desktop -default_platform = "web" - -# Web `build` & `serve` dist path -out_dir = "dist" - -# resource (static) file folder -asset_dir = "public" - -[web.app] - -# HTML title tag content -title = "Plate Tool" - -[web.watcher] - -watch_path = ["src"] -index_on_404 = true - -# include `assets` in web platform -[web.resource] - -# CSS style file -style = [] - -# Javascript code file -script = [] - -[web.resource.dev] - -# Javascript code file -# serve: [dev-server] only -script = [] - -[application.tools] - -# use binaryen.wasm-opt for output Wasm file -# binaryen just will trigger in `web` platform -binaryen = { wasm_opt = true } diff --git a/src/components/global.css b/assets/css/global.css similarity index 67% rename from src/components/global.css rename to assets/css/global.css index e226c6c..1709ef5 100644 --- a/src/components/global.css +++ b/assets/css/global.css @@ -6,6 +6,12 @@ font: inherit; vertical-align: baseline; } +h1, h2, h3 { + padding: 0; + margin: 0; + margin-bottom: 0.4em; + margin-top: 0.4em; +} div.main_container { height: 95vh; @@ -25,6 +31,12 @@ div.tree { height: 100%; border: 2px solid green; } +div.tree li { + user-select: none; +} +div.tree li.selected { + background: rgba(0,0,150,0.2); +} div.transfer_menu { grid-column: left / left; @@ -33,9 +45,19 @@ div.transfer_menu { height: 100%; border: 2px solid orange; } +div.transfer_menu input:invalid { + background-color: #faa; +} div.plate_container { border: 2px dashed purple; grid-column: right / right; grid-row: upper / 3; } + +.dialog { + padding: 1em; +} +.dialog::backdrop { + background: rgba(0,125,255,0.3); +} diff --git a/assets/css/plate.css b/assets/css/plate.css new file mode 100644 index 0000000..6d52374 --- /dev/null +++ b/assets/css/plate.css @@ -0,0 +1,40 @@ +table, tr, td { + user-select: none; /* Prevents dragging issue */ + border-spacing: 0px; +} +td.plate_cell { + height: 2vmin; + background: none; +} + +div.plate_cell_inner { + aspect-ratio: 1 / 1; + height: 90%; + border-radius: 50%; + border: 2px solid black; +} +td.plate_cell:hover div.plate_cell_inner { + background: black !important; +} +td.plate_cell.in_transfer div.plate_cell_inner::after { + content: ""; + width: 100%; + height: 100%; + display: block; + border-radius: 50%; + background-image: repeating-linear-gradient( + 45deg, + rgba(0,0,0,0.8), + rgba(0,0,0,0.8) 2px, + transparent 2px, + transparent 4px + ); +} + +div.source_plate td.current_select div.plate_cell_inner { + background-image: linear-gradient(lightblue, lightblue); +} +div.dest_plate td.current_select div.plate_cell_inner { + background: lightcoral; +} + diff --git a/src/components/plates/plate_container.css b/assets/css/plate_container.css similarity index 100% rename from src/components/plates/plate_container.css rename to assets/css/plate_container.css diff --git a/assets/fonts/Inconsolata.ttf b/assets/fonts/Inconsolata.ttf new file mode 100644 index 0000000..34848ca Binary files /dev/null and b/assets/fonts/Inconsolata.ttf differ diff --git a/assets/fonts/Jost.ttf b/assets/fonts/Jost.ttf new file mode 100644 index 0000000..e758df3 Binary files /dev/null and b/assets/fonts/Jost.ttf differ diff --git a/assets/scss/default_theme/_variables.scss b/assets/scss/default_theme/_variables.scss new file mode 100644 index 0000000..874f271 --- /dev/null +++ b/assets/scss/default_theme/_variables.scss @@ -0,0 +1,33 @@ +@use "sass:color"; +@use "sass:math"; + +$-color-white: hsl(30 5% 90%); +$-color-dark: color.adjust($-color-white, $lightness: -60%); +$-color-light: hsl(190 80% 30%); +$-ff-serif: "Inconsolata", monospace; +$-ff-sans: "Jost", sans-serif; +$-fs-900: math.div(100rem, 16); + +@forward "base" with ( + $color-white: $-color-white, + $color-dark: $-color-dark, + $color-light: $-color-light, + $ff-serif: $-ff-serif, + $ff-sans: $-ff-sans, + $fs-900: $-fs-900 +); + +@font-face { + font-family: "Inconsolata"; + src: url("/fonts/Inconsolata.ttf"); + + font-display: swap; + font-variation-settings: "wdth" 85; +} + +@font-face { + font-family: "Jost"; + src: url("/fonts/Jost.ttf"); + + font-display: swap; +} diff --git a/assets/scss/default_theme/base.scss b/assets/scss/default_theme/base.scss new file mode 100644 index 0000000..4c9b0c4 --- /dev/null +++ b/assets/scss/default_theme/base.scss @@ -0,0 +1,214 @@ +// +// +// Do Not Change This File! +// +// +@use "sass:math"; +/* ----------------- */ +/* Custom Properties */ +/* ----------------- */ +/* + This values are to be overridden + after being injected into + the global scope. +*/ + + /* colors */ + +$color-dark: hsl(0 0% 0%) !default; /* Black */ +$color-light: hsl(0 0% 50%) !default; /* Gray */ +$color-white: hsl(0 0% 100%) !default;/* White */ + + /* font */ + + /* Sizes divided by 16 so values given in px */ +$fs-900: math.div(125rem, 16) !default; +$fs-800: math.div(75rem, 16) !default; +$fs-700: math.div(56rem, 16) !default; +$fs-600: math.div(32rem, 16) !default; +$fs-500: math.div(28rem, 16) !default; +$fs-400: math.div(24rem, 16) !default; +$fs-300: math.div(18rem, 16) !default; +$fs-200: math.div(16rem, 16) !default; + +$ff-serif: serif !default; +$ff-sans-cond: sans-serif !default; +$ff-sans: sans-serif !default; + +/* --------------- */ +/* Utility Classes */ +/* --------------- */ + +/* Layouts */ + +.container { + padding-inline: clamp(0.5rem, 4rem, 5rem); + margin-inline: auto; + max-width: 80rem; +} + +.flex { + display: flex; + gap: 2rem; +} + +.column { + justify-content: center; + align-items: center; + flex-direction: column; + align-content: center; +} + +.row { + flex-direction: row; + flex-wrap: wrap; + justify-content: space-evenly; + align-content: baseline; + max-width: 100%; +} + +.two-columns { + display: grid; + /* Will shrink to one column, never exceed two! + * The `max` in `minmax` asks that the columns + * be no smaller */ + grid-template-columns: repeat(auto-fit, minmax(max(30rem, 40%), 1fr)); + column-gap: 1rem; + justify-content: space-evenly; +} + +.lock-bottom { + position: fixed; + bottom: 0%; +} + +/* Other */ + +.hr::after { /* Add fake hr after header */ + content: ''; + + position: absolute; + display: block; + clear: both; + width: 100%; + height: 0.15rem; + + background-color: black; +} + +/* Color Classes */ + +.bg-dark { background-color: $color-dark; } +.bg-light { background-color: $color-light; } +.bg-white { background-color: $color-white; } + +.text-dark { color: $color-dark; } +.text-light { color: $color-light; } +.text-white { color: $color-white; } + +/* Font Classes */ + +.fs-900 { font-size: $fs-900; } +.fs-800 { font-size: $fs-800; } +.fs-700 { font-size: $fs-700; } +.fs-600 { font-size: $fs-600; } +.fs-500 { font-size: $fs-500; } +.fs-400 { font-size: $fs-400; } +.fs-300 { font-size: $fs-300; } +.fs-200 { font-size: $fs-200; } + +.ff-serif { font-family: $ff-serif; } +.ff-sans-cond { font-family: $ff-sans-cond; } +.ff-sans { font-family: $ff-sans; } + +.uppercase { text-transform: uppercase; } +.lowercase { text-transform: lowercase; } + +/* Semantic Tags and Their Classes */ + +header { + margin-bottom: 3vh; +} + +section:not(:last-of-type) { + margin-bottom: 3vh; +} + +footer { + margin-top: 3vh; +} + +/* ----- */ +/* Reset */ +/* ----- */ + +*, +*::before, +*::after { + box-sizing: border-box; +} + +body, h1, h2, h3, h4, h5, h6, p { + margin: 0; +} + +h1, h2, h3, h4, h5, h6, p { + font-weight: 400; +} + +h1, h2, h3 { + line-height: 1.1; +} + +body { + font-family: $ff-sans; + font-size: $fs-400; + color: $color-dark; + background-color: $color-white; + line-height: 1.5; + min-height: 100vh; +} + +main { + margin-left: 1vw; + margin-top: 1vh; + * { + z-index: 2; + } +} + +footer { + z-index: 2; +} + +img, picture { + max-width: 100%; + display: block; +} + +input, button, textarea, select { + font: inherit; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behaviour: auto !important; + } +} + +/* -------------------- */ +/* Non-Reusable Classes */ +/* -------------------- */ +/* meant for these pages + * only, not to be used + * in practice */ + +.colors--block { + padding: 3rem 1rem 1rem; + border: 1px solid black; +} diff --git a/assets/scss/default_theme/components/_index.scss b/assets/scss/default_theme/components/_index.scss new file mode 100644 index 0000000..bea7850 --- /dev/null +++ b/assets/scss/default_theme/components/_index.scss @@ -0,0 +1,5 @@ +@forward "main_window"; +@forward "plate_container"; +@forward "plates"; +@forward "tree"; +@forward "transfer_menu"; diff --git a/assets/scss/default_theme/components/_main_window.scss b/assets/scss/default_theme/components/_main_window.scss new file mode 100644 index 0000000..b9b887c --- /dev/null +++ b/assets/scss/default_theme/components/_main_window.scss @@ -0,0 +1,20 @@ +div.main_container { + height: 95vh; + width: 98vw; + margin-top: 2.5vh; + margin-left: 1vw; + + display: grid; + grid-template-columns: [left] minmax(min-content, 1fr) [right] 2fr; + grid-template-rows: [upper] 2fr [lower] 1fr; + + column-gap: 1vw; + row-gap: 1vh; +} + +.dialog { + padding: 1em; +} +.dialog::backdrop { + background: rgba(0,125,255,0.3); +} diff --git a/assets/scss/default_theme/components/_plate_container.scss b/assets/scss/default_theme/components/_plate_container.scss new file mode 100644 index 0000000..0458708 --- /dev/null +++ b/assets/scss/default_theme/components/_plate_container.scss @@ -0,0 +1,18 @@ +@use "sass:color"; +@use "../variables" as *; + +div.plate_container { + display: flex; + flex-direction: column; + justify-content: space-around; + align-items: center; + + border: 2px solid $color-dark; + grid-column: right / right; + grid-row: upper / 3; + + h2 { + margin-bottom: 1%; + text-align: center; + } +} diff --git a/assets/scss/default_theme/components/_plates.scss b/assets/scss/default_theme/components/_plates.scss new file mode 100644 index 0000000..e91cf79 --- /dev/null +++ b/assets/scss/default_theme/components/_plates.scss @@ -0,0 +1,52 @@ +div.source_plate, div.dest_plate { + padding: 3px 3px 3px 3px; +} + +div.source_plate { + border: 2px solid blue; +} +div.dest_plate { + border: 2px solid red; +} + +table, tr, td { + user-select: none; /* Prevents dragging issue */ + border-spacing: 0px; +} +td.plate_cell { + height: 2.3vmin; + background: none; +} + +div.plate_cell_inner { + aspect-ratio: 1 / 1; + height: 90%; + border-radius: 50%; + border: 2px solid black; +} +td.plate_cell:hover div.plate_cell_inner { + background: black !important; +} +td.plate_cell.in_transfer div.plate_cell_inner::after { + content: ""; + width: 100%; + height: 100%; + display: block; + border-radius: 50%; + background-image: repeating-linear-gradient( + 45deg, + rgba(0,0,0,0.8), + rgba(0,0,0,0.8) 2px, + transparent 2px, + transparent 4px + ); +} + +div.source_plate td.current_select div.plate_cell_inner { + background-image: linear-gradient(lightblue, lightblue); +} +div.dest_plate td.current_select div.plate_cell_inner { + background: lightcoral; +} + + diff --git a/assets/scss/default_theme/components/_transfer_menu.scss b/assets/scss/default_theme/components/_transfer_menu.scss new file mode 100644 index 0000000..b34c4f6 --- /dev/null +++ b/assets/scss/default_theme/components/_transfer_menu.scss @@ -0,0 +1,61 @@ +@use "sass:color"; +@use "../variables" as *; + +div.transfer_menu { + position: relative; + width: 100%; + height: 100%; + + grid-column: left / left; + grid-row: lower / lower; + + border: 2px solid $color-dark; + + form { + padding-top: 3%; + padding-bottom: 1%; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + + label { + display: inline; + * { display: inline; } + } + } + + padding-left: 0.5rem; + + input:invalid { + background-color: #faa; + } + + div#controls { + align-self: flex-end; + input { + padding: 2px 3px 2px 3px; + margin-left: 0; + } + } +} + +input { + text-align: center; + margin-left: 0.5em; + margin-right: 0.5em; + margin-top: 1%; + margin-bottom: 1%; + line-height: 1em; + padding: 0; + + &[type="text"] { + width: 4em; + } + &[name="name"] { + width: 6em; // Override above + } + &[type="number"] { + width: 2em; + } +} diff --git a/assets/scss/default_theme/components/_tree.scss b/assets/scss/default_theme/components/_tree.scss new file mode 100644 index 0000000..7ef8833 --- /dev/null +++ b/assets/scss/default_theme/components/_tree.scss @@ -0,0 +1,55 @@ +@use "sass:color"; +@use "../variables" as *; + +$selection-border-width: 2px; + +div.tree { + position: relative; + + grid-column: left / left; + grid-row: upper / upper; + width: 100%; + height: 100%; + border: 2px solid $color-dark; + + h3 { + margin-left: 0.5rem; + } + + div#controls { + position: absolute; + bottom: 2%; + right: 2%; + } +} + +div.tree ul { + width: 80%; + margin-left: 10%; + padding: 0; + + display: flex; + flex-direction: column; + align-items: stretch; + + overflow: scroll; +} + +div.tree li { + display: inline; + margin-left: 0; + margin-bottom: 0.4rem; + border: 2px solid transparent; + + user-select: none; + list-style: none; + line-height: 1em; + + &:hover { + background: color.change($color-light, $alpha: 0.08); + border: $selection-border-width solid color.change($color-light, $alpha:0.3); + } + &.selected { + background: color.change($color-light, $alpha: 0.2); + } +} diff --git a/assets/scss/default_theme/main.scss b/assets/scss/default_theme/main.scss new file mode 100644 index 0000000..6e05a5d --- /dev/null +++ b/assets/scss/default_theme/main.scss @@ -0,0 +1,10 @@ +// Global Variables +@use "variables" as *; +@use "components"; + +.fs-900 { font-size: $fs-900; font-weight: 400;} +.fs-800 { font-size: $fs-800; font-weight: 300;} +.fs-700 { font-size: $fs-700; font-weight: 250;} +.fs-600 { font-size: $fs-600; font-weight: 300;} +.fs-500 { font-size: $fs-500; font-weight: 200;} +.fs-400 { font-size: $fs-400; font-weight: 200;} diff --git a/assets/scss/index.scss b/assets/scss/index.scss new file mode 100644 index 0000000..cf86353 --- /dev/null +++ b/assets/scss/index.scss @@ -0,0 +1,2 @@ +@use "default_theme/main"; +@use "default_theme/variables" as *; diff --git a/index.html b/index.html new file mode 100644 index 0000000..7c93c7a --- /dev/null +++ b/index.html @@ -0,0 +1,9 @@ + + + + + + + Plate Tool + + diff --git a/src/components/main_window.rs b/src/components/main_window.rs index 9eb47f1..d4f4cef 100644 --- a/src/components/main_window.rs +++ b/src/components/main_window.rs @@ -1,22 +1,64 @@ #![allow(non_snake_case)] -use dioxus::prelude::*; +use yew::prelude::*; +use yewdux::prelude::*; + +use super::new_plate_dialog::NewPlateDialog; use super::plates::plate_container::PlateContainer; -use super::tree::Tree; +use super::states::{CurrentTransfer, MainState}; use super::transfer_menu::TransferMenu; +use super::tree::Tree; -static STYLE: &'static str = include_str!("global.css"); +use crate::data::plate_instances::PlateInstance; -pub fn MainWindow(cx: Scope) -> Element { - cx.render(rsx! { - style { STYLE }, - div { - class: "main_container", - Tree {}, - TransferMenu {}, - PlateContainer { - source_dims: (24,16), - destination_dims: (24,16) +#[function_component] +pub fn MainWindow() -> Html { + let (main_state, main_dispatch) = use_store::(); + let (ct_state, ct_dispatch) = use_store::(); + + let source_plate_instance: Option = main_state + .source_plates + .iter() + .find(|spi| spi.get_uuid() == main_state.selected_source_plate) + .cloned(); + if let Some(spi) = source_plate_instance.clone() { + ct_dispatch.reduce_mut(|state| { + state.transfer.transfer_region.source_plate = spi.plate; + }); + } + let destination_plate_instance: Option = main_state + .destination_plates + .iter() + .find(|dpi| dpi.get_uuid() == main_state.selected_dest_plate) + .cloned(); + if let Some(dpi) = destination_plate_instance.clone() { + ct_dispatch.reduce_mut(|state| { + state.transfer.transfer_region.dest_plate = dpi.plate; + }); + } + + let new_plate_dialog_is_open = use_state_eq(|| false); + let new_plate_dialog_callback = { + let new_plate_dialog_is_open = new_plate_dialog_is_open.clone(); + Callback::from(move |_| { + new_plate_dialog_is_open.set(false); + }) + }; + let open_new_plate_dialog_callback = { + let new_plate_dialog_is_open = new_plate_dialog_is_open.clone(); + Callback::from(move |_| { + new_plate_dialog_is_open.set(true); + }) + }; + + html! { +
+ + + + if {*new_plate_dialog_is_open} { + } - } - }) +
+ } } diff --git a/src/components/mod.rs b/src/components/mod.rs index 6ff64b0..ac482b6 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,4 +1,6 @@ -pub mod plates; pub mod main_window; -pub mod tree; +pub mod new_plate_dialog; +pub mod plates; +pub mod states; pub mod transfer_menu; +pub mod tree; diff --git a/src/components/new_plate_dialog.rs b/src/components/new_plate_dialog.rs new file mode 100644 index 0000000..dcfb117 --- /dev/null +++ b/src/components/new_plate_dialog.rs @@ -0,0 +1,104 @@ +use yew::prelude::*; +use yewdux::prelude::*; + +use wasm_bindgen::JsCast; +use web_sys::{EventTarget, FormData, HtmlDialogElement, HtmlFormElement}; + +use crate::components::states::MainState; +use crate::data::plate::*; +use crate::data::{plate_instances::PlateInstance, transfer::Transfer}; + +#[derive(PartialEq, Properties)] +pub struct NewPlateDialogProps { + pub close_callback: Callback<()>, +} + +#[function_component] +pub fn NewPlateDialog(props: &NewPlateDialogProps) -> Html { + let (state, dispatch) = use_store::(); + + let new_plate_callback = { + let dispatch = dispatch.clone(); + let close_callback = props.close_callback.clone(); + Callback::from(move |e: SubmitEvent| { + e.prevent_default(); + close_callback.emit(()); + let target: Option = e.target(); + let form = target.and_then(|t| t.dyn_into::().ok()); + if let Some(form) = form { + if let Ok(form_data) = FormData::new_with_form(&form) { + let name = form_data.get("new_plate_name").as_string().unwrap(); + let format = match form_data.get("plate_format").as_string().unwrap().as_str() { + "384" => PlateFormat::W384, + "96" => PlateFormat::W96, + _ => PlateFormat::W6, + }; + if let Some(pt_string) = form_data.get("new_plate_type").as_string() { + let plate_type = match pt_string.as_str() { + "src" => PlateType::Source, + "dest" => PlateType::Destination, + _ => PlateType::Source, + }; + dispatch.reduce_mut(|s| { + if plate_type == PlateType::Source { + s.add_source_plate(PlateInstance::new( + PlateType::Source, + format, + name, + )) + } else { + s.add_dest_plate(PlateInstance::new( + PlateType::Destination, + format, + name, + )) + } + }); + } + } + } + }) + }; + + // This whole section is optional, only if you want the backdrop + let dialog_ref = use_node_ref(); + { + let dialog_ref = dialog_ref.clone(); + + use_effect_with_deps( + |dialog_ref| { + dialog_ref + .cast::() + .unwrap() + .show_modal() + .ok(); + }, + dialog_ref, + ); + } + + html! { + +

{"Create a plate:"}

+
+ + + + + + + +
+
+ } +} + +impl From<&PlateInstance> for String { + fn from(value: &PlateInstance) -> Self { + // Could have other formatting here + format!("{}, {}", value.name, value.plate.plate_format) + } +} diff --git a/src/components/plates/destination_plate.rs b/src/components/plates/destination_plate.rs index ccc76a1..9de0048 100644 --- a/src/components/plates/destination_plate.rs +++ b/src/components/plates/destination_plate.rs @@ -1,40 +1,151 @@ #![allow(non_snake_case)] -use dioxus::prelude::*; +use std::rc::Rc; +use yew::prelude::*; +use yewdux::prelude::*; -#[inline_props] -pub fn DestinationPlate(cx: Scope, width: u8, height: u8) -> Element { - cx.render(rsx! { - div { - class: "dest_plate", - table { - for i in 1..=cx.props.height { - tr { - draggable: "false", - for j in 1..=cx.props.width { - DestPlateCell {i: i, j: j} - } - } - }, - } - } - }) +use crate::components::states::CurrentTransfer; +use crate::data::plate_instances::PlateInstance; +use crate::data::transfer_region::{Region, TransferRegion}; + +use super::super::transfer_menu::RegionDisplay; + +#[derive(Properties, PartialEq)] +pub struct DestinationPlateProps { + pub source_plate: PlateInstance, + pub destination_plate: PlateInstance, } -#[inline_props] -fn DestPlateCell(cx: Scope, i: u8, j: u8, color: Option) -> Element { - let color_string = match color { - Some(c) => c.clone(), - None => "None".to_string(), +#[function_component] +pub fn DestinationPlate(props: &DestinationPlateProps) -> Html { + let (ct_state, ct_dispatch) = use_store::(); + let m_start_handle: UseStateHandle> = use_state_eq(|| None); + let m_end_handle: UseStateHandle> = use_state_eq(|| None); + let m_stat_handle: UseStateHandle = use_state_eq(|| false); + let m_start = m_start_handle.clone(); + let m_end = m_end_handle.clone(); + + if !(*m_stat_handle) { + let (pt1, pt2) = match ct_state.transfer.transfer_region.dest_region { + Region::Point((x, y)) => ((x, y), (x, y)), + Region::Rect(c1, c2) => (c1, c2), + }; + m_start_handle.set(Some(pt1)); + m_end_handle.set(Some(pt2)); + } + let destination_wells = ct_state.transfer.transfer_region.get_destination_wells(); + + let mouse_callback = { + let m_start_handle = m_start_handle.clone(); + let m_end_handle = m_end_handle.clone(); + let m_stat_handle = m_stat_handle.clone(); + + Callback::from(move |(i, j, t)| match t { + MouseEventType::MOUSEDOWN => { + m_start_handle.set(Some((i, j))); + m_end_handle.set(Some((i, j))); + m_stat_handle.set(true); + } + MouseEventType::MOUSEENTER => { + if *m_stat_handle { + m_end_handle.set(Some((i, j))); + } + } + }) }; - cx.render(rsx! { - td { - class: "plate_cell", - draggable: "false", - style: "background: {color_string}", - div { - class: "plate_cell_inner" + let mouseup_callback = { + let m_start_handle = m_start_handle.clone(); + let m_end_handle = m_end_handle.clone(); + let m_stat_handle = m_stat_handle.clone(); + + Callback::from(move |_: MouseEvent| { + m_stat_handle.set(false); + if let Some(ul) = *m_start_handle { + if let Some(br) = *m_end_handle { + if let Ok(rd) = RegionDisplay::try_from((ul.0, ul.1, br.0, br.1)) { + ct_dispatch.reduce_mut(|state| { + state.transfer.transfer_region.dest_region = Region::from(&rd); + }); + } + } } - } - }) + }) + }; + + let mouseleave_callback = Callback::clone(&mouseup_callback); + + let rows = (1..=props.destination_plate.plate.size().0) + .map(|i| { + let row = (1..=props.destination_plate.plate.size().1).map(|j| { + html! { + + } + }).collect::(); + html! { + + { row } + + } + }) + .collect::(); + + html! { +
+ + { rows } +
+
+ } +} + +#[derive(Debug)] +pub enum MouseEventType { + MOUSEDOWN, + MOUSEENTER, +} + +#[derive(Properties, PartialEq)] +pub struct DestPlateCellProps { + pub i: u8, + pub j: u8, + pub selected: bool, + pub mouse: Callback<(u8, u8, MouseEventType)>, + pub in_transfer: Option, +} + +#[function_component] +fn DestPlateCell(props: &DestPlateCellProps) -> Html { + let selected_class = match props.selected { + true => Some("current_select"), + false => None, + }; + let in_transfer_class = match props.in_transfer { + Some(true) => Some("in_transfer"), + _ => None, + }; + let mouse = Callback::clone(&props.mouse); + let mouse2 = Callback::clone(&props.mouse); + let (i, j) = (props.i.clone(), props.j.clone()); + + html! { + +
+ + } } diff --git a/src/components/plates/mod.rs b/src/components/plates/mod.rs index 6bda88a..e93c903 100644 --- a/src/components/plates/mod.rs +++ b/src/components/plates/mod.rs @@ -1,3 +1,3 @@ -pub mod source_plate; pub mod destination_plate; pub mod plate_container; +pub mod source_plate; diff --git a/src/components/plates/plate.css b/src/components/plates/plate.css deleted file mode 100644 index b4b4a6d..0000000 --- a/src/components/plates/plate.css +++ /dev/null @@ -1,22 +0,0 @@ -table, tr, td { - user-select: none; /* Prevents dragging issue */ - border-spacing: 0px; -} -td.plate_cell { - height: 2vmin; - background: none; -} - -div.plate_cell_inner { - aspect-ratio: 1 / 1; - height: 90%; - border-radius: 50%; - border: 2px solid black; -} -td.plate_cell:hover div.plate_cell_inner { - background: black !important; -} - -td.current_select div.plate_cell_inner { - background: lightblue !important; -} diff --git a/src/components/plates/plate_container.rs b/src/components/plates/plate_container.rs index d1b4009..e11e6ea 100644 --- a/src/components/plates/plate_container.rs +++ b/src/components/plates/plate_container.rs @@ -1,20 +1,37 @@ #![allow(non_snake_case)] -use dioxus::prelude::*; -use super::source_plate::SourcePlate; +use yew::prelude::*; + +use crate::data::plate_instances::PlateInstance; + use super::destination_plate::DestinationPlate; +use super::source_plate::SourcePlate; -static STYLE: &'static str = include_str!("plate_container.css"); - -#[inline_props] -pub fn PlateContainer(cx: Scope, source_dims: (u8,u8), destination_dims: (u8,u8)) -> Element { - cx.render(rsx! { - style { STYLE } - div { - class: "plate_container", - SourcePlate {width: source_dims.0, - height: source_dims.1}, - DestinationPlate {width: destination_dims.0, - height: destination_dims.1} - } - }) +#[derive(Properties, PartialEq)] +pub struct PlateContainerProps { + pub source_dims: Option, + pub destination_dims: Option, +} + +#[function_component] +pub fn PlateContainer(props: &PlateContainerProps) -> Html { + html! { +
+ if let Some(spi) = props.source_dims.clone() { + if let Some(dpi) = props.destination_dims.clone() { +
+

{spi.name.clone()}

+ +
+
+

{dpi.name.clone()}

+ +
+ } else { +

{"No Destination Plate Selected"}

+ } + } else { +

{"No Source Plate Selected"}

+ } +
+ } } diff --git a/src/components/plates/source_plate.rs b/src/components/plates/source_plate.rs index 181c513..f911d3d 100644 --- a/src/components/plates/source_plate.rs +++ b/src/components/plates/source_plate.rs @@ -1,91 +1,159 @@ #![allow(non_snake_case)] -use dioxus::prelude::*; -static STYLE: &'static str = include_str!("plate.css"); +use std::rc::Rc; +use yew::prelude::*; +use yewdux::prelude::*; -#[derive(PartialEq, Props)] +use crate::components::states::CurrentTransfer; +use crate::data::plate_instances::PlateInstance; +use crate::data::transfer_region::{Region, TransferRegion}; + +use super::super::transfer_menu::RegionDisplay; + +#[derive(PartialEq, Properties)] pub struct SourcePlateProps { - width: u8, - height: u8, -} -struct SelectionState { - m_start: Option<(u8, u8)>, - m_end: Option<(u8, u8)>, - m_stat: bool, + pub source_plate: PlateInstance, + pub destination_plate: PlateInstance, } -pub fn SourcePlate(cx: Scope) -> Element { - use_shared_state_provider(cx, || SelectionState { - m_start: None, - m_end: None, - m_stat: false, - }); +#[function_component] +pub fn SourcePlate(props: &SourcePlateProps) -> Html { + let (ct_state, ct_dispatch) = use_store::(); + let m_start_handle: UseStateHandle> = use_state_eq(|| None); + let m_end_handle: UseStateHandle> = use_state_eq(|| None); + let m_stat_handle: UseStateHandle = use_state_eq(|| false); + let m_start = m_start_handle.clone(); + let m_end = m_end_handle.clone(); - cx.render(rsx! { - div{ - class: "source_plate", - style { STYLE } - table { - draggable: "false", - for i in 1..=cx.props.height { - tr { - draggable: "false", - for j in 1..=cx.props.width { - SourcePlateCell {i: i, j: j} - } + if !(*m_stat_handle) { + let (pt1, pt2) = match ct_state.transfer.transfer_region.source_region { + Region::Point((x, y)) => ((x, y), (x, y)), + Region::Rect(c1, c2) => (c1, c2), + }; + m_start_handle.set(Some(pt1)); + m_end_handle.set(Some(pt2)); + } + + let source_wells = ct_state.transfer.transfer_region.get_source_wells(); + + let mouse_callback = { + let m_start_handle = m_start_handle.clone(); + let m_end_handle = m_end_handle.clone(); + let m_stat_handle = m_stat_handle.clone(); + + Callback::from(move |(i, j, t)| match t { + MouseEventType::MOUSEDOWN => { + m_start_handle.set(Some((i, j))); + m_end_handle.set(Some((i, j))); + m_stat_handle.set(true); + } + MouseEventType::MOUSEENTER => { + if *m_stat_handle { + m_end_handle.set(Some((i, j))); + } + } + }) + }; + + let mouseup_callback = { + let m_start_handle = m_start_handle.clone(); + let m_end_handle = m_end_handle.clone(); + let m_stat_handle = m_stat_handle.clone(); + + Callback::from(move |_: MouseEvent| { + m_stat_handle.set(false); + if let Some(ul) = *m_start_handle { + if let Some(br) = *m_end_handle { + if let Ok(rd) = RegionDisplay::try_from((ul.0, ul.1, br.0, br.1)) { + ct_dispatch.reduce_mut(|state| { + state.transfer.transfer_region.source_region = Region::from(&rd); + }); } - }, + } } - } - }) -} - -#[inline_props] -fn SourcePlateCell(cx: Scope, i: u8, j: u8, color: Option) -> Element { - let selection_state = use_shared_state::(cx).unwrap(); - let selected = in_rect( - selection_state.read().m_start, - selection_state.read().m_end, - (*i, *j), - ); - let selected_class = match selected { - true => "current_select", - false => "", - }; - let color_string = match color { - Some(c) => c.clone(), - None => "None".to_string(), + }) }; - cx.render(rsx! { - td { - class: "plate_cell {selected_class}", - draggable: "false", - style: "background: {color_string}", - onmousedown: move |_| { - selection_state.write().m_start = Some((*i,*j)); - selection_state.write().m_end = None; - selection_state.write().m_stat = true; - }, - onmouseenter: move |me: MouseEvent| { - if me.data.held_buttons().is_empty() { - selection_state.write().m_stat = false; - } - if selection_state.read().m_stat { - selection_state.write().m_end = Some((*i,*j)) - } - }, - onmouseup: move |_| { - selection_state.write().m_stat = false - }, - div { - class: "plate_cell_inner" + let mouseleave_callback = Callback::clone(&mouseup_callback); + + let rows = (1..=props.source_plate.plate.size().0) + .map(|i| { + let row = (1..=props.source_plate.plate.size().1) + .map(|j| { + html! { + + } + }) + .collect::(); + html! { + + { row } + } - } - }) + }) + .collect::(); + + html! { +
+ + { rows } +
+
+ } } -fn in_rect(corner1: Option<(u8, u8)>, corner2: Option<(u8, u8)>, pt: (u8, u8)) -> bool { +#[derive(PartialEq, Properties)] +pub struct SourcePlateCellProps { + i: u8, + j: u8, + selected: bool, + mouse: Callback<(u8, u8, MouseEventType)>, + in_transfer: Option, +} +#[derive(Debug)] +pub enum MouseEventType { + MOUSEDOWN, + MOUSEENTER, +} + +#[function_component] +fn SourcePlateCell(props: &SourcePlateCellProps) -> Html { + let selected_class = match props.selected { + true => Some("current_select"), + false => None, + }; + let in_transfer_class = match props.in_transfer { + Some(true) => Some("in_transfer"), + _ => None, + }; + let mouse = Callback::clone(&props.mouse); + let mouse2 = Callback::clone(&props.mouse); + let (i, j) = (props.i.clone(), props.j.clone()); + + html! { + +
+ + } +} + +pub fn in_rect(corner1: Option<(u8, u8)>, corner2: Option<(u8, u8)>, pt: (u8, u8)) -> bool { if let (Some(c1), Some(c2)) = (corner1, corner2) { return pt.0 <= u8::max(c1.0, c2.0) && pt.0 >= u8::min(c1.0, c2.0) @@ -98,10 +166,13 @@ fn in_rect(corner1: Option<(u8, u8)>, corner2: Option<(u8, u8)>, pt: (u8, u8)) - #[cfg(test)] mod tests { + use wasm_bindgen_test::*; + use super::in_rect; // in_rect tests #[test] + #[wasm_bindgen_test] fn test_in_rect1() { // Test in center of rect let c1 = (1, 1); @@ -113,6 +184,7 @@ mod tests { } #[test] + #[wasm_bindgen_test] fn test_in_rect2() { // Test on top/bottom edges of rect let c1 = (1, 1); @@ -127,6 +199,7 @@ mod tests { } #[test] + #[wasm_bindgen_test] fn test_in_rect3() { // Test on left/right edges of rect let c1 = (1, 1); @@ -141,6 +214,7 @@ mod tests { } #[test] + #[wasm_bindgen_test] fn test_in_rect4() { // Test cases that should fail let c1 = (1, 1); diff --git a/src/components/states.rs b/src/components/states.rs new file mode 100644 index 0000000..3d81e29 --- /dev/null +++ b/src/components/states.rs @@ -0,0 +1,90 @@ +use serde::{Deserialize, Serialize}; +use uuid::Uuid; +use yewdux::{prelude::*, storage}; + +use super::transfer_menu::RegionDisplay; +use crate::data::plate::*; +use crate::data::plate_instances::PlateInstance; +use crate::data::transfer::Transfer; + +#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, Store)] +#[store(storage = "session")] +pub struct CurrentTransfer { + pub transfer: Transfer, +} + +#[derive(Default, PartialEq, Clone, Serialize, Deserialize)] +pub struct MainState { + pub source_plates: Vec, + pub destination_plates: Vec, + pub transfers: Vec, + pub selected_source_plate: Uuid, + pub selected_dest_plate: Uuid, + pub selected_transfer: Uuid, +} + +impl Store for MainState { + fn new() -> Self { + init_listener(storage::StorageListener::::new(storage::Area::Local)); + + storage::load(storage::Area::Local) + .expect("Unable to load state") + .unwrap_or_default() + /* + Self { + source_plates: Vec::new(), + destination_plates: Vec::new(), + transfers: Vec::new(), + } + */ + } + + fn should_notify(&self, old: &Self) -> bool { + self != old + } +} + +impl MainState { + pub fn purge_transfers(&mut self) { + // Removes any transfers for which the associated plates are gone + self.transfers = self + .transfers + .iter() + .filter(|tr| { + self.source_plates + .iter() + .any(|spi| spi.get_uuid() == tr.source_id) + && self + .destination_plates + .iter() + .any(|dpi| dpi.get_uuid() == tr.dest_id) + }) + .map(|tr| tr.clone()) + .collect(); + } + + pub fn add_source_plate(&mut self, plate: PlateInstance) { + assert!(plate.plate.plate_type == PlateType::Source); + self.source_plates.push(plate); + } + pub fn add_dest_plate(&mut self, plate: PlateInstance) { + assert!(plate.plate.plate_type == PlateType::Destination); + self.destination_plates.push(plate); + } + pub fn del_plate(&mut self, id: Uuid) { + if let Some(index) = self + .source_plates + .iter() + .position(|spi| spi.get_uuid() == id) + { + self.source_plates.swap_remove(index); + } + if let Some(index) = self + .destination_plates + .iter() + .position(|dpi| dpi.get_uuid() == id) + { + self.destination_plates.swap_remove(index); + } + } +} diff --git a/src/components/transfer_menu.rs b/src/components/transfer_menu.rs index abfb7c9..c8fc567 100644 --- a/src/components/transfer_menu.rs +++ b/src/components/transfer_menu.rs @@ -1,42 +1,285 @@ #![allow(non_snake_case)] -use dioxus::prelude::*; -use regex::Regex; -use lazy_static::lazy_static; -#[inline_props] -pub fn TransferMenu(cx: Scope) -> Element { - cx.render(rsx! { - div { - class: "transfer_menu", - form{ - label { - r#for: "src_region", - "Source Region:" - }, - input { - r#type: "text", - name: "src_region", - }, - label { - r#for: "dest_region", - "Destination Region:" - }, - input { - r#type: "text", - name: "dest_region", +use lazy_static::lazy_static; +use regex::Regex; +use serde::{Deserialize, Serialize}; +use wasm_bindgen::JsCast; +use web_sys::{EventTarget, HtmlInputElement}; +use uuid::Uuid; +use yew::prelude::*; +use yewdux::prelude::*; + +use crate::data::{transfer::Transfer, transfer_region::Region}; + +use super::states::{CurrentTransfer, MainState}; + +#[function_component] +pub fn TransferMenu() -> Html { + let (main_state, main_dispatch) = use_store::(); + let (ct_state, ct_dispatch) = use_store::(); + + let on_name_change = { + let ct_dispatch = ct_dispatch.clone(); + + Callback::from(move |e: Event| { + let target: Option = e.target(); + let input = target.and_then(|t| t.dyn_into::().ok()); + if let Some(input) = input { + ct_dispatch.reduce_mut(|state| { + state.transfer.name = input.value().clone(); + }); } } - } - }) + + )}; + + let on_src_region_change = { + let ct_dispatch = ct_dispatch.clone(); + + Callback::from(move |e: Event| { + let target: Option = e.target(); + let input = target.and_then(|t| t.dyn_into::().ok()); + if let Some(input) = input { + if let Ok(rd) = RegionDisplay::try_from(input.value()) { + ct_dispatch.reduce_mut(|state| { + state.transfer.transfer_region.source_region = Region::from(&rd); + }); + input.set_custom_validity(""); + } else { + input.set_custom_validity("Invalid region.") + } + } + }) + }; + let on_dest_region_change = { + let ct_dispatch = ct_dispatch.clone(); + + Callback::from(move |e: Event| { + let target: Option = e.target(); + let input = target.and_then(|t| t.dyn_into::().ok()); + if let Some(input) = input { + if let Ok(rd) = RegionDisplay::try_from(input.value()) { + ct_dispatch.reduce_mut(|state| { + state.transfer.transfer_region.dest_region = Region::from(&rd); + }); + input.set_custom_validity(""); + } else { + input.set_custom_validity("Invalid region.") + } + } + }) + }; + + let on_source_interleave_x_change = { + let ct_dispatch = ct_dispatch.clone(); + + Callback::from(move |e: Event| { + let target: Option = e.target(); + let input = target.and_then(|t| t.dyn_into::().ok()); + if let Some(input) = input { + if let Ok(num) = input.value().parse::() { + ct_dispatch.reduce_mut(|state| { + state.transfer.transfer_region.interleave_source = + (num, state.transfer.transfer_region.interleave_source.1); + }); + } + } + }) + }; + let on_source_interleave_y_change = { + let ct_dispatch = ct_dispatch.clone(); + + Callback::from(move |e: Event| { + let target: Option = e.target(); + let input = target.and_then(|t| t.dyn_into::().ok()); + if let Some(input) = input { + if let Ok(num) = input.value().parse::() { + ct_dispatch.reduce_mut(|state| { + state.transfer.transfer_region.interleave_source = + (state.transfer.transfer_region.interleave_source.0, num); + }); + } + } + }) + }; + let on_dest_interleave_x_change = { + let ct_dispatch = ct_dispatch.clone(); + + Callback::from(move |e: Event| { + let target: Option = e.target(); + let input = target.and_then(|t| t.dyn_into::().ok()); + if let Some(input) = input { + if let Ok(num) = input.value().parse::() { + ct_dispatch.reduce_mut(|state| { + state.transfer.transfer_region.interleave_dest = + (num, state.transfer.transfer_region.interleave_dest.1); + }); + } + } + }) + }; + let on_dest_interleave_y_change = { + let ct_dispatch = ct_dispatch.clone(); + + Callback::from(move |e: Event| { + let target: Option = e.target(); + let input = target.and_then(|t| t.dyn_into::().ok()); + if let Some(input) = input { + if let Ok(num) = input.value().parse::() { + ct_dispatch.reduce_mut(|state| { + state.transfer.transfer_region.interleave_dest = + (state.transfer.transfer_region.interleave_dest.0, num); + }); + } + } + }) + }; + + let new_transfer_button_callback = { + let main_dispatch = main_dispatch.clone(); + let main_state = main_state.clone(); + let ct_dispatch = ct_dispatch.clone(); + + Callback::from(move |_: MouseEvent| { + main_dispatch.reduce_mut(|state| { + state.selected_transfer = Uuid::nil(); + }); + ct_dispatch.reduce_mut(|state| { + state.transfer = Transfer::default(); + state.transfer.source_id = main_state.selected_source_plate; + state.transfer.dest_id = main_state.selected_dest_plate; + }); + }) + }; + + let save_transfer_button_callback = { + let main_dispatch = main_dispatch.clone(); + let main_state = main_state.clone(); + let ct_state = ct_state.clone(); + + Callback::from(move |_: MouseEvent| { + log::debug!("Button pressed"); + if main_state.selected_transfer.is_nil() { + if let Some(spi) = main_state + .source_plates + .iter() + .find(|spi| spi.get_uuid() == main_state.selected_source_plate) + { + if let Some(dpi) = main_state + .destination_plates + .iter() + .find(|dpi| dpi.get_uuid() == main_state.selected_dest_plate) + { + let new_transfer = Transfer::new( + spi.clone(), + dpi.clone(), + ct_state.transfer.transfer_region, + ct_state.transfer.name.clone() + ); + main_dispatch.reduce_mut(|state| { + state.transfers.push(new_transfer); + state.selected_transfer = state.transfers.last() + .expect("An element should have just been added") + .get_uuid(); + }); + } + } + } else { + if let Some(index) = main_state.transfers.iter() + .position(|t| t.get_uuid() == main_state.selected_transfer) { + main_dispatch.reduce_mut(|state| { + state.transfers[index] = ct_state.transfer.clone(); + }); + } + } + }) + }; + + let delete_transfer_button_callback = { + let main_dispatch = main_dispatch.clone(); + let main_state = main_state.clone(); + let ct_state = ct_state.clone(); + let new_callback = new_transfer_button_callback.clone(); + + Callback::from(move |e: MouseEvent| { + if main_state.selected_transfer.is_nil() { + () // Maybe reset transfer? + } else { + if let Some(index) = main_state.transfers.iter() + .position(|t| t.get_uuid() == ct_state.transfer.get_uuid()) { + main_dispatch.reduce_mut(|state| { + state.transfers.remove(index); + state.selected_transfer = Uuid::nil(); + }); + new_callback.emit(e); // We need a new transfer now + } + } + }) + }; + + html! { +
+
+
+ + +
+
+ + +
+
+ + +
+
+

{"Source Interleave "}

+ + + + +
+
+

{"Destination Interleave "}

+ + + + +
+
+ + + +
+
+
+ } } -#[derive(PartialEq, Eq, Debug)] -struct RegionDisplay { - text: String, - col_start: u8, - row_start: u8, - col_end: u8, - row_end: u8, +#[derive(PartialEq, Eq, Debug, Clone, Default, Serialize, Deserialize)] +pub struct RegionDisplay { + pub text: String, + pub col_start: u8, + pub row_start: u8, + pub col_end: u8, + pub row_end: u8, } impl TryFrom for RegionDisplay { @@ -47,28 +290,57 @@ impl TryFrom for RegionDisplay { static ref REGION_REGEX: Regex = Regex::new(r"([A-Z]+)(\d+):([A-Z]+)(\d+)").unwrap(); } if let Some(captures) = REGION_REGEX.captures(&value) { - if captures.len() != 5 { return Err("Not enough capture groups") } + if captures.len() != 5 { + return Err("Not enough capture groups"); + } let col_start = letters_to_num(&captures[1]).ok_or("Column start failed to parse")?; let col_end = letters_to_num(&captures[3]).ok_or("Column end failed to parse")?; - let row_start: u8 = captures[2].parse::().or(Err("Row start failed to parse"))?; - let row_end: u8 = captures[4].parse::().or(Err("Row end failed to parse"))?; - return Ok(RegionDisplay { + let row_start: u8 = captures[2] + .parse::() + .or(Err("Row start failed to parse"))?; + let row_end: u8 = captures[4] + .parse::() + .or(Err("Row end failed to parse"))?; + return Ok(RegionDisplay { text: value, col_start, row_start, col_end, row_end, - }) + }); } else { - return Err("Regex match failed") + return Err("Regex match failed"); } } - } -impl TryFrom<(u8,u8,u8,u8)> for RegionDisplay { - type Error = &'static str; +impl From<&Region> for RegionDisplay { + fn from(value: &Region) -> Self { + match *value { + Region::Point((col, row)) => { + RegionDisplay::try_from((col, row, col, row)).ok().unwrap() + } + Region::Rect(c1, c2) => RegionDisplay::try_from((c1.0, c1.1, c2.0, c2.1)) + .ok() + .unwrap(), + } + } +} +impl From<&RegionDisplay> for Region { + fn from(value: &RegionDisplay) -> Self { + if value.col_start == value.col_end && value.row_start == value.row_end { + Region::Point((value.col_start, value.row_start)) + } else { + Region::Rect( + (value.col_start, value.row_start), + (value.col_end, value.row_end), + ) + } + } +} +impl TryFrom<(u8, u8, u8, u8)> for RegionDisplay { + type Error = &'static str; - fn try_from(value: (u8,u8,u8,u8)) -> Result { + fn try_from(value: (u8, u8, u8, u8)) -> Result { // (Column Start, Row Start, Column End, Row End) // This can only possibly fail if one of the coordinates is zero... let cs = num_to_letters(value.0).ok_or("Column start failed to parse")?; @@ -86,15 +358,19 @@ fn letters_to_num(letters: &str) -> Option { let mut num: u8 = 0; for (i, letter) in letters.chars().rev().enumerate() { let n = letter as u8; - if n < 65 || n > 90 { return None } - num = num.checked_add((26_i32.pow(i as u32)*(n as i32 - 64)).try_into().ok()?)?; + if n < 65 || n > 90 { + return None; + } + num = num.checked_add((26_i32.pow(i as u32) * (n as i32 - 64)).try_into().ok()?)?; } - return Some(num) + return Some(num); } fn num_to_letters(num: u8) -> Option { - if num == 0 { return None } // Otherwise, we will not return none! - // As another note, we can't represent higher than "IV" anyway; - // thus there's no reason for a loop (26^n with n>1 will NOT occur). + if num == 0 { + return None; + } // Otherwise, we will not return none! + // As another note, we can't represent higher than "IV" anyway; + // thus there's no reason for a loop (26^n with n>1 will NOT occur). let mut text = "".to_string(); let mut digit1 = num.div_euclid(26u8); let mut digit2 = num.rem_euclid(26u8); @@ -103,26 +379,30 @@ fn num_to_letters(num: u8) -> Option { digit2 = 26; } if digit1 != 0 { - text.push((64+digit1) as char) + text.push((64 + digit1) as char) } - text.push((64+digit2) as char); + text.push((64 + digit2) as char); return Some(text.to_string()); } #[cfg(test)] mod tests { + use wasm_bindgen_test::*; + use super::{letters_to_num, num_to_letters, RegionDisplay}; #[test] + #[wasm_bindgen_test] fn test_letters_to_num() { assert_eq!(letters_to_num("D"), Some(4)); assert_eq!(letters_to_num("d"), None); - assert_eq!(letters_to_num("AD"), Some(26+4)); - assert_eq!(letters_to_num("CG"), Some(3*26+7)); + assert_eq!(letters_to_num("AD"), Some(26 + 4)); + assert_eq!(letters_to_num("CG"), Some(3 * 26 + 7)); } #[test] + #[wasm_bindgen_test] fn test_num_to_letters() { println!("27 is {:?}", num_to_letters(27)); assert_eq!(num_to_letters(1), Some("A".to_string())); @@ -132,22 +412,30 @@ mod tests { } #[test] + #[wasm_bindgen_test] fn test_l2n_and_n2l() { - assert_eq!(num_to_letters(letters_to_num("A").unwrap()), Some("A".to_string())); - assert_eq!(num_to_letters(letters_to_num("BJ").unwrap()), Some("BJ".to_string())); + assert_eq!( + num_to_letters(letters_to_num("A").unwrap()), + Some("A".to_string()) + ); + assert_eq!( + num_to_letters(letters_to_num("BJ").unwrap()), + Some("BJ".to_string()) + ); for i in 1..=255 { assert_eq!(letters_to_num(&num_to_letters(i as u8).unwrap()), Some(i)); } } #[test] + #[wasm_bindgen_test] fn test_try_from_string_for_regiondisplay() { let desired = RegionDisplay { text: "A1:E5".to_string(), row_start: 1, row_end: 5, col_start: 1, - col_end: 5 + col_end: 5, }; assert_eq!(desired, "A1:E5".to_string().try_into().unwrap()); } diff --git a/src/components/tree.rs b/src/components/tree.rs index a70acad..35e7c08 100644 --- a/src/components/tree.rs +++ b/src/components/tree.rs @@ -1,11 +1,264 @@ #![allow(non_snake_case)] -use dioxus::prelude::*; -#[inline_props] -pub fn Tree(cx: Scope) -> Element { - cx.render(rsx! { - div { - class: "tree", - } - }) +use uuid::Uuid; +use wasm_bindgen::JsCast; +use web_sys::{EventTarget, HtmlDialogElement, HtmlElement}; +use yew::prelude::*; +use yewdux::prelude::*; + +use crate::components::states::{CurrentTransfer, MainState}; +use crate::components::transfer_menu::RegionDisplay; +use crate::data::transfer_region::Region; + +#[derive(PartialEq, Properties)] +pub struct TreeProps { + pub open_new_plate_callback: Callback<()>, +} + +#[function_component] +pub fn Tree(props: &TreeProps) -> Html { + let (main_state, main_dispatch) = use_store::(); + let (ct_state, ct_dispatch) = use_store::(); + let plate_modal_id: UseStateHandle> = use_state(|| None); + + let open_plate_info_callback = { + let plate_menu_id = plate_modal_id.clone(); + Callback::from(move |e: MouseEvent| { + let target: Option = e.target(); + let li = target.and_then(|t| t.dyn_into::().ok()); + if let Some(li) = li { + if let Ok(id) = u128::from_str_radix(li.id().as_str(), 10) { + plate_menu_id.set(Some(Uuid::from_u128(id))); + } + } + }) + }; + let plate_info_close_callback = { + let plate_menu_id = plate_modal_id.clone(); + Callback::from(move |_| { + plate_menu_id.set(None); + }) + }; + let plate_info_delete_callback = { + let dispatch = main_dispatch.clone(); + let plate_menu_id = plate_modal_id.clone(); + Callback::from(move |_| { + if let Some(id) = *plate_menu_id { + dispatch.reduce_mut(|state| { + state.del_plate(id); + }); + } + }) + }; + let source_plate_select_callback = { + let main_dispatch = main_dispatch.clone(); + let ct_dispatch = ct_dispatch.clone(); + + Callback::from(move |e: MouseEvent| { + let target: Option = e.target(); + let li = target.and_then(|t| t.dyn_into::().ok()); + if let Some(li) = li { + if let Ok(id) = u128::from_str_radix(li.id().as_str(), 10) { + ct_dispatch.reduce_mut(|state| { + state.transfer.transfer_region.source_region = Region::default(); + }); + main_dispatch.reduce_mut(|state| { + state.selected_source_plate = Uuid::from_u128(id); + state.selected_transfer = Uuid::nil(); + }); + } + } + }) + }; + let destination_plate_select_callback = { + let main_dispatch = main_dispatch.clone(); + let ct_dispatch = ct_dispatch.clone(); + + Callback::from(move |e: MouseEvent| { + let target: Option = e.target(); + let li = target.and_then(|t| t.dyn_into::().ok()); + if let Some(li) = li { + if let Ok(id) = u128::from_str_radix(li.id().as_str(), 10) { + ct_dispatch.reduce_mut(|state| { + state.transfer.transfer_region.dest_region = Region::default(); + }); + main_dispatch.reduce_mut(|state| { + state.selected_dest_plate = Uuid::from_u128(id); + state.selected_transfer = Uuid::nil(); + }); + } + } + }) + }; + + let transfer_select_callback = { + let main_state = main_state.clone(); + let main_dispatch = main_dispatch.clone(); + let ct_dispatch = ct_dispatch.clone(); + + Callback::from(move |e: MouseEvent| { + let target: Option = e.target(); + let li = target.and_then(|t| t.dyn_into::().ok()); + if let Some(li) = li { + if let Ok(id) = u128::from_str_radix(li.id().as_str(), 10) { + let id = Uuid::from_u128(id); + if let Some(transfer) = main_state.transfers + .iter().find(|transfer| transfer.get_uuid() == id) { + + main_dispatch.reduce_mut(|state| { + state.selected_source_plate = transfer.source_id; + state.selected_dest_plate = transfer.dest_id; + state.selected_transfer = id; + }); + ct_dispatch.reduce_mut(|state| { + state.transfer = transfer.clone(); + }); + } + } + } + }) + }; + + let source_plates = main_state + .source_plates + .iter() + .map(|spi| { + html! {
  • + {String::from(spi)} +
  • } + }) + .collect::(); + let dest_plates = main_state + .destination_plates + .iter() + .map(|dpi| { + html! {
  • {String::from(dpi)}
  • } + }) + .collect::(); + let transfers = main_state + .transfers + .iter() + .map(|transfer| { + html! {
  • + {transfer.name.clone()} +
  • + } + }) + .collect::(); + + html! { +
    +
    +

    {"Source Plates:"}

    +
      + {source_plates} +
    +
    +
    +

    {"Destination Plates:"}

    +
      + {dest_plates} +
    +
    +
    +

    {"Transfers:"}

    +
      + {transfers} +
    +
    + if let Some(id) = *plate_modal_id { + + } + +
    + +
    +
    + } +} + +#[derive(PartialEq, Properties)] +struct PlateInfoModalProps { + id: Uuid, + dialog_close_callback: Callback<()>, + delete_button_callback: Callback<()>, +} + +#[function_component] +fn PlateInfoModal(props: &PlateInfoModalProps) -> Html { + let (state, dispatch) = use_store::(); + let dialog_ref = use_node_ref(); + + let mut plate = state + .source_plates + .iter() + .find(|spi| spi.get_uuid() == props.id); + if plate == None { + plate = state + .destination_plates + .iter() + .find(|dpi| dpi.get_uuid() == props.id); + } + let plate_name = match plate { + Some(plate) => plate.name.clone(), + None => "Not Found".to_string(), + }; + let onclose = { + let dialog_close_callback = props.dialog_close_callback.clone(); + move |_| dialog_close_callback.emit(()) + }; + + let delete_onclick = { + let delete_button_callback = props.delete_button_callback.clone(); + let dialog_ref = dialog_ref.clone(); + move |_| { + delete_button_callback.emit(()); + dialog_ref.cast::().unwrap().close(); + } + }; + + { + let dialog_ref = dialog_ref.clone(); + + use_effect_with_deps( + |dialog_ref| { + dialog_ref + .cast::() + .unwrap() + .show_modal() + .ok(); + }, + dialog_ref, + ); + } + + html! { + +

    {"Plate Info"}

    +

    {"Name: "}

    + +
    + } } diff --git a/src/data/mod.rs b/src/data/mod.rs index e065044..3654d37 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -1,2 +1,4 @@ pub mod plate; +pub mod plate_instances; +pub mod transfer; pub mod transfer_region; diff --git a/src/data/plate.rs b/src/data/plate.rs index 96ab5ed..97634a4 100644 --- a/src/data/plate.rs +++ b/src/data/plate.rs @@ -1,3 +1,6 @@ +use serde::{Deserialize, Serialize}; + +#[derive(PartialEq, Eq, Default, Clone, Copy, Serialize, Deserialize, Debug)] pub struct Plate { pub plate_type: PlateType, pub plate_format: PlateFormat, @@ -16,11 +19,18 @@ impl Plate { } } +#[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize, Debug)] pub enum PlateType { Source, Destination, } +impl Default for PlateType { + fn default() -> Self { + Self::Source + } +} +#[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize, Debug)] pub enum PlateFormat { W6, W12, @@ -31,9 +41,40 @@ pub enum PlateFormat { W1536, W3456, } +impl Default for PlateFormat { + fn default() -> Self { + Self::W96 + } +} +impl std::fmt::Display for PlateFormat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PlateFormat::W6 => write!(f, "6"), + PlateFormat::W12 => write!(f, "12"), + PlateFormat::W24 => write!(f, "24"), + PlateFormat::W48 => write!(f, "48"), + PlateFormat::W96 => write!(f, "96"), + PlateFormat::W384 => write!(f, "384"), + PlateFormat::W1536 => write!(f, "1536"), + PlateFormat::W3456 => write!(f, "3456"), + } + } +} impl PlateFormat { pub fn size(&self) -> (u8, u8) { + /* + match self { + PlateFormat::W6 => (3, 2), + PlateFormat::W12 => (4, 3), + PlateFormat::W24 => (6, 4), + PlateFormat::W48 => (8, 6), + PlateFormat::W96 => (12, 8), + PlateFormat::W384 => (24, 16), + PlateFormat::W1536 => (48, 32), + PlateFormat::W3456 => (72, 48), + } + */ match self { PlateFormat::W6 => (2, 3), PlateFormat::W12 => (3, 4), @@ -46,10 +87,3 @@ impl PlateFormat { } } } - -/* -#[cfg(test)] -mod tests { - use super::{Plate, PlateFormat, PlateType}; -} -*/ diff --git a/src/data/plate_instances.rs b/src/data/plate_instances.rs new file mode 100644 index 0000000..23599b8 --- /dev/null +++ b/src/data/plate_instances.rs @@ -0,0 +1,41 @@ +use super::plate::*; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(PartialEq, Clone, Serialize, Deserialize)] +pub struct PlateInstance { + pub plate: Plate, + id: Uuid, + pub name: String, +} + +impl PlateInstance { + pub fn new(sort: PlateType, format: PlateFormat, name: String) -> Self { + PlateInstance { + plate: Plate { + plate_type: sort, + plate_format: format, + }, + id: Uuid::new_v4(), + name, + } + } + + pub fn get_uuid(&self) -> Uuid { + self.id + } + + pub fn change_name(&mut self, new_name: String) { + self.name = new_name; + } +} + +impl From for PlateInstance { + fn from(value: Plate) -> Self { + PlateInstance { + plate: value, + id: Uuid::new_v4(), + name: "New Plate".to_string(), + } + } +} diff --git a/src/data/transfer.rs b/src/data/transfer.rs new file mode 100644 index 0000000..f65b36d --- /dev/null +++ b/src/data/transfer.rs @@ -0,0 +1,35 @@ +use super::plate_instances::*; +use super::transfer_region::*; +use serde::Deserialize; +use serde::Serialize; +use uuid::Uuid; + +#[derive(PartialEq, Clone, Default, Debug, Serialize, Deserialize)] +pub struct Transfer { + pub source_id: Uuid, + pub dest_id: Uuid, + pub name: String, + id: Uuid, + pub transfer_region: TransferRegion, +} + +impl Transfer { + pub fn new( + source: PlateInstance, + dest: PlateInstance, + tr: TransferRegion, + name: String, + ) -> Self { + Self { + source_id: source.get_uuid(), + dest_id: dest.get_uuid(), + name, + id: Uuid::new_v4(), + transfer_region: tr, + } + } + + pub fn get_uuid(&self) -> Uuid { + self.id + } +} diff --git a/src/data/transfer_region.rs b/src/data/transfer_region.rs index fd3d88c..865d2dd 100644 --- a/src/data/transfer_region.rs +++ b/src/data/transfer_region.rs @@ -1,10 +1,17 @@ +use serde::{Deserialize, Serialize}; + use super::plate::Plate; -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Debug)] pub enum Region { Rect((u8, u8), (u8, u8)), Point((u8, u8)), } +impl Default for Region { + fn default() -> Self { + Region::Point((1, 1)) + } +} impl TryFrom for ((u8, u8), (u8, u8)) { type Error = &'static str; fn try_from(region: Region) -> Result { @@ -17,51 +24,71 @@ impl TryFrom for ((u8, u8), (u8, u8)) { } } -pub struct TransferRegion<'a> { - pub source_plate: &'a Plate, +#[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize, Debug)] +pub struct TransferRegion { + pub source_plate: Plate, pub source_region: Region, // Even if it is just a point, we don't want corners. - pub dest_plate: &'a Plate, + pub dest_plate: Plate, pub dest_region: Region, - pub interleave_source: Option<(i8, i8)>, - pub interleave_dest: Option<(i8, i8)>, + pub interleave_source: (i8, i8), + pub interleave_dest: (i8, i8), } -impl TransferRegion<'_> { - pub fn get_source_wells(&self) -> Vec<(u8, u8)> { - if let Region::Rect(c1, c2) = self.source_region { - let mut wells = Vec::<(u8, u8)>::new(); - let (ul, br) = standardize_rectangle(&c1, &c2); - let (interleave_i, interleave_j) = self.interleave_source.unwrap_or((1, 1)); - // NOTE: This will panic if either is 0! - // We'll reassign these values (still not mutable) just in case. - // This behaviour shouldn't be replicated for destination wells - // because a zero step permits pooling. - let (interleave_i, interleave_j) = (i8::max(interleave_i, 1), i8::max(interleave_j, 1)); - - for i in (ul.0..=br.0).step_by(i8::abs(interleave_i) as usize) { - for j in (ul.1..=br.1).step_by(i8::abs(interleave_j) as usize) { - // NOTE: It looks like we're ignoring negative interleaves, - // because it wouldn't make a difference here---the same - // wells will still be involved in the transfer. - wells.push((i, j)) - } - } - return wells; - } else { - panic!("Source region is just a point!") +impl Default for TransferRegion { + fn default() -> Self { + TransferRegion { + source_plate: Plate::default(), + source_region: Region::default(), + dest_plate: Plate::default(), + dest_region: Region::default(), + interleave_source: (1, 1), + interleave_dest: (1, 1), } } +} + +impl TransferRegion { + pub fn get_source_wells(&self) -> Vec<(u8, u8)> { + match self.source_region { + Region::Rect(c1, c2) => { + let mut wells = Vec::<(u8, u8)>::new(); + let (ul, br) = standardize_rectangle(&c1, &c2); + let (interleave_i, interleave_j) = self.interleave_source; + // NOTE: This will panic if either is 0! + // We'll reassign these values (still not mutable) just in case. + // This behaviour shouldn't be replicated for destination wells + // because a zero step permits pooling. + let (interleave_i, interleave_j) = + (i8::max(interleave_i, 1), i8::max(interleave_j, 1)); + + for i in (ul.0..=br.0).step_by(i8::abs(interleave_i) as usize) { + for j in (ul.1..=br.1).step_by(i8::abs(interleave_j) as usize) { + // NOTE: It looks like we're ignoring negative interleaves, + // because it wouldn't make a difference here---the same + // wells will still be involved in the transfer. + wells.push((i, j)) + } + } + return wells; + } + Region::Point(p) => return vec![p], + } + } + pub fn get_destination_wells(&self) -> Vec<(u8, u8)> { let map = self.calculate_map(); let source_wells = self.get_source_wells(); let mut wells = Vec::<(u8, u8)>::new(); + // log::debug!("GDW:"); for well in source_wells { if let Some(mut dest_wells) = map(well) { + // log::debug!("Map {:?} to {:?}", well, dest_wells); wells.append(&mut dest_wells); } } + // log::debug!("GDW END."); return wells; } @@ -69,20 +96,22 @@ impl TransferRegion<'_> { pub fn calculate_map(&self) -> Box Option> + '_> { // By validating first, we have a stronger guarantee that // this function will not panic. :) + // log::debug!("Validating: {:?}", self.validate()); if let Err(msg) = self.validate() { eprintln!("{}", msg); eprintln!("This transfer will be empty."); return Box::new(|(_, _)| None); } + // log::debug!("What is ild? {:?}", self); let source_wells = self.get_source_wells(); - let il_dest = self.interleave_dest.unwrap_or((1, 1)); - let il_source = self.interleave_source.unwrap_or((1, 1)); + let il_dest = self.interleave_dest; + let il_source = self.interleave_source; - let source_corners: ((u8, u8), (u8, u8)) = self - .source_region - .try_into() - .expect("Source region should not be a point"); + let source_corners: ((u8, u8), (u8, u8)) = match self.source_region { + Region::Point((x, y)) => ((x, y), (x, y)), + Region::Rect(c1, c2) => (c1, c2), + }; let (source_ul, _) = standardize_rectangle(&source_corners.0, &source_corners.1); // This map is not necessarily injective or surjective, // but we will have these properties in certain cases. @@ -116,50 +145,80 @@ impl TransferRegion<'_> { } Region::Rect(c1, c2) => { return Box::new(move |(i, j)| { - // Because of our call to validate, - // we can assume that our destination region contains - // an integer number of our source regions. if source_wells.contains(&(i, j)) { - // Find points by checking congruence class let possible_destination_wells = create_dense_rectangle(&c1, &c2); - let (ds1, _) = standardize_rectangle(&c1, &c2); - let (s1, s2) = standardize_rectangle(&source_corners.0, &source_corners.1); - let dims = ( - s2.0.checked_sub(s1.0).unwrap() + 1, - s2.1.checked_sub(s1.1).unwrap() + 1, + let (d_ul, d_br) = standardize_rectangle(&c1, &c2); + let (s_ul, s_br) = + standardize_rectangle(&source_corners.0, &source_corners.1); + let s_dims = ( + s_br.0.checked_sub(s_ul.0).unwrap() + 1, + s_br.1.checked_sub(s_ul.1).unwrap() + 1, ); - - /* - println!("{} % {} == {}", i, dims.0, i*il_dest.0.abs() as u8 % dims.0); - for a in ds1.0..=ds2.0 { - for b in ds1.1..=ds2.1 { - println!("({},{}): {} % {} == {}", a, b, - a.checked_sub(ds1.0).unwrap()+1, dims.0, - (a.checked_sub(ds1.0).unwrap()+1) % dims.0); - } - } - for a in ds1.0..=ds2.0 { - for b in ds1.1..=ds2.1 { - println!("({},{}): {} % {} == {}", a, b, - a.checked_sub(ds1.0).unwrap()+1, il_dest.0.abs() as u8, - (a.checked_sub(ds1.0).unwrap()+1) % il_dest.0.abs() as u8); - } - } - */ + let d_dims = ( + d_br.0.checked_sub(d_ul.0).unwrap() + 1, + d_br.1.checked_sub(d_ul.1).unwrap() + 1, + ); + let N_s = ( + // Number of used source wells + (s_dims.0 + il_source.0.abs() as u8 - 1) + .div_euclid(il_source.0.abs() as u8), + (s_dims.1 + il_source.1.abs() as u8 - 1) + .div_euclid(il_source.1.abs() as u8), + ); + let D_per_replicate = ( + // How many wells are used per replicate? + (N_s.0 * (il_dest.0.abs() as u8)), + (N_s.1 * (il_dest.1.abs() as u8)), + ); + let count = ( + // How many times can we replicate? + (1..) + .position(|n| { + n * N_s.0 * il_dest.0.abs() as u8 - il_dest.0.abs() as u8 + 1 + > d_dims.0 + }) + .unwrap() as u8, + (1..) + .position(|n| { + n * N_s.1 * il_dest.1.abs() as u8 - il_dest.1.abs() as u8 + 1 + > d_dims.1 + }) + .unwrap() as u8, + ); + let i = i + .saturating_sub(s_ul.0) + .saturating_div(il_source.0.abs() as u8); + let j = j + .saturating_sub(s_ul.1) + .saturating_div(il_source.1.abs() as u8); + // log::debug!("N_s: {:?}, d_dims: {:?}, D_per: {:?}, count: {:?}", N_s, d_dims, D_per_replicate, count); Some( possible_destination_wells .into_iter() - .filter(|(x, y)| { - i * il_dest.0.abs() as u8 % dims.0 - == (x.checked_sub(ds1.0).unwrap() + 1) % dims.0 - && j * il_dest.1.abs() as u8 % dims.1 - == (y.checked_sub(ds1.1).unwrap() + 1) % dims.1 + .filter(|(x, _)| { + x.checked_sub(d_ul.0).unwrap() + % (N_s.0 * il_dest.0.abs() as u8) // Counter along x + == ((il_dest.0.abs() as u8 *i)) + % (N_s.0 * il_dest.0.abs() as u8) + }) + .filter(|(_, y)| { + y.checked_sub(d_ul.1).unwrap() + % (N_s.1 * il_dest.1.abs() as u8) // Counter along u + == ((il_dest.1.abs() as u8 *j)) + % (N_s.1 * il_dest.1.abs() as u8) }) .filter(|(x, y)| { - (x.checked_sub(ds1.0).unwrap()) % il_dest.0.abs() as u8 == 0 - && (y.checked_sub(ds1.1).unwrap()) % il_dest.1.abs() as u8 - == 0 + // How many times have we replicated? < How many are we allowed + // to replicate? + x.checked_sub(d_ul.0) + .unwrap() + .div_euclid(N_s.0 * il_dest.0.abs() as u8) + < count.0 + && y.checked_sub(d_ul.1) + .unwrap() + .div_euclid(N_s.1 * il_dest.1.abs() as u8) + < count.1 }) .collect(), ) @@ -180,11 +239,12 @@ impl TransferRegion<'_> { // - Are the wells in the source really there? // - In a replication region, do the source lengths divide the destination lengths? // - Are the interleaves valid? - let il_source = self.interleave_source.unwrap_or((1, 1)); - let il_dest = self.interleave_dest.unwrap_or((1, 1)); + let il_source = self.interleave_source; + let il_dest = self.interleave_dest; match self.source_region { - Region::Point(_) => return Err("Source region should not be a point!"), + Region::Point(_) => return Ok(()), // Should make sure it's actually in the plate, leave for + // later Region::Rect(s1, s2) => { // Check if all source wells exist: if s1.0 == 0 || s1.1 == 0 || s2.0 == 0 || s2.1 == 0 { @@ -196,6 +256,7 @@ impl TransferRegion<'_> { return Err("Source region is out-of-bounds! (Too tall)"); } if s1.1 > source_max.1 || s2.1 > source_max.1 { + // log::debug!("s1.1: {}, max.1: {}", s1.1, source_max.1); return Err("Source region is out-of-bounds! (Too wide)"); } // Check that source lengths divide destination lengths @@ -235,10 +296,8 @@ impl TransferRegion<'_> { } } - if let Some(source_il) = self.interleave_source { - if source_il.0 == 0 || source_il.1 == 0 { - return Err("Source interleave cannot be zero!"); - } + if il_source.0 == 0 || il_dest.1 == 0 { + return Err("Source interleave cannot be zero!"); } // Check if all destination wells exist: @@ -292,7 +351,7 @@ use std::fmt; use std::ops::Mul; #[cfg(debug_assertions)] // There should be no reason to print a transfer otherwise -impl fmt::Display for TransferRegion<'_> { +impl fmt::Display for TransferRegion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "Source Plate:")?; let source_dims = self.source_plate.size(); @@ -330,75 +389,131 @@ impl fmt::Display for TransferRegion<'_> { #[cfg(test)] mod tests { + use wasm_bindgen_test::*; + use crate::data::plate::*; use crate::data::transfer_region::*; #[test] + #[wasm_bindgen_test] fn test_simple_transfer() { let source = Plate::new(PlateType::Source, PlateFormat::W96); let destination = Plate::new(PlateType::Destination, PlateFormat::W384); let transfer1 = TransferRegion { - source_plate: &source, + source_plate: source, source_region: Region::Rect((1, 1), (3, 3)), - dest_plate: &destination, - dest_region: Region::Point((3,3)), - interleave_source: None, - interleave_dest: None, + dest_plate: destination, + dest_region: Region::Point((3, 3)), + interleave_source: (1, 1), + interleave_dest: (1, 1), }; let transfer1_map = transfer1.calculate_map(); - assert_eq!(transfer1_map((1,1)), Some(vec!{(3,3)}), "Failed basic shift transfer 1"); - assert_eq!(transfer1_map((1,2)), Some(vec!{(3,4)}), "Failed basic shift transfer 2"); - assert_eq!(transfer1_map((2,2)), Some(vec!{(4,4)}), "Failed basic shift transfer 3"); + assert_eq!( + transfer1_map((1, 1)), + Some(vec! {(3,3)}), + "Failed basic shift transfer 1" + ); + assert_eq!( + transfer1_map((1, 2)), + Some(vec! {(3,4)}), + "Failed basic shift transfer 2" + ); + assert_eq!( + transfer1_map((2, 2)), + Some(vec! {(4,4)}), + "Failed basic shift transfer 3" + ); let transfer2 = TransferRegion { - source_plate: &source, + source_plate: source, source_region: Region::Rect((1, 1), (3, 3)), - dest_plate: &destination, - dest_region: Region::Point((3,3)), - interleave_source: Some((2,2)), - interleave_dest: None, - }; + dest_plate: destination, + dest_region: Region::Point((3, 3)), + interleave_source: (2, 2), + interleave_dest: (1, 1), + }; let transfer2_map = transfer2.calculate_map(); - assert_eq!(transfer2_map((1,1)), Some(vec!{(3,3)}), "Failed source interleave, type simple 1"); - assert_eq!(transfer2_map((1,2)), None, "Failed source interleave, type simple 2"); - assert_eq!(transfer2_map((2,2)), None, "Failed source interleave, type simple 3"); - assert_eq!(transfer2_map((3,3)), Some(vec!{(4,4)}), "Failed source interleave, type simple 4"); + assert_eq!( + transfer2_map((1, 1)), + Some(vec! {(3,3)}), + "Failed source interleave, type simple 1" + ); + assert_eq!( + transfer2_map((1, 2)), + None, + "Failed source interleave, type simple 2" + ); + assert_eq!( + transfer2_map((2, 2)), + None, + "Failed source interleave, type simple 3" + ); + assert_eq!( + transfer2_map((3, 3)), + Some(vec! {(4,4)}), + "Failed source interleave, type simple 4" + ); let transfer3 = TransferRegion { - source_plate: &source, + source_plate: source, source_region: Region::Rect((1, 1), (3, 3)), - dest_plate: &destination, - dest_region: Region::Point((3,3)), - interleave_source: None, - interleave_dest: Some((2,3)), - }; + dest_plate: destination, + dest_region: Region::Point((3, 3)), + interleave_source: (1, 1), + interleave_dest: (2, 3), + }; let transfer3_map = transfer3.calculate_map(); - assert_eq!(transfer3_map((1,1)), Some(vec!{(3,3)}), "Failed destination interleave, type simple 1"); - assert_eq!(transfer3_map((2,1)), Some(vec!{(5,3)}), "Failed destination interleave, type simple 2"); - assert_eq!(transfer3_map((1,2)), Some(vec!{(3,6)}), "Failed destination interleave, type simple 3"); - assert_eq!(transfer3_map((2,2)), Some(vec!{(5,6)}), "Failed destination interleave, type simple 4"); + assert_eq!( + transfer3_map((1, 1)), + Some(vec! {(3,3)}), + "Failed destination interleave, type simple 1" + ); + assert_eq!( + transfer3_map((2, 1)), + Some(vec! {(5,3)}), + "Failed destination interleave, type simple 2" + ); + assert_eq!( + transfer3_map((1, 2)), + Some(vec! {(3,6)}), + "Failed destination interleave, type simple 3" + ); + assert_eq!( + transfer3_map((2, 2)), + Some(vec! {(5,6)}), + "Failed destination interleave, type simple 4" + ); } #[test] + #[wasm_bindgen_test] fn test_replicate_transfer() { let source = Plate::new(PlateType::Source, PlateFormat::W96); let destination = Plate::new(PlateType::Destination, PlateFormat::W384); let transfer1 = TransferRegion { - source_plate: &source, + source_plate: source, source_region: Region::Rect((1, 1), (2, 2)), - dest_plate: &destination, - dest_region: Region::Rect((2,2),(11,11)), - interleave_source: None, - interleave_dest: Some((3,3)), + dest_plate: destination, + dest_region: Region::Rect((2, 2), (11, 11)), + interleave_source: (1, 1), + interleave_dest: (3, 3), }; let transfer1_map = transfer1.calculate_map(); - assert_eq!(transfer1_map((1,1)), Some(vec!{(2, 2), (2, 8), (8, 2), (8, 8)}), "Failed type replicate 1"); - assert_eq!(transfer1_map((2,1)), Some(vec!{(5, 2), (5, 8), (11, 2), (11, 8)}), "Failed type replicate 1"); + assert_eq!( + transfer1_map((1, 1)), + Some(vec! {(2, 2), (2, 8), (8, 2), (8, 8)}), + "Failed type replicate 1" + ); + assert_eq!( + transfer1_map((2, 1)), + Some(vec! {(5, 2), (5, 8), (11, 2), (11, 8)}), + "Failed type replicate 1" + ); } #[test] - fn test_pooling_transfer() { - } + #[wasm_bindgen_test] + fn test_pooling_transfer() {} } diff --git a/src/lib.rs b/src/lib.rs index e6d7195..d5b84f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,17 +3,16 @@ mod components; mod data; use components::main_window::MainWindow; -use dioxus::prelude::*; -use fermi::*; +use yew::prelude::*; #[cfg(debug_assertions)] use data::*; -pub fn App(cx: Scope) -> Element { - use_init_atom_root(cx); - cx.render(rsx! { - MainWindow {} - }) +#[function_component] +pub fn App() -> Html { + html! { + + } } #[cfg(debug_assertions)] @@ -22,17 +21,17 @@ pub fn plate_test() { let destination = plate::Plate::new(plate::PlateType::Destination, plate::PlateFormat::W384); let transfer = transfer_region::TransferRegion { - source_plate: &source, + source_plate: source, source_region: transfer_region::Region::Rect((1, 1), (2, 2)), - dest_plate: &destination, - dest_region: transfer_region::Region::Rect((2,2),(11,11)), - interleave_source: None, - interleave_dest: Some((3,3)), + dest_plate: destination, + dest_region: transfer_region::Region::Rect((2, 2), (11, 11)), + interleave_source: (1, 1), + interleave_dest: (3, 3), }; println!("{}", transfer); let sws = transfer.get_source_wells(); let m = transfer.calculate_map(); for w in sws { - println!("{:?} -> {:?}", w,m(w)); + println!("{:?} -> {:?}", w, m(w)); } } diff --git a/src/main.rs b/src/main.rs index 0fe845a..ba179e7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,9 +3,10 @@ use plate_tool::plate_test; use plate_tool::App; use wasm_logger; +use yew::prelude::*; fn main() { wasm_logger::init(wasm_logger::Config::default()); - dioxus_web::launch(App); + yew::Renderer::::new().render(); //plate_test(); }