Compare commits

..

11 Commits

11 changed files with 347 additions and 267 deletions

16
.gitignore vendored
View File

@ -1,16 +1,10 @@
# Generated by Cargo .vscode/
coverage/
debug/ debug/
node_modules/
public/
target/ target/
# Code coverage results
coverage/
# Environment configuration
.env .env
compose.yaml
# NodeJS files
node_modules/
pnpm-lock.yaml pnpm-lock.yaml
# Default web build output directory
public/

341
Cargo.lock generated
View File

@ -141,24 +141,31 @@ checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
[[package]] [[package]]
name = "askama" name = "askama"
version = "0.11.1" version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb98f10f371286b177db5eeb9a6e5396609555686a35e1d4f7b9a9c6d8af0139" checksum = "47cbc3cf73fa8d9833727bbee4835ba5c421a0d65b72daf9a7b5d0e0f9cfb57e"
dependencies = [ dependencies = [
"askama_derive", "askama_derive",
"askama_escape", "askama_escape",
"askama_shared", "humansize",
"num-traits",
"percent-encoding",
] ]
[[package]] [[package]]
name = "askama_derive" name = "askama_derive"
version = "0.11.2" version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87bf87e6e8b47264efa9bde63d6225c6276a52e05e91bf37eaa8afd0032d6b71" checksum = "c22fbe0413545c098358e56966ff22cdd039e10215ae213cfbd65032b119fc94"
dependencies = [ dependencies = [
"askama_shared", "basic-toml",
"mime",
"mime_guess",
"nom 7.1.1",
"proc-macro2", "proc-macro2",
"syn", "quote",
"serde",
"syn 2.0.18",
] ]
[[package]] [[package]]
@ -167,36 +174,6 @@ version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
[[package]]
name = "askama_shared"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf722b94118a07fcbc6640190f247334027685d4e218b794dbfe17c32bf38ed0"
dependencies = [
"askama_escape",
"humansize",
"mime",
"mime_guess",
"nom 7.1.1",
"num-traits",
"percent-encoding",
"proc-macro2",
"quote",
"serde",
"syn",
"toml",
]
[[package]]
name = "async-attributes"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5"
dependencies = [
"quote",
"syn",
]
[[package]] [[package]]
name = "async-channel" name = "async-channel"
version = "1.7.1" version = "1.7.1"
@ -245,7 +222,6 @@ dependencies = [
"blocking", "blocking",
"futures-lite", "futures-lite",
"once_cell", "once_cell",
"tokio",
] ]
[[package]] [[package]]
@ -317,7 +293,6 @@ version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d"
dependencies = [ dependencies = [
"async-attributes",
"async-channel", "async-channel",
"async-global-executor", "async-global-executor",
"async-io", "async-io",
@ -357,7 +332,7 @@ checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -387,7 +362,7 @@ checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -447,7 +422,7 @@ dependencies = [
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -468,12 +443,32 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "basic-toml"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c0de75129aa8d0cceaf750b89013f0e08804d6ec61416da787b35ad0d7cddf1"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "beef" name = "beef"
version = "0.5.2" version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
[[package]]
name = "bigdecimal"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa"
dependencies = [
"num-bigint",
"num-integer",
"num-traits",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -594,14 +589,11 @@ version = "3.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750"
dependencies = [ dependencies = [
"atty",
"bitflags", "bitflags",
"clap_derive 3.2.18", "clap_derive 3.2.18",
"clap_lex 0.2.4", "clap_lex 0.2.4",
"indexmap", "indexmap",
"once_cell", "once_cell",
"strsim 0.10.0",
"termcolor",
"textwrap 0.15.1", "textwrap 0.15.1",
] ]
@ -630,7 +622,7 @@ dependencies = [
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -643,7 +635,7 @@ dependencies = [
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -767,21 +759,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba"
[[package]]
name = "crc"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3"
dependencies = [
"crc-catalog",
]
[[package]]
name = "crc-catalog"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff"
[[package]] [[package]]
name = "crossbeam-queue" name = "crossbeam-queue"
version = "0.3.6" version = "0.3.6"
@ -835,7 +812,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"smallvec", "smallvec",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -845,7 +822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e"
dependencies = [ dependencies = [
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -855,7 +832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdffe87e1d521a10f9696f833fe502293ea446d7f256c06128293a4119bdf4cb" checksum = "cdffe87e1d521a10f9696f833fe502293ea446d7f256c06128293a4119bdf4cb"
dependencies = [ dependencies = [
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -904,7 +881,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"rustc_version 0.4.0", "rustc_version 0.4.0",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -953,12 +930,6 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
[[package]]
name = "dotenv"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
[[package]] [[package]]
name = "dotenvy" name = "dotenvy"
version = "0.15.5" version = "0.15.5"
@ -1020,12 +991,6 @@ dependencies = [
"once_cell", "once_cell",
] ]
[[package]]
name = "fallible-iterator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "1.8.0" version = "1.8.0"
@ -1136,7 +1101,7 @@ checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -1386,7 +1351,7 @@ dependencies = [
"markup5ever", "markup5ever",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -1438,9 +1403,12 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]] [[package]]
name = "humansize" name = "humansize"
version = "1.1.1" version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7"
dependencies = [
"libm",
]
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
@ -1569,6 +1537,12 @@ version = "0.2.134"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb"
[[package]]
name = "libm"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.9" version = "0.4.9"
@ -1703,6 +1677,16 @@ dependencies = [
"minimal-lexical", "minimal-lexical",
] ]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]] [[package]]
name = "num-bigint" name = "num-bigint"
version = "0.4.3" version = "0.4.3"
@ -1811,9 +1795,15 @@ dependencies = [
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]] [[package]]
name = "owo-colors" name = "owo-colors"
version = "3.5.0" version = "3.5.0"
@ -1978,7 +1968,7 @@ dependencies = [
"proc-macro-hack", "proc-macro-hack",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -1992,7 +1982,7 @@ dependencies = [
"proc-macro-hack", "proc-macro-hack",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -2039,7 +2029,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -2107,40 +2097,6 @@ dependencies = [
"universal-hash", "universal-hash",
] ]
[[package]]
name = "postgres-protocol"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "878c6cbf956e03af9aa8204b407b9cbf47c072164800aa918c516cd4b056c50c"
dependencies = [
"base64 0.13.0",
"byteorder",
"bytes",
"fallible-iterator",
"hmac 0.12.1",
"md-5",
"memchr",
"rand 0.8.5",
"sha2 0.10.6",
"stringprep",
]
[[package]]
name = "postgres-types"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73d946ec7d256b04dfadc4e6a3292324e6f417124750fc5c0950f981b703a0f1"
dependencies = [
"bytes",
"chrono",
"fallible-iterator",
"postgres-protocol",
"serde",
"serde_json",
"time 0.3.15",
"uuid",
]
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.16" version = "0.2.16"
@ -2162,7 +2118,7 @@ dependencies = [
"proc-macro-error-attr", "proc-macro-error-attr",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
"version_check", "version_check",
] ]
@ -2185,18 +2141,18 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.46" version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.21" version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -2468,25 +2424,26 @@ dependencies = [
[[package]] [[package]]
name = "sea-orm" name = "sea-orm"
version = "0.9.3" version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c7282fc3d7f79f6c5bd57e603319862fc778bf74118c0ce2a0dc82d9141dee" checksum = "fade86e8d41fd1a4721f84cb834f4ca2783f973cc30e6212b7fafc134f169214"
dependencies = [ dependencies = [
"async-stream", "async-stream",
"async-trait", "async-trait",
"bigdecimal",
"chrono", "chrono",
"futures", "futures",
"futures-util",
"log", "log",
"once_cell",
"ouroboros", "ouroboros",
"rust_decimal", "rust_decimal",
"sea-orm-macros", "sea-orm-macros",
"sea-query", "sea-query",
"sea-query-binder",
"sea-strum", "sea-strum",
"serde", "serde",
"serde_json", "serde_json",
"sqlx", "sqlx",
"thiserror",
"time 0.3.15", "time 0.3.15",
"tracing", "tracing",
"url", "url",
@ -2495,14 +2452,13 @@ dependencies = [
[[package]] [[package]]
name = "sea-orm-cli" name = "sea-orm-cli"
version = "0.9.3" version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de07b4a0fc83b1b7ef8a2fe5d42c2662b1c60315446e6ebb4151a301c35fe484" checksum = "efbf34a2caf70c2e3be9bb1e674e9540f6dfd7c8f40f6f05daf3b9740e476005"
dependencies = [ dependencies = [
"async-std",
"chrono", "chrono",
"clap 3.2.22", "clap 3.2.22",
"dotenv", "dotenvy",
"regex", "regex",
"sea-schema", "sea-schema",
"tracing", "tracing",
@ -2512,26 +2468,27 @@ dependencies = [
[[package]] [[package]]
name = "sea-orm-macros" name = "sea-orm-macros"
version = "0.9.3" version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f96b8a479d25d8110751a0511265556dd9139bc11e342357a98e60910fbb07e3" checksum = "28936f26d62234ff0be16f80115dbdeb3237fe9c25cf18fbcd1e3b3592360f20"
dependencies = [ dependencies = [
"bae", "bae",
"heck 0.3.3", "heck 0.3.3",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
name = "sea-orm-migration" name = "sea-orm-migration"
version = "0.9.3" version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f80e3ebbc654c1915686898de119d33a449a9512567009df0a3e95b1afe4e36c" checksum = "278d3adfd0832b6ffc17d3cfbc574d3695a5c1b38814e0bc8ac238d33f3d87cf"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"clap 3.2.22", "clap 3.2.22",
"dotenv", "dotenvy",
"futures",
"sea-orm", "sea-orm",
"sea-orm-cli", "sea-orm-cli",
"sea-schema", "sea-schema",
@ -2541,49 +2498,53 @@ dependencies = [
[[package]] [[package]]
name = "sea-query" name = "sea-query"
version = "0.26.3" version = "0.28.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6a1de9d0334895f7eb51bd1603c3c9f6737413f905a134001f1e198f43bfd70" checksum = "bbab99b8cd878ab7786157b7eb8df96333a6807cc6e45e8888c85b51534b401a"
dependencies = [ dependencies = [
"bigdecimal",
"chrono", "chrono",
"postgres-types",
"rust_decimal", "rust_decimal",
"sea-query-derive", "sea-query-derive",
"sea-query-driver",
"serde_json", "serde_json",
"time 0.3.15", "time 0.3.15",
"uuid", "uuid",
] ]
[[package]] [[package]]
name = "sea-query-derive" name = "sea-query-binder"
version = "0.2.0" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34cdc022b4f606353fe5dc85b09713a04e433323b70163e81513b141c6ae6eb5" checksum = "4cea85029985b40dfbf18318d85fe985c04db7c1b4e5e8e0a0a0cdff5f1e30f9"
dependencies = [ dependencies = [
"heck 0.3.3", "bigdecimal",
"chrono",
"rust_decimal",
"sea-query",
"serde_json",
"sqlx",
"time 0.3.15",
"uuid",
]
[[package]]
name = "sea-query-derive"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63f62030c60f3a691f5fe251713b4e220b306e50a71e1d6f9cce1f24bb781978"
dependencies = [
"heck 0.4.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
"thiserror", "thiserror",
] ]
[[package]]
name = "sea-query-driver"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d7f0cae2e7ebb2affc378c40bc343c8197181d601d6755c3e66f1bd18cac253"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "sea-schema" name = "sea-schema"
version = "0.9.4" version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f737a6819fcad9727207d7090ccd6a33c0b384f3794e8838f952b52d599e3a17" checksum = "eeb2940bb5a10bc6cd05b450ce6cd3993e27fddd7eface2becb97fc5af3a040e"
dependencies = [ dependencies = [
"futures", "futures",
"sea-query", "sea-query",
@ -2599,7 +2560,7 @@ dependencies = [
"heck 0.3.3", "heck 0.3.3",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -2621,7 +2582,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"rustversion", "rustversion",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -2682,7 +2643,7 @@ checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -2883,11 +2844,11 @@ dependencies = [
"ahash", "ahash",
"atoi", "atoi",
"base64 0.13.0", "base64 0.13.0",
"bigdecimal",
"bitflags", "bitflags",
"byteorder", "byteorder",
"bytes", "bytes",
"chrono", "chrono",
"crc",
"crossbeam-queue", "crossbeam-queue",
"dirs", "dirs",
"dotenvy", "dotenvy",
@ -2944,10 +2905,9 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"serde_json", "serde_json",
"sha2 0.10.6",
"sqlx-core", "sqlx-core",
"sqlx-rt", "sqlx-rt",
"syn", "syn 1.0.101",
"url", "url",
] ]
@ -3006,7 +2966,7 @@ dependencies = [
"quote", "quote",
"serde", "serde",
"serde_derive", "serde_derive",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -3022,7 +2982,7 @@ dependencies = [
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"sha1 0.6.1", "sha1 0.6.1",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -3120,6 +3080,17 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "syn"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]] [[package]]
name = "tendril" name = "tendril"
version = "0.4.3" version = "0.4.3"
@ -3178,7 +3149,7 @@ checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -3256,6 +3227,7 @@ dependencies = [
"itoa 1.0.3", "itoa 1.0.3",
"libc", "libc",
"num_threads", "num_threads",
"serde",
"time-macros 0.2.4", "time-macros 0.2.4",
] ]
@ -3285,7 +3257,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"standback", "standback",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
@ -3310,19 +3282,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"num_cpus",
"pin-project-lite", "pin-project-lite",
] ]
[[package]]
name = "toml"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "tracing" name = "tracing"
version = "0.1.36" version = "0.1.36"
@ -3344,14 +3306,14 @@ checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
] ]
[[package]] [[package]]
name = "tracing-core" name = "tracing-core"
version = "0.1.29" version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"valuable", "valuable",
@ -3380,12 +3342,12 @@ dependencies = [
[[package]] [[package]]
name = "tracing-subscriber" name = "tracing-subscriber"
version = "0.3.15" version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
dependencies = [ dependencies = [
"ansi_term",
"matchers", "matchers",
"nu-ansi-term",
"once_cell", "once_cell",
"regex", "regex",
"sharded-slab", "sharded-slab",
@ -3490,7 +3452,6 @@ version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f"
dependencies = [ dependencies = [
"getrandom 0.2.7",
"serde", "serde",
] ]
@ -3567,7 +3528,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3601,7 +3562,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.101",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]

View File

@ -12,13 +12,13 @@ name = "tildes-statistics"
path = "source/main.rs" path = "source/main.rs"
[dependencies] [dependencies]
askama = "0.11.1" askama = "0.12.0"
async-std = "1.12.0" async-std = "1.12.0"
chrono = "0.4.22" chrono = "0.4.22"
color-eyre = "0.6.2" color-eyre = "0.6.2"
dotenvy = "0.15.5" dotenvy = "0.15.5"
grass = "0.11.2" grass = "0.11.2"
sea-orm-migration = "0.9.3" sea-orm-migration = "0.11.3"
tracing = "0.1.36" tracing = "0.1.36"
[dependencies.clap] [dependencies.clap]
@ -32,7 +32,7 @@ version = "0.3.4"
[dependencies.sea-orm] [dependencies.sea-orm]
features = ["macros", "mock", "runtime-async-std-rustls", "sqlx-postgres"] features = ["macros", "mock", "runtime-async-std-rustls", "sqlx-postgres"]
version = "0.9.3" version = "0.11.3"
[dependencies.surf] [dependencies.surf]
default-features = false default-features = false

View File

@ -4,11 +4,11 @@
"test": "stylelint 'source/**/*.scss'" "test": "stylelint 'source/**/*.scss'"
}, },
"dependencies": { "dependencies": {
"modern-normalize": "^1.1.0" "modern-normalize": "^2.0.0"
}, },
"devDependencies": { "devDependencies": {
"stylelint": "^14.12.1", "stylelint": "^15.7.0",
"stylelint-config-standard-scss": "^5.0.0" "stylelint-config-standard-scss": "^9.0.0"
}, },
"stylelint": { "stylelint": {
"extends": [ "extends": [

View File

@ -23,8 +23,13 @@ pub struct UserCountChart {
impl UserCountChart { impl UserCountChart {
/// Render the chart and write it to file. /// Render the chart and write it to file.
pub async fn render(&self, parent: &PathBuf, group_name: &str) -> Result<()> { pub async fn render(
let parent = parent.join("charts"); &self,
parent: &PathBuf,
group_name: &str,
render_point_circles: bool,
) -> Result<PathBuf> {
let parent = parent.join("charts/user-count");
create_dir_all(&parent).await?; create_dir_all(&parent).await?;
let (mut datapoints, mut min_count, mut max_count) = (vec![], i64::MAX, 0); let (mut datapoints, mut min_count, mut max_count) = (vec![], i64::MAX, 0);
@ -45,7 +50,8 @@ impl UserCountChart {
let min_count = min_count - 10; let min_count = min_count - 10;
let max_count = max_count + 10; let max_count = max_count + 10;
let path = parent.join("user-count.svg"); let path = parent.join(format!("{group_name}.svg"));
let output_path = path.clone();
let chart_root = SVGBackend::new(&path, (1280, 720)).into_drawing_area(); let chart_root = SVGBackend::new(&path, (1280, 720)).into_drawing_area();
chart_root.fill(&BACKGROUND_2)?; chart_root.fill(&BACKGROUND_2)?;
@ -71,7 +77,13 @@ impl UserCountChart {
chart chart
.configure_mesh() .configure_mesh()
.x_labels(datapoints.len() + 2) .x_labels(datapoints.len() + 2)
.x_label_formatter(&|x| format!("{:0}", datapoints_len - x)) .x_label_formatter(&|x| {
if (x - 1) % (datapoints_len / 20) != 0 {
String::new()
} else {
format!("{:0}", datapoints_len - x)
}
})
.x_desc("N days ago") .x_desc("N days ago")
.y_labels(5) .y_labels(5)
.y_label_formatter(&|y| format!("{y:0}")) .y_label_formatter(&|y| format!("{y:0}"))
@ -97,21 +109,29 @@ impl UserCountChart {
&ACCENT_1, &ACCENT_1,
&|(x, y), size, style| { &|(x, y), size, style| {
EmptyElement::at((x, y)) EmptyElement::at((x, y))
+ Circle::new((0, 0), size, style.filled()) + Circle::new(
(0, 0),
size,
if render_point_circles {
style.filled()
} else {
TRANSPARENT.filled()
},
)
+ Text::new( + Text::new(
{ {
if (x - 1) % 2 != 0 { if (x - 1) % (datapoints_len / 10) != 0 {
String::new() String::new()
} else { } else {
format!("{:0}", y) format!("{:0}", y)
} }
}, },
(-10, 15), (-20, -25),
text_style(20), text_style(20),
) )
}, },
))?; ))?;
Ok(()) Ok(output_path)
} }
} }

View File

@ -1,8 +1,11 @@
//! All logic for running the CLI. //! All logic for running the CLI.
use { use {
async_std::fs::create_dir_all, clap::Parser, color_eyre::Result, async_std::fs::{copy, create_dir_all},
sea_orm_migration::MigratorTrait, tracing::info, clap::Parser,
color_eyre::Result,
sea_orm_migration::MigratorTrait,
tracing::info,
}; };
use crate::{ use crate::{
@ -16,7 +19,7 @@ use crate::{
migrations::Migrator, migrations::Migrator,
scss::generate_css, scss::generate_css,
snapshots::SnapshotModel, snapshots::SnapshotModel,
templates::HomeTemplate, templates::{GroupTemplate, HomeTemplate},
utilities::{create_db, today}, utilities::{create_db, today},
}; };
@ -106,6 +109,21 @@ pub async fn run() -> Result<()> {
}; };
create_dir_all(&output).await?; create_dir_all(&output).await?;
for group in &groups {
UserCountChart {
groups: GroupDataModel::get_n_most_recent(&db, 31, &group.name)
.await?,
}
.render(&output, &group.name, true)
.await?;
GroupTemplate::new(&group.name)
.await
.render_to_file(&output)
.await?;
}
HomeTemplate::new( HomeTemplate::new(
groups, groups,
user_count_group.as_ref().map(|group| group.subscribers), user_count_group.as_ref().map(|group| group.subscribers),
@ -117,11 +135,9 @@ pub async fn run() -> Result<()> {
write_assets(&output).await?; write_assets(&output).await?;
if let Some(group) = user_count_group { if let Some(group) = user_count_group {
let groups = let path =
GroupDataModel::get_n_most_recent(&db, 30, &group.name).await?; output.join(&format!("charts/user-count/{}.svg", &group.name));
UserCountChart { groups } copy(path, output.join("charts/main-user-count.svg")).await?;
.render(&output, &group.name)
.await?;
} }
} }
}, },

View File

@ -36,6 +36,20 @@ li {
padding: 0; padding: 0;
} }
details {
border: 1px dashed var(--foreground-1);
summary {
background-color: var(--background-2);
cursor: pointer;
padding: var(--medium-spacing);
}
&[open] > summary {
border-bottom: 1px dashed var(--foreground-1);
}
}
.bold { .bold {
font-weight: bold; font-weight: bold;
} }

View File

@ -15,6 +15,26 @@
<body> <body>
{% block body %}{% endblock %} {% block body %}{% endblock %}
<footer class="page-footer">
<p>
Last generated on
<time class="underline" datetime="{{ today }}">{{- today -}}</time>.
</p>
<p>
&copy; Code
<a href="https://git.bauke.xyz/Bauke/tildes-statistics">AGPL-3.0-or-later</a>,
charts & data
<a href="https://creativecommons.org/licenses/by-nc/4.0/">CC BY-NC 4.0</a>.
</p>
<p class="bold">
Consider joining <a href="{{ base_url }}">Tildes</a>, a non-profit
community site driven by its users' interests.
</p>
</footer>
{{ extra_body_html|safe }} {{ extra_body_html|safe }}
</body> </body>

View File

@ -0,0 +1,19 @@
{% extends "base.html" %}
{% block head %}
<link rel="stylesheet" href="/css/index.css">
{% endblock %}
{% block body %}
<header class="page-header">
<img src="/tildes-statistics.png" alt="Tildes Statistics Logo">
<h1>{{ group_name }} Statistics</h1>
</header>
<main class="page-main">
<h2>General</h2>
<img class="chart" src="/charts/user-count/{{ group_name }}.svg"
alt="{{ group_name }} User Count Chart">
</main>
{% endblock %}

View File

@ -19,7 +19,10 @@
registered users on Tildes. registered users on Tildes.
</p> </p>
<img class="chart" src="/charts/user-count.svg" alt="User Count Chart"> <img class="chart" src="/charts/main-user-count.svg" alt="User Count Chart">
<details open>
<summary>Groups Overview</summary>
<table> <table>
<thead> <thead>
@ -34,7 +37,7 @@
{% for group in groups %} {% for group in groups %}
<tr> <tr>
<td> <td>
<a href="{{ base_url }}/{{ group.name }}">{{ group.name }}</a> <a href="/{{ group.name }}">{{ group.name }}</a>
</td> </td>
<td>{{ group.subscribers }}</td> <td>{{ group.subscribers }}</td>
<td> <td>
@ -46,24 +49,6 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</details>
</main> </main>
<footer class="page-footer">
<p>
Last generated on
<time class="underline" datetime="{{ today }}">{{- today -}}</time>.
</p>
<p>
&copy; Code
<a href="https://git.bauke.xyz/Bauke/tildes-statistics">AGPL-3.0-or-later</a>,
charts & data
<a href="https://creativecommons.org/licenses/by-nc/4.0/">CC BY-NC 4.0</a>.
</p>
<p class="bold">
Consider joining <a href="{{ base_url }}">Tildes</a>, a non-profit
community site driven by its users' interests.
</p>
</footer>
{% endblock %} {% endblock %}

View File

@ -10,6 +10,8 @@ use {
color_eyre::Result, color_eyre::Result,
}; };
use async_std::fs::create_dir_all;
use crate::{ use crate::{
group_data::GroupDataModel, group_data::GroupDataModel,
utilities::{get_base_url, today}, utilities::{get_base_url, today},
@ -70,3 +72,52 @@ impl HomeTemplate {
Ok(()) Ok(())
} }
} }
/// The template for group-specific pages.
#[derive(Template)]
#[template(path = "group.html")]
pub struct GroupTemplate {
/// The base URL for links to the Tildes instance.
pub base_url: String,
/// Extra HTML to insert in the body.
pub extra_body_html: String,
/// Extra HTML to insert in the head.
pub extra_head_html: String,
/// The group name for this group.
pub group_name: String,
/// The string for the `<title>` element.
pub page_title: String,
/// The date of today's snapshot.
pub today: NaiveDate,
}
impl GroupTemplate {
/// Create a new [`GroupTemplate`].
pub async fn new(group_name: &str) -> Self {
let extra_body_html = read_to_string("extra-body.html").await;
let extra_head_html = read_to_string("extra-head.html").await;
Self {
base_url: get_base_url(),
extra_body_html: extra_body_html.unwrap_or_default(),
extra_head_html: extra_head_html.unwrap_or_default(),
group_name: group_name.to_string(),
page_title: "Tildes Statistics".to_string(),
today: today(),
}
}
/// Render the template and write it to file.
pub async fn render_to_file(&self, parent: &PathBuf) -> Result<()> {
let output_dir = parent.join(&self.group_name);
create_dir_all(&output_dir).await?;
write(output_dir.join("index.html"), self.render()?).await?;
Ok(())
}
}