feat: Integerated the DB:
- Added an initialization with the db - Implemented 'add_new_proposal' function to be used in the form
This commit is contained in:
parent
2fd74defab
commit
e4e403e231
2
actix_mvc_app/.cargo/config.toml
Normal file
2
actix_mvc_app/.cargo/config.toml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[net]
|
||||||
|
git-fetch-with-cli = true
|
259
actix_mvc_app/Cargo.lock
generated
259
actix_mvc_app/Cargo.lock
generated
@ -296,6 +296,8 @@ dependencies = [
|
|||||||
"env_logger",
|
"env_logger",
|
||||||
"futures",
|
"futures",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"heromodels",
|
||||||
|
"heromodels_core",
|
||||||
"jsonwebtoken",
|
"jsonwebtoken",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
@ -309,6 +311,14 @@ dependencies = [
|
|||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adapter_macros"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"rhai",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
version = "0.24.2"
|
version = "0.24.2"
|
||||||
@ -366,6 +376,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"const-random",
|
||||||
|
"getrandom 0.2.15",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"version_check",
|
"version_check",
|
||||||
"zerocopy 0.7.35",
|
"zerocopy 0.7.35",
|
||||||
@ -478,6 +490,12 @@ version = "0.5.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236"
|
checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayvec"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.88"
|
version = "0.1.88"
|
||||||
@ -547,6 +565,26 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bincode"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740"
|
||||||
|
dependencies = [
|
||||||
|
"bincode_derive",
|
||||||
|
"serde",
|
||||||
|
"unty",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bincode_derive"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09"
|
||||||
|
dependencies = [
|
||||||
|
"virtue",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.9.0"
|
version = "2.9.0"
|
||||||
@ -1285,12 +1323,54 @@ dependencies = [
|
|||||||
"hashbrown 0.14.5",
|
"hashbrown 0.14.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heromodels"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"adapter_macros",
|
||||||
|
"bincode",
|
||||||
|
"chrono",
|
||||||
|
"heromodels-derive",
|
||||||
|
"heromodels_core",
|
||||||
|
"ourdb",
|
||||||
|
"rhai",
|
||||||
|
"rhai_autobind_macros",
|
||||||
|
"rhai_client_macros",
|
||||||
|
"rhai_wrapper",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tst",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heromodels-derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heromodels_core"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hkdf"
|
name = "hkdf"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
@ -1557,6 +1637,15 @@ dependencies = [
|
|||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_terminal_polyfill"
|
name = "is_terminal_polyfill"
|
||||||
version = "1.70.1"
|
version = "1.70.1"
|
||||||
@ -1756,6 +1845,15 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "no-std-compat"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
|
||||||
|
dependencies = [
|
||||||
|
"spin",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "7.1.3"
|
version = "7.1.3"
|
||||||
@ -1824,6 +1922,9 @@ name = "once_cell"
|
|||||||
version = "1.21.3"
|
version = "1.21.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
dependencies = [
|
||||||
|
"portable-atomic",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opaque-debug"
|
name = "opaque-debug"
|
||||||
@ -1841,6 +1942,16 @@ dependencies = [
|
|||||||
"hashbrown 0.14.5",
|
"hashbrown 0.14.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ourdb"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"crc32fast",
|
||||||
|
"log",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
@ -1907,7 +2018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6"
|
checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
"thiserror",
|
"thiserror 2.0.12",
|
||||||
"ucd-trie",
|
"ucd-trie",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2210,6 +2321,75 @@ version = "0.8.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rhai"
|
||||||
|
version = "1.21.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce4d759a4729a655ddfdbb3ff6e77fb9eadd902dae12319455557796e435d2a6"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"bitflags",
|
||||||
|
"instant",
|
||||||
|
"no-std-compat",
|
||||||
|
"num-traits",
|
||||||
|
"once_cell",
|
||||||
|
"rhai_codegen",
|
||||||
|
"rust_decimal",
|
||||||
|
"smallvec",
|
||||||
|
"smartstring",
|
||||||
|
"thin-vec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rhai_autobind_macros"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rhai_client_macros"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rhai",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rhai_codegen"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5a11a05ee1ce44058fa3d5961d05194fdbe3ad6b40f904af764d81b86450e6b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rhai_macros_derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rhai_wrapper"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"rhai",
|
||||||
|
"rhai_macros_derive",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.16.20"
|
version = "0.16.20"
|
||||||
@ -2247,6 +2427,16 @@ dependencies = [
|
|||||||
"ordered-multimap",
|
"ordered-multimap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust_decimal"
|
||||||
|
version = "1.37.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "faa7de2ba56ac291bd90c6b9bece784a52ae1411f9506544b3eae36dd2356d50"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.24"
|
version = "0.1.24"
|
||||||
@ -2421,7 +2611,7 @@ checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"thiserror",
|
"thiserror 2.0.12",
|
||||||
"time",
|
"time",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2456,6 +2646,17 @@ version = "1.15.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
|
checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smartstring"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"static_assertions",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.4.10"
|
version = "0.4.10"
|
||||||
@ -2488,6 +2689,12 @@ version = "1.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "static_assertions"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
@ -2557,13 +2764,39 @@ dependencies = [
|
|||||||
"unic-segment",
|
"unic-segment",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thin-vec"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "144f754d318415ac792f9d69fc87abbbfc043ce2ef041c60f16ad828f638717d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.12"
|
version = "2.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl 2.0.12",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2723,6 +2956,14 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tst"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"ourdb",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.18.0"
|
version = "1.18.0"
|
||||||
@ -2831,6 +3072,12 @@ version = "0.7.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unty"
|
||||||
|
version = "0.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.5.4"
|
version = "2.5.4"
|
||||||
@ -2888,6 +3135,12 @@ version = "0.9.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "virtue"
|
||||||
|
version = "0.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
@ -15,6 +15,8 @@ env_logger = "0.11.2"
|
|||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
chrono = { version = "0.4.35", features = ["serde"] }
|
chrono = { version = "0.4.35", features = ["serde"] }
|
||||||
|
heromodels = { path = "../../db/heromodels" }
|
||||||
|
heromodels_core = { path = "../../db/heromodels_core" }
|
||||||
config = "0.14.0"
|
config = "0.14.0"
|
||||||
num_cpus = "1.16.0"
|
num_cpus = "1.16.0"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
@ -27,3 +29,8 @@ redis = { version = "0.23.0", features = ["tokio-comp"] }
|
|||||||
jsonwebtoken = "8.3.0"
|
jsonwebtoken = "8.3.0"
|
||||||
pulldown-cmark = "0.13.0"
|
pulldown-cmark = "0.13.0"
|
||||||
urlencoding = "2.1.3"
|
urlencoding = "2.1.3"
|
||||||
|
|
||||||
|
[patch."https://git.ourworld.tf/herocode/db.git"]
|
||||||
|
rhai_autobind_macros = { path = "../../rhaj/rhai_autobind_macros" }
|
||||||
|
rhai_wrapper = { path = "../../rhaj/rhai_wrapper" }
|
||||||
|
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
use actix_web::{web, HttpResponse, Responder, Result};
|
use crate::db::proposals;
|
||||||
use actix_session::Session;
|
use crate::models::governance::{Proposal, ProposalStatus, Vote, VoteType, VotingResults};
|
||||||
use tera::Tera;
|
|
||||||
use serde_json::Value;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use chrono::{Utc, Duration};
|
|
||||||
use crate::models::governance::{Proposal, Vote, ProposalStatus, VoteType, VotingResults};
|
|
||||||
use crate::utils::render_template;
|
use crate::utils::render_template;
|
||||||
|
use actix_session::Session;
|
||||||
|
use actix_web::{HttpResponse, Responder, Result, web};
|
||||||
|
use chrono::{Duration, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::Value;
|
||||||
|
use tera::Tera;
|
||||||
|
|
||||||
|
use chrono::prelude::*;
|
||||||
|
|
||||||
/// Controller for handling governance-related routes
|
/// Controller for handling governance-related routes
|
||||||
pub struct GovernanceController;
|
pub struct GovernanceController;
|
||||||
@ -15,10 +18,12 @@ impl GovernanceController {
|
|||||||
/// For testing purposes, this will always return a mock user
|
/// For testing purposes, this will always return a mock user
|
||||||
fn get_user_from_session(session: &Session) -> Option<Value> {
|
fn get_user_from_session(session: &Session) -> Option<Value> {
|
||||||
// Try to get user from session first
|
// Try to get user from session first
|
||||||
let session_user = session.get::<String>("user").ok().flatten().and_then(|user_json| {
|
let session_user = session
|
||||||
serde_json::from_str(&user_json).ok()
|
.get::<String>("user")
|
||||||
});
|
.ok()
|
||||||
|
.flatten()
|
||||||
|
.and_then(|user_json| serde_json::from_str(&user_json).ok());
|
||||||
|
|
||||||
// If user is not in session, return a mock user for testing
|
// If user is not in session, return a mock user for testing
|
||||||
session_user.or_else(|| {
|
session_user.or_else(|| {
|
||||||
// Create a mock user
|
// Create a mock user
|
||||||
@ -37,38 +42,39 @@ impl GovernanceController {
|
|||||||
pub async fn index(tmpl: web::Data<Tera>, session: Session) -> Result<impl Responder> {
|
pub async fn index(tmpl: web::Data<Tera>, session: Session) -> Result<impl Responder> {
|
||||||
let mut ctx = tera::Context::new();
|
let mut ctx = tera::Context::new();
|
||||||
ctx.insert("active_page", "governance");
|
ctx.insert("active_page", "governance");
|
||||||
|
|
||||||
// Add user to context (will always be available with our mock user)
|
// Add user to context (will always be available with our mock user)
|
||||||
let user = Self::get_user_from_session(&session).unwrap();
|
let user = Self::get_user_from_session(&session).unwrap();
|
||||||
ctx.insert("user", &user);
|
ctx.insert("user", &user);
|
||||||
|
|
||||||
// Get mock proposals for the dashboard
|
// Get mock proposals for the dashboard
|
||||||
let mut proposals = Self::get_mock_proposals();
|
let proposals = Self::get_mock_proposals();
|
||||||
|
|
||||||
// Filter for active proposals only
|
// Filter for active proposals only
|
||||||
let active_proposals: Vec<Proposal> = proposals.into_iter()
|
let active_proposals: Vec<Proposal> = proposals
|
||||||
|
.into_iter()
|
||||||
.filter(|p| p.status == ProposalStatus::Active)
|
.filter(|p| p.status == ProposalStatus::Active)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Sort active proposals by voting end date (ascending)
|
// Sort active proposals by voting end date (ascending)
|
||||||
let mut sorted_active_proposals = active_proposals.clone();
|
let mut sorted_active_proposals = active_proposals.clone();
|
||||||
sorted_active_proposals.sort_by(|a, b| a.voting_ends_at.cmp(&b.voting_ends_at));
|
sorted_active_proposals.sort_by(|a, b| a.voting_ends_at.cmp(&b.voting_ends_at));
|
||||||
|
|
||||||
ctx.insert("proposals", &sorted_active_proposals);
|
ctx.insert("proposals", &sorted_active_proposals);
|
||||||
|
|
||||||
// Get the nearest deadline proposal for the voting pane
|
// Get the nearest deadline proposal for the voting pane
|
||||||
if let Some(nearest_proposal) = sorted_active_proposals.first() {
|
if let Some(nearest_proposal) = sorted_active_proposals.first() {
|
||||||
ctx.insert("nearest_proposal", nearest_proposal);
|
ctx.insert("nearest_proposal", nearest_proposal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get recent activity for the timeline
|
// Get recent activity for the timeline
|
||||||
let recent_activity = Self::get_mock_recent_activity();
|
let recent_activity = Self::get_mock_recent_activity();
|
||||||
ctx.insert("recent_activity", &recent_activity);
|
ctx.insert("recent_activity", &recent_activity);
|
||||||
|
|
||||||
// Get some statistics
|
// Get some statistics
|
||||||
let stats = Self::get_mock_statistics();
|
let stats = Self::get_mock_statistics();
|
||||||
ctx.insert("stats", &stats);
|
ctx.insert("stats", &stats);
|
||||||
|
|
||||||
render_template(&tmpl, "governance/index.html", &ctx)
|
render_template(&tmpl, "governance/index.html", &ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,72 +83,80 @@ impl GovernanceController {
|
|||||||
let mut ctx = tera::Context::new();
|
let mut ctx = tera::Context::new();
|
||||||
ctx.insert("active_page", "governance");
|
ctx.insert("active_page", "governance");
|
||||||
ctx.insert("active_tab", "proposals");
|
ctx.insert("active_tab", "proposals");
|
||||||
|
|
||||||
// Add user to context if available
|
// Add user to context if available
|
||||||
if let Some(user) = Self::get_user_from_session(&session) {
|
if let Some(user) = Self::get_user_from_session(&session) {
|
||||||
ctx.insert("user", &user);
|
ctx.insert("user", &user);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mock proposals
|
// Get mock proposals
|
||||||
let proposals = Self::get_mock_proposals();
|
let proposals = Self::get_mock_proposals();
|
||||||
ctx.insert("proposals", &proposals);
|
ctx.insert("proposals", &proposals);
|
||||||
|
|
||||||
render_template(&tmpl, "governance/proposals.html", &ctx)
|
render_template(&tmpl, "governance/proposals.html", &ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles the proposal detail page route
|
/// Handles the proposal detail page route
|
||||||
pub async fn proposal_detail(
|
pub async fn proposal_detail(
|
||||||
path: web::Path<String>,
|
path: web::Path<String>,
|
||||||
tmpl: web::Data<Tera>,
|
tmpl: web::Data<Tera>,
|
||||||
session: Session
|
session: Session,
|
||||||
) -> Result<impl Responder> {
|
) -> Result<impl Responder> {
|
||||||
let proposal_id = path.into_inner();
|
let proposal_id = path.into_inner();
|
||||||
let mut ctx = tera::Context::new();
|
let mut ctx = tera::Context::new();
|
||||||
ctx.insert("active_page", "governance");
|
ctx.insert("active_page", "governance");
|
||||||
|
|
||||||
// Add user to context if available
|
// Add user to context if available
|
||||||
if let Some(user) = Self::get_user_from_session(&session) {
|
if let Some(user) = Self::get_user_from_session(&session) {
|
||||||
ctx.insert("user", &user);
|
ctx.insert("user", &user);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mock proposal detail
|
// Get mock proposal detail
|
||||||
let proposal = Self::get_mock_proposal_by_id(&proposal_id);
|
let proposal = Self::get_mock_proposal_by_id(&proposal_id);
|
||||||
if let Some(proposal) = proposal {
|
if let Some(proposal) = proposal {
|
||||||
ctx.insert("proposal", &proposal);
|
ctx.insert("proposal", &proposal);
|
||||||
|
|
||||||
// Get mock votes for this proposal
|
// Get mock votes for this proposal
|
||||||
let votes = Self::get_mock_votes_for_proposal(&proposal_id);
|
let votes = Self::get_mock_votes_for_proposal(&proposal_id);
|
||||||
ctx.insert("votes", &votes);
|
ctx.insert("votes", &votes);
|
||||||
|
|
||||||
// Get voting results
|
// Get voting results
|
||||||
let results = Self::get_mock_voting_results(&proposal_id);
|
let results = Self::get_mock_voting_results(&proposal_id);
|
||||||
ctx.insert("results", &results);
|
ctx.insert("results", &results);
|
||||||
|
|
||||||
render_template(&tmpl, "governance/proposal_detail.html", &ctx)
|
render_template(&tmpl, "governance/proposal_detail.html", &ctx)
|
||||||
} else {
|
} else {
|
||||||
// Proposal not found
|
// Proposal not found
|
||||||
ctx.insert("error", "Proposal not found");
|
ctx.insert("error", "Proposal not found");
|
||||||
// For the error page, we'll use a special case to set the status code to 404
|
// For the error page, we'll use a special case to set the status code to 404
|
||||||
match tmpl.render("error.html", &ctx) {
|
match tmpl.render("error.html", &ctx) {
|
||||||
Ok(content) => Ok(HttpResponse::NotFound().content_type("text/html").body(content)),
|
Ok(content) => Ok(HttpResponse::NotFound()
|
||||||
|
.content_type("text/html")
|
||||||
|
.body(content)),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error rendering error template: {}", e);
|
eprintln!("Error rendering error template: {}", e);
|
||||||
Err(actix_web::error::ErrorInternalServerError(format!("Error: {}", e)))
|
Err(actix_web::error::ErrorInternalServerError(format!(
|
||||||
|
"Error: {}",
|
||||||
|
e
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles the create proposal page route
|
/// Handles the create proposal page route
|
||||||
pub async fn create_proposal_form(tmpl: web::Data<Tera>, session: Session) -> Result<impl Responder> {
|
pub async fn create_proposal_form(
|
||||||
|
tmpl: web::Data<Tera>,
|
||||||
|
session: Session,
|
||||||
|
) -> Result<impl Responder> {
|
||||||
let mut ctx = tera::Context::new();
|
let mut ctx = tera::Context::new();
|
||||||
ctx.insert("active_page", "governance");
|
ctx.insert("active_page", "governance");
|
||||||
ctx.insert("active_tab", "create");
|
ctx.insert("active_tab", "create");
|
||||||
|
|
||||||
// Add user to context (will always be available with our mock user)
|
// Add user to context (will always be available with our mock user)
|
||||||
let user = Self::get_user_from_session(&session).unwrap();
|
let user = Self::get_user_from_session(&session).unwrap();
|
||||||
ctx.insert("user", &user);
|
ctx.insert("user", &user);
|
||||||
|
|
||||||
render_template(&tmpl, "governance/create_proposal.html", &ctx)
|
render_template(&tmpl, "governance/create_proposal.html", &ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,23 +164,66 @@ impl GovernanceController {
|
|||||||
pub async fn submit_proposal(
|
pub async fn submit_proposal(
|
||||||
_form: web::Form<ProposalForm>,
|
_form: web::Form<ProposalForm>,
|
||||||
tmpl: web::Data<Tera>,
|
tmpl: web::Data<Tera>,
|
||||||
session: Session
|
session: Session,
|
||||||
) -> Result<impl Responder> {
|
) -> Result<impl Responder> {
|
||||||
let mut ctx = tera::Context::new();
|
let mut ctx = tera::Context::new();
|
||||||
ctx.insert("active_page", "governance");
|
ctx.insert("active_page", "governance");
|
||||||
|
|
||||||
// Add user to context (will always be available with our mock user)
|
// Add user to context (will always be available with our mock user)
|
||||||
let user = Self::get_user_from_session(&session).unwrap();
|
let user = Self::get_user_from_session(&session).unwrap();
|
||||||
ctx.insert("user", &user);
|
ctx.insert("user", &user);
|
||||||
|
|
||||||
// In a real application, we would save the proposal to a database
|
let proposal_title = &_form.title;
|
||||||
|
let proposal_description = &_form.description;
|
||||||
|
|
||||||
|
// Use the DB-backed proposal creation
|
||||||
|
// Parse voting_start_date and voting_end_date from the form (YYYY-MM-DD expected)
|
||||||
|
let voting_start_date = _form.voting_start_date.as_ref().and_then(|s| {
|
||||||
|
chrono::NaiveDate::parse_from_str(s, "%Y-%m-%d")
|
||||||
|
.ok()
|
||||||
|
.and_then(|d| d.and_hms_opt(0, 0, 0))
|
||||||
|
.map(|naive| chrono::Utc.from_utc_datetime(&naive))
|
||||||
|
});
|
||||||
|
let voting_end_date = _form.voting_end_date.as_ref().and_then(|s| {
|
||||||
|
chrono::NaiveDate::parse_from_str(s, "%Y-%m-%d")
|
||||||
|
.ok()
|
||||||
|
.and_then(|d| d.and_hms_opt(23, 59, 59))
|
||||||
|
.map(|naive| chrono::Utc.from_utc_datetime(&naive))
|
||||||
|
});
|
||||||
|
|
||||||
|
// Extract user id and name from serde_json::Value
|
||||||
|
let user_id = user
|
||||||
|
.get("id")
|
||||||
|
.and_then(|v| v.as_i64())
|
||||||
|
.unwrap_or(1)
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
match proposals::create_new_proposal(
|
||||||
|
&user_id,
|
||||||
|
proposal_title,
|
||||||
|
proposal_description,
|
||||||
|
voting_start_date,
|
||||||
|
voting_end_date,
|
||||||
|
) {
|
||||||
|
Ok((proposal_id, saved_proposal)) => {
|
||||||
|
println!(
|
||||||
|
"Proposal saved to DB: ID={}, title={:?}",
|
||||||
|
proposal_id, saved_proposal.title
|
||||||
|
);
|
||||||
|
ctx.insert("success", "Proposal created successfully!");
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
println!("Failed to save proposal: {err}");
|
||||||
|
ctx.insert("error", &format!("Failed to save proposal: {err}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// For now, we'll just redirect to the proposals page with a success message
|
// For now, we'll just redirect to the proposals page with a success message
|
||||||
ctx.insert("success", "Proposal created successfully!");
|
|
||||||
|
|
||||||
// Get mock proposals
|
// Get mock proposals
|
||||||
let proposals = Self::get_mock_proposals();
|
let proposals = Self::get_mock_proposals();
|
||||||
ctx.insert("proposals", &proposals);
|
ctx.insert("proposals", &proposals);
|
||||||
|
|
||||||
render_template(&tmpl, "governance/proposals.html", &ctx)
|
render_template(&tmpl, "governance/proposals.html", &ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,47 +232,54 @@ impl GovernanceController {
|
|||||||
path: web::Path<String>,
|
path: web::Path<String>,
|
||||||
_form: web::Form<VoteForm>,
|
_form: web::Form<VoteForm>,
|
||||||
tmpl: web::Data<Tera>,
|
tmpl: web::Data<Tera>,
|
||||||
session: Session
|
session: Session,
|
||||||
) -> Result<impl Responder> {
|
) -> Result<impl Responder> {
|
||||||
let proposal_id = path.into_inner();
|
let proposal_id = path.into_inner();
|
||||||
|
|
||||||
// Check if user is logged in
|
// Check if user is logged in
|
||||||
if Self::get_user_from_session(&session).is_none() {
|
if Self::get_user_from_session(&session).is_none() {
|
||||||
return Ok(HttpResponse::Found().append_header(("Location", "/login")).finish());
|
return Ok(HttpResponse::Found()
|
||||||
|
.append_header(("Location", "/login"))
|
||||||
|
.finish());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ctx = tera::Context::new();
|
let mut ctx = tera::Context::new();
|
||||||
ctx.insert("active_page", "governance");
|
ctx.insert("active_page", "governance");
|
||||||
|
|
||||||
// Add user to context if available
|
// Add user to context if available
|
||||||
if let Some(user) = Self::get_user_from_session(&session) {
|
if let Some(user) = Self::get_user_from_session(&session) {
|
||||||
ctx.insert("user", &user);
|
ctx.insert("user", &user);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mock proposal detail
|
// Get mock proposal detail
|
||||||
let proposal = Self::get_mock_proposal_by_id(&proposal_id);
|
let proposal = Self::get_mock_proposal_by_id(&proposal_id);
|
||||||
if let Some(proposal) = proposal {
|
if let Some(proposal) = proposal {
|
||||||
ctx.insert("proposal", &proposal);
|
ctx.insert("proposal", &proposal);
|
||||||
ctx.insert("success", "Your vote has been recorded!");
|
ctx.insert("success", "Your vote has been recorded!");
|
||||||
|
|
||||||
// Get mock votes for this proposal
|
// Get mock votes for this proposal
|
||||||
let votes = Self::get_mock_votes_for_proposal(&proposal_id);
|
let votes = Self::get_mock_votes_for_proposal(&proposal_id);
|
||||||
ctx.insert("votes", &votes);
|
ctx.insert("votes", &votes);
|
||||||
|
|
||||||
// Get voting results
|
// Get voting results
|
||||||
let results = Self::get_mock_voting_results(&proposal_id);
|
let results = Self::get_mock_voting_results(&proposal_id);
|
||||||
ctx.insert("results", &results);
|
ctx.insert("results", &results);
|
||||||
|
|
||||||
render_template(&tmpl, "governance/proposal_detail.html", &ctx)
|
render_template(&tmpl, "governance/proposal_detail.html", &ctx)
|
||||||
} else {
|
} else {
|
||||||
// Proposal not found
|
// Proposal not found
|
||||||
ctx.insert("error", "Proposal not found");
|
ctx.insert("error", "Proposal not found");
|
||||||
// For the error page, we'll use a special case to set the status code to 404
|
// For the error page, we'll use a special case to set the status code to 404
|
||||||
match tmpl.render("error.html", &ctx) {
|
match tmpl.render("error.html", &ctx) {
|
||||||
Ok(content) => Ok(HttpResponse::NotFound().content_type("text/html").body(content)),
|
Ok(content) => Ok(HttpResponse::NotFound()
|
||||||
|
.content_type("text/html")
|
||||||
|
.body(content)),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error rendering error template: {}", e);
|
eprintln!("Error rendering error template: {}", e);
|
||||||
Err(actix_web::error::ErrorInternalServerError(format!("Error: {}", e)))
|
Err(actix_web::error::ErrorInternalServerError(format!(
|
||||||
|
"Error: {}",
|
||||||
|
e
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,15 +290,15 @@ impl GovernanceController {
|
|||||||
let mut ctx = tera::Context::new();
|
let mut ctx = tera::Context::new();
|
||||||
ctx.insert("active_page", "governance");
|
ctx.insert("active_page", "governance");
|
||||||
ctx.insert("active_tab", "my_votes");
|
ctx.insert("active_tab", "my_votes");
|
||||||
|
|
||||||
// Add user to context (will always be available with our mock user)
|
// Add user to context (will always be available with our mock user)
|
||||||
let user = Self::get_user_from_session(&session).unwrap();
|
let user = Self::get_user_from_session(&session).unwrap();
|
||||||
ctx.insert("user", &user);
|
ctx.insert("user", &user);
|
||||||
|
|
||||||
// Get mock votes for this user
|
// Get mock votes for this user
|
||||||
let votes = Self::get_mock_votes_for_user(1); // Assuming user ID 1 for mock data
|
let votes = Self::get_mock_votes_for_user(1); // Assuming user ID 1 for mock data
|
||||||
ctx.insert("votes", &votes);
|
ctx.insert("votes", &votes);
|
||||||
|
|
||||||
render_template(&tmpl, "governance/my_votes.html", &ctx)
|
render_template(&tmpl, "governance/my_votes.html", &ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +365,7 @@ impl GovernanceController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mock data generation methods
|
// Mock data generation methods
|
||||||
|
|
||||||
/// Generate mock proposals for testing
|
/// Generate mock proposals for testing
|
||||||
fn get_mock_proposals() -> Vec<Proposal> {
|
fn get_mock_proposals() -> Vec<Proposal> {
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
@ -489,11 +553,13 @@ impl GovernanceController {
|
|||||||
updated_at: Utc::now() - Duration::days(5),
|
updated_at: Utc::now() - Duration::days(5),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
let proposals = Self::get_mock_proposals();
|
let proposals = Self::get_mock_proposals();
|
||||||
votes.into_iter()
|
votes
|
||||||
|
.into_iter()
|
||||||
.filter_map(|vote| {
|
.filter_map(|vote| {
|
||||||
proposals.iter()
|
proposals
|
||||||
|
.iter()
|
||||||
.find(|p| p.id == vote.proposal_id)
|
.find(|p| p.id == vote.proposal_id)
|
||||||
.map(|p| (vote.clone(), p.clone()))
|
.map(|p| (vote.clone(), p.clone()))
|
||||||
})
|
})
|
||||||
@ -504,11 +570,11 @@ impl GovernanceController {
|
|||||||
fn get_mock_voting_results(proposal_id: &str) -> VotingResults {
|
fn get_mock_voting_results(proposal_id: &str) -> VotingResults {
|
||||||
let votes = Self::get_mock_votes_for_proposal(proposal_id);
|
let votes = Self::get_mock_votes_for_proposal(proposal_id);
|
||||||
let mut results = VotingResults::new(proposal_id.to_string());
|
let mut results = VotingResults::new(proposal_id.to_string());
|
||||||
|
|
||||||
for vote in votes {
|
for vote in votes {
|
||||||
results.add_vote(&vote.vote_type);
|
results.add_vote(&vote.vote_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
results
|
results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
actix_mvc_app/src/db/mod.rs
Normal file
1
actix_mvc_app/src/db/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod proposals;
|
44
actix_mvc_app/src/db/proposals.rs
Normal file
44
actix_mvc_app/src/db/proposals.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
use chrono::{Duration, Utc};
|
||||||
|
use heromodels::db::hero::OurDB;
|
||||||
|
use heromodels::{
|
||||||
|
db::{Collection, Db},
|
||||||
|
models::governance::{Proposal, ProposalStatus},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The path to the database file. Change this as needed for your environment.
|
||||||
|
pub const DB_PATH: &str = "/tmp/ourdb_governance";
|
||||||
|
|
||||||
|
/// Returns a shared OurDB instance for the given path. You can wrap this in Arc/Mutex for concurrent access if needed.
|
||||||
|
pub fn get_db(db_path: &str) -> Result<OurDB, String> {
|
||||||
|
let db = heromodels::db::hero::OurDB::new(db_path, true).expect("Can create DB");
|
||||||
|
Ok(db)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new proposal and saves it to the database. Returns the saved proposal and its ID.
|
||||||
|
pub fn create_new_proposal(
|
||||||
|
creator_id: &str,
|
||||||
|
title: &str,
|
||||||
|
description: &str,
|
||||||
|
voting_start_date: Option<chrono::DateTime<Utc>>,
|
||||||
|
voting_end_date: Option<chrono::DateTime<Utc>>,
|
||||||
|
) -> Result<(u32, Proposal), String> {
|
||||||
|
let db = get_db(DB_PATH).expect("Can create DB");
|
||||||
|
|
||||||
|
// Create a new proposal (with auto-generated ID)
|
||||||
|
let mut proposal = Proposal::new(
|
||||||
|
None,
|
||||||
|
creator_id,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
voting_start_date.unwrap_or_else(Utc::now),
|
||||||
|
voting_end_date.unwrap_or_else(|| Utc::now() + Duration::days(7)),
|
||||||
|
);
|
||||||
|
proposal.status = ProposalStatus::Draft;
|
||||||
|
|
||||||
|
// Save the proposal to the database
|
||||||
|
let collection = db
|
||||||
|
.collection::<Proposal>()
|
||||||
|
.expect("can open proposal collection");
|
||||||
|
let (proposal_id, saved_proposal) = collection.set(&proposal).expect("can save proposal");
|
||||||
|
Ok((proposal_id, saved_proposal))
|
||||||
|
}
|
@ -8,6 +8,7 @@ use lazy_static::lazy_static;
|
|||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod controllers;
|
mod controllers;
|
||||||
|
mod db;
|
||||||
mod middleware;
|
mod middleware;
|
||||||
mod models;
|
mod models;
|
||||||
mod routes;
|
mod routes;
|
||||||
|
Loading…
Reference in New Issue
Block a user