From 60061224af6cc043ac71645a7cea60185c547d48 Mon Sep 17 00:00:00 2001 From: Miroito Date: Wed, 1 Mar 2023 10:10:49 +0100 Subject: [PATCH 1/4] Use perseus beta.21 --- .cargo/config.toml | 2 + Cargo.lock | 872 +++++++++++------- client/.gitignore | 2 +- client/Cargo.toml | 27 +- client/src/api/routes/transaction.rs | 58 +- client/src/api/types/paginated_response.rs | 54 +- client/src/components/base_async_select.rs | 119 ++- client/src/components/base_button.rs | 28 +- client/src/components/base_table.rs | 71 +- client/src/components/loading.rs | 6 +- client/src/components/paginated_data_table.rs | 150 +-- client/src/components/the_header.rs | 6 +- client/src/env.rs | 12 +- client/src/error_pages.rs | 73 +- client/src/global_state.rs | 17 +- client/src/{lib.rs => main.rs} | 12 +- client/src/templates/index.rs | 106 ++- client/tests/index.rs | 15 +- makefile | 6 +- server/Cargo.toml | 1 - 20 files changed, 956 insertions(+), 681 deletions(-) create mode 100644 .cargo/config.toml rename client/src/{lib.rs => main.rs} (69%) diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..8262cb8 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +rustflags = ["--cfg", "engine"] diff --git a/Cargo.lock b/Cargo.lock index b3414db..09a39e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,17 @@ dependencies = [ "version_check 0.9.4", ] +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", + "version_check 0.9.4", +] + [[package]] name = "aho-corasick" version = "0.7.20" @@ -97,7 +108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" dependencies = [ "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -200,23 +211,24 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e" dependencies = [ "async-stream-impl", "futures-core", + "pin-project-lite", ] [[package]] name = "async-stream-impl" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -231,9 +243,9 @@ version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -277,6 +289,56 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "axum" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fb79c228270dcf2426e74864cabc94babb5dbab01a4314e702d2f16540e1591" +dependencies = [ + "async-trait", + "axum-core", + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "hyper 0.14.24", + "itoa", + "matchit", + "memchr", + "mime 0.3.16", + "percent-encoding 2.2.0", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-http", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cae3e661676ffbacb30f1a824089a8c9150e71017f7e1e38f2aa32009188d34" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime 0.3.16", + "rustversion", + "tower-layer", + "tower-service", +] + [[package]] name = "bae" version = "0.1.7" @@ -285,9 +347,9 @@ checksum = "33b8de67cc41132507eeece2584804efcb15f85ba516e34c944b7667f480397a" dependencies = [ "heck 0.3.3", "proc-macro-error", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -367,47 +429,47 @@ dependencies = [ [[package]] name = "borsh" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +checksum = "40f9ca3698b2e4cb7c15571db0abc5551dca417a21ae8140460b50309bb2cc62" dependencies = [ "borsh-derive", - "hashbrown 0.11.2", + "hashbrown 0.13.2", ] [[package]] name = "borsh-derive" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +checksum = "598b3eacc6db9c3ee57b22707ad8f6a8d2f6d442bfe24ffeb8cbb70ca59e6a35" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", "proc-macro-crate", - "proc-macro2 1.0.50", - "syn 1.0.107", + "proc-macro2 1.0.51", + "syn 1.0.108", ] [[package]] name = "borsh-derive-internal" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +checksum = "186b734fa1c9f6743e90c95d7233c9faab6360d1a96d4ffa19d9cfd1e9350f8a" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] name = "borsh-schema-derive-internal" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +checksum = "99b7ff1008316626f485991b960ade129253d4034014616b94f309a15366cc49" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -432,9 +494,9 @@ version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -521,9 +583,9 @@ checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ "heck 0.4.1", "proc-macro-error", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -540,11 +602,11 @@ name = "client" version = "0.1.0" dependencies = [ "chrono", - "dotenvy", - "envy", "fantoccini", "perseus", + "perseus-axum", "reqwasm", + "reqwest", "serde", "serde_json", "sycamore", @@ -592,6 +654,12 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "cookie" version = "0.11.5" @@ -616,7 +684,7 @@ dependencies = [ "rand", "sha2", "subtle", - "time 0.3.17", + "time 0.3.19", "version_check 0.9.4", ] @@ -709,6 +777,17 @@ dependencies = [ "typenum", ] +[[package]] +name = "css-minify" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874c6e2d19f8d4a285083b11a3241bfbe01ac3ed85f26e1e6b34888d960552bd" +dependencies = [ + "derive_more", + "indexmap", + "nom", +] + [[package]] name = "ctor" version = "0.1.26" @@ -716,7 +795,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -730,9 +809,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.89" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc831ee6a32dd495436e317595e639a587aa9907bef96fe6e6abc290ab6204e9" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" dependencies = [ "cc", "cxxbridge-flags", @@ -742,34 +821,34 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.89" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94331d54f1b1a8895cd81049f7eaaaef9d05a7dcb4d1fd08bf3ff0806246789d" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" dependencies = [ "cc", "codespan-reporting", "once_cell", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", "scratch", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] name = "cxxbridge-flags" -version = "1.0.89" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48dcd35ba14ca9b40d6e4b4b39961f23d835dbb8eed74565ded361d93e1feb8a" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" [[package]] name = "cxxbridge-macro" -version = "1.0.89" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bbeb29798b407ccd82a3324ade1a7286e0d29851475990b612670f6f5124d2" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -790,10 +869,10 @@ checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", "strsim", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -804,7 +883,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -818,6 +897,19 @@ dependencies = [ "pem-rfc7468", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2 1.0.51", + "quote 1.0.23", + "rustc_version 0.4.0", + "syn 1.0.108", +] + [[package]] name = "deunicode" version = "0.4.3" @@ -883,10 +975,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841ef46f4787d9097405cac4e70fb8644fc037b526e8c14054247c0263c400d0" dependencies = [ "bitflags", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "proc-macro2-diagnostics", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -1035,7 +1127,7 @@ dependencies = [ "mime 0.3.16", "serde", "serde_json", - "time 0.3.17", + "time 0.3.19", "tokio", "url 2.3.1", "webdriver", @@ -1051,9 +1143,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] @@ -1074,14 +1166,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -1130,6 +1222,12 @@ dependencies = [ "percent-encoding 2.2.0", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "fsevent" version = "0.4.0" @@ -1245,9 +1343,9 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -1282,9 +1380,9 @@ dependencies = [ [[package]] name = "generator" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266041a359dfa931b370ef684cceb84b166beb14f7f0421f4a6a3d0c446d12e" +checksum = "33a20a288a94683f5f4da0adecdbe095c94a77c295e514cc6484e9394dd8376e" dependencies = [ "cc", "libc", @@ -1396,20 +1494,20 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "ahash 0.7.6", ] [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash", + "ahash 0.8.3", ] [[package]] @@ -1492,9 +1590,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ "bytes", "fnv", @@ -1512,6 +1610,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-range-header" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" + [[package]] name = "httparse" version = "1.8.0" @@ -1548,7 +1652,7 @@ dependencies = [ "time 0.1.45", "traitobject", "typeable", - "unicase", + "unicase 1.4.2", "url 1.7.2", ] @@ -1787,79 +1891,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" -[[package]] -name = "lexical" -version = "6.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7aefb36fd43fef7003334742cbf77b243fcd36418a1d1bdd480d613a67968f6" -dependencies = [ - "lexical-core", -] - -[[package]] -name = "lexical-core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" -dependencies = [ - "lexical-parse-float", - "lexical-parse-integer", - "lexical-util", - "lexical-write-float", - "lexical-write-integer", -] - -[[package]] -name = "lexical-parse-float" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" -dependencies = [ - "lexical-parse-integer", - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-parse-integer" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" -dependencies = [ - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-util" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" -dependencies = [ - "static_assertions", -] - -[[package]] -name = "lexical-write-float" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" -dependencies = [ - "lexical-util", - "lexical-write-integer", - "static_assertions", -] - -[[package]] -name = "lexical-write-integer" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" -dependencies = [ - "lexical-util", - "static_assertions", -] - [[package]] name = "libc" version = "0.2.139" @@ -1963,6 +1994,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" +[[package]] +name = "matchit" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" + [[package]] name = "memchr" version = "2.5.0" @@ -1992,6 +2029,40 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime 0.3.16", + "unicase 2.6.0", +] + +[[package]] +name = "minify-html-onepass" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89548d0be6d3c7295335473fbe5c021fde64de738e01312301c90b9f1dd8476" +dependencies = [ + "aho-corasick", + "css-minify", + "lazy_static", + "memchr", + "minify-js", + "rustc-hash", +] + +[[package]] +name = "minify-js" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c300f90ba1138b5c5daf5d9441dc9bdc67b808aac22cf638362a2647bc213be4" +dependencies = [ + "lazy_static", + "parse-js", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -2028,14 +2099,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log 0.4.17", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -2076,7 +2147,7 @@ dependencies = [ "log 0.4.17", "memchr", "mime 0.3.16", - "spin 0.9.4", + "spin 0.9.5", "tokio", "tokio-util", "version_check 0.9.4", @@ -2220,9 +2291,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "opaque-debug" @@ -2251,9 +2322,9 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -2283,9 +2354,9 @@ checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "ouroboros" -version = "0.15.5" +version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbb50b356159620db6ac971c6d5c9ab788c9cc38a6f49619fca2a27acb062ca" +checksum = "e1358bd1558bd2a083fed428ffeda486fbfb323e698cdda7794259d592ca72db" dependencies = [ "aliasable", "ouroboros_macro", @@ -2293,15 +2364,15 @@ dependencies = [ [[package]] name = "ouroboros_macro" -version = "0.15.5" +version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0d9d1a6191c4f391f87219d1ea42b23f09ee84d64763cd05ee6ea88d9f384d" +checksum = "5f7d21ccd03305a674437ee1248f3ab5d4b1db095cf1caf49f1713ddf61956b7" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -2364,6 +2435,17 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "parse-js" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30534759e6ad87aa144c396544747e1c25b1020bd133356fd758c8facec764e5" +dependencies = [ + "aho-corasick", + "lazy_static", + "memchr", +] + [[package]] name = "paste" version = "1.0.11" @@ -2409,10 +2491,10 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82a5ca643c2303ecb740d506539deba189e16f2754040a42901cd8105d0282d0" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "proc-macro2-diagnostics", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -2438,22 +2520,26 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "perseus" -version = "0.3.6" +version = "0.4.0-beta.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0f6fff08e4cf346b91bd7c09b523e6bc6c0a45b6751bd1951ec8462bf774c95" +checksum = "579ff750d340ca202fd782e34ea6c55119a50defbcbbaa04858f9dfafcd21cc9" dependencies = [ "async-trait", "chrono", + "console_error_panic_hook", "fmterr", + "fs_extra", "futures", "http", "js-sys", + "minify-html-onepass", "perseus-macro", "regex", "rexie", "serde", "serde_json", "sycamore", + "sycamore-futures", "sycamore-router", "thiserror", "tokio", @@ -2463,18 +2549,27 @@ dependencies = [ "web-sys", ] +[[package]] +name = "perseus-axum" +version = "0.4.0-beta.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "584a80e74289626f89a0defb3a213f5ee44b5d6dc20bf345624be057a91edaa3" +dependencies = [ + "axum", + "perseus", + "tower-http", +] + [[package]] name = "perseus-macro" -version = "0.3.6" +version = "0.4.0-beta.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23876d449f9ce8f4f82207406863d9f75afda68dbf7951d14452e0d6e0b1e745" +checksum = "749da07e987c60900c2110421554aeb23b79c4914e16851712e3ef635f2592f0" dependencies = [ "darling", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "serde_json", - "sycamore-reactive", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -2492,9 +2587,9 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -2601,9 +2696,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", "version_check 0.9.4", ] @@ -2613,7 +2708,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", "version_check 0.9.4", ] @@ -2635,9 +2730,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -2648,9 +2743,9 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", "version_check 0.9.4", "yansi", ] @@ -2670,9 +2765,9 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -2696,7 +2791,7 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", ] [[package]] @@ -2753,9 +2848,9 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f9c0c92af03644e4806106281fe2e068ac5bc0ae74a707266d06ea27bccee5f" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -2795,9 +2890,9 @@ dependencies = [ [[package]] name = "rend" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95" +checksum = "581008d2099240d37fb08d77ad713bcaec2c4d89d50b5b21a8bb1996bbab68ab" dependencies = [ "bytecheck", ] @@ -2855,11 +2950,10 @@ dependencies = [ [[package]] name = "rexie" -version = "0.2.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ed2b22c65c32a8bd7cc1517fe02a8240839cba64e4cba7787e758f70f011b25" +checksum = "fef172ff9cdf146cdc934e28cdeb137517bf954fb75e6ee8987dd44b58f351b1" dependencies = [ - "console_error_panic_hook", "js-sys", "num-traits", "thiserror", @@ -2885,9 +2979,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.7.39" +version = "0.7.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" +checksum = "c30f1d45d9aa61cbc8cd1eb87705470892289bb2d01943e7803b873a57404dc3" dependencies = [ "bytecheck", "hashbrown 0.12.3", @@ -2899,13 +2993,13 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.39" +version = "0.7.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" +checksum = "ff26ed6c7c4dfc2aa9480b86a60e3c7233543a270a680e10758a507c5a4ce476" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -2959,7 +3053,7 @@ dependencies = [ "serde_json", "state 0.5.3", "tempfile", - "time 0.3.17", + "time 0.3.19", "tokio", "tokio-stream", "tokio-util", @@ -2992,10 +3086,10 @@ dependencies = [ "devise 0.3.1", "glob", "indexmap", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", "rocket_http 0.5.0-rc.2", - "syn 1.0.107", + "syn 1.0.108", "unicode-xid 0.2.4", ] @@ -3051,7 +3145,7 @@ dependencies = [ "smallvec", "stable-pattern", "state 0.5.3", - "time 0.3.17", + "time 0.3.19", "tokio", "uncased", ] @@ -3078,9 +3172,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.28.0" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe32e8c89834541077a5c5bbe5691aa69324361e27e6aeb3552a737db4a70c8" +checksum = "e13cf35f7140155d02ba4ec3294373d513a3c7baa8364c162b030e33c61520a8" dependencies = [ "arrayvec", "borsh", @@ -3094,13 +3188,28 @@ dependencies = [ "serde_json", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver", + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.16", ] [[package]] @@ -3210,7 +3319,7 @@ dependencies = [ "serde_json", "sqlx", "thiserror", - "time 0.3.17", + "time 0.3.19", "tracing", "url 2.3.1", "uuid", @@ -3240,9 +3349,9 @@ checksum = "7216195de9c6b2474fd0efab486173dccd0eff21f28cc54aa4c0205d52fb3af0" dependencies = [ "bae", "heck 0.3.3", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -3291,7 +3400,7 @@ dependencies = [ "rust_decimal", "sea-query-derive", "serde_json", - "time 0.3.17", + "time 0.3.19", "uuid", ] @@ -3306,7 +3415,7 @@ dependencies = [ "sea-query", "serde_json", "sqlx", - "time 0.3.17", + "time 0.3.19", "uuid", ] @@ -3317,9 +3426,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34cdc022b4f606353fe5dc85b09713a04e433323b70163e81513b141c6ae6eb5" dependencies = [ "heck 0.3.3", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", "thiserror", ] @@ -3341,9 +3450,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56821b7076f5096b8f726e2791ad255a99c82498e08ec477a65a96c461ff1927" dependencies = [ "heck 0.3.3", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -3362,10 +3471,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69b4397b825df6ccf1e98bcdabef3bbcfc47ff5853983467850eeab878384f21" dependencies = [ "heck 0.3.3", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", "rustversion", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -3406,6 +3515,12 @@ dependencies = [ "semver-parser", ] +[[package]] +name = "semver" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" + [[package]] name = "semver-parser" version = "0.7.0" @@ -3427,22 +3542,31 @@ version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b04f22b563c91331a10074bda3dd5492e3cc39d56bd557e91c0af42b6c7341" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3469,7 +3593,6 @@ dependencies = [ "log 0.4.17", "lopdf", "migration", - "perseus", "pretty_env_logger", "reqwest", "rocket 0.5.0-rc.2", @@ -3532,22 +3655,31 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg", ] +[[package]] +name = "slotmap" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" +dependencies = [ + "version_check 0.9.4", +] + [[package]] name = "slug" version = "0.1.4" @@ -3581,9 +3713,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc" [[package]] name = "spki" @@ -3622,7 +3754,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcbc16ddba161afc99e14d1713a453747a2b07fc097d2009f4c300ec99286105" dependencies = [ - "ahash", + "ahash 0.7.6", "atoi", "bitflags", "byteorder", @@ -3664,7 +3796,7 @@ dependencies = [ "sqlx-rt", "stringprep", "thiserror", - "time 0.3.17", + "time 0.3.19", "tokio-stream", "url 2.3.1", "uuid", @@ -3681,13 +3813,13 @@ dependencies = [ "either", "heck 0.4.1", "once_cell", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", "serde_json", "sha2", "sqlx-core", "sqlx-rt", - "syn 1.0.107", + "syn 1.0.108", "url 2.3.1", ] @@ -3735,12 +3867,6 @@ dependencies = [ "loom", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "stdweb" version = "0.4.20" @@ -3748,7 +3874,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" dependencies = [ "discard", - "rustc_version", + "rustc_version 0.2.3", "stdweb-derive", "stdweb-internal-macros", "stdweb-internal-runtime", @@ -3761,11 +3887,11 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", "serde", "serde_derive", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -3775,13 +3901,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" dependencies = [ "base-x", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", "serde", "serde_derive", "serde_json", "sha1 0.6.1", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -3814,56 +3940,80 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "sycamore" -version = "0.7.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5cea65876897bb946a623e16bf3df2de4997a6872d95b99dfaed5dd8e14e264" +checksum = "67817393b3c9828db84614f64db9a1ebb94729ce3a3751c41e7ff23d3f8e7f00" dependencies = [ - "ahash", + "ahash 0.7.6", + "futures", "html-escape", "indexmap", "js-sys", - "lexical", "once_cell", "paste", - "smallvec", + "sycamore-core", + "sycamore-futures", "sycamore-macro", "sycamore-reactive", + "sycamore-web", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", ] +[[package]] +name = "sycamore-core" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dce7f0440c5ea2b74a544deb5423708c023fade36e63515423d3f3ab5e1a998" +dependencies = [ + "ahash 0.7.6", + "sycamore-reactive", +] + +[[package]] +name = "sycamore-futures" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69e4f2b65a22059f711cb36adc454791248e9abdc0b6b04c5dda396098674f2" +dependencies = [ + "futures", + "sycamore-reactive", + "tokio", + "wasm-bindgen-futures", +] + [[package]] name = "sycamore-macro" -version = "0.7.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6911dba86d928ed3c898ee182c1a8a9f00299aa78875bc9308e7fd389e5bb4" +checksum = "8f3abd3f402c1a943cf70860b91a40c79c713e269156445998dbfd647deac8a5" dependencies = [ "once_cell", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] name = "sycamore-reactive" -version = "0.7.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20809429d0f9c2ffcbb3f192957a5d0c505519138e41c5d38808c5b42b3c53ab" +checksum = "6376b578ad32f5f3ab6943bccec906fb0e1f0258a8bedf811afdec8c3330ef80" dependencies = [ - "ahash", + "ahash 0.7.6", + "bumpalo", "indexmap", "serde", + "slotmap", "smallvec", - "wasm-bindgen", - "web-sys", ] [[package]] name = "sycamore-router" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cace57b69d923ef7ac5a1291bee73fa62e7d75b1f3a713db70d30ab0ee032185" +checksum = "123b34a150dac877d7bfae82dadfb0c586fd35a8f5fcdf1721dafa079fdc4c40" dependencies = [ "sycamore", "sycamore-router-macro", @@ -3873,17 +4023,33 @@ dependencies = [ [[package]] name = "sycamore-router-macro" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1f83a4862484dba897a6dc64c4a72b5c808c9af05573f7a55133b4f110ac66" +checksum = "92914a2f809b636d245b28d8a734801ecb8ff9c4996bbe6ea4176582e12503eb" dependencies = [ "nom", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", "unicode-xid 0.2.4", ] +[[package]] +name = "sycamore-web" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9520735f765e60718df8125eb27db19b990bed1116c9b3e8aae374dde1fe8" +dependencies = [ + "html-escape", + "indexmap", + "js-sys", + "once_cell", + "sycamore-core", + "sycamore-reactive", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "syn" version = "0.15.44" @@ -3897,15 +4063,21 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "d56e159d99e6c2b93995d171050271edb50ecc5288fbc7cc17de8fdce4e58c14" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "tempfile" version = "3.3.0" @@ -3950,17 +4122,18 @@ version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if 1.0.0", "once_cell", ] @@ -3992,14 +4165,14 @@ dependencies = [ [[package]] name = "time" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +checksum = "53250a3b3fed8ff8fd988587d8925d26a83ac3845d9e03b220b37f34c2b8d6c2" dependencies = [ "itoa", "serde", "time-core", - "time-macros 0.2.6", + "time-macros 0.2.7", ] [[package]] @@ -4020,9 +4193,9 @@ dependencies = [ [[package]] name = "time-macros" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +checksum = "a460aeb8de6dcb0f381e1ee05f1cd56fcf5a5f6eb8187ff3d8f0b11078d38b7c" dependencies = [ "time-core", ] @@ -4034,10 +4207,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", "standback", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -4051,29 +4224,28 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.20.1" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" dependencies = [ "autocfg", "bytes", "libc", "memchr", - "mio 0.8.5", + "mio 0.8.6", "num_cpus", - "once_cell", "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "winapi 0.3.9", + "windows-sys 0.42.0", ] [[package]] @@ -4082,16 +4254,16 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] name = "tokio-native-tls" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", "tokio", @@ -4110,9 +4282,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" +checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" dependencies = [ "futures-core", "pin-project-lite", @@ -4121,9 +4293,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ "bytes", "futures-core", @@ -4151,6 +4323,53 @@ dependencies = [ "serde", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "httpdate", + "mime 0.3.16", + "mime_guess", + "percent-encoding 2.2.0", + "pin-project-lite", + "tokio", + "tokio-util", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -4176,9 +4395,9 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", ] [[package]] @@ -4272,6 +4491,15 @@ dependencies = [ "version_check 0.1.5", ] +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check 0.9.4", +] + [[package]] name = "unicode-bidi" version = "0.3.10" @@ -4477,9 +4705,9 @@ dependencies = [ "bumpalo", "log 0.4.17", "once_cell", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", "wasm-bindgen-shared", ] @@ -4511,9 +4739,9 @@ version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "quote 1.0.23", - "syn 1.0.107", + "syn 1.0.108", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4548,7 +4776,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "time 0.3.17", + "time 0.3.19", "unicode-segmentation", "url 2.3.1", ] @@ -4632,15 +4860,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.39.0" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" +checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" dependencies = [ - "windows_aarch64_msvc 0.39.0", - "windows_i686_gnu 0.39.0", - "windows_i686_msvc 0.39.0", - "windows_x86_64_gnu 0.39.0", - "windows_x86_64_msvc 0.39.0", + "windows-targets", ] [[package]] @@ -4650,12 +4874,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.1", - "windows_i686_gnu 0.42.1", - "windows_i686_msvc 0.42.1", - "windows_x86_64_gnu 0.42.1", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.1", + "windows_x86_64_msvc", ] [[package]] @@ -4674,12 +4898,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.1", - "windows_i686_gnu 0.42.1", - "windows_i686_msvc 0.42.1", - "windows_x86_64_gnu 0.42.1", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.1", + "windows_x86_64_msvc", ] [[package]] @@ -4688,48 +4912,24 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" -[[package]] -name = "windows_aarch64_msvc" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" - [[package]] name = "windows_aarch64_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" -[[package]] -name = "windows_i686_gnu" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" - [[package]] name = "windows_i686_gnu" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" -[[package]] -name = "windows_i686_msvc" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" - [[package]] name = "windows_i686_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" -[[package]] -name = "windows_x86_64_gnu" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" - [[package]] name = "windows_x86_64_gnu" version = "0.42.1" @@ -4742,12 +4942,6 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" -[[package]] -name = "windows_x86_64_msvc" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" - [[package]] name = "windows_x86_64_msvc" version = "0.42.1" diff --git a/client/.gitignore b/client/.gitignore index d421d66..ef5e855 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -1,2 +1,2 @@ -.perseus/ +dist/ pkg/ diff --git a/client/Cargo.toml b/client/Cargo.toml index cd7a6f9..1c8264d 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -9,12 +9,23 @@ edition = "2021" chrono = { workspace = true, features = ["serde"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -dotenvy = { workspace = true } -envy = { workspace = true } -perseus = { version = "0.3.6", features = ["hydrate"] } -sycamore = { version = "0.7.1", features = ["ssr", "serde", "futures"] } -reqwasm = "0.5.0" +perseus = { version = "0.4.0-beta.21", features = ["hydrate"] } +sycamore = { version = "^0.8.1", features = [ + "ssr", + "serde", + "suspense", + "hydrate", +] } + +[target.'cfg(engine)'.dev-dependencies] +fantoccini = "^0.19.3" -[dev-dependencies] -fantoccini = "0.19.3" -tokio = { version = "=1.20.1", features = ["macros", "rt", "rt-multi-thread"] } +[target.'cfg(engine)'.dependencies] +tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread"] } +reqwest = { version = "0.11", features = ["json", "rustls-tls"] } +perseus-axum = { version = "=0.4.0-beta.19", features = ["dflt-server"] } +# dotenvy = { workspace = true } +# envy = { workspace = true } + +[target.'cfg(client)'.dependencies] +reqwasm = "0.5.0" diff --git a/client/src/api/routes/transaction.rs b/client/src/api/routes/transaction.rs index 840b95b..c3fadb8 100644 --- a/client/src/api/routes/transaction.rs +++ b/client/src/api/routes/transaction.rs @@ -1,26 +1,48 @@ -use crate::{ - api::types::{paginated_response::PaginatedResponse, transaction::TransactionCompany}, - env::Config, -}; +use crate::api::types::{paginated_response::PaginatedResponse, transaction::TransactionCompany}; pub async fn get_transactions( company_slug: Option, page: i64, size: i64, ) -> Result, ()> { - let res = reqwasm::http::Request::get(&format!( - "{}transaction{}?page={}&size={}", - Config::new().api_url, - company_slug.unwrap_or_default(), - page, - size, - )) - .send() - .await - .map_err(|_| ())? - .json::>() - .await - .map_err(|_| ())?; + use crate::env::Config; - Ok(res) + #[cfg(client)] + { + // TODO: Remove build-time environment variable + let api_url = Config::new().api_url; + let res = reqwasm::http::Request::get(&format!( + "{}transaction{}?page={}&size={}", + api_url, + company_slug.unwrap_or_default(), + page, + size, + )) + .send() + .await + .map_err(|_| ())? + .json::>() + .await + .map_err(|_| ())?; + + return Ok(res); + } + + #[cfg(engine)] + { + let res = reqwest::get(&format!( + "{}transaction{}?page={}&size={}", + Config::new().api_url, + company_slug.unwrap_or_default(), + page, + size, + )) + .await + .map_err(|_| ())? + .json::>() + .await + .map_err(|_| ())?; + + return Ok(res); + } } diff --git a/client/src/api/types/paginated_response.rs b/client/src/api/types/paginated_response.rs index cecaab1..4b843a2 100644 --- a/client/src/api/types/paginated_response.rs +++ b/client/src/api/types/paginated_response.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use sycamore::{prelude::GenericNode, view}; +use sycamore::prelude::*; use crate::components::base_table::TableContent; @@ -9,7 +9,7 @@ pub trait IntoTableData where G: GenericNode, { - fn into_table_data(self) -> TableContent; + fn into_table_data<'a>(self, cx: Scope<'a>) -> TableContent; } #[derive(Clone, Serialize, Deserialize)] @@ -23,53 +23,53 @@ impl IntoTableData for PaginatedResponse where G: GenericNode, { - fn into_table_data(self) -> TableContent { + fn into_table_data<'a>(self, cx: Scope<'a>) -> TableContent { let headers_view = vec![ - view! { "Company" }, - view! { "Date published" }, - view! { "Date executed" }, - view! { "Person" }, - view! { "Nature" }, - view! { "ISIN" }, - view! { "Instrument" }, - view! { "Exchange" }, - view! { "Volume" }, - view! { "Unit price" }, - view! { "Total" }, + view! {cx, "Company" }, + view! {cx, "Date published" }, + view! {cx, "Date executed" }, + view! {cx, "Person" }, + view! {cx, "Nature" }, + view! {cx, "ISIN" }, + view! {cx, "Instrument" }, + view! {cx, "Exchange" }, + view! {cx, "Volume" }, + view! {cx, "Unit price" }, + view! {cx, "Total" }, ]; - let data_view: Vec>> = self + let data_view: Vec>> = self .list .into_iter() .map(|t| { let mut res = vec![]; let t1 = t.clone(); - res.push(view! { - a (href=format!("index/{}", t1.company.slug), + res.push(view! {cx, + a (href=format!("{}", t1.company.slug), class="text-indigo-800 dark:text-indigo-300 hover:text-indigo-500 dark:hover:text-indigo-600 hover:underline", ) { (t1.company.name.to_owned()) } }); let t1 = t.clone(); - res.push(view! { (t1.date_published.to_owned()) }); + res.push(view! {cx, (t1.date_published.to_owned()) }); let t1 = t.clone(); - res.push(view! { (t1.date_executed.to_owned()) }); + res.push(view! {cx, (t1.date_executed.to_owned()) }); let t1 = t.clone(); - res.push(view! { (t1.person.to_owned()) }); + res.push(view! {cx, (t1.person.to_owned()) }); let t1 = t.clone(); - res.push(view! { (t1.nature.to_owned()) }); + res.push(view! {cx, (t1.nature.to_owned()) }); let t1 = t.clone(); - res.push(view! { (t1.isin.to_owned().unwrap_or_else(|| "-".to_string())) }); + res.push(view! {cx, (t1.isin.to_owned().unwrap_or_else(|| "-".to_string())) }); let t1 = t.clone(); - res.push(view! { (t1.instrument.to_owned()) }); + res.push(view! {cx, (t1.instrument.to_owned()) }); let t1 = t.clone(); - res.push(view! { (t1.exchange.to_owned()) }); + res.push(view! {cx, (t1.exchange.to_owned()) }); let t1 = t.clone(); - res.push(view! { (t1.volume.to_owned()) }); + res.push(view! {cx, (t1.volume.to_owned()) }); let t1 = t.clone(); - res.push(view! { (t1.unit_price.to_owned()) }); - res.push(view! { ((t.volume as f32 * t.unit_price).to_string()) }); + res.push(view! {cx, (t1.unit_price.to_owned()) }); + res.push(view! {cx, ((t.volume as f32 * t.unit_price).to_string()) }); res }) diff --git a/client/src/components/base_async_select.rs b/client/src/components/base_async_select.rs index 24a1d8d..fab4d1f 100644 --- a/client/src/components/base_async_select.rs +++ b/client/src/components/base_async_select.rs @@ -1,4 +1,4 @@ -use perseus::checkpoint; +use perseus::prelude::*; use serde::Deserialize; use sycamore::prelude::*; @@ -6,97 +6,90 @@ pub trait IntoAsyncSelectListItem { fn to_select_list_item(&self) -> String; } -#[derive(Clone)] -pub struct AsyncSelectRx +#[derive(Prop)] +pub struct AsyncSelectRx<'a, T> where T: 'static + PartialEq + Clone + IntoAsyncSelectListItem, { - pub remote_list: ReadSignal, - pub selected_item: Signal>, + pub remote_list: &'a ReadSignal, + pub selected_item: &'a Signal>, } -#[component(BaseAsyncSelect)] -pub fn create_component( - AsyncSelectRx { - remote_list, - selected_item, - }: AsyncSelectRx, -) -> View +#[component] +pub fn BaseAsyncSelect<'a, G, T>(cx: Scope<'a>, props: AsyncSelectRx<'a, T>) -> View where + G: Html, T: 'static + PartialEq + Clone + IntoAsyncSelectListItem, for<'de> T: Deserialize<'de>, { - let input = Signal::new("".to_string()); + let input = create_signal(cx, "".to_string()); - let visible = Signal::new(false); - let hide_dropdown = cloned!((visible, selected_item, input) => move |_| { + let visible = create_signal(cx, false); + let hide_dropdown = move |_| { visible.set(false); - if selected_item.get().is_none() { + if props.selected_item.get().is_none() { input.set("".to_string()); } - }); - let item_list: Signal> = Signal::new(vec![]); - let selected = Signal::new(false); - create_effect( - cloned!((input, visible, item_list, selected, selected_item, remote_list) => move || { - // Early return if: - // - The input is empty, there is nothing to search for nor to show - // - We just selected an item - if input.get().is_empty() || *selected.get_untracked() { - selected.set(false); - visible.set(false); - return; - } + }; + let item_list: &Signal> = create_signal(cx, vec![]); + let selected = create_signal(cx, false); + create_effect(cx, move || { + // Early return if: + // - The input is empty, there is nothing to search for nor to show + // - We just selected an item + if input.get().is_empty() || *selected.get_untracked() { + selected.set(false); + visible.set(false); + return; + } - selected_item.set(None); - if G::IS_BROWSER { - perseus::spawn_local( - cloned!((input, visible, item_list, remote_list) => async move { - let res = reqwasm::http::Request::get( - &format!( "{}/{}?limit={}", remote_list.get(), input.get(), 5) - ) - .send() - .await - .unwrap() - .json::>() - .await - .unwrap(); - visible.set(!res.is_empty()); - item_list.set(res); - checkpoint("async_select_item_change"); - }), - ); - } - }), - ); + props.selected_item.set(None); - let input2 = input.clone(); - let visible2 = visible.clone(); + #[cfg(client)] + spawn_local_scoped(cx, async move { + let res = reqwasm::http::Request::get(&format!( + "{}/{}?limit={}", + props.remote_list.get(), + input.get(), + 5 + )) + .send() + .await + .unwrap() + .json::>() + .await + .unwrap(); + visible.set(!res.is_empty()); + item_list.set(res); + checkpoint("async_select_item_change"); + }); + }); - view! { + view! { cx, input (bind:value=input, class="p-2 w-full rounded-md bg-slate-300 dark:bg-slate-800", on:blur=hide_dropdown) {} div (class="relative") { div (class=format!("absolute -top-1 w-80 rounded-b-md dark:bg-slate-800 bg-slate-300 {}", if *visible.get() { "visible" } else { "collapse" })) { ul { - Indexed(IndexedProps { - iterable: item_list.handle(), - template: move |x| { - view! { + Indexed( + iterable=item_list, + view= move |cx, x| { + let item = x.clone(); + view! {cx, li ( class="w-full p-2 cursor-pointer dark:hover:bg-slate-900 hover:bg-slate-400", - on:mousedown=cloned!((x, input2, selected_item, visible2, selected) => move |_| { + on:mousedown=move |_| { selected.set(true); - selected_item.set(Some(x.clone())); - input2.set(x.clone().to_select_list_item()); - visible2.set(false); - }), + props.selected_item.set(Some(item.clone())); + input.set(item.to_select_list_item()); + visible.set(false); + }, ) { (x.to_select_list_item()) } } }, - }) + ) } } } diff --git a/client/src/components/base_button.rs b/client/src/components/base_button.rs index 59764ea..6107346 100644 --- a/client/src/components/base_button.rs +++ b/client/src/components/base_button.rs @@ -1,29 +1,23 @@ use sycamore::prelude::*; -#[derive(Clone)] -pub struct BaseButtonStateRx { - pub label: ReadSignal, - pub disabled: ReadSignal, - pub clicked: Signal, +#[derive(Prop)] +pub struct BaseButtonStateRx<'a> { + pub label: &'a ReadSignal, + pub disabled: &'a ReadSignal, + pub clicked: &'a Signal, } -#[component(BaseButton)] -pub fn create_component( - BaseButtonStateRx { - label, - disabled, - clicked, - }: BaseButtonStateRx, -) -> View { - let click_event = cloned!((clicked) => move |_| { clicked.set(true) }); +#[component] +pub fn BaseButton<'a, G: Html>(cx: Scope<'a>, props: BaseButtonStateRx<'a>) -> View { + let click_event = |_| props.clicked.set(true); - view! { + view! { cx, button ( class="my-2 z-0 p-2 bg-slate-300 dark:bg-slate-800 hover:bg-slate-400 dark:hover:bg-slate-900 disabled:cursor-not-allowed hover:cursor-pointer rounded-md ", - disabled=*disabled.get(), + disabled=*props.disabled.get(), on:click=click_event, ) { - (label.get()) + (props.label.get()) } } } diff --git a/client/src/components/base_table.rs b/client/src/components/base_table.rs index f187ecb..fd16834 100644 --- a/client/src/components/base_table.rs +++ b/client/src/components/base_table.rs @@ -9,13 +9,13 @@ where pub data_view: Vec>>, } -#[derive(Debug, Clone)] -pub struct TableContentRx +#[derive(Prop)] +pub struct TableContentRx<'a, G> where G: GenericNode, { - pub headers_view: Signal>>, - pub data_view: Signal>>>, + pub headers_view: &'a Signal>>, + pub data_view: &'a Signal>>>, } #[derive(Debug, Clone)] @@ -29,65 +29,64 @@ impl PartialEq> for PEqView { impl Eq for PEqView {} -#[component(BaseTable)] -pub fn the_header( - TableContentRx { - headers_view, - data_view, - }: TableContentRx, -) -> View +#[component] +pub fn BaseTable<'a, G>(cx: Scope<'a>, props: TableContentRx<'a, G>) -> View where - G: GenericNode, + G: Html, { - let headers = create_memo(cloned!((headers_view) => move || { - (*headers_view.get()).clone().into_iter().enumerate().map(|(idx, v)| PEqView(idx,v)).collect::>>>() - })); + let headers = create_memo(cx, || { + (*props.headers_view.get()) + .clone() + .into_iter() + .enumerate() + .map(|(idx, v)| PEqView(idx, v)) + .collect::>>>() + }); - let data = Signal::new(vec![]); - let data2 = data.clone(); - create_effect(cloned!((data_view, data2, data) => move || { + let data = create_signal(cx, vec![]); + create_effect(cx, move || { data.set(vec![]); - let v_table = data_view.get(); + let v_table = props.data_view.get(); for (idx, row) in v_table.iter().enumerate() { let views = PEqView(idx, View::new_fragment( row.iter().map(|cell| { - view!{ th (class="m-2 p-2 border-slate-500 border-x border-dashed") { (cell) } } + view!{cx, th (class="m-2 p-2 border-slate-500 border-x border-dashed") { (cell) } } } ).collect() )); - let mut d = (*data2.get()).clone(); + let mut d = (*data.get()).clone(); d.push(views); - data.set(d); + data.set(d.to_vec()); } - })); + }); - view! { + view! { cx, table (class="table-auto bg-slate-200 text-left dark:bg-slate-800 rounded-lg mx-auto my-2") { thead { tr (class="border-b-2 border-slate-500 text-center") { - Keyed(KeyedProps { - iterable: headers, - template: |v| { - view! { + Keyed( + iterable=headers, + view=|cx, v| { + view! {cx, th (class="m-2 p-2") { (v.1) } } }, - key: |v| v.0, - }) + key=|v| v.0, + ) } } tbody { - Keyed(KeyedProps { - iterable: data.handle(), - key: |x| x.0, - template: |t| { - view! { + Keyed( + iterable=data, + view=|cx, t| { + view! {cx, tr (class="m-2 p-2 border-slate-500 border") { (t.1) } } }, - }) + key=|x| x.0, + ) } } } diff --git a/client/src/components/loading.rs b/client/src/components/loading.rs index 9ef0f58..20d79ec 100644 --- a/client/src/components/loading.rs +++ b/client/src/components/loading.rs @@ -1,8 +1,8 @@ use sycamore::prelude::*; -#[component(Loading)] -pub fn component() -> View { - view! { +#[component] +pub fn Loading(cx: Scope) -> View { + view! { cx, svg (version="1.1", id="loader-1", xmlns="http://www.w3.org/2000/svg", xlink="http://www.w3.org/1999/xlink", x="0px", y="0px", width="40px", height="40px", viewBox="0 0 50 50", space="preserve") { path (fill="#000", d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z"){ diff --git a/client/src/components/paginated_data_table.rs b/client/src/components/paginated_data_table.rs index 64967cc..a9fd9fb 100644 --- a/client/src/components/paginated_data_table.rs +++ b/client/src/components/paginated_data_table.rs @@ -1,5 +1,6 @@ use std::rc::Rc; +use perseus::prelude::*; use serde::Deserialize; use sycamore::prelude::*; @@ -11,7 +12,7 @@ use crate::{ }, }; -#[derive(Clone)] +#[derive(Prop)] pub struct PaginatedTableStateRx where M: 'static, @@ -33,99 +34,100 @@ where } } -#[component(PaginatedTable)] -pub fn component(state: PaginatedTableStateRx) -> View +#[component] +pub fn PaginatedTable<'a, G, M, F, C>( + cx: Scope<'a>, + props: PaginatedTableStateRx, +) -> View where + G: Html, M: 'static + Clone, PaginatedResponse: IntoTableData, for<'de> M: Deserialize<'de>, C: Fn(Option, i64, i64) -> F + 'static, F: std::future::Future, ()>> + 'static, { - let paginated_data: Signal>> = Signal::new(None); + let paginated_data = create_signal(cx, None); let table_prop: TableContentRx = TableContentRx { - headers_view: Signal::new(vec![]), - data_view: Signal::new(vec![vec![]]), + headers_view: create_signal(cx, vec![]), + data_view: create_signal(cx, vec![vec![]]), }; - let table_prop2 = table_prop.clone(); - let page: Signal = Signal::new(0); - let n_page: Signal = Signal::new(1); - let n_rows: Signal = Signal::new(0); + let page = create_signal(cx, 0); + let n_page = create_signal(cx, 1); + let n_rows = create_signal(cx, 0); - let page_up = cloned!((page, paginated_data, n_page) => move |_| { - n_page.set((*paginated_data.get()).as_ref().map_or(0, |t| t.num_pages)); + let page_up = move |_| { + n_page.set( + (*paginated_data.get()) + .clone() + .map_or(0, |t: PaginatedResponse| t.num_pages), + ); if *page.get() + 1 < *n_page.get() { page.set((*page.get()).min(*n_page.get() - 1) + 1) } - }); - let page_down = cloned!((page) => move |_| { + }; + let page_down = |_| { if *page.get() > 0 { - page.set((*page.get()-1).max(0)); + page.set((*page.get() - 1).max(0)); } - }); + }; - let page_size_string = Signal::new("20".to_string()); + let page_size_string = create_signal(cx, "20".to_string()); let page_size_string2 = page_size_string.clone(); - let state_rc = Rc::new(state); - create_effect( - cloned!((page_size_string, paginated_data, page, n_page, n_rows, state_rc) => move || { - let page = *page.get(); - let page_size_s = page_size_string.get(); - let page_size = page_size_s.parse().unwrap_or(20); - if G::IS_BROWSER { - perseus::spawn_local( - cloned!((table_prop2, page, paginated_data, n_page, n_rows, state_rc) => async move { - let res = state_rc.get_data(page, page_size).await.unwrap(); - paginated_data.set(Some(res.clone())); - n_rows.set(res.count); - let table_content = res.into_table_data(); - table_prop2.data_view.set(table_content.data_view); - table_prop2.headers_view.set(table_content.headers_view); - n_page.set((*paginated_data.get()).as_ref().map_or(0, |t| t.num_pages)); - }), - ); - } - }), - ); - view! { - (cloned!((n_rows, page_size_string, page_down, page_up, page, n_page, page_size_string2) => - view! { - p (class="text-right") { (format!("{} transactions", n_rows.get())) } - div (class="flex flex-row justify-between") { - select (bind:value=page_size_string, - class="p-2 justify-end text-slate-700 dark:text-slate-100 bg-slate-200 dark:bg-slate-800 rounded-md", - id="size-select", - ) { - option (value="20") { "20" } - option (value="10") { "10" } - option (value="30", selected=page_size_string2.get().eq(&Rc::new("30".to_string()))) { "30" } - option (value="40") { "40" } - option (value="50") { "50" } - } - div (class="flex flex-row p-2 bg-slate-200 dark:bg-slate-800 rounded-md") { - button (on:click=page_down,class="m-1 hover:font-bold") { - "<<" - } - div (class="m-1 align-middle text-center") { - (format!("{}/{}",*page.get() + 1, *n_page.get()) ) - } - button (on:click=page_up, class="m-1 hover:font-bold") { - ">>" - } - } - } - })) - (if paginated_data.get().is_some() { - view! { - BaseTable(table_prop.clone()) + //let props_ref = Rc::new(props); + let props_sig = create_signal(cx, props); + create_effect(cx, move || { + let page = *page.get(); + let page_size_s = page_size_string.get(); + let page_size = page_size_s.parse().unwrap_or(20); + #[cfg(client)] + spawn_local_scoped(cx, async move { + let res = props_sig.get().get_data(page, page_size).await.unwrap(); + paginated_data.set(Some(res.clone())); + n_rows.set(res.count); + let table_content = res.into_table_data(cx); + table_prop.data_view.set(table_content.data_view); + table_prop.headers_view.set(table_content.headers_view); + n_page.set((*paginated_data.get()).as_ref().map_or(0, |t| t.num_pages)); + }); + }); + + view! { cx, + (if paginated_data.get().is_some() { + view! {cx, + p (class="text-right") { (format!("{} transactions", n_rows.get())) } + div (class="flex flex-row justify-between") { + select (bind:value=page_size_string, + class="p-2 justify-end text-slate-700 dark:text-slate-100 bg-slate-200 dark:bg-slate-800 rounded-md", + id="size-select", + ) { + option (value="20") { "20" } + option (value="10") { "10" } + option (value="30", selected=page_size_string2.get().eq(&Rc::new("30".to_string()))) { "30" } + option (value="40") { "40" } + option (value="50") { "50" } } - } else { - view! { - div (class="flex flex-row justify-center") { - Loading() + div (class="flex flex-row p-2 bg-slate-200 dark:bg-slate-800 rounded-md") { + button (on:click=page_down,class="m-1 hover:font-bold") { + "<<" + } + div (class="m-1 align-middle text-center") { + (format!("{}/{}",*page.get() + 1, *n_page.get()) ) + } + button (on:click=page_up, class="m-1 hover:font-bold") { + ">>" } } - }) + } + BaseTable(headers_view=table_prop.headers_view, data_view=table_prop.data_view) + } + } else { + view! {cx, + div (class="flex flex-row justify-center") { + Loading() + } + } + }) } } diff --git a/client/src/components/the_header.rs b/client/src/components/the_header.rs index e1aae9b..d7738f7 100644 --- a/client/src/components/the_header.rs +++ b/client/src/components/the_header.rs @@ -1,8 +1,8 @@ use sycamore::prelude::*; -#[component(TheHeader)] -pub fn the_header(_: ()) -> View { - view! { +#[component] +pub fn the_header(cx: Scope) -> View { + view! { cx, "Don't use until global state is recheable from a component" // header (class="shadow-md h-10 sm:p-2 w-full mb-20 bg-gray-100 dark:bg-slate-500/30 backdrop-blur-lg") { // nav () { diff --git a/client/src/env.rs b/client/src/env.rs index 6238bd1..41e3dce 100644 --- a/client/src/env.rs +++ b/client/src/env.rs @@ -1,12 +1,13 @@ use serde::{Deserialize, Serialize}; -use std::env; +// use std::env; #[derive(Clone, Serialize, Deserialize)] pub struct Config { pub api_url: String, } +#[cfg(engine)] impl Config { pub fn new() -> Self { let api_url = env!("API_URL").to_string(); @@ -14,6 +15,15 @@ impl Config { } } +#[cfg(client)] +impl Config { + pub fn new() -> Self { + let api_url = env!("API_URL").to_string(); + Config { api_url } + } +} + +#[cfg(engine)] impl Default for Config { fn default() -> Self { Config::new() diff --git a/client/src/error_pages.rs b/client/src/error_pages.rs index d472912..a7505aa 100644 --- a/client/src/error_pages.rs +++ b/client/src/error_pages.rs @@ -1,17 +1,62 @@ -use perseus::{ErrorPages, Html}; -use sycamore::view; +use perseus::errors::ClientError; +use perseus::prelude::*; +use sycamore::prelude::*; -pub fn get_error_pages() -> ErrorPages { - let mut error_pages = ErrorPages::new(|url, status, err, _| { - view! { - p { (format!("An error with HTTP code {} occurred at '{}': '{}'.", status, url, err)) } +pub fn get_error_views() -> ErrorViews { + ErrorViews::new(|cx, err, _err_info, _err_pos| { + match err { + ClientError::ServerError { status, message: _ } => match status { + 404 => ( + view! { cx, + title { "Page not found" } + }, + view! { cx, + p { "Sorry, that page doesn't seem to exist." } + }, + ), + // 4xx is a client error + _ if (400..500).contains(&status) => ( + view! { cx, + title { "Error" } + }, + view! { cx, + p { "There was something wrong with the last request, please try reloading the page." } + }, + ), + // 5xx is a server error + _ => ( + view! { cx, + title { "Error" } + }, + view! { cx, + p { "Sorry, our server experienced an internal error. Please try reloading the page." } + }, + ), + }, + ClientError::Panic(_) => ( + view! { cx, + title { "Critical error" } + }, + view! { cx, + p { "A critical error occured" } + }, + ), + ClientError::FetchError(_) => ( + view! { cx, + title { "Error" } + }, + view! { cx, + p { "A network error occurred, do you have an internet connection? (If you do, try reloading the page.)" } + }, + ), + _ => ( + view! { cx, + title { "Error" } + }, + view! { cx, + p { (format!("An internal error has occurred: '{}'.", err)) } + }, + ), } - }); - error_pages.add_page(404, |_, _, _, _| { - view! { - p { "Page not found." } - } - }); - - error_pages + }) } diff --git a/client/src/global_state.rs b/client/src/global_state.rs index 483273b..34ae344 100644 --- a/client/src/global_state.rs +++ b/client/src/global_state.rs @@ -1,21 +1,26 @@ +use perseus::prelude::*; +use serde::{Deserialize, Serialize}; + use crate::env::Config; -use perseus::{state::GlobalStateCreator, RenderFnResult}; +use perseus::state::GlobalStateCreator; pub fn get_global_state_creator() -> GlobalStateCreator { GlobalStateCreator::new().build_state_fn(get_build_state) } -#[perseus::make_rx(AppStateRx)] +#[derive(Serialize, Deserialize, ReactiveState)] +#[rx(alias = "AppStateRx")] pub struct AppState { pub dark_mode: bool, pub config: Config, } -#[perseus::autoserde(global_build_state)] -pub async fn get_build_state() -> RenderFnResult { +#[engine_only_fn] +pub async fn get_build_state(_locale: String) -> AppState { + use crate::env::Config; let config = Config::new(); - Ok(AppState { + AppState { config, dark_mode: true, - }) + } } diff --git a/client/src/lib.rs b/client/src/main.rs similarity index 69% rename from client/src/lib.rs rename to client/src/main.rs index 859dbf9..9c5b1e4 100644 --- a/client/src/lib.rs +++ b/client/src/main.rs @@ -1,4 +1,4 @@ -use perseus::{Html, PerseusApp, PerseusRoot}; +use perseus::prelude::*; use sycamore::view; mod api; @@ -8,14 +8,14 @@ pub mod error_pages; pub mod global_state; pub mod templates; -#[perseus::main] +#[perseus::main(perseus_axum::dflt_server)] pub fn main() -> PerseusApp { PerseusApp::new() - .template(crate::templates::index::get_template) + .template(crate::templates::index::get_template()) .global_state_creator(crate::global_state::get_global_state_creator()) - .error_pages(crate::error_pages::get_error_pages) - .index_view(|| { - view! { + .error_views(crate::error_pages::get_error_views()) + .index_view(|cx| { + view! {cx, head() { title { "Fast Insiders" } link (rel="stylesheet", href = "/.perseus/static/tailwind.css") {} diff --git a/client/src/templates/index.rs b/client/src/templates/index.rs index 7ab7988..7885bbb 100644 --- a/client/src/templates/index.rs +++ b/client/src/templates/index.rs @@ -1,11 +1,10 @@ -use perseus::{navigate, Html, RenderFnResult, RenderFnResultWithCause, SsrNode, Template}; +use perseus::prelude::*; +use serde::{Deserialize, Serialize}; use sycamore::prelude::*; use crate::{ - api::{ - routes::transaction::get_transactions, - types::{company::Company, transaction::TransactionCompany}, - }, + api::routes::transaction::get_transactions, + api::types::{company::Company, transaction::TransactionCompany}, components::{ base_async_select::{AsyncSelectRx, BaseAsyncSelect}, base_button::{BaseButton, BaseButtonStateRx}, @@ -14,68 +13,69 @@ use crate::{ global_state::AppStateRx, }; -#[perseus::make_rx(IndexPageStateRx)] +#[derive(Serialize, Deserialize, Clone, ReactiveState)] +#[rx(alias = "IndexPageStateRx")] pub struct IndexPageState { pub company_slug: String, } -#[perseus::template_rx] -pub fn index_page( - IndexPageStateRx { company_slug }: IndexPageStateRx, - global_state: AppStateRx, -) -> View { - let dark_mode = global_state.dark_mode; +#[auto_scope] +fn index_page(cx: Scope, state: &IndexPageStateRx) -> View { + let global_state = Reactor::::from_cx(cx).get_global_state::(cx); + let dark_mode = &global_state.dark_mode; let dark_mode_2 = dark_mode.clone(); let dark_mode_3 = dark_mode.clone(); - let expand = Signal::new(false); + let expand = create_signal(cx, false); let filter_expand = BaseButtonStateRx { - label: Signal::new("Filters".to_string()).handle(), - disabled: Signal::new(false).handle(), - clicked: Signal::new(false), + label: create_signal(cx, "Filters".to_string()), + disabled: create_signal(cx, false), + clicked: create_signal(cx, false), }; - create_effect(cloned!((filter_expand, expand) => move || { + create_effect(cx, move || { if *filter_expand.clicked.get() { filter_expand.clicked.set(false); expand.set(!*expand.get()); } - })); + }); - let toggle_dark_mode = cloned!(() => move |_| dark_mode_2.set(!*dark_mode.get())); + let toggle_dark_mode = move |_| dark_mode_2.set(!*dark_mode.get()); let paginated_table_state: PaginatedTableStateRx = PaginatedTableStateRx { route: get_transactions, - filter: if (*company_slug.get()).is_empty() { + filter: if (*state.company_slug.get()).is_empty() { None } else { - Some((*company_slug.get()).clone()) + Some((*state.company_slug.get()).clone()) }, }; let async_select_prop: AsyncSelectRx = AsyncSelectRx { - remote_list: Signal::new(format!("{}company/", global_state.config.get().api_url)).handle(), - selected_item: Signal::new(None), + remote_list: create_signal(cx, format!("{}company/", "http://localhost:8000/v1/")), + selected_item: create_signal(cx, None), }; - let async_select_prop2 = async_select_prop.clone(); let search_button = BaseButtonStateRx { - label: Signal::new("Search".to_string()).handle(), - disabled: create_memo(cloned!((async_select_prop) => move || { - async_select_prop.selected_item.get().is_none() - })), - clicked: Signal::new(false), + label: create_signal(cx, "Search".to_string()), + disabled: create_memo(cx, move || async_select_prop.selected_item.get().is_none()), + clicked: create_signal(cx, false), }; - create_effect(cloned!((search_button) => move || { + create_effect(cx, || { if *search_button.clicked.get() { search_button.clicked.set(false); - navigate(&format!("/index/{}", (*async_select_prop2.selected_item.get()).clone().map_or("".to_string(), |c| c.slug))); + navigate(&format!( + "/{}", + (*async_select_prop.selected_item.get()) + .clone() + .map_or("".to_string(), |c| c.slug) + )); } - })); + }); - view! { + view! {cx, main (class=if *dark_mode_3.get() { "dark" } else { "" }) { div (class="bg-slate-200 dark:bg-slate-700 text-slate-700 dark:text-slate-100 font-sans") { header (class="shadow-md h-12 p-2 align-middle w-full bg-gray-100 dark:bg-slate-500/30 backdrop-blur-lg") { @@ -101,7 +101,7 @@ pub fn index_page( } } BaseButton(filter_expand) - div () {} // Without this useless div, the code doesn't run in the browser + div {} // Without this useless div, the code doesn't run in the browser div (id="filters", class=format!("p-2 border rounded-lg border-slate-200 dark:border-slate-800 bg-slate-200 dark:bg-slate-700 transition-all ease-in {}", if *expand.get() { "h-40 visible" } else { "h-0 collapse" }, ) @@ -122,30 +122,38 @@ pub fn index_page( } pub fn get_template() -> Template { - Template::new("index") - .build_paths_fn(get_build_paths) + Template::build("index") + .head(head) .build_state_fn(get_build_state) - .template(index_page) + .build_paths_fn(get_build_paths) .incremental_generation() - .head(head) + .view_with_state(index_page) + .build() } -#[perseus::head] -pub fn head(_props: IndexPageState) -> View { - view! { +#[engine_only_fn] +fn head(cx: Scope) -> View { + view! {cx, title { "Fast Insiders" } } } -#[perseus::autoserde(build_state)] -pub async fn get_build_state( - path: String, - _locale: String, -) -> RenderFnResultWithCause { - let company_slug: String = path.clone().drain("index".len()..).collect(); +#[engine_only_fn] +async fn get_build_state( + StateGeneratorInfo { path, .. }: StateGeneratorInfo<()>, +) -> Result> { + let company_slug: String = path + .split("transactions") + .nth(1) + .unwrap_or(&("/".to_owned() + &path)) + .to_string(); Ok(IndexPageState { company_slug }) } -pub async fn get_build_paths() -> RenderFnResult> { - Ok(vec!["".to_string()]) +#[engine_only_fn] +async fn get_build_paths() -> BuildPaths { + BuildPaths { + paths: vec!["".to_string()], + extra: ().into(), + } } diff --git a/client/tests/index.rs b/client/tests/index.rs index 4157e9d..5bd0f35 100644 --- a/client/tests/index.rs +++ b/client/tests/index.rs @@ -1,10 +1,5 @@ -use fantoccini::{ - actions::{InputSource, KeyAction, KeyActions}, - error::CmdError, - Client, Locator, -}; +use fantoccini::{Client, Locator}; use perseus::wait_for_checkpoint; -use std::time::Duration; // This is is an E2E test with the following steps: // - Go to the index page @@ -27,12 +22,11 @@ async fn index(c: &mut Client) -> Result<(), fantoccini::error::CmdError> { let url = c.current_url().await?; assert!(url.as_ref().starts_with("http://localhost:8080")); - wait_for_checkpoint!("page_visible", 0, c); + wait_for_checkpoint!("page_interactive", 0, c); // Verify the page title let title = c.find(Locator::Css("title")).await?.html(false).await?; assert!(title.contains("Fast Insiders")); - wait_for_checkpoint!("page_interactive", 0, c); // let table = c.find(Locator::Css("table")).await?.html(true).await?; let filter_button = c.find(Locator::Css("#main button")).await?; filter_button.click().await?; @@ -50,10 +44,11 @@ async fn index(c: &mut Client) -> Result<(), fantoccini::error::CmdError> { search_button.click().await?; let page = c.current_url().await?; assert!( - page.as_ref().starts_with("http://localhost:8080/index/"), + page.as_ref().starts_with("http://localhost:8080/"), "Unexpected target url reached: {}", page ); + wait_for_checkpoint!("page_interactive", 1, c); for a in c.find_all(Locator::Css("table a")).await? { let a_text = a.text().await?; assert_eq!(clicked_company, a_text, "The clicked company is different from the target page list of companies, respectively {} and {}", clicked_company, a_text); @@ -70,7 +65,7 @@ async fn index(c: &mut Client) -> Result<(), fantoccini::error::CmdError> { assert_eq!(company_name, a_text, "The clicked company is different from the target page list of companies, respectively {} and {}", company_name, a_text); } assert!( - page.as_ref().starts_with("http://localhost:8080/index/"), + page.as_ref().starts_with("http://localhost:8080/"), "Unexpected target url reached: {}", page ); diff --git a/makefile b/makefile index 488c926..b60ea05 100644 --- a/makefile +++ b/makefile @@ -24,12 +24,8 @@ client-deploy: test-client: cd client && \ - perseus test -w + perseus test --show-browser test-server: cd server && \ cargo test - -test-client-cargo: - cd client && \ - PERSEUS_RUN_WASM_TESTS=true cargo test -- --test-threads 1 diff --git a/server/Cargo.toml b/server/Cargo.toml index ec74d3c..c4c9d88 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -8,7 +8,6 @@ edition = "2021" [dependencies] migration = { version = "0.1.0", path = "./migration" } chrono = { workspace = true, features = ["serde"] } -perseus = { version = "0.3.6", features = ["hydrate"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } dotenvy = { workspace = true } -- 2.36.3 From 163fe66ccbf6e19f2ce25d7b89c7cd590c364bc3 Mon Sep 17 00:00:00 2001 From: Miroito Date: Wed, 1 Mar 2023 12:47:44 +0100 Subject: [PATCH 2/4] Docker with perseus beta --- client/Dockerfile | 22 +++++++++------------- docker-compose.yml | 2 ++ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/client/Dockerfile b/client/Dockerfile index f956ab1..969589c 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -4,13 +4,13 @@ FROM rust:1.66-slim AS build # install build dependencies RUN apt update \ && apt install -y --no-install-recommends lsb-release apt-transport-https \ - build-essential curl wget pkg-config + build-essential curl wget pkg-config libssl-dev # vars -ENV PERSEUS_VERSION=0.3.6 \ +ENV PERSEUS_VERSION=0.4.0-beta.21 \ PERSEUS_SIZE_OPT_VERSION=0.1.9 \ ESBUILD_VERSION=0.14.7 \ - BINARYEN_VERSION=104 + BINARYEN_VERSION=112 # prepare root project dir WORKDIR /app @@ -32,24 +32,22 @@ WORKDIR /app/client RUN cargo install perseus-cli --version $PERSEUS_VERSION # clean and prep app -RUN perseus clean && perseus prep +RUN perseus clean # specify deps in app config RUN sed -i s"/perseus = .*/perseus = \"${PERSEUS_VERSION}\"/" ./Cargo.toml \ && sed -i s"/perseus-size-opt = .*/perseus-size-opt = \"${PERSEUS_SIZE_OPT_VERSION}\"/" ./Cargo.toml \ && cat ./Cargo.toml -# modify lib.rs -RUN sed -i s'/SizeOpts::default()/SizeOpts { wee_alloc: true, lto: true, opt_level: "s".to_string(), codegen_units: 1, enable_fluent_bundle_patch: false, }/' ./src/lib.rs \ - && cat ./src/lib.rs +# modify main.rs +RUN sed -i s'/SizeOpts::default()/SizeOpts { wee_alloc: true, lto: true, opt_level: "s".to_string(), codegen_units: 1, enable_fluent_bundle_patch: false, }/' ./src/main.rs \ + && cat ./src/main.rs ARG API_URL ENV API_URL $API_URL # run plugin(s) to adjust app -RUN perseus tinker \ - && cat .perseus/Cargo.toml \ - && cat ./src/lib.rs +RUN perseus tinker # single-threaded perseus CLI mode required for low memory environments #ENV PERSEUS_CLI_SEQUENTIAL=true @@ -75,8 +73,7 @@ RUN wget -nv https://github.com/WebAssembly/binaryen/releases/download/version_$ && ./binaryen-version_${BINARYEN_VERSION}/bin/wasm-opt --version # run wasm-opt against bundle.wasm -RUN ./binaryen-version_${BINARYEN_VERSION}/bin/wasm-opt -Os ./client/pkg/dist/pkg/perseus_engine_bg.wasm -o ./client/pkg/dist/pkg/perseus_engine_bg.wasm \ - && ls -lha ./client/pkg/dist/pkg +RUN ./binaryen-version_${BINARYEN_VERSION}/bin/wasm-opt -Os ./client/pkg/dist/pkg/perseus_engine_bg.wasm -o ./client/pkg/dist/pkg/perseus_engine_bg.wasm # prepare deployment image FROM debian:stable-slim @@ -88,4 +85,3 @@ COPY --from=build /app/client/pkg /app/ ENV HOST=0.0.0.0 CMD ./server - diff --git a/docker-compose.yml b/docker-compose.yml index e760152..c03b3a1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,6 +11,8 @@ services: restart: always ports: - 8080:8080 + environment: + - PERSEUS_HOST=0.0.0.0 server: container_name: fast-insiders-server image: fast-insiders-server:latest -- 2.36.3 From eeb3d2bc87dba5b58ecf6584113f3c2daea72e64 Mon Sep 17 00:00:00 2001 From: Miroito Date: Wed, 1 Mar 2023 13:00:03 +0100 Subject: [PATCH 3/4] fix/Page size bug --- client/src/components/paginated_data_table.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/client/src/components/paginated_data_table.rs b/client/src/components/paginated_data_table.rs index a9fd9fb..e3e7324 100644 --- a/client/src/components/paginated_data_table.rs +++ b/client/src/components/paginated_data_table.rs @@ -73,9 +73,7 @@ where }; let page_size_string = create_signal(cx, "20".to_string()); - let page_size_string2 = page_size_string.clone(); - //let props_ref = Rc::new(props); let props_sig = create_signal(cx, props); create_effect(cx, move || { let page = *page.get(); @@ -102,11 +100,11 @@ where class="p-2 justify-end text-slate-700 dark:text-slate-100 bg-slate-200 dark:bg-slate-800 rounded-md", id="size-select", ) { - option (value="20") { "20" } - option (value="10") { "10" } - option (value="30", selected=page_size_string2.get().eq(&Rc::new("30".to_string()))) { "30" } - option (value="40") { "40" } - option (value="50") { "50" } + option (value="10", selected=(*page_size_string.get()).eq("10")) { "10" } + option (value="20", selected=(*page_size_string.get()).eq("20")) { "20" } + option (value="30", selected=(*page_size_string.get()).eq("30")) { "30" } + option (value="40", selected=(*page_size_string.get()).eq("40")) { "40" } + option (value="50", selected=(*page_size_string.get()).eq("50")) { "50" } } div (class="flex flex-row p-2 bg-slate-200 dark:bg-slate-800 rounded-md") { button (on:click=page_down,class="m-1 hover:font-bold") { -- 2.36.3 From d0920196534c14823bdefa0b1d66df4925cecbee Mon Sep 17 00:00:00 2001 From: Miroito Date: Wed, 1 Mar 2023 13:47:57 +0100 Subject: [PATCH 4/4] update index test --- client/src/components/paginated_data_table.rs | 2 +- client/tests/index.rs | 56 ++++++++++++++++++- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/client/src/components/paginated_data_table.rs b/client/src/components/paginated_data_table.rs index e3e7324..f900175 100644 --- a/client/src/components/paginated_data_table.rs +++ b/client/src/components/paginated_data_table.rs @@ -106,7 +106,7 @@ where option (value="40", selected=(*page_size_string.get()).eq("40")) { "40" } option (value="50", selected=(*page_size_string.get()).eq("50")) { "50" } } - div (class="flex flex-row p-2 bg-slate-200 dark:bg-slate-800 rounded-md") { + div (id="page_buttons", class="flex flex-row p-2 bg-slate-200 dark:bg-slate-800 rounded-md") { button (on:click=page_down,class="m-1 hover:font-bold") { "<<" } diff --git a/client/tests/index.rs b/client/tests/index.rs index 5bd0f35..9cc54dc 100644 --- a/client/tests/index.rs +++ b/client/tests/index.rs @@ -3,6 +3,8 @@ use perseus::wait_for_checkpoint; // This is is an E2E test with the following steps: // - Go to the index page +// - Try all page sizes and verify that they are respected +// - Try to go to page 2 // - Use the async select component to find any company // - Click on this company and verify that we arrived // - Come back to the root using the top left link @@ -12,9 +14,7 @@ use perseus::wait_for_checkpoint; // Run like this: // - Run any headless browser drive like geckodriver // - Run perseus test -// - The backend should be available with some data -// - run PERSEUS_RUN_WASM_TESTS=true cargo test -- --test-threads 1 -// (or use make test-client-cargo) +// - The backend should be available with at least 11 saved transactions #[perseus::test] async fn index(c: &mut Client) -> Result<(), fantoccini::error::CmdError> { c.goto("http://localhost:8080").await?; @@ -27,6 +27,56 @@ async fn index(c: &mut Client) -> Result<(), fantoccini::error::CmdError> { let title = c.find(Locator::Css("title")).await?.html(false).await?; assert!(title.contains("Fast Insiders")); + // Verify that the default table size is 20 + let page_size_select = c.find(Locator::Css("#size-select")).await?; + let default_page_size = page_size_select + .prop("value") + .await? + .expect("The value prop must be set"); + assert_eq!(default_page_size.parse::().unwrap(), 20); + + // Test all page sizes + let page_sizes = [20, 30, 40, 50, 10].iter(); + for page_size in page_sizes { + let page_size_select = c.find(Locator::Css("#size-select")).await?; + page_size_select + .select_by_value(&page_size.to_string()) + .await?; + + let table_rows = c.find_all(Locator::Css("table tr")).await?.iter().count(); + let page_size_select = c.find(Locator::Css("#size-select")).await?; + let browser_page_size = page_size_select + .prop("value") + .await? + .expect("The value prop must be set"); + assert_eq!(browser_page_size.parse::().unwrap(), *page_size); + assert_eq!(table_rows, page_size + 1); // The header also counts as a table row + } + + // Verify that we can change pages + let page_buttons = c.find_all(Locator::Css("#page_buttons button")).await?; + assert_eq!(page_buttons[0].text().await?, "<<"); + assert_eq!(page_buttons[1].text().await?, ">>"); + let page_numbers = c + .find(Locator::Css("#page_buttons div")) + .await? + .text() + .await? + .split("/") + .map(|x| x.parse().unwrap()) + .collect::>(); + assert_eq!(page_numbers[0], 1); + page_buttons[1].click().await?; + let new_page_numbers = c + .find(Locator::Css("#page_buttons div")) + .await? + .text() + .await? + .split("/") + .map(|x| x.parse().unwrap()) + .collect::>(); + assert_eq!(new_page_numbers[0], page_numbers[0] + 1); + // let table = c.find(Locator::Css("table")).await?.html(true).await?; let filter_button = c.find(Locator::Css("#main button")).await?; filter_button.click().await?; -- 2.36.3