From 81569f89b9681a14e977a298b8301213d8254ab3 Mon Sep 17 00:00:00 2001 From: Ben Burdette Date: Wed, 7 Aug 2024 06:53:49 -0600 Subject: [PATCH 01/34] invoice command --- Cargo.lock | 1730 +++++++++++++++++++++++++++++++++++++-- elm/src/Data.elm | 10 + elm/src/Main.elm | 13 + elm/src/ProjectTime.elm | 16 +- flake.lock | 42 +- flake.nix | 5 +- server/Cargo.toml | 1 + server/config.toml | 2 +- server/src/config.rs | 1 + server/src/main.rs | 65 +- server/src/messages.rs | 6 + 11 files changed, 1817 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 340170a..0f6c357 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,7 +52,7 @@ dependencies = [ "actix-rt", "actix-service", "actix-utils", - "ahash 0.8.3", + "ahash 0.8.11", "base64 0.21.2", "bitflags 1.3.2", "brotli", @@ -207,7 +207,7 @@ dependencies = [ "serde_urlencoded", "smallvec", "socket2", - "time 0.3.22", + "time 0.3.36", "url", ] @@ -277,14 +277,15 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -347,6 +348,27 @@ version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "arrayref" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "askama_escape" version = "0.10.3" @@ -361,7 +383,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.72", ] [[package]] @@ -381,6 +403,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" + [[package]] name = "barrel" version = "0.7.0" @@ -411,6 +439,49 @@ version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "biblatex" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27fe7285040d0227cd8b5395e1c4783f44f0b673eca5a657f4432ae401f2b7b8" +dependencies = [ + "numerals", + "paste", + "strum", + "unicode-normalization", + "unscanny", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -419,9 +490,12 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] [[package]] name = "block-buffer" @@ -459,6 +533,24 @@ version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" + +[[package]] +name = "bytemuck" +version = "1.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.4.0" @@ -489,6 +581,24 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chinese-number" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49fccaef6346f6d6a741908d3b79fe97c2debe2fbb5eb3a7d00ff5981b52bb6c" +dependencies = [ + "chinese-variant", + "enum-ordinalize", + "num-bigint", + "num-traits", +] + +[[package]] +name = "chinese-variant" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7588475145507237ded760e52bf2f1085495245502033756d28ea72ade0e498b" + [[package]] name = "chrono" version = "0.4.26" @@ -504,6 +614,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "cipher" version = "0.4.4" @@ -514,6 +651,16 @@ dependencies = [ "inout", ] +[[package]] +name = "citationberg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d259fe9fd78ffa05a119581d20fddb50bfba428311057b12741ffb9015123d0b" +dependencies = [ + "quick-xml 0.31.0", + "serde", +] + [[package]] name = "clap" version = "2.34.0" @@ -538,6 +685,41 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "comemo" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df6916408a724339aa77b18214233355f3eb04c42eb895e5f8909215bd8a7a91" +dependencies = [ + "comemo-macros", + "once_cell", + "parking_lot", + "siphasher 1.0.1", +] + +[[package]] +name = "comemo-macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8936e42f9b4f5bdfaf23700609ac1f11cb03ad4c1ec128a4ee4fd0903e228db" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "commoncrypto" version = "0.2.0" @@ -582,7 +764,7 @@ dependencies = [ "rand 0.8.5", "sha2", "subtle", - "time 0.3.22", + "time 0.3.36", "version_check", ] @@ -602,6 +784,15 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +[[package]] +name = "core_maths" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b02505ccb8c50b0aa21ace0fc08c3e53adebd4e58caa18a36152803c7709a3" +dependencies = [ + "libm", +] + [[package]] name = "cpufeatures" version = "0.2.8" @@ -620,6 +811,37 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -643,6 +865,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + [[package]] name = "ctr" version = "0.9.2" @@ -652,6 +895,21 @@ dependencies = [ "cipher", ] +[[package]] +name = "data-url" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -682,6 +940,32 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "ecow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54bfbb1708988623190a6c4dbedaeaf0f53c20c6395abd6a01feb327b3146f4b" +dependencies = [ + "serde", +] + [[package]] name = "either" version = "1.8.1" @@ -704,6 +988,12 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112" +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + [[package]] name = "encoding_rs" version = "0.8.32" @@ -713,6 +1003,26 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-ordinalize" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "env_logger" version = "0.5.13" @@ -726,6 +1036,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.3.1" @@ -759,6 +1075,22 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" +[[package]] +name = "fancy-regex" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" +dependencies = [ + "bit-set", + "regex", +] + +[[package]] +name = "fast-srgb8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" + [[package]] name = "fastrand" version = "1.9.0" @@ -768,6 +1100,15 @@ dependencies = [ "instant", ] +[[package]] +name = "fdeflate" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +dependencies = [ + "simd-adler32", +] + [[package]] name = "flate2" version = "1.0.26" @@ -778,12 +1119,30 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "fontdb" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3" +dependencies = [ + "log", + "slotmap", + "tinyvec", + "ttf-parser", +] + [[package]] name = "foreign-types" version = "0.3.2" @@ -890,6 +1249,16 @@ dependencies = [ "polyval", ] +[[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "h2" version = "0.3.19" @@ -902,13 +1271,23 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -917,11 +1296,11 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.11", "allocator-api2", ] @@ -931,29 +1310,62 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f" dependencies = [ - "hashbrown 0.14.0", + "hashbrown 0.14.5", ] [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "hayagriva" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "1d0d20c98b77b86ce737876b2a1653e2e6abbeee84afbb39d72111091191c97a" dependencies = [ - "libc", + "biblatex", + "ciborium", + "citationberg", + "indexmap 2.3.0", + "numerals", + "paste", + "serde", + "serde_yaml", + "thiserror", + "unic-langid", + "unicode-segmentation", + "unscanny", + "url", ] [[package]] -name = "hermit-abi" -version = "0.2.6" +name = "heck" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] -name = "hermit-abi" +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" @@ -1031,6 +1443,12 @@ dependencies = [ "quick-error", ] +[[package]] +name = "hypher" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b24ad5637230df201ab1034d593f1d09bf7f2a9274f2e8897638078579f4265" + [[package]] name = "iana-time-zone" version = "0.1.57" @@ -1054,6 +1472,154 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "serde", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "serde", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "postcard", + "serde", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_adapters" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6324dfd08348a8e0374a447ebd334044d766b1839bb8d5ccf2482a99a77c0bc" +dependencies = [ + "icu_locid", + "icu_locid_transform", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_provider_blob" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c24b98d1365f55d78186c205817631a4acf08d7a45bdf5dc9dcf9c5d54dccf51" +dependencies = [ + "icu_provider", + "postcard", + "serde", + "writeable", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "icu_segmenter" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a717725612346ffc2d7b42c94b820db6908048f39434504cb130e8b46256b0de" +dependencies = [ + "core_maths", + "displaydoc", + "icu_collections", + "icu_locid", + "icu_provider", + "icu_segmenter_data", + "serde", + "utf8_iter", + "zerovec", +] + +[[package]] +name = "icu_segmenter_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f739ee737260d955e330bc83fdeaaf1631f7fb7ed218761d3c04bb13bb7d79df" + [[package]] name = "idna" version = "0.3.0" @@ -1074,6 +1640,33 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "if_chain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" + +[[package]] +name = "image" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "gif", + "jpeg-decoder", + "num-traits", + "png", +] + +[[package]] +name = "imagesize" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284" + [[package]] name = "indexmap" version = "1.9.3" @@ -1084,6 +1677,23 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "indexmap" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", + "serde", +] + +[[package]] +name = "indexmap-nostd" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" + [[package]] name = "inout" version = "0.1.3" @@ -1128,6 +1738,12 @@ dependencies = [ "libc", ] +[[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" + [[package]] name = "js-sys" version = "0.3.64" @@ -1143,6 +1759,24 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" +[[package]] +name = "kamadak-exif" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef4fc70d0ab7e5b6bafa30216a6b48705ea964cdfc29c050f2412295eba58077" +dependencies = [ + "mutate_once", +] + +[[package]] +name = "kurbo" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd85a5776cd9500c2e2059c8c76c3b01528566b7fcbaf8098b55a33fc298849b" +dependencies = [ + "arrayvec", +] + [[package]] name = "language-tags" version = "0.3.2" @@ -1184,6 +1818,12 @@ version = "0.2.146" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "libsqlite3-sys" version = "0.26.0" @@ -1194,12 +1834,37 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-raw-sys" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +[[package]] +name = "lipsum" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "636860251af8963cc40f6b4baadee105f02e21b28131d76eba8e40ce84ab8064" +dependencies = [ + "rand 0.8.5", + "rand_chacha", +] + +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +dependencies = [ + "serde", +] + [[package]] name = "local-channel" version = "0.1.3" @@ -1275,6 +1940,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", + "simd-adler32", ] [[package]] @@ -1289,6 +1955,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mutate_once" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16cf681a23b4d0a43fc35024c176437f9dcd818db34e0f42ab456a0ee5ad497b" + [[package]] name = "native-tls" version = "0.2.11" @@ -1317,11 +1989,36 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -1336,6 +2033,12 @@ dependencies = [ "libc", ] +[[package]] +name = "numerals" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e25be21376a772d15f97ae789845340a9651d3c4246ff5ebb6a2b35f9c37bd31" + [[package]] name = "once_cell" version = "1.18.0" @@ -1371,7 +2074,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.72", ] [[package]] @@ -1420,6 +2123,30 @@ dependencies = [ "uuid", ] +[[package]] +name = "palette" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" +dependencies = [ + "approx", + "fast-srgb8", + "libm", + "palette_derive", +] + +[[package]] +name = "palette_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" +dependencies = [ + "by_address", + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -1445,9 +2172,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.12" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "percent-encoding" @@ -1455,6 +2182,54 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -1473,6 +2248,32 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "plist" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" +dependencies = [ + "base64 0.22.1", + "indexmap 2.3.0", + "quick-xml 0.32.0", + "serde", + "time 0.3.36", +] + +[[package]] +name = "png" +version = "0.17.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "polyval" version = "0.6.1" @@ -1485,6 +2286,29 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "portable-atomic" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" + +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "embedded-io", + "serde", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1499,13 +2323,28 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + +[[package]] +name = "qcms" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edecfcd5d755a5e5d98e24cf43113e7cdaec5a070edd0f6b250c03a573da30fa" + [[package]] name = "quick-error" version = "1.2.3" @@ -1513,12 +2352,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] -name = "quote" -version = "1.0.28" +name = "quick-xml" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" dependencies = [ - "proc-macro2", + "memchr", + "serde", +] + +[[package]] +name = "quick-xml" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", ] [[package]] @@ -1585,6 +2443,26 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.3.5" @@ -1602,7 +2480,7 @@ checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.7.2", ] [[package]] @@ -1611,13 +2489,25 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "roxmltree" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" + [[package]] name = "rusqlite" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" dependencies = [ - "bitflags 2.3.2", + "bitflags 2.6.0", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -1657,12 +2547,43 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "rustybuzz" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0ae5692c5beaad6a9e22830deeed7874eae8a4e3ba4076fb48e12c56856222c" +dependencies = [ + "bitflags 2.6.0", + "bytemuck", + "smallvec", + "ttf-parser", + "unicode-bidi-mirroring", + "unicode-ccc", + "unicode-properties", + "unicode-script", +] + [[package]] name = "ryu" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.21" @@ -1724,19 +2645,22 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.164" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +dependencies = [ + "serde_derive", +] [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.72", ] [[package]] @@ -1750,6 +2674,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1762,6 +2695,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.3.0", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sha1" version = "0.6.1" @@ -1808,12 +2754,39 @@ dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "simple-error" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc47a29ce97772ca5c927f75bac34866b16d64e07f330c3248e2d7226623901b" +[[package]] +name = "simplecss" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a11be7c62927d9427e9f40f3444d5499d868648e2edbc4e2116de69e7ec0e89d" +dependencies = [ + "log", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.8" @@ -1823,11 +2796,20 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + [[package]] name = "smallvec" -version = "1.10.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" @@ -1839,6 +2821,31 @@ dependencies = [ "winapi", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stacker" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "winapi", +] + [[package]] name = "standback" version = "0.2.17" @@ -1897,18 +2904,59 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +dependencies = [ + "float-cmp", +] + [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.72", +] + [[package]] name = "subtle" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "svgtypes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e44e288cd960318917cbd540340968b90becc8bc81f171345d706e7a89d9d70" +dependencies = [ + "kurbo", + "siphasher 0.3.11", +] + [[package]] name = "syn" version = "1.0.109" @@ -1922,15 +2970,48 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.18" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "syntect" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1" +dependencies = [ + "bincode", + "bitflags 1.3.2", + "fancy-regex", + "flate2", + "fnv", + "once_cell", + "plist", + "regex-syntax 0.8.4", + "serde", + "serde_derive", + "serde_json", + "thiserror", + "walkdir", + "yaml-rust", +] + [[package]] name = "tempfile" version = "3.6.0" @@ -1963,6 +3044,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "time" version = "0.1.45" @@ -1991,21 +3092,24 @@ dependencies = [ [[package]] name = "time" -version = "0.3.22" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ + "deranged", "itoa", + "num-conv", + "powerfmt", "serde", "time-core", - "time-macros 0.2.9", + "time-macros 0.2.18", ] [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" @@ -2019,10 +3123,11 @@ dependencies = [ [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -2065,6 +3170,7 @@ dependencies = [ "time 0.2.27", "timer", "toml 0.4.10", + "typst", "uuid", ] @@ -2077,6 +3183,28 @@ dependencies = [ "chrono", ] +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "serde", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -2141,6 +3269,40 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +dependencies = [ + "indexmap 2.3.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tracing" version = "0.1.37" @@ -2162,12 +3324,163 @@ dependencies = [ "once_cell", ] +[[package]] +name = "ttf-parser" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" + +[[package]] +name = "two-face" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37bed2135b2459c7eefba72c906d374697eb15949c205f2f124e3636a46b5eeb" +dependencies = [ + "once_cell", + "serde", + "syntect", +] + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + [[package]] name = "typenum" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "typst" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12492297d20937494f0143ae50ef339e5fd3d927b4096af1c52fe73fb9c5fa9a" +dependencies = [ + "az", + "bitflags 2.6.0", + "chinese-number", + "ciborium", + "comemo", + "csv", + "ecow", + "fontdb", + "hayagriva", + "hypher", + "icu_properties", + "icu_provider", + "icu_provider_adapters", + "icu_provider_blob", + "icu_segmenter", + "if_chain", + "image", + "indexmap 2.3.0", + "kamadak-exif", + "kurbo", + "lipsum", + "log", + "once_cell", + "palette", + "phf", + "png", + "portable-atomic", + "qcms", + "rayon", + "regex", + "roxmltree", + "rustybuzz", + "serde", + "serde_json", + "serde_yaml", + "siphasher 1.0.1", + "smallvec", + "stacker", + "syntect", + "time 0.3.36", + "toml 0.8.19", + "ttf-parser", + "two-face", + "typed-arena", + "typst-assets", + "typst-macros", + "typst-syntax", + "typst-timing", + "unicode-bidi", + "unicode-math-class", + "unicode-script", + "unicode-segmentation", + "usvg", + "wasmi", +] + +[[package]] +name = "typst-assets" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b3061f8d268e8eec7481c9ab24540455cb4912983c49aae38fa6e8bf8ef4d9c" + +[[package]] +name = "typst-macros" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a0fdfd46b4920b0f8e4215e5b8438c737e8bc3498a681ea59b0130228363fc" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "typst-syntax" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3db69f2f41613b1ff6edbec44fd7dc524137f099ee36c46f560cedeaadb40c4" +dependencies = [ + "comemo", + "ecow", + "once_cell", + "serde", + "unicode-ident", + "unicode-math-class", + "unicode-script", + "unicode-segmentation", + "unscanny", +] + +[[package]] +name = "typst-timing" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b58e17192bcacb2a39aace6d3eece70f008b2949ce384ac501a58357fafee67" +dependencies = [ + "parking_lot", + "serde", + "serde_json", + "typst-syntax", +] + +[[package]] +name = "unic-langid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dd9d1e72a73b25e07123a80776aae3e7b0ec461ef94f9151eed6ec88005a44" +dependencies = [ + "unic-langid-impl", +] + +[[package]] +name = "unic-langid-impl" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a5422c1f65949306c99240b81de9f3f15929f5a8bfe05bb44b034cc8bf593e5" +dependencies = [ + "serde", + "tinystr", +] + [[package]] name = "unicase" version = "2.6.0" @@ -2183,12 +3496,30 @@ version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +[[package]] +name = "unicode-bidi-mirroring" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56d12260fb92d52f9008be7e4bca09f584780eb2266dc8fecc6a192bec561694" + +[[package]] +name = "unicode-ccc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2520efa644f8268dce4dcd3050eaa7fc044fca03961e9998ac7e2e92b77cf1" + [[package]] name = "unicode-ident" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +[[package]] +name = "unicode-math-class" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d246cf599d5fae3c8d56e04b20eb519adb89a8af8d0b0fbcded369aa3647d65" + [[package]] name = "unicode-normalization" version = "0.1.22" @@ -2198,6 +3529,30 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" + +[[package]] +name = "unicode-script" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8d71f5726e5f285a935e9fe8edfd53f0491eb6e9a5774097fdabee7cd8c9cd" + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-vo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" + [[package]] name = "unicode-width" version = "0.1.10" @@ -2214,6 +3569,18 @@ dependencies = [ "subtle", ] +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "unscanny" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9df2af067a7953e9c3831320f35c1cc0600c30d44d9f7a12b01db1cd88d6b47" + [[package]] name = "url" version = "2.4.0" @@ -2223,8 +3590,75 @@ dependencies = [ "form_urlencoded", "idna 0.4.0", "percent-encoding", + "serde", +] + +[[package]] +name = "usvg" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "377f62b4a3c173de8654c1aa80ab1dac1154e6f13a779a9943e53780120d1625" +dependencies = [ + "base64 0.21.2", + "log", + "pico-args", + "usvg-parser", + "usvg-text-layout", + "usvg-tree", + "xmlwriter", +] + +[[package]] +name = "usvg-parser" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "351a05e6f2023d6b4e946f734240a3927aefdcf930d7d42587a2c8a8869814b0" +dependencies = [ + "data-url", + "flate2", + "imagesize", + "kurbo", + "log", + "roxmltree", + "simplecss", + "siphasher 0.3.11", + "svgtypes", + "usvg-tree", ] +[[package]] +name = "usvg-text-layout" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c41888b9d5cf431fe852eaf9d047bbde83251b98f1749c2f08b1071e6db46e2" +dependencies = [ + "fontdb", + "kurbo", + "log", + "rustybuzz", + "unicode-bidi", + "unicode-script", + "unicode-vo", + "usvg-tree", +] + +[[package]] +name = "usvg-tree" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18863e0404ed153d6e56362c5b1146db9f4f262a3244e3cf2dbe7d8a85909f05" +dependencies = [ + "strict-num", + "svgtypes", + "tiny-skia-path", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "uuid" version = "0.8.2" @@ -2253,6 +3687,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" @@ -2286,7 +3730,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.72", "wasm-bindgen-shared", ] @@ -2308,7 +3752,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2319,6 +3763,52 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +[[package]] +name = "wasmi" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8281d1d660cdf54c76a3efa9ddd0c270cada1383a995db3ccb43d166456c7" +dependencies = [ + "smallvec", + "spin", + "wasmi_arena", + "wasmi_core", + "wasmparser-nostd", +] + +[[package]] +name = "wasmi_arena" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" + +[[package]] +name = "wasmi_core" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf1a7db34bff95b85c261002720c00c3a6168256dcb93041d3fa2054d19856a" +dependencies = [ + "downcast-rs", + "libm", + "num-traits", + "paste", +] + +[[package]] +name = "wasmparser-nostd" +version = "0.100.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa" +dependencies = [ + "indexmap-nostd", +] + +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + [[package]] name = "winapi" version = "0.3.9" @@ -2482,6 +3972,136 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "winnow" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +dependencies = [ + "memchr", +] + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "xmlwriter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb594dd55d87335c5f60177cee24f19457a5ec10a065e0a3014722ad252d0a1f" +dependencies = [ + "displaydoc", + "litemap", + "serde", + "zerovec", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "serde", + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "zstd" version = "0.12.3+zstd.1.5.2" diff --git a/elm/src/Data.elm b/elm/src/Data.elm index 1deacad..cd9a965 100644 --- a/elm/src/Data.elm +++ b/elm/src/Data.elm @@ -38,6 +38,7 @@ module Data exposing , decodeSavedProjectEdit , decodeTimeEntry , decodeUser + , encodePrintInvoice , encodeRole , encodeSaveAllocation , encodeSavePayEntry @@ -326,6 +327,15 @@ type alias ProjectTime = } +type alias PrintInvoice = + { info : String } + + +encodePrintInvoice : PrintInvoice -> JE.Value +encodePrintInvoice i = + JE.string i.info + + ------------------------------------------- -- Id types. They're all ints underneath. diff --git a/elm/src/Main.elm b/elm/src/Main.elm index 5edeb80..6a6e8c4 100644 --- a/elm/src/Main.elm +++ b/elm/src/Main.elm @@ -81,6 +81,7 @@ type Msg | ProjectTimeData String (Result Http.Error TI.ServerResponse) | ProjectViewData String (Result Http.Error PI.ServerResponse) | TProjectViewData String (Result Http.Error TI.ServerResponse) + | PrintInvoiceReplyData (Result Http.Error ()) | LoadUrl String | InternalUrl Url | SelectedText JD.Value @@ -499,6 +500,9 @@ showMessage msg = ClockTick _ -> "ClockTick" + PrintInvoiceReplyData _ -> + "PrintInvoiceReplyData" + showState : State -> String showState state = @@ -2071,6 +2075,15 @@ handleProjectTime model ( nm, cmd ) login = ProjectTime.ToClipboard text -> ( { model | state = ProjectTime nm login }, toClipBoard text ) + ProjectTime.PrintInvoice text -> + ( { model | state = ProjectTime nm login } + , Http.post + { url = model.location ++ "/invoice" + , body = Http.jsonBody (Data.encodePrintInvoice { info = text }) + , expect = Http.expectWhatever PrintInvoiceReplyData + } + ) + handleProjectView : Model -> ( ProjectView.Model, ProjectView.Command ) -> Maybe Data.LoginData -> ( Model, Cmd Msg ) handleProjectView model ( nm, cmd ) mblogin = diff --git a/elm/src/ProjectTime.elm b/elm/src/ProjectTime.elm index 6ddf758..6d9bfe1 100644 --- a/elm/src/ProjectTime.elm +++ b/elm/src/ProjectTime.elm @@ -82,6 +82,7 @@ type Msg | ClearDistribution | CalcDistribution | ToClipboardMsg String + | PrintInvoiceMsg String | OnPaymentChanged UserId String | AddPaymentPress UserId Int Data.PayType | AddPayment UserId Int Data.PayType Int @@ -192,6 +193,7 @@ type Command | ShowError String | SelectMember (List Data.User) | ToClipboard String + | PrintInvoice String | None @@ -2005,9 +2007,14 @@ distributionview ld size zone model = |> String.concat ) in - EI.button Common.buttonStyle - { onPress = Just <| ToClipboardMsg textdist, label = E.text "⧉" } - |> E.el [ E.centerY ] + E.row [] + [ EI.button Common.buttonStyle + { onPress = Just <| ToClipboardMsg textdist, label = E.text "⧉" } + |> E.el [ E.centerY ] + , EI.button Common.buttonStyle + { onPress = Just <| PrintInvoiceMsg textdist, label = E.text "pdf invoice" } + |> E.el [ E.centerY ] + ] , width = E.shrink , view = \( user, hours ) -> @@ -3852,6 +3859,9 @@ update msg model ld zone = ToClipboardMsg text -> ( model, ToClipboard text ) + PrintInvoiceMsg text -> + ( model, PrintInvoice text ) + DonePress -> ( model, Done ) diff --git a/flake.lock b/flake.lock index bb2d27b..22597b0 100644 --- a/flake.lock +++ b/flake.lock @@ -1,12 +1,15 @@ { "nodes": { "flake-utils": { + "inputs": { + "systems": "systems" + }, "locked": { - "lastModified": 1667395993, - "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -20,11 +23,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1671096816, - "narHash": "sha256-ezQCsNgmpUHdZANDCILm3RvtO1xH8uujk/+EqNvzIOg=", + "lastModified": 1721727458, + "narHash": "sha256-r/xppY958gmZ4oTfLiHN0ZGuQ+RSTijDblVgVLFi1mw=", "owner": "nmattia", "repo": "naersk", - "rev": "d998160d6a076cfe8f9741e56aeec7e267e3e114", + "rev": "3fb418eaf352498f6b6c30592e3beb63df42ef11", "type": "github" }, "original": { @@ -35,11 +38,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1671249438, - "narHash": "sha256-5e+CcnbZA3/i2BRXbnzRS52Ly67MUNdZR+Zpbb2C65k=", + "lastModified": 1722926584, + "narHash": "sha256-sLA+lfCxTkXf4o3JVxcfe+w9kAzauGfEnJ9roNbNng8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "067bfc6c90a301572cec7da48f09c447a9a8eae0", + "rev": "d33cf80b603b3d0cddb48f9816cae707a59e2334", "type": "github" }, "original": { @@ -49,11 +52,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1671249438, - "narHash": "sha256-5e+CcnbZA3/i2BRXbnzRS52Ly67MUNdZR+Zpbb2C65k=", + "lastModified": 1722926584, + "narHash": "sha256-sLA+lfCxTkXf4o3JVxcfe+w9kAzauGfEnJ9roNbNng8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "067bfc6c90a301572cec7da48f09c447a9a8eae0", + "rev": "d33cf80b603b3d0cddb48f9816cae707a59e2334", "type": "github" }, "original": { @@ -67,6 +70,21 @@ "naersk": "naersk", "nixpkgs": "nixpkgs_2" } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 783381a..ec1e081 100644 --- a/flake.nix +++ b/flake.nix @@ -45,7 +45,7 @@ cargo rustc sqlite - pkgconfig + pkg-config openssl.dev ]; }; @@ -79,13 +79,14 @@ # `nix develop` devShell = pkgs.mkShell { nativeBuildInputs = with pkgs; [ + typst cargo cargo-watch rustc rustfmt rust-analyzer sqlite - pkgconfig + pkg-config openssl.dev elm2nix elmPackages.elm diff --git a/server/Cargo.toml b/server/Cargo.toml index 57a0279..106e35e 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -30,3 +30,4 @@ clap = "2.33.2" timer = "0.2.0" chrono = "0.4.26" either = "1.6.1" +typst = "0.11.1" diff --git a/server/config.toml b/server/config.toml index 4c8bf6f..d8da4b0 100644 --- a/server/config.toml +++ b/server/config.toml @@ -14,5 +14,5 @@ email_token_expiration_ms = 86400000 reset_token_expiration_ms = 86400000 invite_token_expiration_ms = 86400000 static_path = "./static/" -open_registration = false +open_registration = true non_admin_invite = true diff --git a/server/src/config.rs b/server/src/config.rs index 4addf78..234530d 100644 --- a/server/src/config.rs +++ b/server/src/config.rs @@ -7,5 +7,6 @@ pub struct Config { pub ip: String, pub port: u16, pub static_path: Option, + pub invoice_template: Option, pub orgauth_config: orgauth_data::Config, } diff --git a/server/src/main.rs b/server/src/main.rs index a00f22e..c4fac8f 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -14,7 +14,7 @@ use actix_web::{ use clap::Arg; use config::Config; use log::{error, info}; -use messages::{PublicMessage, ServerResponse, UserMessage}; +use messages::{PublicMessage, ServerResponse, UserMessage, Invoice}; use orgauth::data::WhatMessage; use orgauth::endpoints::Callbacks; use serde_json; @@ -24,6 +24,8 @@ use std::path::PathBuf; use std::str::FromStr; use timer; use uuid::Uuid; +use typst; +use typst::world; /* use actix_files::NamedFile; @@ -254,6 +256,7 @@ fn defcon() -> Config { ip: "127.0.0.1".to_string(), port: 8000, static_path: None, + invoice_template: None, orgauth_config: oc, } } @@ -372,6 +375,7 @@ async fn err_main() -> Result<(), Box> { .service(web::resource("/admin").route(web::post().to(admin))) .service(web::resource(r"/register/{uid}/{key}").route(web::get().to(register))) .service(web::resource(r"/newemail/{uid}/{token}").route(web::get().to(new_email))) + .service(web::resource(r"/invoice").route(web::post().to(invoice))) .service(actix_files::Files::new("/static/", staticpath)) .service(web::resource("/{tail:.*}").route(web::get().to(mainpage))) }) @@ -383,3 +387,62 @@ async fn err_main() -> Result<(), Box> { } } } +async fn invoice(session: Session, config: web::Data, + item: web::Json, + req: HttpRequest) -> HttpResponse { + + typst::world::SystemWorld + + typst::compile("blah"); + + // let conn = match sqldata::connection_open(config.orgauth_config.db.as_path()) { + // Ok(c) => c, + // Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)), + // }; + + // let suser = match session_user(&conn, session, &config) { + // Ok(Either::Left(user)) => Some(user), + // Ok(Either::Right(_sr)) => None, + // Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)), + // }; + + // let uid = suser.map(|user| user.id); + + // match req + // .match_info() + // .get("id") + // // .and_then(|s| s.parse::().ok()) + // { + // Some(noteid) => { + // let uuid = match Uuid::parse_str(noteid) { + // Ok(id) => id, + // Err(e) => return HttpResponse::BadRequest().body(e.to_string()) + // }; + // let nid = match sqldata::note_id_for_uuid(&conn, &uuid) { + // Ok(id) => id, + // Err(e) => return HttpResponse::NotFound().body(e.to_string()) + // }; + // let hash = match sqldata::read_zknote_filehash(&conn, uid, nid) { + // Ok(Some(hash)) => hash, + // Ok(None) => return HttpResponse::NotFound().body("not found"), + // Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)), + // }; + + // let zkln = match sqldata::read_zklistnote(&conn, &config.file_path, uid, nid) { + // Ok(zkln) => zkln, + // Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)), + // }; + + // let stpath = config.file_path.join(hash); + + // match File::open(stpath).and_then(|f| NamedFile::from_file(f, Path::new(zkln.title.as_str()))) + // { + // Ok(f) => f.into_response(&req), + // Err(e) => HttpResponse::NotFound().body(format!("{:?}", e)), + // } + // } + // None => HttpResponse::BadRequest().body("file id required: /file/"), + // } + HttpResponse::Ok().body("") +} + diff --git a/server/src/messages.rs b/server/src/messages.rs index 69d2e21..f1216e6 100644 --- a/server/src/messages.rs +++ b/server/src/messages.rs @@ -18,3 +18,9 @@ pub struct PublicMessage { pub what: String, pub data: Option, } + +#[derive(Deserialize, Serialize, Debug)] +pub struct Invoice { + pub info: String, +} + From f4a04dd1063e64f6a67364623e95aa9adfc97a70 Mon Sep 17 00:00:00 2001 From: Ben Burdette Date: Wed, 7 Aug 2024 07:37:20 -0600 Subject: [PATCH 02/34] getting going on generating --- server/src/data.rs | 5 + server/src/main.rs | 237 ++++++++++++++++++++++++++++++++++++++++- server/src/messages.rs | 6 -- 3 files changed, 239 insertions(+), 9 deletions(-) diff --git a/server/src/data.rs b/server/src/data.rs index 3f4b9d2..add13dc 100644 --- a/server/src/data.rs +++ b/server/src/data.rs @@ -216,3 +216,8 @@ pub struct SaveAllocation { pub allocationdate: i64, pub description: String, } + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct PrintInvoice { + pub info: String, +} diff --git a/server/src/main.rs b/server/src/main.rs index c4fac8f..073cbf3 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -14,7 +14,7 @@ use actix_web::{ use clap::Arg; use config::Config; use log::{error, info}; -use messages::{PublicMessage, ServerResponse, UserMessage, Invoice}; +use messages::{PublicMessage, ServerResponse, UserMessage}; use orgauth::data::WhatMessage; use orgauth::endpoints::Callbacks; use serde_json; @@ -25,7 +25,7 @@ use std::str::FromStr; use timer; use uuid::Uuid; use typst; -use typst::world; +use data::PrintInvoice; /* use actix_files::NamedFile; @@ -388,7 +388,7 @@ async fn err_main() -> Result<(), Box> { } } async fn invoice(session: Session, config: web::Data, - item: web::Json, + item: web::Json, req: HttpRequest) -> HttpResponse { typst::world::SystemWorld @@ -446,3 +446,234 @@ async fn invoice(session: Session, config: web::Data, HttpResponse::Ok().body("") } +pub fn invoice( + conn: &Connection, + uid: i64, + savedir: &Path, + printInvoice: PrintInvoice, +) -> Result { + + + + let mut child = Command::new("typst") + .arg("compile") + .arg(format!("-o{}/%(title)s-%(id)s.%(ext)s", savedir.display())) + .arg(yeet.url.clone()) + .spawn() + .expect("youtube-dl failed to execute"); + + match child.wait() { + Ok(exit_code) => { + if exit_code.success() { + // find the yeeted file by 'v'. + let file: PathBuf = match glob::glob(format!("{}/*{}*", savedir.display(), hv.v).as_str()) { + Ok(mut paths) => match paths.next() { + Some(rpb) => match rpb { + Ok(pb) => pb, + Err(e) => return Err(orgauth::error::Error::String(format!("glob error {:?}", e))), + }, + None => { + return Err(orgauth::error::Error::String(format!( + "yeet file not found {:?}", + hv.v + ))) + } + }, + Err(e) => return Err(orgauth::error::Error::String(format!("glob error {:?}", e))), + }; + let filename = file + .as_path() + .file_name() + .and_then(|x| x.to_str()) + .unwrap_or("meh.txt") + .to_string(); + let (noteid, fid) = make_file_note(&conn, uid, &filename, file.as_path())?; + + // yeetfile table entry. + conn.execute( + "insert into yeetfile (yeetkey, audio, filename, fileid) + values (?1, ?2, ?3, ?4)", + params![hv.v, true, filename, fid], + )?; + + // return zknoteedit. + let zne = read_zknoteedit(&conn, uid, noteid)?; + + let znew = ZkNoteEditWhat { + what: "yeet".to_string(), + zne: zne, + }; + + info!( + "user#yeet-new-zknote: {} - {}", + znew.zne.zknote.id.clone(), + znew.zne.zknote.title.clone() + ); + + return Ok(znew); + } else { + Err(orgauth::error::Error::String(format!( + "yeet err {:?}", + exit_code + ))) + } + } + Err(e) => Err(orgauth::error::Error::String(format!("yeet err {:?}", e))), + } +} + +// pub fn yeet( +// conn: &Connection, +// uid: i64, +// savedir: &Path, +// yeet: Yeet, +// ) -> Result { +// // parse 'url' +// let uri: Uri = match yeet.url.parse() { +// Ok(uri) => uri, +// Err(e) => return Err(orgauth::error::Error::String(format!("yeet err {:?}", e))), +// }; + +// // get 'v' parameter. +// let query = match uri.path_and_query() { +// Some(paq) => { +// println!("paq: {:?}", paq); +// match paq.query() { +// Some(query) => query, +// None => { +// return Err(orgauth::error::Error::String( +// "query string not present in url".to_string(), +// )) +// } +// } +// } +// None => { +// return Err(orgauth::error::Error::String(format!( +// "query string not present in url" +// ))) +// } +// }; + +// // with 'v' paramter, scan for existing files. +// let hv = match web::Query::::from_query(query) { +// Ok(hv) => hv, +// Err(e) => { +// return Err(orgauth::error::Error::String(format!( +// "query parse error {:?}", +// e +// ))) +// } +// }; + +// // if there's already a file, return a new zknote that points at it. +// match conn.query_row( +// "select fileid, filename from yeetfile where +// yeetkey = ?1 and audio = ?2", +// params![hv.v, yeet.audio], +// |row| Ok((row.get(0)?, row.get(1)?)), +// ) { +// Ok((fileid, filename)) => { +// // now make a new note. +// let sn = save_zknote( +// &conn, +// uid, +// &SaveZkNote { +// id: None, +// title: filename, +// pubid: None, +// content: "".to_string(), +// editable: false, +// showtitle: false, +// deleted: false, +// }, +// )?; + +// // set the file id in that note. +// set_zknote_file(&conn, sn.id, fileid)?; + +// // return zknoteedit. +// let note = read_zknoteedit(&conn, uid, sn.id)?; + +// let znew = ZkNoteEditWhat { +// what: "yeet".to_string(), +// zne: note, +// }; + +// info!( +// "user#yeet-copy-zknote: {} - {}", +// znew.zne.zknote.id.clone(), +// znew.zne.zknote.title.clone() +// ); + +// return Ok(znew); +// } +// Err(rusqlite::Error::QueryReturnedNoRows) => (), +// Err(x) => return Err(x.into()), +// }; + +// let mut child = Command::new("yt-dlp") +// .arg("-x") +// .arg(format!("-o{}/%(title)s-%(id)s.%(ext)s", savedir.display())) +// .arg(yeet.url.clone()) +// .spawn() +// .expect("youtube-dl failed to execute"); + +// match child.wait() { +// Ok(exit_code) => { +// if exit_code.success() { +// // find the yeeted file by 'v'. +// let file: PathBuf = match glob::glob(format!("{}/*{}*", savedir.display(), hv.v).as_str()) { +// Ok(mut paths) => match paths.next() { +// Some(rpb) => match rpb { +// Ok(pb) => pb, +// Err(e) => return Err(orgauth::error::Error::String(format!("glob error {:?}", e))), +// }, +// None => { +// return Err(orgauth::error::Error::String(format!( +// "yeet file not found {:?}", +// hv.v +// ))) +// } +// }, +// Err(e) => return Err(orgauth::error::Error::String(format!("glob error {:?}", e))), +// }; +// let filename = file +// .as_path() +// .file_name() +// .and_then(|x| x.to_str()) +// .unwrap_or("meh.txt") +// .to_string(); +// let (noteid, fid) = make_file_note(&conn, uid, &filename, file.as_path())?; + +// // yeetfile table entry. +// conn.execute( +// "insert into yeetfile (yeetkey, audio, filename, fileid) +// values (?1, ?2, ?3, ?4)", +// params![hv.v, true, filename, fid], +// )?; + +// // return zknoteedit. +// let zne = read_zknoteedit(&conn, uid, noteid)?; + +// let znew = ZkNoteEditWhat { +// what: "yeet".to_string(), +// zne: zne, +// }; + +// info!( +// "user#yeet-new-zknote: {} - {}", +// znew.zne.zknote.id.clone(), +// znew.zne.zknote.title.clone() +// ); + +// return Ok(znew); +// } else { +// Err(orgauth::error::Error::String(format!( +// "yeet err {:?}", +// exit_code +// ))) +// } +// } +// Err(e) => Err(orgauth::error::Error::String(format!("yeet err {:?}", e))), +// } +// } diff --git a/server/src/messages.rs b/server/src/messages.rs index f1216e6..69d2e21 100644 --- a/server/src/messages.rs +++ b/server/src/messages.rs @@ -18,9 +18,3 @@ pub struct PublicMessage { pub what: String, pub data: Option, } - -#[derive(Deserialize, Serialize, Debug)] -pub struct Invoice { - pub info: String, -} - From 9de177080bc16c32f8d3ab5016618df7befe7f08 Mon Sep 17 00:00:00 2001 From: Ben Burdette <> Date: Wed, 7 Aug 2024 10:03:16 -0600 Subject: [PATCH 03/34] pdf file comes up in new tab --- elm/src/Data.elm | 2 +- elm/src/Main.elm | 35 +++++- server/src/main.rs | 259 ++++++++++++++++++++++++--------------------- 3 files changed, 173 insertions(+), 123 deletions(-) diff --git a/elm/src/Data.elm b/elm/src/Data.elm index cd9a965..0ea7fc6 100644 --- a/elm/src/Data.elm +++ b/elm/src/Data.elm @@ -333,7 +333,7 @@ type alias PrintInvoice = encodePrintInvoice : PrintInvoice -> JE.Value encodePrintInvoice i = - JE.string i.info + JE.object [ ( "info", JE.string i.info ) ] diff --git a/elm/src/Main.elm b/elm/src/Main.elm index 6a6e8c4..5815424 100644 --- a/elm/src/Main.elm +++ b/elm/src/Main.elm @@ -81,7 +81,7 @@ type Msg | ProjectTimeData String (Result Http.Error TI.ServerResponse) | ProjectViewData String (Result Http.Error PI.ServerResponse) | TProjectViewData String (Result Http.Error TI.ServerResponse) - | PrintInvoiceReplyData (Result Http.Error ()) + | PrintInvoiceReplyData (Result Http.Error (Cmd Msg)) | LoadUrl String | InternalUrl Url | SelectedText JD.Value @@ -1093,6 +1093,14 @@ actualupdate msg model = ( WindowSize s, _ ) -> ( { model | size = s }, Cmd.none ) + ( PrintInvoiceReplyData meh, _ ) -> + case meh of + Ok cmd -> + ( model, cmd ) + + Err e -> + ( displayMessageDialog model <| Util.httpErrorString e, Cmd.none ) + ( ChangePasswordDialogMsg sdmsg, ChangePasswordDialog sdmod instate ) -> case GD.update sdmsg sdmod of GD.Dialog nmod -> @@ -2080,11 +2088,34 @@ handleProjectTime model ( nm, cmd ) login = , Http.post { url = model.location ++ "/invoice" , body = Http.jsonBody (Data.encodePrintInvoice { info = text }) - , expect = Http.expectWhatever PrintInvoiceReplyData + , expect = + Http.expectBytesResponse PrintInvoiceReplyData <| + resolve <| + \bytes -> + Ok <| FD.bytes "woot.pdf" "application/pdf" bytes } ) +resolve : (body -> Result String a) -> Http.Response body -> Result Http.Error a +resolve toResult response = + case response of + Http.BadUrl_ url -> + Err (Http.BadUrl url) + + Http.Timeout_ -> + Err Http.Timeout + + Http.NetworkError_ -> + Err Http.NetworkError + + Http.BadStatus_ metadata _ -> + Err (Http.BadStatus metadata.statusCode) + + Http.GoodStatus_ _ body -> + Result.mapError Http.BadBody (toResult body) + + handleProjectView : Model -> ( ProjectView.Model, ProjectView.Command ) -> Maybe Data.LoginData -> ( Model, Cmd Msg ) handleProjectView model ( nm, cmd ) mblogin = case cmd of diff --git a/server/src/main.rs b/server/src/main.rs index 073cbf3..cd4ce25 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -4,28 +4,32 @@ mod interfaces; mod messages; mod migrations; mod sqldata; +use actix_files::NamedFile; use actix_session::{ config::PersistentSession, storage::CookieSessionStore, Session, SessionMiddleware, }; use actix_web::{ cookie::{self, Key}, - middleware, web, App, HttpRequest, HttpResponse, HttpServer, Result, + error::ErrorInternalServerError, + http::StatusCode, + middleware, web, App, HttpRequest, HttpResponse, HttpResponseBuilder, HttpServer, Responder, + ResponseError, }; use clap::Arg; use config::Config; +use data::PrintInvoice; use log::{error, info}; use messages::{PublicMessage, ServerResponse, UserMessage}; use orgauth::data::WhatMessage; use orgauth::endpoints::Callbacks; use serde_json; -use std::env; use std::error::Error; use std::path::PathBuf; +use std::process::Command; use std::str::FromStr; +use std::{env, fmt::Display}; use timer; use uuid::Uuid; -use typst; -use data::PrintInvoice; /* use actix_files::NamedFile; @@ -387,141 +391,156 @@ async fn err_main() -> Result<(), Box> { } } } -async fn invoice(session: Session, config: web::Data, + +// impl ResponseError for orgauth::error::Error { +// fn status_code(&self) -> StatusCode { +// StatusCode::INTERNAL_SERVER_ERROR +// } +// } + +async fn invoice( + session: Session, + config: web::Data, item: web::Json, - req: HttpRequest) -> HttpResponse { - - typst::world::SystemWorld - - typst::compile("blah"); - - // let conn = match sqldata::connection_open(config.orgauth_config.db.as_path()) { - // Ok(c) => c, - // Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)), - // }; - - // let suser = match session_user(&conn, session, &config) { - // Ok(Either::Left(user)) => Some(user), - // Ok(Either::Right(_sr)) => None, - // Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)), - // }; - - // let uid = suser.map(|user| user.id); - - // match req - // .match_info() - // .get("id") - // // .and_then(|s| s.parse::().ok()) - // { - // Some(noteid) => { - // let uuid = match Uuid::parse_str(noteid) { - // Ok(id) => id, - // Err(e) => return HttpResponse::BadRequest().body(e.to_string()) - // }; - // let nid = match sqldata::note_id_for_uuid(&conn, &uuid) { - // Ok(id) => id, - // Err(e) => return HttpResponse::NotFound().body(e.to_string()) - // }; - // let hash = match sqldata::read_zknote_filehash(&conn, uid, nid) { - // Ok(Some(hash)) => hash, - // Ok(None) => return HttpResponse::NotFound().body("not found"), - // Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)), - // }; - - // let zkln = match sqldata::read_zklistnote(&conn, &config.file_path, uid, nid) { - // Ok(zkln) => zkln, - // Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)), - // }; - - // let stpath = config.file_path.join(hash); - - // match File::open(stpath).and_then(|f| NamedFile::from_file(f, Path::new(zkln.title.as_str()))) - // { - // Ok(f) => f.into_response(&req), - // Err(e) => HttpResponse::NotFound().body(format!("{:?}", e)), - // } - // } - // None => HttpResponse::BadRequest().body("file id required: /file/"), - // } - HttpResponse::Ok().body("") -} + req: HttpRequest, +) -> actix_web::Result { + info!("invoice start {:?}", item.0); + let path = run_invoice(item.0).map_err(|e| ErrorInternalServerError(e.to_string()))?; // .map_err(|e| actix_web::Error::fmt(, ) -pub fn invoice( - conn: &Connection, - uid: i64, - savedir: &Path, - printInvoice: PrintInvoice, -) -> Result { + info!("invoice here {}", path.display()); + Ok(NamedFile::open(path)?) - + // match run_invoice(item) { + // Ok(path) => { + // Ok(NamedFile::open(path)?) + // Err(e) => + // Err( + + // HttpResponse::Ok().body("") +} +pub fn run_invoice( + // conn: &Connection, + // uid: i64, + // savedir: &Path, + print_invoice: PrintInvoice, +) -> Result { + return Ok("./invoice-maker/meh/en.pdf".into()); let mut child = Command::new("typst") .arg("compile") - .arg(format!("-o{}/%(title)s-%(id)s.%(ext)s", savedir.display())) - .arg(yeet.url.clone()) + .arg("./invoice-maker/meh/en.typ") .spawn() - .expect("youtube-dl failed to execute"); + .expect("typst failed to execute"); match child.wait() { Ok(exit_code) => { if exit_code.success() { - // find the yeeted file by 'v'. - let file: PathBuf = match glob::glob(format!("{}/*{}*", savedir.display(), hv.v).as_str()) { - Ok(mut paths) => match paths.next() { - Some(rpb) => match rpb { - Ok(pb) => pb, - Err(e) => return Err(orgauth::error::Error::String(format!("glob error {:?}", e))), - }, - None => { - return Err(orgauth::error::Error::String(format!( - "yeet file not found {:?}", - hv.v - ))) - } - }, - Err(e) => return Err(orgauth::error::Error::String(format!("glob error {:?}", e))), - }; - let filename = file - .as_path() - .file_name() - .and_then(|x| x.to_str()) - .unwrap_or("meh.txt") - .to_string(); - let (noteid, fid) = make_file_note(&conn, uid, &filename, file.as_path())?; - - // yeetfile table entry. - conn.execute( - "insert into yeetfile (yeetkey, audio, filename, fileid) - values (?1, ?2, ?3, ?4)", - params![hv.v, true, filename, fid], - )?; - - // return zknoteedit. - let zne = read_zknoteedit(&conn, uid, noteid)?; - - let znew = ZkNoteEditWhat { - what: "yeet".to_string(), - zne: zne, - }; - - info!( - "user#yeet-new-zknote: {} - {}", - znew.zne.zknote.id.clone(), - znew.zne.zknote.title.clone() - ); - - return Ok(znew); + // add file to result. + Ok("./invoice-maker/meh/en.pdf".into()) } else { Err(orgauth::error::Error::String(format!( - "yeet err {:?}", + "typst err {:?}", exit_code ))) } } - Err(e) => Err(orgauth::error::Error::String(format!("yeet err {:?}", e))), + Err(e) => Err(orgauth::error::Error::String(format!( + "invoice err {:?}", + e + ))), } } +// write data file, *typ file. +/* #import "../invoice-maker.typ": * +#import "../fixtures/example-data.typ": * + +#show: invoice.with( + language: "en", + banner-image: image("../fixtures/banner.png"), + invoice-id: "2024-03-10t172205", + // Set this to create a cancellation invoice + // cancellation-id: "2024-03-24t210835", + issuing-date: "2024-03-10", + delivery-date: "2024-02-29", + due-date: "2024-03-20", + biller: biller, + hourly-rate: 100, + recipient: recipient, + items: table-data, + styling: ( font: none ), // Explicitly use Typst's default font +) */ + +/* +#let biller = ( + name: "Gyro Gearloose", + title: "Inventor", + company: "Crazy Inventions Ltd.", + vat-id: "DL1234567", + iban: "DE89370400440532013000", + address: ( + country: "Disneyland", + city: "Duckburg", + postal-code: "123456", + street: "Inventor Drive 23", + ), + ) + +#let recipient = ( + name: "Scrooge McDuck", + title: "Treasure Hunter", + vat-id: "DL7654321", + address: ( + country: "Disneyland", + city: "Duckburg", + postal-code: "123456", + street: "Killmotor Hill 1", + ) + ) + +#let table-data = ( + ( + number: 1, + date: "2016-04-03", + description: "Arc reactor", + dur-min: 0, + quantity: 1, + price: 13000, + ), + ( + number: 2, + date: "2016-04-05", + description: "Flux capacitor", + dur-min: 0, + quantity: 1, + price: 27000, + ), + ( + number: 3, + date: "2016-04-07", + description: "Lightsaber", + dur-min: 0, + quantity: 2, + price: 3600, + ), + ( + number: 4, + date: "2016-04-08", + description: "Sonic screwdriver", + dur-min: 0, + quantity: 10, + price: 800, + ), + ( + number: 5, + date: "2016-04-12", + description: "Assembly", + dur-min: 160, + quantity: 1, + price: 53.33, + ) + ) + */ // pub fn yeet( // conn: &Connection, // uid: i64, @@ -567,7 +586,7 @@ pub fn invoice( // // if there's already a file, return a new zknote that points at it. // match conn.query_row( -// "select fileid, filename from yeetfile where +// "select fileid, filename from yeetfile where // yeetkey = ?1 and audio = ?2", // params![hv.v, yeet.audio], // |row| Ok((row.get(0)?, row.get(1)?)), From e4843e67a0541ef217c4d2991d78533b452c86b5 Mon Sep 17 00:00:00 2001 From: Ben Burdette <> Date: Wed, 7 Aug 2024 16:31:00 -0600 Subject: [PATCH 04/34] payer, payee, invoice_seq --- elm/src/Data.elm | 12 ++++++ elm/src/ProjectEdit.elm | 82 ++++++++++++++++++++++++++++++++++++++++ server/src/data.rs | 6 +++ server/src/main.rs | 3 +- server/src/migrations.rs | 67 ++++++++++++++++++++++++++++++++ server/src/sqldata.rs | 44 +++++++++++++++------ 6 files changed, 202 insertions(+), 12 deletions(-) diff --git a/elm/src/Data.elm b/elm/src/Data.elm index 0ea7fc6..dabb1cf 100644 --- a/elm/src/Data.elm +++ b/elm/src/Data.elm @@ -143,6 +143,9 @@ type alias Project = { id : ProjectId , name : String , description : String + , invoiceSeq : Int + , payer : String + , payee : String , public : Bool , rate : Maybe Float , currency : Maybe String @@ -155,6 +158,9 @@ type alias SaveProject = { id : Maybe ProjectId , name : String , description : String + , invoiceSeq : Int + , payer : String + , payee : String , public : Bool , rate : Maybe Float , currency : Maybe String @@ -452,6 +458,9 @@ encodeSaveProject sp = JE.object <| [ ( "name", JE.string sp.name ) , ( "description", JE.string sp.description ) + , ( "invoice_seq", JE.int sp.invoiceSeq ) + , ( "payer", JE.string sp.payer ) + , ( "payee", JE.string sp.payee ) , ( "public", JE.bool sp.public ) ] ++ (sp.rate @@ -474,6 +483,9 @@ decodeProject = |> andMap (JD.field "id" JD.int |> JD.map makeProjectId) |> andMap (JD.field "name" JD.string) |> andMap (JD.field "description" JD.string) + |> andMap (JD.field "invoice_seq" JD.int) + |> andMap (JD.field "payer" JD.string) + |> andMap (JD.field "payee" JD.string) |> andMap (JD.field "public" JD.bool) |> andMap (JD.field "rate" <| JD.maybe JD.float) |> andMap (JD.field "currency" <| JD.maybe JD.string) diff --git a/elm/src/ProjectEdit.elm b/elm/src/ProjectEdit.elm index ee3b603..42613f1 100644 --- a/elm/src/ProjectEdit.elm +++ b/elm/src/ProjectEdit.elm @@ -24,6 +24,9 @@ import WindowKeys as WK type Msg = NameChanged String | DescriptionChanged String + | InvoiceSeqChanged String + | PayerChanged String + | PayeeChanged String | RateChanged String | CurrencyChanged String | SavePress @@ -41,6 +44,9 @@ type alias Model = { id : Maybe Data.ProjectId , name : String , description : String + , invoiceSeq : Int + , payer : String + , payee : String , public : Bool , ratestring : String , currency : String @@ -100,6 +106,9 @@ toSaveProject model = { id = model.id , name = model.name , description = model.description + , invoiceSeq = model.invoiceSeq + , payer = model.payer + , payee = model.payee , public = model.public , rate = rate , currency = currency @@ -189,6 +198,9 @@ isDirty model = ((model.id == Just ip.id) && (model.name == ip.name) && (model.description == ip.description) + && (model.invoiceSeq == ip.invoiceSeq) + && (model.payer == ip.payer) + && (model.payee == ip.payee) && (model.public == ip.public) && (model.ratestring == (ip.rate |> Maybe.map String.fromFloat |> Maybe.withDefault "") @@ -213,6 +225,9 @@ initNew ld = { id = Nothing , name = "" , description = "" + , invoiceSeq = 0 + , payer = "" + , payee = "" , public = False , ratestring = "" , currency = "" @@ -235,6 +250,9 @@ initEdit proj members = { id = Just proj.id , name = proj.name , description = proj.description + , invoiceSeq = proj.invoiceSeq + , payer = proj.payer + , payee = proj.payee , public = proj.public , ratestring = proj.rate |> Maybe.map String.fromFloat |> Maybe.withDefault "" , currency = proj.currency |> Maybe.withDefault "" @@ -362,6 +380,56 @@ view ld size model = [] (E.text "currency") } + , EI.text + (if isdirty then + [ E.focused [ EBd.glow TC.darkYellow 3 ] ] + + else + [] + ) + { onChange = + InvoiceSeqChanged + , text = String.fromInt model.invoiceSeq + , placeholder = Nothing + , label = + EI.labelLeft + [] + (E.text "invoice sequence number") + } + , EI.multiline + (if isdirty then + [ E.focused [ EBd.glow TC.darkYellow 3 ] ] + + else + [] + ) + { onChange = + PayerChanged + , text = model.payer + , placeholder = Nothing + , label = + EI.labelLeft + [] + (E.text "payer") + , spellcheck = True + } + , EI.multiline + (if isdirty then + [ E.focused [ EBd.glow TC.darkYellow 3 ] ] + + else + [] + ) + { onChange = + PayeeChanged + , text = model.payee + , placeholder = Nothing + , label = + EI.labelLeft + [] + (E.text "payee") + , spellcheck = True + } , E.row [ E.spacing 8 ] [ EI.checkbox [] { onChange = TogglePublic @@ -425,6 +493,20 @@ update msg model ld = DescriptionChanged t -> ( { model | description = t }, None ) + InvoiceSeqChanged t -> + case String.toInt t of + Just i -> + ( { model | invoiceSeq = i }, None ) + + Nothing -> + ( model, None ) + + PayerChanged t -> + ( { model | payer = t }, None ) + + PayeeChanged t -> + ( { model | payee = t }, None ) + RateChanged t -> ( { model | ratestring = t }, None ) diff --git a/server/src/data.rs b/server/src/data.rs index add13dc..1a09f8e 100644 --- a/server/src/data.rs +++ b/server/src/data.rs @@ -27,6 +27,9 @@ pub struct SaveProject { pub id: Option, pub name: String, pub description: Option, + pub invoice_seq: i64, + pub payer: String, + pub payee: String, pub public: bool, pub rate: Option, pub currency: Option, @@ -94,6 +97,9 @@ pub struct Project { pub id: i64, pub name: String, pub description: String, + pub invoice_seq: i64, + pub payer: String, + pub payee: String, pub public: bool, pub rate: Option, pub currency: Option, diff --git a/server/src/main.rs b/server/src/main.rs index cd4ce25..dfad4f0 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -452,7 +452,8 @@ pub fn run_invoice( } // write data file, *typ file. -/* #import "../invoice-maker.typ": * +/* +#import "../invoice-maker.typ": * #import "../fixtures/example-data.typ": * #show: invoice.with( diff --git a/server/src/migrations.rs b/server/src/migrations.rs index 855b017..3a4242c 100644 --- a/server/src/migrations.rs +++ b/server/src/migrations.rs @@ -968,3 +968,70 @@ pub fn udpate11(dbfile: &Path) -> Result<(), orgauth::error::Error> { Ok(()) } + +pub fn udpate12(dbfile: &Path) -> Result<(), orgauth::error::Error> { + // db connection without foreign key checking. + let conn = Connection::open(dbfile)?; + let mut m1 = Migration::new(); + + // add 'rate' to timeentry. + m1.create_table("projecttemp", |t| { + t.add_column( + "id", + types::integer() + .primary(true) + .increments(true) + .nullable(false), + ); + t.add_column("name", types::text().nullable(false)); + t.add_column("description", types::text().nullable(false)); + t.add_column("public", types::boolean().nullable(false)); + t.add_column("rate", types::float().nullable(true)); + t.add_column("currency", types::text().nullable(true)); + t.add_column("createdate", types::integer().nullable(false)); + t.add_column("changeddate", types::integer().nullable(false)); + }); + + conn.execute_batch(m1.make::().as_str())?; + + // copy everything from current table.. + conn.execute( + "insert into projecttemp ( id, name, description, public, rate, currency, createdate, changeddate) + select id, name, description, public, rate, currency, createdate, changeddate from project ", + params![], + )?; + + let mut m2 = Migration::new(); + m2.drop_table("project"); + // timeclonk specific tables. + m2.create_table("project", |t| { + t.add_column( + "id", + types::integer() + .primary(true) + .increments(true) + .nullable(false), + ); + t.add_column("name", types::text().nullable(false)); + t.add_column("description", types::text().nullable(false)); + t.add_column("public", types::boolean().nullable(false)); + t.add_column("rate", types::float().nullable(true)); + t.add_column("currency", types::text().nullable(true)); + t.add_column("invoice_seq", types::integer().nullable(false)); + t.add_column("payer", types::text().nullable(false)); + t.add_column("payee", types::text().nullable(false)); + t.add_column("createdate", types::integer().nullable(false)); + t.add_column("changeddate", types::integer().nullable(false)); + }); + + conn.execute_batch(m2.make::().as_str())?; + + // copy everything from current table.. + conn.execute( + "insert into project (id, name, description, public, rate, currency, invoice_seq, payer, payee, createdate, changeddate) + select id, name, description, public, rate, currency, 0, '', '', createdate, changeddate from projecttemp ", + params![], + )?; + + Ok(()) +} diff --git a/server/src/sqldata.rs b/server/src/sqldata.rs index 2d0040b..c844aef 100644 --- a/server/src/sqldata.rs +++ b/server/src/sqldata.rs @@ -185,6 +185,11 @@ pub fn dbinit( tm::udpate11(&dbfile)?; set_single_value(&conn, "migration_level", "11")?; } + if nlevel < 12 { + info!("udpate12"); + tm::udpate12(&dbfile)?; + set_single_value(&conn, "migration_level", "12")?; + } info!("db up to date."); @@ -318,9 +323,20 @@ pub fn save_project( let proj = match project.id { Some(id) => { conn.execute( - "update project set name = ?1, description = ?2, public = ?3, rate = ?4, currency = ?5, changeddate = ?6 - where id = ?7", - params![project.name, project.description, project.public, project.rate, project.currency, now, id], + "update project set name = ?1, description = ?2 , invoice_seq = ?3, payer = ?4, payee = ?5, public = ?6, rate = ?7, currency = ?8, changeddate = ?9 + where id = ?10", + params![ + project.name, + project.description, + project.invoice_seq, + project.payer, + project.payee, + project.public, + project.rate, + project.currency, + now, + id], + )?; SavedProject { id: id, @@ -329,11 +345,14 @@ pub fn save_project( } None => { conn.execute( - "insert into project (name, description, public, rate, currency, createdate, changeddate) - values (?1, ?2, ?3, ?4, ?5, ?6, ?7)", + "insert into project (name, description, invoice_seq, payer, payee, public, rate, currency, createdate, changeddate) + values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)", params![ project.name, project.description, + project.invoice_seq, + project.payer, + project.payee, project.public, project.rate, project.currency, @@ -358,7 +377,7 @@ pub fn save_project( pub fn read_project(conn: &Connection, projectid: i64) -> Result { let mut pstmt = conn.prepare( - "select project.id, project.name, project.description, project.public, project.rate, project.currency, project.createdate, project.changeddate + "select project.id, project.name, project.description, project.invoice_seq, project.payer, project.payee, project.public, project.rate, project.currency, project.createdate, project.changeddate from project, projectmember where project.id = ?1", )?; @@ -367,11 +386,14 @@ pub fn read_project(conn: &Connection, projectid: i64) -> Result Date: Wed, 7 Aug 2024 16:31:56 -0600 Subject: [PATCH 05/34] format --- server/src/sqldata.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/src/sqldata.rs b/server/src/sqldata.rs index c844aef..89530ed 100644 --- a/server/src/sqldata.rs +++ b/server/src/sqldata.rs @@ -326,7 +326,7 @@ pub fn save_project( "update project set name = ?1, description = ?2 , invoice_seq = ?3, payer = ?4, payee = ?5, public = ?6, rate = ?7, currency = ?8, changeddate = ?9 where id = ?10", params![ - project.name, + project.name, project.description, project.invoice_seq, project.payer, @@ -336,7 +336,6 @@ pub fn save_project( project.currency, now, id], - )?; SavedProject { id: id, From 491e9949a3bc395f77c24257da25629558bee627 Mon Sep 17 00:00:00 2001 From: Ben Burdette <> Date: Wed, 7 Aug 2024 21:49:51 -0600 Subject: [PATCH 06/34] sending, recieving, ignoring invoice params --- elm/src/Data.elm | 41 +++++++++++++++++++++++++++++++++++++--- elm/src/Main.elm | 4 ++-- elm/src/ProjectEdit.elm | 4 ++++ elm/src/ProjectTime.elm | 39 ++++++++++++++++++++++++++++++++------ server/src/data.rs | 16 +++++++++++++++- server/src/main.rs | 19 +++++++++++++++++++ server/src/migrations.rs | 5 +++-- server/src/sqldata.rs | 29 +++++++++++++++------------- 8 files changed, 130 insertions(+), 27 deletions(-) diff --git a/elm/src/Data.elm b/elm/src/Data.elm index dabb1cf..1df207f 100644 --- a/elm/src/Data.elm +++ b/elm/src/Data.elm @@ -1,11 +1,13 @@ module Data exposing ( Allocation , AllocationId(..) + , InvoiceItem , ListProject , LoginData , PayEntry , PayEntryId(..) , PayType(..) + , PrintInvoice , Project , ProjectEdit , ProjectId(..) @@ -143,6 +145,7 @@ type alias Project = { id : ProjectId , name : String , description : String + , invoiceIdTemplate : String , invoiceSeq : Int , payer : String , payee : String @@ -158,6 +161,7 @@ type alias SaveProject = { id : Maybe ProjectId , name : String , description : String + , invoiceIdTemplate : String , invoiceSeq : Int , payer : String , payee : String @@ -333,13 +337,42 @@ type alias ProjectTime = } +type alias InvoiceItem = + { date : String + , description : String + , dur_min : Float + , quantity : Float + , price : Float + } + + type alias PrintInvoice = - { info : String } + { id : String + , payer : String + , payee : String + , items : List InvoiceItem + } + + +encodeInvoiceItem : InvoiceItem -> JE.Value +encodeInvoiceItem ii = + JE.object + [ ( "date", JE.string ii.date ) + , ( "description", JE.string ii.description ) + , ( "dur_min", JE.float ii.dur_min ) + , ( "quantity", JE.float ii.quantity ) + , ( "price", JE.float ii.price ) + ] encodePrintInvoice : PrintInvoice -> JE.Value -encodePrintInvoice i = - JE.object [ ( "info", JE.string i.info ) ] +encodePrintInvoice pi = + JE.object + [ ( "id", JE.string pi.id ) + , ( "payer", JE.string pi.payer ) + , ( "payee", JE.string pi.payee ) + , ( "items", JE.list encodeInvoiceItem pi.items ) + ] @@ -458,6 +491,7 @@ encodeSaveProject sp = JE.object <| [ ( "name", JE.string sp.name ) , ( "description", JE.string sp.description ) + , ( "invoice_id_template", JE.string sp.invoiceIdTemplate ) , ( "invoice_seq", JE.int sp.invoiceSeq ) , ( "payer", JE.string sp.payer ) , ( "payee", JE.string sp.payee ) @@ -483,6 +517,7 @@ decodeProject = |> andMap (JD.field "id" JD.int |> JD.map makeProjectId) |> andMap (JD.field "name" JD.string) |> andMap (JD.field "description" JD.string) + |> andMap (JD.field "invoice_id_template" JD.string) |> andMap (JD.field "invoice_seq" JD.int) |> andMap (JD.field "payer" JD.string) |> andMap (JD.field "payee" JD.string) diff --git a/elm/src/Main.elm b/elm/src/Main.elm index 5815424..bd1ae81 100644 --- a/elm/src/Main.elm +++ b/elm/src/Main.elm @@ -2083,11 +2083,11 @@ handleProjectTime model ( nm, cmd ) login = ProjectTime.ToClipboard text -> ( { model | state = ProjectTime nm login }, toClipBoard text ) - ProjectTime.PrintInvoice text -> + ProjectTime.PrintInvoice pi -> ( { model | state = ProjectTime nm login } , Http.post { url = model.location ++ "/invoice" - , body = Http.jsonBody (Data.encodePrintInvoice { info = text }) + , body = Http.jsonBody (Data.encodePrintInvoice pi) , expect = Http.expectBytesResponse PrintInvoiceReplyData <| resolve <| diff --git a/elm/src/ProjectEdit.elm b/elm/src/ProjectEdit.elm index 42613f1..19caee7 100644 --- a/elm/src/ProjectEdit.elm +++ b/elm/src/ProjectEdit.elm @@ -44,6 +44,7 @@ type alias Model = { id : Maybe Data.ProjectId , name : String , description : String + , invoiceIdTemplate : String , invoiceSeq : Int , payer : String , payee : String @@ -106,6 +107,7 @@ toSaveProject model = { id = model.id , name = model.name , description = model.description + , invoiceIdTemplate = model.invoiceIdTemplate , invoiceSeq = model.invoiceSeq , payer = model.payer , payee = model.payee @@ -225,6 +227,7 @@ initNew ld = { id = Nothing , name = "" , description = "" + , invoiceIdTemplate = "example" , invoiceSeq = 0 , payer = "" , payee = "" @@ -250,6 +253,7 @@ initEdit proj members = { id = Just proj.id , name = proj.name , description = proj.description + , invoiceIdTemplate = proj.invoiceIdTemplate , invoiceSeq = proj.invoiceSeq , payer = proj.payer , payee = proj.payee diff --git a/elm/src/ProjectTime.elm b/elm/src/ProjectTime.elm index 6d9bfe1..04ca75b 100644 --- a/elm/src/ProjectTime.elm +++ b/elm/src/ProjectTime.elm @@ -3,7 +3,7 @@ module ProjectTime exposing (..) import Calendar import Common import Csv -import Data +import Data exposing (InvoiceItem) import Dict exposing (Dict) import Element as E exposing (Element) import Element.Background as EBk @@ -82,7 +82,7 @@ type Msg | ClearDistribution | CalcDistribution | ToClipboardMsg String - | PrintInvoiceMsg String + | PrintInvoiceMsg (List InvoiceItem) | OnPaymentChanged UserId String | AddPaymentPress UserId Int Data.PayType | AddPayment UserId Int Data.PayType Int @@ -193,7 +193,7 @@ type Command | ShowError String | SelectMember (List Data.User) | ToClipboard String - | PrintInvoice String + | PrintInvoice Data.PrintInvoice | None @@ -2006,13 +2006,33 @@ distributionview ld size zone model = ) |> String.concat ) + + totehours = + dl + |> List.foldl (\( _, hours ) t -> t + (Maybe.withDefault 0 <| String.toFloat hours)) 0 in E.row [] [ EI.button Common.buttonStyle { onPress = Just <| ToClipboardMsg textdist, label = E.text "⧉" } |> E.el [ E.centerY ] , EI.button Common.buttonStyle - { onPress = Just <| PrintInvoiceMsg textdist, label = E.text "pdf invoice" } + { onPress = + case model.project.rate of + Just rate -> + Just <| + PrintInvoiceMsg + [ { date = "niaow" + , description = "hours" + , dur_min = 0 + , quantity = totehours + , price = rate + } + ] + + Nothing -> + Nothing + , label = E.text "pdf invoice" + } |> E.el [ E.centerY ] ] , width = E.shrink @@ -3859,8 +3879,15 @@ update msg model ld zone = ToClipboardMsg text -> ( model, ToClipboard text ) - PrintInvoiceMsg text -> - ( model, PrintInvoice text ) + PrintInvoiceMsg items -> + ( model + , PrintInvoice + { id = String.replace "" (String.fromInt model.project.invoiceSeq) model.project.invoiceIdTemplate + , payer = model.project.payer + , payee = model.project.payee + , items = items + } + ) DonePress -> ( model, Done ) diff --git a/server/src/data.rs b/server/src/data.rs index 1a09f8e..ed75762 100644 --- a/server/src/data.rs +++ b/server/src/data.rs @@ -27,6 +27,7 @@ pub struct SaveProject { pub id: Option, pub name: String, pub description: Option, + pub invoice_id_template: String, pub invoice_seq: i64, pub payer: String, pub payee: String, @@ -97,6 +98,7 @@ pub struct Project { pub id: i64, pub name: String, pub description: String, + pub invoice_id_template: String, pub invoice_seq: i64, pub payer: String, pub payee: String, @@ -225,5 +227,17 @@ pub struct SaveAllocation { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct PrintInvoice { - pub info: String, + id: String, + payer: String, + payee: String, + items: Vec, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct InvoiceItem { + date: String, + description: String, + dur_min: i64, + quantity: i64, + price: f64, } diff --git a/server/src/main.rs b/server/src/main.rs index dfad4f0..2836092 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -451,6 +451,25 @@ pub fn run_invoice( } } +/* + +add to project: + +invoice id template