lib migration pt4

This commit is contained in:
Emilia Allison 2024-02-11 20:49:52 -05:00
parent 4d82ea5567
commit 9db0d4aa19
Signed by: emilia
GPG Key ID: 05D5D1107E5100A1
59 changed files with 9984 additions and 1203 deletions

500
Cargo.lock generated
View File

@ -3,10 +3,25 @@
version = 3
[[package]]
name = "aho-corasick"
version = "1.0.1"
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
@ -25,13 +40,13 @@ checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c"
[[package]]
name = "async-trait"
version = "0.1.68"
version = "0.1.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.48",
]
[[package]]
@ -46,6 +61,21 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bincode"
version = "1.3.3"
@ -63,9 +93,24 @@ checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9"
[[package]]
name = "bumpalo"
version = "3.12.2"
version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
[[package]]
name = "bytes"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]]
name = "cfg-if"
@ -85,9 +130,9 @@ dependencies = [
[[package]]
name = "csv"
version = "1.2.2"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086"
checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"
dependencies = [
"csv-core",
"itoa",
@ -97,18 +142,18 @@ dependencies = [
[[package]]
name = "csv-core"
version = "0.1.10"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
dependencies = [
"memchr",
]
[[package]]
name = "darling"
version = "0.13.4"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
checksum = "fc5d6b04b3fd0ba9926f945895de7d806260a2d7431ba82e7edaecb043c4c6b8"
dependencies = [
"darling_core",
"darling_macro",
@ -116,27 +161,27 @@ dependencies = [
[[package]]
name = "darling_core"
version = "0.13.4"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
checksum = "04e48a959bcd5c761246f5d090ebc2fbf7b9cd527a492b07a67510c108f1e7e3"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 1.0.109",
"syn 2.0.48",
]
[[package]]
name = "darling_macro"
version = "0.13.4"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
checksum = "1d1545d67a2149e1d93b7e5c7752dce5a7426eb5d1357ddcfd89336b94444f77"
dependencies = [
"darling_core",
"quote",
"syn 1.0.109",
"syn 2.0.48",
]
[[package]]
@ -147,18 +192,18 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "form_urlencoded"
version = "1.1.0"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
[[package]]
name = "futures"
version = "0.3.28"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
@ -170,9 +215,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.28"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
@ -180,44 +225,44 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.28"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-io"
version = "0.3.28"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-macro"
version = "0.3.28"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.48",
]
[[package]]
name = "futures-sink"
version = "0.3.28"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
version = "0.3.28"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
version = "0.3.28"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-channel",
"futures-core",
@ -233,9 +278,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.9"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if",
"js-sys",
@ -245,10 +290,16 @@ dependencies = [
]
[[package]]
name = "gloo"
version = "0.8.0"
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a4bef6b277b3ab073253d4bca60761240cf8d6998f4bd142211957b69a61b20"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "gloo"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28999cda5ef6916ffd33fb4a7b87e1de633c47c0dc6d97905fee1cdaa142b94d"
dependencies = [
"gloo-console",
"gloo-dialogs",
@ -310,9 +361,9 @@ dependencies = [
[[package]]
name = "gloo-history"
version = "0.1.3"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd451019e0b7a2b8a7a7b23e74916601abf1135c54664e57ff71dcc26dfcdeb7"
checksum = "85725d90bf0ed47063b3930ef28e863658a7905989e9929a8708aab74a1d5e7f"
dependencies = [
"gloo-events",
"gloo-utils",
@ -326,14 +377,15 @@ dependencies = [
[[package]]
name = "gloo-net"
version = "0.2.6"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9902a044653b26b99f7e3693a42f171312d9be8b26b5697bd1e43ad1f8a35e10"
checksum = "a66b4e3c7d9ed8d315fd6b97c8b1f74a7c6ecbbc2320e65ae7ed38b7068cc620"
dependencies = [
"futures-channel",
"futures-core",
"futures-sink",
"gloo-utils",
"http",
"js-sys",
"pin-project",
"serde",
@ -381,9 +433,9 @@ dependencies = [
[[package]]
name = "gloo-utils"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8e8fc851e9c7b9852508bc6e3f690f452f474417e8545ec9857b7f7377036b5"
checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e"
dependencies = [
"js-sys",
"serde",
@ -417,11 +469,19 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hermit-abi"
version = "0.2.6"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3"
[[package]]
name = "http"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
dependencies = [
"libc",
"bytes",
"fnv",
"itoa",
]
[[package]]
@ -432,9 +492,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "implicit-clone"
version = "0.3.5"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40fc102e70475c320b185cd18c1e48bba2d7210b63970a4d581ef903e4368ef7"
checksum = "cfd6201e7c30ccb24773cac7efa6fec1e06189d414b7439ce756a481c8bfbf53"
dependencies = [
"indexmap",
]
@ -451,15 +511,15 @@ dependencies = [
[[package]]
name = "itoa"
version = "1.0.6"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "js-sys"
version = "0.3.63"
version = "0.3.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790"
checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
dependencies = [
"wasm-bindgen",
]
@ -472,72 +532,87 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.144"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "log"
version = "0.4.17"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "memchr"
version = "2.5.0"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "miniz_oxide"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
"adler",
]
[[package]]
name = "num_cpus"
version = "1.15.0"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "once_cell"
version = "1.17.1"
name = "object"
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "percent-encoding"
version = "2.2.0"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project"
version = "1.1.0"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead"
checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.0"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07"
checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.48",
]
[[package]]
name = "pin-project-lite"
version = "0.2.9"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
@ -557,7 +632,21 @@ dependencies = [
]
[[package]]
name = "plate-tool"
name = "plate-tool-lib"
version = "0.1.0"
dependencies = [
"csv",
"getrandom",
"log",
"rand",
"regex",
"serde",
"serde_json",
"uuid",
]
[[package]]
name = "plate-tool-web"
version = "0.2.0"
dependencies = [
"csv",
@ -579,20 +668,6 @@ dependencies = [
"yewdux",
]
[[package]]
name = "plate-tool-lib"
version = "0.1.0"
dependencies = [
"csv",
"getrandom",
"log",
"rand",
"regex",
"serde",
"serde_json",
"uuid",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
@ -635,9 +710,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.58"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
@ -661,9 +736,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.27"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@ -700,9 +775,21 @@ dependencies = [
[[package]]
name = "regex"
version = "1.8.1"
version = "1.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
dependencies = [
"aho-corasick",
"memchr",
@ -711,21 +798,27 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.7.1"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustversion"
version = "1.0.12"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
[[package]]
name = "ryu"
version = "1.0.13"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "scoped-tls"
@ -735,18 +828,18 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "serde"
version = "1.0.163"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde-wasm-bindgen"
version = "0.4.5"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf"
checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e"
dependencies = [
"js-sys",
"serde",
@ -755,20 +848,20 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.163"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.48",
]
[[package]]
name = "serde_json"
version = "1.0.96"
version = "1.0.113"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
dependencies = [
"itoa",
"ryu",
@ -789,9 +882,9 @@ dependencies = [
[[package]]
name = "slab"
version = "0.4.8"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
@ -815,9 +908,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.16"
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
@ -826,33 +919,32 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.40"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.40"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.48",
]
[[package]]
name = "tokio"
version = "1.28.1"
version = "1.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105"
checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
dependencies = [
"autocfg",
"backtrace",
"pin-project-lite",
"windows-sys",
]
[[package]]
@ -868,11 +960,10 @@ dependencies = [
[[package]]
name = "tracing"
version = "0.1.37"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
"cfg-if",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
@ -880,35 +971,35 @@ dependencies = [
[[package]]
name = "tracing-attributes"
version = "0.1.24"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.48",
]
[[package]]
name = "tracing-core"
version = "0.1.31"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
]
[[package]]
name = "unicode-ident"
version = "1.0.8"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "uuid"
version = "1.6.1"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
dependencies = [
"atomic",
"getrandom",
@ -920,13 +1011,13 @@ dependencies = [
[[package]]
name = "uuid-macro-internal"
version = "1.6.1"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f49e7f3f3db8040a100710a11932239fd30697115e2ba4107080d8252939845e"
checksum = "7abb14ae1a50dad63eaa768a458ef43d298cd1bd44951677bd10b732a9ba2a2d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.48",
]
[[package]]
@ -943,9 +1034,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.86"
version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73"
checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@ -953,24 +1044,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.86"
version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb"
checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.48",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.36"
version = "0.4.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e"
checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97"
dependencies = [
"cfg-if",
"js-sys",
@ -980,9 +1071,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.86"
version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258"
checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -990,28 +1081,28 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.86"
version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.48",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.86"
version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93"
checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.36"
version = "0.3.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9e636f3a428ff62b3742ebc3c70e254dfe12b8c2b469d688ea59cdd4abcf502"
checksum = "143ddeb4f833e2ed0d252e618986e18bfc7b0e52f2d28d77d05b2f045dd8eb61"
dependencies = [
"console_error_panic_hook",
"js-sys",
@ -1023,12 +1114,13 @@ dependencies = [
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.36"
version = "0.3.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f18c1fad2f7c4958e7bcce014fa212f59a65d5e3721d0f77e6c0b27ede936ba3"
checksum = "a5211b7550606857312bba1d978a8ec75692eae187becc5e680444fffc5e6f89"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
@ -1044,80 +1136,14 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.63"
version = "0.3.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2"
checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
dependencies = [
"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.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[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.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[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.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[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.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "yew"
version = "0.20.0"
@ -1160,9 +1186,9 @@ dependencies = [
[[package]]
name = "yewdux"
version = "0.9.2"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "653ba356bc60d1804c28ec6cc8ddac2741c686bde2a65074d07faba735914464"
checksum = "3c528544a814a0beb30059c8340eb78c88160141db788112b51a5a08098cef2d"
dependencies = [
"anymap",
"async-trait",
@ -1179,13 +1205,13 @@ dependencies = [
[[package]]
name = "yewdux-macros"
version = "0.9.2"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25bcd923aceaa85cb4affad8657cc36e3d6b6932740e711574182f7817492739"
checksum = "d22b1832d3e3eaa61a5c2ecd40affa876507457180d1e599143368c1c3317c2d"
dependencies = [
"darling",
"proc-macro-error",
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.48",
]

View File

@ -1,30 +1,3 @@
[package]
name = "plate-tool"
version = "0.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
plate-tool-lib = { path = "lib" }
yew = { version = "0.20.0", features = ["csr"] }
yewdux = "0.9"
wasm-bindgen = "0.2"
web-sys = { version = "0.3", features = ["FormData", "HtmlFormElement",
"HtmlDialogElement", "Blob", "Url", "Window",
"HtmlAnchorElement", "ReadableStream", "HtmlSelectElement", "HtmlOptionElement", "HtmlButtonElement",
"FileReader"] }
js-sys = "0.3"
log = "0.4"
wasm-logger = "0.2"
regex = "1"
lazy_static = "1.4"
uuid = { version = "1.6", features = ["v7", "fast-rng", "macro-diagnostics", "js", "serde"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
csv = "1.2"
getrandom = { version = "0.2", features = ["js"] }
rand = { version = "0.8", features = ["small_rng"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.0"
[workspace]
members = ["plate-tool-web", "plate-tool-lib"]
resolver = "2"

View File

@ -1,62 +0,0 @@
// use crate::components::states::MainState;
use crate::transfer::Transfer;
use crate::util::*;
use serde::{Serialize, Deserialize};
use std::error::Error;
#[derive(Serialize, Deserialize, Debug)]
pub struct TransferRecord {
#[serde(rename = "Source Plate", alias = "source plate", alias = "src plate")]
pub source_plate: String,
#[serde(rename = "Source Well", alias = "source well", alias = "src well")]
pub source_well: String,
#[serde(rename = "Dest Plate", alias = "dest plate", alias = "destination plate")]
pub destination_plate: String,
#[serde(rename = "Destination Well", alias = "destination well", alias = "dest well")]
pub destination_well: String,
#[serde(rename = "Transfer Volume", alias = "transfer volume")]
pub volume: f32,
#[serde(rename = "Concentration", alias = "concentration")]
pub concentration: Option<f32>,
}
/*
*/
pub fn transfer_to_records(
tr: &Transfer,
src_barcode: &str,
dest_barcode: &str,
) -> Vec<TransferRecord> {
let source_wells = tr.transfer_region.get_source_wells();
let map = tr.transfer_region.calculate_map();
let mut records: Vec<TransferRecord> = vec![];
for s_well in source_wells {
let dest_wells = map(s_well);
if let Some(dest_wells) = dest_wells {
for d_well in dest_wells {
records.push(TransferRecord {
source_plate: src_barcode.to_string(),
source_well: format!("{}{}", num_to_letters(s_well.0).unwrap(), s_well.1),
destination_plate: dest_barcode.to_string(),
destination_well: format!("{}{}", num_to_letters(d_well.0).unwrap(), d_well.1),
volume: tr.volume,
concentration: None,
})
}
}
}
records
}
pub fn records_to_csv(trs: Vec<TransferRecord>) -> Result<String, Box<dyn Error>> {
let mut wtr = csv::WriterBuilder::new().from_writer(vec![]);
for record in trs {
wtr.serialize(record)?
}
let data = String::from_utf8(wtr.into_inner()?)?;
Ok(data)
}

View File

@ -1,6 +0,0 @@
pub mod csv;
pub mod plate;
pub mod plate_instances;
pub mod transfer;
pub mod transfer_region;
pub mod util;

View File

@ -1,77 +0,0 @@
use serde::{Deserialize, Serialize};
#[derive(PartialEq, Eq, Default, Clone, Copy, Serialize, Deserialize, Debug)]
pub struct Plate {
pub plate_type: PlateType,
pub plate_format: PlateFormat,
}
impl Plate {
pub fn new(plate_type: PlateType, plate_format: PlateFormat) -> Self {
Plate {
plate_type,
plate_format,
}
}
pub fn size(&self) -> (u8, u8) {
self.plate_format.size()
}
}
#[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,
W24,
W48,
W96,
W384,
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 => (2, 3),
PlateFormat::W12 => (3, 4),
PlateFormat::W24 => (4, 6),
PlateFormat::W48 => (6, 8),
PlateFormat::W96 => (8, 12),
PlateFormat::W384 => (16, 24),
PlateFormat::W1536 => (32, 48),
PlateFormat::W3456 => (48, 72),
}
}
}

View File

@ -1,50 +0,0 @@
use super::plate::*;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(PartialEq, Clone, Serialize, Deserialize)]
pub struct PlateInstance {
pub plate: Plate,
#[serde(rename = "id_v7")]
#[serde(default = "Uuid::now_v7")]
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::now_v7(),
name,
}
}
pub fn get_uuid(&self) -> Uuid {
self.id
}
pub fn change_name(&mut self, new_name: String) {
self.name = new_name;
}
}
impl From<Plate> for PlateInstance {
fn from(value: Plate) -> Self {
PlateInstance {
plate: value,
id: Uuid::now_v7(),
name: "New Plate".to_string(),
}
}
}
impl From<&PlateInstance> for String {
fn from(value: &PlateInstance) -> Self {
// Could have other formatting here
format!("{}, {}", value.name, value.plate.plate_format)
}
}

View File

@ -1,58 +0,0 @@
use super::plate_instances::*;
use super::transfer_region::*;
use serde::Deserialize;
use serde::Serialize;
use uuid::Uuid;
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Transfer {
pub source_id: Uuid,
pub dest_id: Uuid,
pub name: String,
#[serde(rename = "id_v7")]
#[serde(default = "Uuid::now_v7")]
pub id: Uuid,
pub transfer_region: TransferRegion,
#[serde(default = "default_volume")]
pub volume: f32,
}
impl Default for Transfer {
fn default() -> Self {
Transfer {
source_id: Default::default(),
dest_id: Default::default(),
name: "New Transfer".to_string(),
id: Default::default(),
transfer_region: Default::default(),
volume: 2.5f32,
}
}
}
fn default_volume() -> f32 {
2.5f32
}
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::now_v7(),
transfer_region: tr,
volume: 2.5,
}
}
pub fn get_uuid(&self) -> Uuid {
self.id
}
}

View File

@ -1,591 +0,0 @@
use serde::{Deserialize, Serialize};
use super::plate::Plate;
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct CustomRegion {
src: Vec<(u8, u8)>,
dest: Vec<(u8, u8)>,
}
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub enum Region {
Rect((u8, u8), (u8, u8)),
Point((u8, u8)),
Custom(CustomRegion),
}
impl Default for Region {
fn default() -> Self {
Region::Point((1, 1))
}
}
impl TryFrom<Region> for ((u8, u8), (u8, u8)) {
type Error = &'static str;
fn try_from(region: Region) -> Result<Self, Self::Error> {
if let Region::Rect(c1, c2) = region {
Ok((c1, c2))
} else {
// Should consider returning a degenerate rectangle here instead
Err("Cannot convert this region to a rectangle, it was a point.")
}
}
}
type Corner = (u8, u8);
type Rectangle = (Corner, Corner);
impl Region {
pub fn new_custom(transfers: &Vec<Rectangle>) -> Self {
let mut src_pts: Vec<(u8, u8)> = Vec::with_capacity(transfers.len());
let mut dest_pts: Vec<(u8, u8)> = Vec::with_capacity(transfers.len());
for transfer in transfers {
src_pts.push(transfer.0);
dest_pts.push(transfer.1);
}
Region::Custom(CustomRegion {
src: src_pts,
dest: dest_pts,
})
}
}
#[derive(PartialEq, Eq, Clone, 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: Plate,
pub dest_region: Region,
pub interleave_source: (i8, i8),
pub interleave_dest: (i8, i8),
}
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))
}
}
wells
}
Region::Point(p) => vec![*p],
Region::Custom(c) => c.src.clone(),
}
}
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.");
wells
}
#[allow(clippy::type_complexity)] // Resolving gives inherent associated type error
pub fn calculate_map(&self) -> Box<dyn Fn((u8, u8)) -> Option<Vec<(u8, u8)>> + '_> {
// 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;
let il_source = self.interleave_source;
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),
Region::Custom(_) => ((0, 0), (0, 0)),
};
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.
// If the transfer is not a pooling transfer (interleave == 0)
// and simple then we *will* have injectivity.
// Non-replicate transfers:
match &self.dest_region {
Region::Point((x, y)) => {
Box::new(move |(i, j)| {
if source_wells.contains(&(i, j)) {
// Validity here already checked by self.validate()
Some(vec![(
x + i
.checked_sub(source_ul.0)
.expect("Point cannot have been less than UL")
.checked_div(il_source.0.unsigned_abs())
.expect("Source interleave cannot be 0")
.mul(il_dest.0.unsigned_abs()),
y + j
.checked_sub(source_ul.1)
.expect("Point cannot have been less than UL")
.checked_div(il_source.1.unsigned_abs())
.expect("Source interleave cannot be 0")
.mul(il_dest.1.unsigned_abs()),
)])
} else {
None
}
})
}
Region::Rect(c1, c2) => {
Box::new(move |(i, j)| {
if source_wells.contains(&(i, j)) {
let possible_destination_wells = create_dense_rectangle(c1, c2);
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,
);
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.unsigned_abs() - 1)
.div_euclid(il_source.0.unsigned_abs()),
(s_dims.1 + il_source.1.unsigned_abs() - 1)
.div_euclid(il_source.1.unsigned_abs()),
);
let count = (
// How many times can we replicate?
(1..)
.position(|n| {
n * N_s.0 * il_dest.0.unsigned_abs() - il_dest.0.unsigned_abs()
+ 1
> d_dims.0
})
.unwrap() as u8,
(1..)
.position(|n| {
n * N_s.1 * il_dest.1.unsigned_abs() - il_dest.1.unsigned_abs()
+ 1
> d_dims.1
})
.unwrap() as u8,
);
let i = i
.saturating_sub(s_ul.0)
.saturating_div(il_source.0.unsigned_abs());
let j = j
.saturating_sub(s_ul.1)
.saturating_div(il_source.1.unsigned_abs());
Some(
possible_destination_wells
.into_iter()
.filter(|(x, _)| {
x.checked_sub(d_ul.0).unwrap()
% (N_s.0 * il_dest.0.unsigned_abs()) // Counter along x
== (il_dest.0.unsigned_abs() *i)
% (N_s.0 * il_dest.0.unsigned_abs())
})
.filter(|(_, y)| {
y.checked_sub(d_ul.1).unwrap()
% (N_s.1 * il_dest.1.unsigned_abs()) // Counter along u
== (il_dest.1.unsigned_abs() *j)
% (N_s.1 * il_dest.1.unsigned_abs())
})
.filter(|(x, y)| {
// 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.unsigned_abs())
< count.0
&& y.checked_sub(d_ul.1)
.unwrap()
.div_euclid(N_s.1 * il_dest.1.unsigned_abs())
< count.1
})
.collect(),
)
} else {
None
}
})
}
Region::Custom(c) => Box::new(move |(i, j)| {
let src = c.src.clone();
let dest = c.dest.clone();
let points: Vec<(u8, u8)> = src
.iter()
.enumerate()
.filter(|(_index, (x, y))| *x == i && *y == j)
.map(|(index, _)| dest[index])
.collect();
if points.is_empty() {
None
} else {
Some(points)
}
}),
}
}
pub fn validate(&self) -> Result<(), &'static str> {
// Checks if the region does anything suspect
//
// If validation fails, we pass a string to show to the user.
//
// We check:
// - 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;
let il_dest = self.interleave_dest;
match self.source_region {
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 {
return Err("Source region is out-of-bounds! (Too small)");
}
// Sufficient to check if the corners are in-bounds
let source_max = self.source_plate.size();
if s1.0 > source_max.0 || s2.0 > source_max.0 {
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)");
}
}
Region::Custom(_) => return Ok(()),
}
if il_source.0 == 0 || il_dest.1 == 0 {
return Err("Source interleave cannot be zero!");
}
// Check if all destination wells exist:
// NOT IMPLEMENTED
// Should *not* happen in this function---otherwise
// we'd get a nasty recursive loop.
Ok(())
}
}
fn create_dense_rectangle(c1: &(u8, u8), c2: &(u8, u8)) -> Vec<(u8, u8)> {
// Creates a vector of every point between two corners
let (c1, c2) = standardize_rectangle(c1, c2);
let mut points = Vec::<(u8, u8)>::new();
for i in c1.0..=c2.0 {
for j in c1.1..=c2.1 {
points.push((i, j));
}
}
points
}
fn standardize_rectangle(c1: &(u8, u8), c2: &(u8, u8)) -> ((u8, u8), (u8, u8)) {
let upper_left_i = u8::min(c1.0, c2.0);
let upper_left_j = u8::min(c1.1, c2.1);
let bottom_right_i = u8::max(c1.0, c2.0);
let bottom_right_j = u8::max(c1.1, c2.1);
(
(upper_left_i, upper_left_j),
(bottom_right_i, bottom_right_j),
)
}
#[cfg(debug_assertions)]
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 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Source Plate:")?;
let source_dims = self.source_plate.size();
let source_wells = self.get_source_wells();
let mut source_string = String::new();
for i in 1..=source_dims.0 {
for j in 1..=source_dims.1 {
if source_wells.contains(&(i, j)) {
source_string.push('x')
} else {
source_string.push('.')
}
}
source_string.push('\n');
}
write!(f, "{}", source_string)?;
writeln!(f, "Dest Plate:")?;
let dest_dims = self.dest_plate.size();
let dest_wells = self.get_destination_wells();
let mut dest_string = String::new();
for i in 1..=dest_dims.0 {
for j in 1..=dest_dims.1 {
if dest_wells.contains(&(i, j)) {
dest_string.push('x')
} else {
dest_string.push('.')
}
}
dest_string.push('\n');
}
write!(f, "{}", dest_string)
}
}
#[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_region: Region::Rect((1, 1), (3, 3)),
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"
);
let transfer2 = TransferRegion {
source_plate: source,
source_region: Region::Rect((1, 1), (3, 3)),
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"
);
let transfer3 = TransferRegion {
source_plate: source,
source_region: Region::Rect((1, 1), (3, 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"
);
}
#[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_region: Region::Rect((1, 1), (2, 2)),
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"
);
let transfer2 = TransferRegion {
source_plate: Plate::new(PlateType::Source, PlateFormat::W384),
dest_plate: Plate::new(PlateType::Destination, PlateFormat::W384),
source_region: Region::Rect((1, 1), (2, 3)),
dest_region: Region::Rect((2, 2), (11, 16)),
interleave_source: (1, 1),
interleave_dest: (2, 2),
};
let transfer2_source = transfer2.get_source_wells();
let transfer2_dest = transfer2.get_destination_wells();
assert_eq!(
transfer2_source,
vec![(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3)],
"Failed type replicate 2 source"
);
assert_eq!(
transfer2_dest,
vec![
(2, 2),
(2, 8),
(6, 2),
(6, 8),
(2, 4),
(2, 10),
(6, 4),
(6, 10),
(2, 6),
(2, 12),
(6, 6),
(6, 12),
(4, 2),
(4, 8),
(8, 2),
(8, 8),
(4, 4),
(4, 10),
(8, 4),
(8, 10),
(4, 6),
(4, 12),
(8, 6),
(8, 12)
],
"Failed type replicate 2 destination"
);
}
#[test]
#[wasm_bindgen_test]
fn test_pooling_transfer() {
let transfer1 = TransferRegion {
source_plate: Plate::new(PlateType::Source, PlateFormat::W384),
dest_plate: Plate::new(PlateType::Destination, PlateFormat::W384),
source_region: Region::Rect((1, 4), (3, 7)),
dest_region: Region::Point((1, 9)),
interleave_source: (1, 1),
interleave_dest: (0, 2),
};
//let transfer1_source = transfer1.get_source_wells();
let mut transfer1_dest = transfer1.get_destination_wells();
transfer1_dest.sort();
transfer1_dest.dedup(); // Makes our check easier, otherwise we have repeated wells
let transfer1_map = transfer1.calculate_map();
// Skipping source check---it's just 12 wells.
assert_eq!(
transfer1_dest,
vec![(1, 9), (1, 11), (1, 13), (1, 15)],
"Failed type pool 1 dest"
);
assert_eq!(
transfer1_map((2, 6)),
Some(vec![(1, 13)]),
"Failed type pool 1 map 1"
);
assert_eq!(
transfer1_map((3, 7)),
Some(vec![(1, 15)]),
"Failed type pool 1 map 2"
);
}
}

View File

@ -1,70 +0,0 @@
pub fn letters_to_num(letters: &str) -> Option<u8> {
let mut num: u8 = 0;
for (i, letter) in letters.to_ascii_uppercase().chars().rev().enumerate() {
log::debug!("{}, {}", i, letter);
let n = letter as u8;
if !(65..=90).contains(&n) {
return None;
}
num = num.checked_add((26_i32.pow(i as u32) * (n as i32 - 64)).try_into().ok()?)?;
}
Some(num)
}
pub fn num_to_letters(num: u8) -> Option<String> {
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);
if digit1 > 0 && digit2 == 0u8 {
digit1 -= 1;
digit2 = 26;
}
if digit1 != 0 {
text.push((64 + digit1) as char)
}
text.push((64 + digit2) as char);
Some(text.to_string())
}
#[cfg(test)]
mod tests {
use super::{letters_to_num, num_to_letters, RegionDisplay};
#[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));
}
#[test]
fn test_num_to_letters() {
println!("27 is {:?}", num_to_letters(27));
assert_eq!(num_to_letters(1), Some("A".to_string()));
assert_eq!(num_to_letters(26), Some("Z".to_string()));
assert_eq!(num_to_letters(27), Some("AA".to_string()));
assert_eq!(num_to_letters(111), Some("DG".to_string()));
}
#[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())
);
for i in 1..=255 {
assert_eq!(letters_to_num(&num_to_letters(i).unwrap()), Some(i));
}
}
}

View File

@ -2,7 +2,7 @@
use crate::transfer::Transfer;
use crate::util::*;
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
use std::error::Error;
#[derive(Serialize, Deserialize, Debug)]
@ -11,18 +11,28 @@ pub struct TransferRecord {
pub source_plate: String,
#[serde(rename = "Source Well", alias = "source well", alias = "src well")]
pub source_well: String,
#[serde(rename = "Dest Plate", alias = "dest plate", alias = "destination plate")]
#[serde(
rename = "Dest Plate",
alias = "dest plate",
alias = "destination plate"
)]
pub destination_plate: String,
#[serde(rename = "Destination Well", alias = "destination well", alias = "dest well")]
#[serde(
rename = "Destination Well",
alias = "destination well",
alias = "dest well"
)]
pub destination_well: String,
#[serde(rename = "Transfer Volume", alias = "transfer volume")]
#[serde(default = "volume_default")]
pub volume: f32,
#[serde(rename = "Concentration", alias = "concentration")]
pub concentration: Option<f32>,
}
/*
*/
pub fn volume_default() -> f32 {
1f32
}
pub fn transfer_to_records(
tr: &Transfer,
@ -60,3 +70,23 @@ pub fn records_to_csv(trs: Vec<TransferRecord>) -> Result<String, Box<dyn Error>
let data = String::from_utf8(wtr.into_inner()?)?;
Ok(data)
}
pub fn read_csv(data: &str) -> Vec<TransferRecord> {
let (header, data) = data.split_at(data.find('\n').unwrap());
let modified: String = header.to_lowercase() + data;
let mut rdr = csv::Reader::from_reader(modified.as_bytes());
let mut records: Vec<TransferRecord> = Vec::new();
for record in rdr.deserialize::<TransferRecord>() {
match record {
Ok(r) => {
//log::debug!("{:?}", r);
records.push(r);
}
Err(e) => {
log::debug!("{:?}", e);
}
}
}
records
}

30
plate-tool-web/Cargo.toml Normal file
View File

@ -0,0 +1,30 @@
[package]
name = "plate-tool-web"
version = "0.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
plate-tool-lib = { path = "../plate-tool-lib" }
yew = { version = "0.20.0", features = ["csr"] }
yewdux = "0.9"
wasm-bindgen = "0.2"
web-sys = { version = "0.3", features = ["FormData", "HtmlFormElement",
"HtmlDialogElement", "Blob", "Url", "Window",
"HtmlAnchorElement", "ReadableStream", "HtmlSelectElement", "HtmlOptionElement", "HtmlButtonElement",
"FileReader"] }
js-sys = "0.3"
log = "0.4"
wasm-logger = "0.2"
regex = "1"
lazy_static = "1.4"
uuid = { version = "1.6", features = ["v7", "fast-rng", "macro-diagnostics", "js", "serde"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
csv = "1.2"
getrandom = { version = "0.2", features = ["js"] }
rand = { version = "0.8", features = ["small_rng"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.0"

Binary file not shown.

BIN
plate-tool-web/dist/fonts/Jost.ttf vendored Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,608 @@
@charset "UTF-8";
/* ----------------- */
/* Custom Properties */
/* ----------------- */
/*
This values are to be overridden
after being injected into
the global scope.
*/
/* colors */
/* Black */
/* Gray */
/* White */
/* font */
/* Sizes divided by 16 so values given in px */
/* --------------- */
/* Utility Classes */
/* --------------- */
/* Layouts */
.container {
padding-inline: 4rem;
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: #504d49;
}
.bg-light {
background-color: hsl(190, 80%, 30%);
}
.bg-white {
background-color: hsl(30, 5%, 90%);
}
.text-dark {
color: #504d49;
}
.text-light {
color: hsl(190, 80%, 30%);
}
.text-white {
color: hsl(30, 5%, 90%);
}
/* Font Classes */
.fs-900 {
font-size: 6.25rem;
}
.fs-800 {
font-size: 4.6875rem;
}
.fs-700 {
font-size: 3.5rem;
}
.fs-600 {
font-size: 2rem;
}
.fs-500 {
font-size: 1.75rem;
}
.fs-400 {
font-size: 1.5rem;
}
.fs-300 {
font-size: 1.125rem;
}
.fs-200 {
font-size: 1rem;
}
.ff-serif {
font-family: "Inconsolata", monospace;
}
.ff-sans-cond {
font-family: sans-serif;
}
.ff-sans {
font-family: "Jost", sans-serif;
}
.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: "Jost", sans-serif;
font-size: 1.5rem;
color: #504d49;
background-color: hsl(30, 5%, 90%);
line-height: 1.5;
min-height: 100vh;
}
main {
margin-left: 1vw;
margin-top: 1vh;
}
main * {
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;
}
@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;
}
body {
overflow: hidden;
height: 100%;
}
div.main_container {
height: 97vh;
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);
}
div.plate_container {
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
border: 2px solid #504d49;
grid-column: right/right;
grid-row: upper/3;
}
div.plate_container h2 {
margin-bottom: 1%;
text-align: center;
}
div.plate_container > div {
display: grid;
grid-template-rows: auto auto;
grid-template-rows: auto auto;
}
div.plate_container > div > h2:nth-of-type(1) {
grid-column: 2;
grid-row: 1;
}
div.plate_container > div > h2:nth-of-type(2) {
grid-column: 1;
grid-row: 2;
writing-mode: vertical-rl;
transform: rotate(-180deg);
}
div.plate_container > div > div {
grid-column: 2;
grid-row: 2;
}
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;
}
th {
font-family: monospace;
}
td.plate_cell {
background: none;
}
div.plate_cell_inner {
aspect-ratio: 1/1;
height: 90%;
border-radius: 50%;
border: 1px 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 5px);
}
td.current_select div.plate_cell_inner {
border: 3px solid black;
}
.W1536 th {
font-size: 0.9rem;
}
.W3456 th {
font-size: 0.9rem;
line-height: 0px;
padding-bottom: 0.4rem;
}
div.tree {
position: relative;
grid-column: left/left;
grid-row: upper/upper;
width: 100%;
height: 100%;
border: 2px solid #504d49;
}
div.tree h3 {
margin-left: 0.5rem;
}
div.tree 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;
}
div.tree li:hover {
background: rgba(15, 117, 138, 0.08);
border: 2px solid rgba(15, 117, 138, 0.3);
}
div.tree li.selected {
background: rgba(15, 117, 138, 0.2);
}
div.transfer_menu {
position: relative;
width: 100%;
height: 100%;
grid-column: left/left;
grid-row: lower/lower;
border: 2px solid #504d49;
padding-left: 0.5rem;
}
div.transfer_menu form {
padding-top: 3%;
padding-bottom: 1%;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
}
div.transfer_menu form label {
display: inline;
}
div.transfer_menu form label * {
display: inline;
}
div.transfer_menu input:invalid {
background-color: #faa;
}
div.transfer_menu div#controls {
align-self: flex-end;
}
div.transfer_menu div#controls 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;
}
input[type=text] {
width: 4em;
}
input[name=name] {
width: 6em;
}
input[type=number] {
width: 2em;
-webkit-appearance: none;
-moz-appearance: textfield;
}
input.volume_input {
width: 4em;
}
div.upper_menu {
position: absolute;
top: 0px;
left: 0px;
height: min(2.5vh, 25px);
padding-left: 1vw;
visibility: inherit;
display: flex;
}
div.upper_menu div.dropdown {
margin-right: 2px;
position: relative;
display: flex;
flex-direction: column;
}
div.upper_menu div.dropdown button {
vertical-align: top;
border: none;
padding: 0px 0.4em 0px 0.4em;
margin: 0;
cursor: pointer;
font-size: calc(min(2.5vh, 25px) * 0.7);
}
div.upper_menu div.dropdown * {
visibility: hidden;
}
div.upper_menu div.dropdown > *:first-child {
outline: 1px solid #504d49;
visibility: visible;
}
div.upper_menu div.dropdown:hover {
outline: 2px solid #504d49;
z-index: 2;
}
div.upper_menu div.dropdown:hover * {
visibility: visible;
outline: 1px solid #504d49;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.4);
z-index: 1;
}
div.upper_menu div.dropdown-sub {
position: relative;
height: min(2.5vh, 25px);
}
div.upper_menu div.dropdown-sub * {
visibility: hidden;
}
div.upper_menu div.dropdown-sub div {
display: none;
visibility: hidden;
}
div.upper_menu div.dropdown-sub > *:first-child {
visibility: inherit;
}
div.upper_menu div.dropdown-sub:hover {
visibility: visible;
}
div.upper_menu div.dropdown-sub:hover div {
position: absolute;
left: 100%;
top: 0;
visibility: hidden;
display: flex;
flex-direction: column;
width: max-content;
}
dialog {
border: 3px solid #504d49;
border-radius: 2%;
color: #504d49;
background: hsl(30, 5%, 90%);
}
dialog > form[method=dialog] {
position: absolute;
top: 0;
right: 0;
line-height: 0px;
}
dialog > form[method=dialog] button {
padding-top: 6px;
padding-left: 3px;
font-size: 150%;
line-height: 0px;
color: #504d49;
border: 0;
background: transparent;
}
dialog > form[method=dialog] button::before {
text-align: center;
vertical-align: middle;
content: "×";
}
dialog > form[method=dialog] button:hover {
color: black;
transition: color 0.1s;
}
.close_button {
color: red;
position: absolute;
top: 5%;
right: 2%;
background: rgba(0, 0, 0, 0.1);
}
.close_button:hover {
color: rgb(0, 255, 255);
background: rgba(0, 0, 0, 0.8);
}
.fs-900 {
font-size: 6.25rem;
font-weight: 400;
}
.fs-800 {
font-size: 4.6875rem;
font-weight: 300;
}
.fs-700 {
font-size: 3.5rem;
font-weight: 250;
}
.fs-600 {
font-size: 2rem;
font-weight: 300;
}
.fs-500 {
font-size: 1.75rem;
font-weight: 200;
}
.fs-400 {
font-size: 1.5rem;
font-weight: 200;
}
html {
font-size: 1vmin;
}

146
plate-tool-web/dist/index.html vendored Normal file
View File

@ -0,0 +1,146 @@
<!DOCTYPE html><html><head>
<meta charset="utf-8">
<link rel="stylesheet" href="/index-136b7d4afc3986e5.css" integrity="sha384-K1xb_hlSB1PuzRgXufX4uYfJCrimViJUZLwHuy2nqRmgR8LHKEVguY8A1ceunwFf">
<script src="/screenshot_utility-18639e2bdd58e7f7.js" integrity="sha384-rRHgJ-Dx271W2uHdkpxy2XEPlo_9wIonkalIbWq_EVn9y0FO8L9MF96Oz57FVXeu"></script>
<script src="/html2canvas-bafc21265de2354d.js" integrity="sha384-q0KsXOmCeCEoVzvj91Xfq-Z9A_MA9_K7PhfVXTTZHQiZ-snp_JlaXl08LNAT7mrM"></script>
<title>Plate Tool</title>
<link rel="preload" href="/plate-tool-web-6c71e2a649203e02_bg.wasm" as="fetch" type="application/wasm" crossorigin="anonymous" integrity="sha384-ZLrGyVAnMTOTUFsd2bIX3oxXsct5Ze-_BbG7YdSAxS-Q8hyJIZNfPBb5LJ6rpPrE">
<link rel="modulepreload" href="/plate-tool-web-6c71e2a649203e02.js" crossorigin="anonymous" integrity="sha384-o-MTA3ga5eJ_8m7WwV3axAGC2KE2rSO345Jk7g7PonnYbt0H_wRHpLIdWZUB1eBv"></head>
<body>
<script type="module">
import init, * as bindings from '/plate-tool-web-6c71e2a649203e02.js';
init('/plate-tool-web-6c71e2a649203e02_bg.wasm');
window.wasmBindings = bindings;
</script><script>"use strict";
(function () {
const address = '{{__TRUNK_ADDRESS__}}';
let protocol = '';
protocol =
protocol
? protocol
: window.location.protocol === 'https:'
? 'wss'
: 'ws';
const url = protocol + '://' + address + '/_trunk/ws';
class Overlay {
constructor() {
// create an overlay
this._overlay = document.createElement("div");
const style = this._overlay.style;
style.height = "100vh";
style.width = "100vw";
style.position = "fixed";
style.top = "0";
style.left = "0";
style.backgroundColor = "rgba(222, 222, 222, 0.5)";
style.fontFamily = "sans-serif";
// not sure that's the right approach
style.zIndex = "1000000";
style.backdropFilter = "blur(1rem)";
const container = document.createElement("div");
// center it
container.style.position = "absolute";
container.style.top = "30%";
container.style.left = "15%";
container.style.maxWidth = "85%";
this._title = document.createElement("div");
this._title.innerText = "Build failure";
this._title.style.paddingBottom = "2rem";
this._title.style.fontSize = "2.5rem";
this._message = document.createElement("div");
this._message.style.whiteSpace = "pre-wrap";
const icon= document.createElement("div");
icon.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" fill="#dc3545" viewBox="0 0 16 16"><path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/></svg>';
this._title.prepend(icon);
container.append(this._title, this._message);
this._overlay.append(container);
this._inject();
window.setInterval(() => {
this._inject();
}, 250);
}
set reason(reason) {
this._message.textContent = reason;
}
_inject() {
if (!this._overlay.isConnected) {
// prepend it
document.body?.prepend(this._overlay);
}
}
}
class Client {
constructor(url) {
this.url = url;
this.poll_interval = 5000;
this._overlay = null;
}
start() {
const ws = new WebSocket(this.url);
ws.onmessage = (ev) => {
const msg = JSON.parse(ev.data);
switch (msg.type) {
case "reload":
this.reload();
break;
case "buildFailure":
this.buildFailure(msg.data)
break;
}
};
ws.onclose = this.onclose;
}
onclose() {
window.setTimeout(
() => {
// when we successfully reconnect, we'll force a
// reload (since we presumably lost connection to
// trunk due to it being killed, so it will have
// rebuilt on restart)
const ws = new WebSocket(this.url);
ws.onopen = () => window.location.reload();
ws.onclose = this.onclose;
},
this.poll_interval);
}
reload() {
window.location.reload();
}
buildFailure({reason}) {
// also log the console
console.error("Build failed:", reason);
console.debug("Overlay", this._overlay);
if (!this._overlay) {
this._overlay = new Overlay();
}
this._overlay.reason = reason;
}
}
new Client(url).start();
})()
</script></body></html>

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,25 @@
function copy_screenshot(el) {
html2canvas(el).then((canvas) => {
console.log("Copying image to clipboard");
canvas.toBlob((b) => {
try {
navigator.clipboard.write([
new ClipboardItem({
'image/png': b
})
]);
} catch (e) {
console.error("Failed to copy!");
}
});
});
}
function copy_screenshot_dest() {
let plate = document.getElementsByClassName("dest_plate")[0];
copy_screenshot(plate);
}
function copy_screenshot_src() {
let plate = document.getElementsByClassName("source_plate")[0];
copy_screenshot(plate);
}

View File

@ -104,22 +104,7 @@ pub fn import_transfer_csv_onload_callback(
) -> Closure<dyn FnMut(Event)> {
Closure::<dyn FnMut(_)>::new(move |_: Event| {
if let Some(value) = &file_reader.result().ok().and_then(|v| v.as_string()) {
let (header, data) = value.split_at(value.find('\n').unwrap());
let modified: String = header.to_lowercase() + data;
log::info!("{}", modified);
let mut rdr = csv::Reader::from_reader(value.as_bytes());
let mut records = Vec::new();
for record in rdr.deserialize::<plate_tool_lib::csv::TransferRecord>() {
match record {
Ok(r) => {
//log::debug!("{:?}", r);
records.push(r);
}
Err(e) => {
log::debug!("{:?}", e);
}
}
}
let records = plate_tool_lib::csv::read_csv(value);
let mut sources: HashSet<String> = HashSet::new();
let mut destinations: HashSet<String> = HashSet::new();

View File

@ -1,4 +1,4 @@
use plate_tool::App;
use plate_tool_web::App;
fn main() {
wasm_logger::init(wasm_logger::Config::default());