Compare commits
24 Commits
5342f91b6c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4db5519341 | ||
|
|
5748a32b59 | ||
|
|
3f1eb33d6a | ||
|
|
3663562b8a | ||
|
|
10196cbbfb | ||
|
|
64e0168443 | ||
|
|
3bf77add88 | ||
|
|
e7a45dc46c | ||
|
|
876bcfe257 | ||
|
|
735abf577c | ||
|
|
4a8d22cb47 | ||
|
|
da99111317 | ||
|
|
31e23086ce | ||
|
|
01e95aa292 | ||
|
|
416aea14d0 | ||
|
|
3a08314824 | ||
|
|
88b7f72e81 | ||
|
|
b806fbab96 | ||
| 4a01b97780 | |||
|
|
b27cdcf579 | ||
|
|
7702419e2d | ||
|
|
c10fd3aa51 | ||
|
|
298ed6a6c9 | ||
|
|
b8f94fa0d8 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,7 @@
|
||||
Todos.db
|
||||
node_modules/
|
||||
target/
|
||||
site/
|
||||
style/output.css
|
||||
.env
|
||||
.env-prod
|
||||
|
||||
335
Cargo.lock
generated
335
Cargo.lock
generated
@@ -1,6 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
@@ -123,6 +123,12 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||
|
||||
[[package]]
|
||||
name = "attribute-derive"
|
||||
version = "0.9.2"
|
||||
@@ -491,6 +497,16 @@ dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
@@ -799,6 +815,21 @@ version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.1"
|
||||
@@ -981,6 +1012,25 @@ dependencies = [
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"http",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "2.4.1"
|
||||
@@ -1134,9 +1184,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
|
||||
checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
@@ -1193,6 +1243,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
@@ -1201,6 +1252,40 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
"smallvec",
|
||||
"tokio",
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.27.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"http",
|
||||
"hyper",
|
||||
"hyper-util",
|
||||
"rustls 0.23.12",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
"tokio-rustls 0.26.0",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http-body-util",
|
||||
"hyper",
|
||||
"hyper-util",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1210,13 +1295,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1895,6 +1983,23 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"openssl",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
@@ -2003,6 +2108,50 @@ version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"openssl-macros",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.76",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
@@ -2377,6 +2526,49 @@ version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.12.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"hyper",
|
||||
"hyper-rustls",
|
||||
"hyper-tls",
|
||||
"hyper-util",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"log",
|
||||
"mime",
|
||||
"native-tls",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustls-pemfile 2.1.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper 1.0.1",
|
||||
"system-configuration",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"windows-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "resolv-conf"
|
||||
version = "0.7.0"
|
||||
@@ -2465,6 +2657,7 @@ dependencies = [
|
||||
"leptos_router",
|
||||
"mail-send",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"sqlx",
|
||||
"tokio",
|
||||
@@ -2594,6 +2787,15 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
@@ -2610,6 +2812,29 @@ dependencies = [
|
||||
"untrusted 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"security-framework-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "self_cell"
|
||||
version = "1.0.4"
|
||||
@@ -3202,6 +3427,30 @@ name = "sync_wrapper"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"system-configuration-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration-sys"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
@@ -3319,6 +3568,16 @@ dependencies = [
|
||||
"syn 2.0.76",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-native-tls"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
|
||||
dependencies = [
|
||||
"native-tls",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.24.1"
|
||||
@@ -3533,6 +3792,12 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "typed-builder"
|
||||
version = "0.18.2"
|
||||
@@ -3679,6 +3944,15 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
|
||||
dependencies = [
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
@@ -3693,24 +3967,24 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.93"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
|
||||
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.93"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
|
||||
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.76",
|
||||
@@ -3731,9 +4005,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.93"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
|
||||
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -3741,9 +4015,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.93"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
|
||||
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3754,9 +4028,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.93"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
|
||||
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-streams"
|
||||
@@ -3846,6 +4123,36 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-registry"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
|
||||
dependencies = [
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
|
||||
dependencies = [
|
||||
"windows-result",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
|
||||
@@ -11,13 +11,14 @@ axum = { version = "0.7", optional = true }
|
||||
jsonwebtoken = { version = "9", optional = true }
|
||||
tokio = { version = "1.39", features = ["rt-multi-thread"], optional = true }
|
||||
tower = { version = "0.4", optional = true }
|
||||
tower-http = { version = "0.5", features = ["fs", "trace"], optional = true }
|
||||
tower-http = { version = "0.5", features = ["fs", "trace", "cors"], optional = true }
|
||||
sqlx = { version = "0.8", features = [
|
||||
"runtime-tokio-rustls",
|
||||
"sqlite",
|
||||
"mysql",
|
||||
"chrono",
|
||||
], optional = true }
|
||||
reqwest = { version = "0.12", features = ["json"] }
|
||||
mail-send = { version = "0.4.7", optional = true }
|
||||
regex = { version = "1.10", optional = true }
|
||||
|
||||
|
||||
15
Makefile
15
Makefile
@@ -1,11 +1,8 @@
|
||||
deploy:
|
||||
install:
|
||||
git pull
|
||||
npx tailwindcss -i ./input.css -o ./style/output.css --minify
|
||||
tac Cargo.toml | sed '1s/^.//' | tac > fichier_temp.txt && mv fichier_temp.txt Cargo.toml
|
||||
#cargo leptos build
|
||||
wasm-pack build --target=web --no-default-features --features=hydrate
|
||||
sudo systemctl stop rust_leptos.service
|
||||
cargo sqlx migrate run
|
||||
cargo leptos build --release
|
||||
tac Cargo.toml | sed '1s/^/#/' | tac > fichier_temp.txt && mv fichier_temp.txt Cargo.toml
|
||||
ssh raspiwork "sudo systemctl stop rust_leptos.service"
|
||||
scp target/aarch64-unknown-linux-gnu/release/rust_leptos raspiwork:/var/www/rust_leptos/rust_leptos
|
||||
#scp target/aarch64-unknown-linux-gnu/debug/rust_leptos raspiwork:/var/www/rust_leptos/rust_leptos
|
||||
scp -r target/site raspiwork:/var/www/rust_leptos/
|
||||
ssh raspiwork "sudo systemctl start rust_leptos.service"
|
||||
sudo systemctl start rust_leptos.service
|
||||
|
||||
23
README.md
23
README.md
@@ -1,24 +1,30 @@
|
||||
# install
|
||||
```
|
||||
cargo install sqlx-cli
|
||||
wasm-pack build --target=web --debug --no-default-features --features=hydrate
|
||||
cargo run --no-default-features --features=ssr
|
||||
```
|
||||
|
||||
# dev
|
||||
```
|
||||
source .env
|
||||
cargo sqlx migrate run
|
||||
cargo leptos watch
|
||||
```
|
||||
|
||||
npx tailwindcss -i ./input.css -o ./style/output.css --watch
|
||||
```npx tailwindcss -i ./input.css -o ./style/output.css --watch```
|
||||
|
||||
# deploy
|
||||
|
||||
example of systemd config
|
||||
```
|
||||
[Unit]
|
||||
Description=Running rust script
|
||||
After=multi-user.target
|
||||
Description=Home website
|
||||
After=mysql.service
|
||||
|
||||
[Service]
|
||||
EnvironmentFile=/home/pi/Scripts/rust_mosquitto/target/release/.env
|
||||
ExecStart=/home/pi/Scripts/rust_mosquitto/target/release/rust_mosquitto
|
||||
EnvironmentFile=/var/www/rust_leptos/.env
|
||||
ExecStart=/var/www/rust_leptos/rust_leptos
|
||||
Type=simple
|
||||
|
||||
[Install]
|
||||
@@ -32,11 +38,16 @@ WantedBy=multi-user.target
|
||||
[x] router
|
||||
[ ] value gestion des erreurs
|
||||
[x] deploy
|
||||
[x] hydratation
|
||||
[x] liens icones
|
||||
[ ] liens position
|
||||
[ ] liens edition
|
||||
|
||||
## pages
|
||||
[x] liens
|
||||
[x] formulaire
|
||||
[ ] recap capteurs
|
||||
[x] recap capteurs
|
||||
[x] volets
|
||||
|
||||
## style
|
||||
[Simple dark dashboard](https://dribbble.com/shots/10090105-Dashboard-UI/attachments/2097885?mode=media)
|
||||
|
||||
24
input.css
24
input.css
@@ -1,6 +1,24 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@import "tailwindcss";
|
||||
|
||||
@theme {
|
||||
/*--font-display: "Satoshi", "sans-serif";*/
|
||||
/*--breakpoint-3xl: 120rem;*/
|
||||
--color-prim: oklch(27.95% 0.0085 255.57);
|
||||
--color-prim-light: oklch(30.28% 0.0092 248.13);
|
||||
--color-second: oklch(99.11% 0 0);
|
||||
--color-second-dark: oklch(66.55% 0.0038 247.88);
|
||||
--color-third: oklch(61.47% 0.2541 24.53);
|
||||
--color-third-light: oklch(64.41% 0.2245 24.53);
|
||||
--color-fourth: oklch(83.29% 0.161 80.36);
|
||||
--color-green: oklch(76.97% 0.261916 142.4953);
|
||||
|
||||
--text-4xl: 4rem;
|
||||
--text-4xl--line-height: calc(2.5 / 2.25);
|
||||
}
|
||||
|
||||
body {
|
||||
@apply dark:bg-prim dark:text-second;
|
||||
}
|
||||
|
||||
.active-link {
|
||||
@apply text-third border-b;
|
||||
|
||||
2
migrations/20250604201415_add_icon_to_links.down.sql
Normal file
2
migrations/20250604201415_add_icon_to_links.down.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE links
|
||||
DROP COLUMN icon;
|
||||
2
migrations/20250604201415_add_icon_to_links.up.sql
Normal file
2
migrations/20250604201415_add_icon_to_links.up.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE links
|
||||
ADD COLUMN icon TEXT NOT NULL DEFAULT "missing" AFTER link;
|
||||
1881
package-lock.json
generated
Normal file
1881
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
9
package.json
Normal file
9
package.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@tailwindcss/cli": "^4.0.14",
|
||||
"@tailwindcss/vite": "^4.0.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tailwindcss": "^4.0.14"
|
||||
}
|
||||
}
|
||||
24
src/app.rs
24
src/app.rs
@@ -13,19 +13,28 @@ pub fn App() -> impl IntoView {
|
||||
|
||||
<Title text="Bienvenue à la maison"/>
|
||||
|
||||
<div class="dark:bg-prim dark:text-second h-screen flex flex-col">
|
||||
<div class="h-screen flex flex-col">
|
||||
<Router>
|
||||
<Navigation />
|
||||
<main class="flex-1">
|
||||
<Routes>
|
||||
<Route path="/" view=move || view! { <Home/> }/>
|
||||
<Route path="/liens" view=move || view! { <Links/> }/>
|
||||
<Route path="/formulaire" view=move || view! { <FormValues/> }/>
|
||||
<Route path="/donnees" view=move || view! { <Data/> }/>
|
||||
<Route path="/volets" view=move || view! { <Shutters/> }/>
|
||||
//<Route path="/*any" view=move || view! { <NotFound/> }/>
|
||||
</Routes>
|
||||
</main>
|
||||
<footer>Footer</footer>
|
||||
<footer>
|
||||
//<span>Footer</span>
|
||||
//<ul>
|
||||
// <li class="xs:block sm:hidden md:hidden lg:hidden xl:hidden">xs</li>
|
||||
// <li class="sm:block xs:hidden md:hidden lg:hidden xl:hidden">sm</li>
|
||||
// <li class="md:block xs:hidden sm:hidden lg:hidden xl:hidden">md</li>
|
||||
// <li class="lg:block xs:hidden sm:hidden md:hidden xl:hidden">lg</li>
|
||||
// <li class="xl:block xs:hidden sm:hidden mg:hidden lg:hidden">xl</li>
|
||||
// <li class="md:hidden lg:hidden xl:hidden">sm</li>
|
||||
//</ul>
|
||||
</footer>
|
||||
</Router>
|
||||
</div>
|
||||
}
|
||||
@@ -43,12 +52,9 @@ pub fn Navigation() -> impl IntoView {
|
||||
<a href="/liens"
|
||||
class="hover:text-third hover:border-b border-third inline-block transition-colors"
|
||||
class:active-link=move || location.pathname.get() == "/liens">Liens</a>
|
||||
<a href="/formulaire"
|
||||
class="hover:text-third hover:border-b border-third inline-block transition-colors"
|
||||
class:active-link=move || location.pathname.get() == "/formulaire">Formulaire</a>
|
||||
<a href="/donnees"
|
||||
<a href="/volets"
|
||||
class="hover:text-third hover:border-b border-third inline-block transition-colors"
|
||||
class:active-link=move || location.pathname.get() == "/donnees">Données</a>
|
||||
class:active-link=move || location.pathname.get() == "/volets">Volets</a>
|
||||
</nav>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ async fn create_pool() -> sqlx::MySqlPool {
|
||||
.await
|
||||
.expect("could not connect to database_url");
|
||||
|
||||
sqlx::migrate!()
|
||||
/*sqlx::migrate!()
|
||||
.run(&pool)
|
||||
.await
|
||||
.expect("migrations failed");
|
||||
.expect("migrations failed");*/
|
||||
|
||||
pool
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ pub struct Link {
|
||||
pub id: u64,
|
||||
pub link: String,
|
||||
pub name: String,
|
||||
pub icon: String,
|
||||
position: i64,
|
||||
created_at: String,
|
||||
}
|
||||
@@ -14,11 +15,13 @@ impl Link {
|
||||
pub async fn insert(
|
||||
name: String,
|
||||
link: String,
|
||||
icon: String,
|
||||
) -> Result<sqlx::mysql::MySqlQueryResult, sqlx::Error> {
|
||||
sqlx::query!(
|
||||
"INSERT INTO links (name, link, position, created_at) VALUES (?, ?, (SELECT COALESCE(MAX(position) + 1, 1) FROM links lin), ?)",
|
||||
"INSERT INTO links (name, link, icon, position, created_at) VALUES (?, ?, ?, (SELECT COALESCE(MAX(position) + 1, 1) FROM links lin), ?)",
|
||||
name,
|
||||
link,
|
||||
icon,
|
||||
chrono::Local::now().naive_local(),
|
||||
)
|
||||
.execute(crate::database::get_db())
|
||||
@@ -27,11 +30,12 @@ impl Link {
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
pub async fn get_all() -> Result<Vec<Self>, sqlx::Error> {
|
||||
sqlx::query!("SELECT id, name, link, position, created_at FROM links ORDER BY position")
|
||||
sqlx::query!("SELECT id, name, link, icon, position, created_at FROM links ORDER BY position")
|
||||
.map(|x| Self {
|
||||
id: x.id,
|
||||
name: x.name,
|
||||
link: x.link,
|
||||
icon: x.icon,
|
||||
position: x.position,
|
||||
created_at: x.created_at.format("%d/%m/%Y %H:%M").to_string(),
|
||||
})
|
||||
@@ -45,13 +49,14 @@ impl Link {
|
||||
direction: String,
|
||||
) -> Result<sqlx::mysql::MySqlQueryResult, sqlx::Error> {
|
||||
let link = sqlx::query!(
|
||||
"SELECT id, name, link, position, created_at FROM links WHERE id = ?",
|
||||
"SELECT id, name, link, icon, position, created_at FROM links WHERE id = ?",
|
||||
link_id
|
||||
)
|
||||
.map(|x| Self {
|
||||
id: x.id,
|
||||
name: x.name,
|
||||
link: x.link,
|
||||
icon: x.icon,
|
||||
position: x.position,
|
||||
created_at: x.created_at.format("%d/%m/%Y %H:%M").to_string(),
|
||||
})
|
||||
@@ -89,6 +94,24 @@ impl Link {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
pub async fn update(
|
||||
id: String,
|
||||
name: String,
|
||||
link: String,
|
||||
icon: String,
|
||||
) -> Result<sqlx::mysql::MySqlQueryResult, sqlx::Error> {
|
||||
sqlx::query!(
|
||||
"UPDATE links SET name = ?, link = ?, icon = ? WHERE id = ?",
|
||||
name,
|
||||
link,
|
||||
icon,
|
||||
id
|
||||
)
|
||||
.execute(crate::database::get_db())
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
pub async fn destroy(id: String) -> Result<sqlx::mysql::MySqlQueryResult, sqlx::Error> {
|
||||
sqlx::query!("DELETE FROM links WHERE id = ? ", id,)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
mod link;
|
||||
mod value;
|
||||
|
||||
pub use link::Link;
|
||||
pub use value::Value;
|
||||
pub use value::OPTIONS;
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Option {
|
||||
pub value: &'static str,
|
||||
pub name: &'static str,
|
||||
service: &'static str,
|
||||
device: &'static str,
|
||||
r_type: &'static str,
|
||||
}
|
||||
|
||||
pub const OPTIONS: &[Option] = &[
|
||||
Option {
|
||||
value: "citerne",
|
||||
name: "Citerne",
|
||||
service: "home",
|
||||
device: "citerne",
|
||||
r_type: "height",
|
||||
},
|
||||
Option {
|
||||
value: "eau",
|
||||
name: "Eau",
|
||||
service: "home",
|
||||
device: "eau",
|
||||
r_type: "volume",
|
||||
},
|
||||
Option {
|
||||
value: "elec-hight",
|
||||
name: "Electricité heure pleine",
|
||||
service: "home",
|
||||
device: "elec",
|
||||
r_type: "pleine",
|
||||
},
|
||||
Option {
|
||||
value: "elec-low",
|
||||
name: "Electricité heure creuse",
|
||||
service: "home",
|
||||
device: "elec",
|
||||
r_type: "creuse",
|
||||
},
|
||||
];
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Value {
|
||||
id: i32,
|
||||
service: String,
|
||||
capteur: String,
|
||||
type_donnee: String,
|
||||
pub donnee: String,
|
||||
pub date_donnee: String,
|
||||
}
|
||||
|
||||
impl Value {
|
||||
#[cfg(feature = "ssr")]
|
||||
pub async fn insert(
|
||||
device: String,
|
||||
value: String,
|
||||
) -> Result<sqlx::mysql::MySqlQueryResult, sqlx::Error> {
|
||||
let option = match find_option(&device) {
|
||||
Ok(option) => option,
|
||||
Err(err) => panic!("{}", err),
|
||||
};
|
||||
|
||||
sqlx::query!(
|
||||
"INSERT INTO donnees(service, capteur, type, donnee, date_donnee) VALUES (?, ?, ?, ?, ?)",
|
||||
option.service,
|
||||
option.device,
|
||||
option.r_type,
|
||||
value,
|
||||
chrono::Local::now().naive_local(),
|
||||
)
|
||||
.execute(crate::database::get_db())
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
pub async fn get_one(topic: String) -> Result<Self, sqlx::Error> {
|
||||
let split: Vec<&str> = topic.split("/").collect();
|
||||
let unknow_value = Value {
|
||||
id: 0,
|
||||
service: "".to_string(),
|
||||
capteur: "".to_string(),
|
||||
type_donnee: "".to_string(),
|
||||
donnee: "--".to_string(),
|
||||
date_donnee: "--:--".to_string(),
|
||||
};
|
||||
|
||||
if split.len() == 3 {
|
||||
let res = sqlx::query!(
|
||||
"SELECT * FROM donnees WHERE service = ? AND capteur = ? AND type = ? ORDER BY date_donnee DESC LIMIT 1",
|
||||
split[0],
|
||||
split[1],
|
||||
split[2],
|
||||
//chrono::Local::now().naive_local(),
|
||||
)
|
||||
.map(|x| Self {
|
||||
id: x.id,
|
||||
service: x.service,
|
||||
capteur: x.capteur,
|
||||
type_donnee: x.r#type,
|
||||
donnee: x.donnee,
|
||||
date_donnee: x.date_donnee.format("%H:%M").to_string(),
|
||||
})
|
||||
.fetch_one(crate::database::get_db())
|
||||
.await;
|
||||
|
||||
match res {
|
||||
Ok(res) => Ok(res),
|
||||
Err(_) => Ok(unknow_value)
|
||||
}
|
||||
} else {
|
||||
Ok(unknow_value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn find_option(value: &str) -> Result<&Option, &str> {
|
||||
OPTIONS
|
||||
.iter()
|
||||
.find(|&option| option.value == value)
|
||||
.ok_or("No option found with the given value")
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
use leptos::*;
|
||||
use leptos_meta::*;
|
||||
|
||||
use crate::models::Value;
|
||||
|
||||
#[component]
|
||||
pub fn Data() -> impl IntoView {
|
||||
view! {
|
||||
<Title text="Capteurs"/>
|
||||
|
||||
<ul class="flex gap-5 flex-wrap m-5">
|
||||
<ValueCard location="Bureau".to_string()
|
||||
sensor="Température".to_string()
|
||||
unity="°C".to_string()
|
||||
color="text-third".to_string()
|
||||
topic="maison/bureau/temperature".to_string() />
|
||||
<ValueCard location="Bureau".to_string()
|
||||
sensor="CO2".to_string()
|
||||
unity="ppm".to_string()
|
||||
color="text-green".to_string()
|
||||
topic="maison/bureau/co2".to_string() />
|
||||
<ValueCard location="Bureau".to_string()
|
||||
sensor="Pression".to_string()
|
||||
unity="hPa".to_string()
|
||||
color="text-fourth".to_string()
|
||||
topic="maison/bureau/pression".to_string() />
|
||||
<ValueCard location="Extérieur".to_string()
|
||||
sensor="Température".to_string()
|
||||
unity="°C".to_string()
|
||||
color="text-third".to_string()
|
||||
topic="meteo/exterieur/temperature".to_string() />
|
||||
<ValueCard location="Véranda".to_string()
|
||||
sensor="Température".to_string()
|
||||
unity="°C".to_string()
|
||||
color="text-third".to_string()
|
||||
topic="meteo/veranda/temperature".to_string() />
|
||||
</ul>
|
||||
}
|
||||
}
|
||||
|
||||
#[server(ValueAction, "/api")]
|
||||
pub async fn get_value(topic: String) -> Result<crate::models::Value, ServerFnError> {
|
||||
crate::models::Value::get_one(topic).await.map_err(|x| {
|
||||
let err = format!("Error while posting a comment: {x:?}");
|
||||
tracing::error!("{err}");
|
||||
ServerFnError::ServerError("Could not post a comment, try again later".into())
|
||||
})
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn ValueCard(topic: String, location: String, sensor: String, unity: String, color: String) -> impl IntoView {
|
||||
let (sensor_props, _) = create_signal((location, sensor, unity, color));
|
||||
let value = create_resource(
|
||||
move || topic.clone(),
|
||||
|topic| async { get_value(topic).await },
|
||||
);
|
||||
|
||||
view! {
|
||||
<li class="flex p-3 w-80 bg-prim-light rounded-lg justify-between">
|
||||
<Suspense fallback=move || view! { <p>"Loading Value"</p> }>
|
||||
<ErrorBoundary fallback=|_| {
|
||||
view! { <p class="error-messages text-xs-center">"Something went wrong, please try again later."</p>}
|
||||
}>
|
||||
{move || {
|
||||
value.get().map(move |x| {
|
||||
x.map(move |result| {
|
||||
view! {
|
||||
<Card sensor_props value=result />
|
||||
}
|
||||
})
|
||||
})
|
||||
}}
|
||||
</ErrorBoundary>
|
||||
</Suspense>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Card(sensor_props: ReadSignal<(String, String, String, String)>, value: Value) -> impl IntoView {
|
||||
let (location, sensor, unity, color) = sensor_props.get();
|
||||
view! {
|
||||
<div class="flex flex-col">
|
||||
<div class="text-xl flex-1">{location}</div>
|
||||
<div class="text-second-dark">{sensor}</div>
|
||||
<div class="text-second-dark text-sm">{value.date_donnee}</div>
|
||||
</div>
|
||||
|
||||
<h2 class="text-4xl flex ml-5 -my-2 text-center {color}">
|
||||
<strong>{value.donnee}</strong>
|
||||
<span class="text-2xl mt-5">{unity}</span>
|
||||
</h2>
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,8 @@ pub async fn get_links() -> Result<Vec<crate::models::Link>, ServerFnError> {
|
||||
}
|
||||
|
||||
#[server(LinkAction, "/api")]
|
||||
pub async fn add_value(name: String, link: String) -> Result<(), ServerFnError> {
|
||||
crate::models::Link::insert(name, link)
|
||||
pub async fn add_value(name: String, link: String, icon: String) -> Result<(), ServerFnError> {
|
||||
crate::models::Link::insert(name, link, icon)
|
||||
.await
|
||||
.map(|_| ())
|
||||
.map_err(|x| {
|
||||
@@ -26,52 +26,28 @@ pub async fn add_value(name: String, link: String) -> Result<(), ServerFnError>
|
||||
|
||||
#[component]
|
||||
pub fn Links() -> impl IntoView {
|
||||
let (show, set_show) = create_signal(false);
|
||||
let (show_form, set_show_form) = create_signal(false);
|
||||
let (edit_link, set_edit_link) = create_signal::<Option<crate::models::Link>>(None);
|
||||
let (edit, set_edit) = create_signal(false);
|
||||
|
||||
let link_action = create_server_action::<LinkAction>();
|
||||
let update_action = create_server_action::<UpdateLinkAction>();
|
||||
|
||||
let result = link_action.version();
|
||||
let reset_form = create_rw_signal("");
|
||||
let update_result = update_action.version();
|
||||
|
||||
let links = create_resource(
|
||||
move || (result.get()),
|
||||
move || (result.get(), update_result.get()),
|
||||
move |_| async move {
|
||||
reset_form.set("");
|
||||
set_show.set(false);
|
||||
set_show_form.set(false);
|
||||
set_edit_link.set(None);
|
||||
get_links().await
|
||||
},
|
||||
);
|
||||
|
||||
let form = move || {
|
||||
show.get().then(|| {
|
||||
view! { <div class="my-0 mx-auto w-72 p-6 bg-prim-light rounded-lg">
|
||||
<h2 class="pb-6 text-2xl text-center">"Ajout d'un lien"</h2>
|
||||
<ActionForm action=link_action attr:class="">
|
||||
<div>
|
||||
<label class="block mt-3 mb-1">"Nom"</label>
|
||||
<input type="text"
|
||||
name="name"
|
||||
prop:value=move || reset_form.get()
|
||||
class="text-center bg-prim border border-transparent rounded-lg focus:border-third px-2 py-2 w-60" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block mt-3 mb-1">"Lien"</label>
|
||||
<input type="url"
|
||||
name="link"
|
||||
prop:value=move || reset_form.get()
|
||||
class="text-center bg-prim border border-transparent rounded-lg focus:border-third px-2 py-2 w-60" />
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="bg-third hover:bg-third-light rounded-lg transition-colors px-2 py-1 w-60 my-5">"Valider"</button>
|
||||
</div>
|
||||
</ActionForm>
|
||||
</div> }
|
||||
})
|
||||
};
|
||||
|
||||
view! {
|
||||
<Title text="Liens"/>
|
||||
<ul class="flex flex-wrap gap-5 m-5 justify-center">
|
||||
<ul class="flex gap-5 m-5 flex-wrap justify-center">
|
||||
<Suspense fallback=move || view! {<p>"Loading Comments from the article"</p> }>
|
||||
<ErrorBoundary fallback=|_| {
|
||||
view! { <p class="error-messages text-xs-center">"Something went wrong."</p>}
|
||||
@@ -83,7 +59,7 @@ pub fn Links() -> impl IntoView {
|
||||
children=move |(_, link)| {
|
||||
let link = create_rw_signal(link);
|
||||
view!{
|
||||
<Link link edit links />
|
||||
<Link link edit set_edit_link set_show_form links />
|
||||
}
|
||||
}/>
|
||||
}
|
||||
@@ -93,13 +69,23 @@ pub fn Links() -> impl IntoView {
|
||||
</ul>
|
||||
|
||||
<div class="flex justify-end gap-5 mx-5">
|
||||
<button on:click=move |_| {set_edit.set(!edit.get())} class="bg-prim-light hover:bg-prim-lightest rounded-full px-5 py-3 text-second-dark hover:text-third transition-colors">"Edit"</button>
|
||||
<button on:click=move |_| {set_show.set(true)} class="bg-prim-light hover:bg-prim-lightest rounded-full px-5 py-3 text-second-dark hover:text-third transition-colors">"Ajouter un lien +"</button>
|
||||
<button on:click=move |_| {set_edit.set(!edit.get())} class="bg-prim-light hover:bg-prim-lightest rounded-full px-5 py-3 text-second-dark hover:text-third transition-colors">"Modifier"</button>
|
||||
<button on:click=move |_| {
|
||||
set_edit_link.set(None);
|
||||
set_show_form.set(true);
|
||||
} class="bg-prim-light hover:bg-prim-lightest rounded-full px-5 py-3 text-second-dark hover:text-third transition-colors">"Ajouter un lien +"</button>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center m-5">
|
||||
{form}
|
||||
</div>
|
||||
{move || {
|
||||
show_form.get().then(|| {
|
||||
view! { <LinkFormModal
|
||||
link=edit_link.get()
|
||||
set_show=set_show_form
|
||||
add_action=link_action
|
||||
update_action=update_action
|
||||
/> }
|
||||
})
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,21 +105,30 @@ pub async fn change_position(link_id: String, direction: String) -> Result<(), S
|
||||
fn Link<T: 'static + Clone, S: 'static>(
|
||||
link: RwSignal<crate::models::Link>,
|
||||
edit: ReadSignal<bool>,
|
||||
set_edit_link: WriteSignal<Option<crate::models::Link>>,
|
||||
set_show_form: WriteSignal<bool>,
|
||||
links: Resource<T, S>,
|
||||
) -> impl IntoView {
|
||||
view! {
|
||||
<li>
|
||||
<a class="bg-prim-light hover:bg-prim-lightest border-b hover:border-third border-transparent text-xl rounded-lg text-center hover:text-third transition-colors px-5 py-4 min-w-60 inline-block"
|
||||
<li class="w-44 lg:w-fit">
|
||||
<a class="bg-prim-light container flex flex-col lg:gap-2 lg:flex-row w-full item-center hover:scale-110 transition hover:bg-prim-lightest border-b hover:border-third border-transparent rounded-lg text-center hover:text-third px-5 py-4"
|
||||
target="_blank"
|
||||
href={move || link.with(|x| x.link.to_string())}>
|
||||
{move || link.with(|x| x.name.to_string())}
|
||||
<img src={move || link.with(|x| x.icon.to_string())}
|
||||
alt={move || link.with(|x| x.name.to_string())}
|
||||
class="size-32 lg:size-10 object-cover overflow-hidden" />
|
||||
|
||||
<span class="flex-1 text-2xl mt-2 lg:mt-0 flex justify-center items-center">{move || link.with(|x| x.name.to_string())}</span>
|
||||
</a>
|
||||
{move || {
|
||||
edit.get().then(|| {
|
||||
view! { <div class="bg-third border border-transparent rounded-b-lg flex justify-between">
|
||||
<MoveButton id=link.with(|x| x.id.to_string()) value="prev".to_string() label="<".to_string() links=links />
|
||||
<button class="block px-2 py-1 flex-1 hover:bg-third-light"
|
||||
//on:click=move |_| {set_show.set(true)}
|
||||
on:click=move |_| {
|
||||
set_edit_link.set(Some(link.get()));
|
||||
set_show_form.set(true);
|
||||
}
|
||||
>"Editer"</button>
|
||||
<DeleteButton id=link.with(|x| x.id.to_string()) links=links />
|
||||
<MoveButton id=link.with(|x| x.id.to_string()) value="next".to_string() label=">".to_string() links=links />
|
||||
@@ -198,3 +193,124 @@ fn DeleteButton<T: 'static + Clone, S: 'static>(
|
||||
</ActionForm>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[server(UpdateLinkAction, "/api")]
|
||||
pub async fn update_link(id: String, name: String, link: String, icon: String) -> Result<(), ServerFnError> {
|
||||
crate::models::Link::update(id, name, link, icon)
|
||||
.await
|
||||
.map(|_| ())
|
||||
.map_err(|x| {
|
||||
let err = format!("Error while updating a link: {x:?}");
|
||||
tracing::error!("{err}");
|
||||
ServerFnError::ServerError("Could not update the link, try again later".into())
|
||||
})
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn LinkFormModal(
|
||||
link: Option<crate::models::Link>,
|
||||
set_show: WriteSignal<bool>,
|
||||
add_action: Action<LinkAction, Result<(), ServerFnError>>,
|
||||
update_action: Action<UpdateLinkAction, Result<(), ServerFnError>>,
|
||||
) -> impl IntoView {
|
||||
let is_edit = link.is_some();
|
||||
let (name, set_name) = create_signal(link.as_ref().map(|x| x.name.clone()).unwrap_or_default());
|
||||
let (link_url, set_link_url) = create_signal(link.as_ref().map(|x| x.link.clone()).unwrap_or_default());
|
||||
let (icon, set_icon) = create_signal(link.as_ref().map(|x| x.icon.clone()).unwrap_or_default());
|
||||
let link_id = link.as_ref().map(|x| x.id.to_string());
|
||||
|
||||
view! {
|
||||
<div class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||
<div class="bg-prim-light p-6 rounded-lg w-96">
|
||||
<h2 class="pb-6 text-2xl text-center">
|
||||
{if is_edit { "Édition du lien" } else { "Ajout d'un lien" }}
|
||||
</h2>
|
||||
|
||||
{if is_edit {
|
||||
view! {
|
||||
<ActionForm action=update_action>
|
||||
<input name="id" type="hidden" value={link_id.unwrap_or_default()} />
|
||||
<LinkFormFields
|
||||
name=name
|
||||
set_name=set_name
|
||||
link_url=link_url
|
||||
set_link_url=set_link_url
|
||||
icon=icon
|
||||
set_icon=set_icon
|
||||
/>
|
||||
<FormButtons set_show=set_show />
|
||||
</ActionForm>
|
||||
}.into_view()
|
||||
} else {
|
||||
view! {
|
||||
<ActionForm action=add_action>
|
||||
<LinkFormFields
|
||||
name=name
|
||||
set_name=set_name
|
||||
link_url=link_url
|
||||
set_link_url=set_link_url
|
||||
icon=icon
|
||||
set_icon=set_icon
|
||||
/>
|
||||
<FormButtons set_show=set_show />
|
||||
</ActionForm>
|
||||
}.into_view()
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn LinkFormFields(
|
||||
name: ReadSignal<String>,
|
||||
set_name: WriteSignal<String>,
|
||||
link_url: ReadSignal<String>,
|
||||
set_link_url: WriteSignal<String>,
|
||||
icon: ReadSignal<String>,
|
||||
set_icon: WriteSignal<String>,
|
||||
) -> impl IntoView {
|
||||
view! {
|
||||
<div>
|
||||
<label class="block mt-3 mb-1">"Nom"</label>
|
||||
<input type="text"
|
||||
name="name"
|
||||
prop:value=move || name.get()
|
||||
on:input=move |ev| set_name.set(event_target_value(&ev))
|
||||
class="text-center bg-prim border border-transparent rounded-lg focus:border-third px-2 py-2 w-full" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block mt-3 mb-1">"Lien"</label>
|
||||
<input type="url"
|
||||
name="link"
|
||||
prop:value=move || link_url.get()
|
||||
on:input=move |ev| set_link_url.set(event_target_value(&ev))
|
||||
class="text-center bg-prim border border-transparent rounded-lg focus:border-third px-2 py-2 w-full" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block mt-3 mb-1">"Icône"</label>
|
||||
<input type="url"
|
||||
name="icon"
|
||||
placeholder="http..."
|
||||
prop:value=move || icon.get()
|
||||
on:input=move |ev| set_icon.set(event_target_value(&ev))
|
||||
class="text-center bg-prim border border-transparent rounded-lg focus:border-third px-2 py-2 w-full" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn FormButtons(set_show: WriteSignal<bool>) -> impl IntoView {
|
||||
view! {
|
||||
<div class="flex gap-2 mt-5">
|
||||
<button type="button"
|
||||
on:click=move |_| set_show.set(false)
|
||||
class="bg-prim hover:bg-prim-light rounded-lg transition-colors px-2 py-1 flex-1">"Annuler"</button>
|
||||
<button type="submit"
|
||||
class="bg-third hover:bg-third-light rounded-lg transition-colors px-2 py-1 flex-1">"Valider"</button>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
mod data;
|
||||
mod link;
|
||||
mod value;
|
||||
mod shutters;
|
||||
|
||||
pub use data::*;
|
||||
pub use link::*;
|
||||
pub use value::*;
|
||||
pub use shutters::*;
|
||||
|
||||
111
src/routes/shutters.rs
Normal file
111
src/routes/shutters.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
use leptos::*;
|
||||
use leptos_meta::*;
|
||||
use reqwest::Client;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Params {
|
||||
command: String,
|
||||
shadeId: i32,
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Shutters() -> impl IntoView {
|
||||
view! {
|
||||
<Title text="Volets"/>
|
||||
|
||||
<div class="flex flex-wrap justify-center gap-2">
|
||||
<Shutter name="Cuisine".to_string() shade_id=6 />
|
||||
<Shutter name="Porte fenêtre".to_string() shade_id=2 />
|
||||
<Shutter name="Salon fenêtre".to_string() shade_id=4 />
|
||||
<Shutter name="Salon vidéo".to_string() shade_id=5 />
|
||||
<Shutter name="Bureau".to_string() shade_id=1 />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Shutter(name: String, shade_id: i32) -> impl IntoView {
|
||||
let (_response, set_response) = create_signal(None::<String>);
|
||||
|
||||
let move_up = create_action(move |_| async move {
|
||||
let client = Client::new();
|
||||
let params = Params {
|
||||
command: "up".to_string(),
|
||||
shadeId: shade_id,
|
||||
};
|
||||
let url = "http://192.168.3.34/shadeCommand";
|
||||
|
||||
match client.put(url).json(¶ms).send().await {
|
||||
Ok(resp) => {
|
||||
let text = resp.text().await.unwrap_or("Réponse vide".to_string());
|
||||
set_response.set(Some(text));
|
||||
}
|
||||
Err(e) => {
|
||||
set_response.set(Some(format!("Erreur: {:?}", e)));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let move_my = create_action(move |_| async move {
|
||||
let client = Client::new();
|
||||
let params = Params {
|
||||
command: "my".to_string(),
|
||||
shadeId: shade_id,
|
||||
};
|
||||
let url = "http://192.168.3.34/shadeCommand";
|
||||
|
||||
match client.put(url).json(¶ms).send().await {
|
||||
Ok(resp) => {
|
||||
let text = resp.text().await.unwrap_or("Réponse vide".to_string());
|
||||
set_response.set(Some(text));
|
||||
}
|
||||
Err(e) => {
|
||||
set_response.set(Some(format!("Erreur: {:?}", e)));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let move_down = create_action(move |_| async move {
|
||||
let client = Client::new();
|
||||
let params = Params {
|
||||
command: "down".to_string(),
|
||||
shadeId: shade_id,
|
||||
};
|
||||
let url = "http://192.168.3.34/shadeCommand";
|
||||
|
||||
match client.put(url).json(¶ms).send().await {
|
||||
Ok(resp) => {
|
||||
let text = resp.text().await.unwrap_or("Réponse vide".to_string());
|
||||
set_response.set(Some(text));
|
||||
}
|
||||
Err(e) => {
|
||||
set_response.set(Some(format!("Erreur: {:?}", e)));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
view! {
|
||||
<div class="bg-prim-light rounded-lg w-48 px-3">
|
||||
<div class="text-2xl text-center">{name}</div>
|
||||
<div class="flex justify-between bg-second-dark rounded-sm *:flex-1 *:transition">
|
||||
<button on:click=move |_| move_up.dispatch(()) class="hover:text-third flex justify-center focus:text-third-light">
|
||||
<Arrow class="-rotate-90 size-12 inline".to_string() />
|
||||
</button>
|
||||
<button on:click=move |_| move_my.dispatch(()) class="hover:text-third text-2xl font-bold focus:text-third-light">"My"</button>
|
||||
<button on:click=move |_| move_down.dispatch(()) class="hover:text-third flex justify-center focus:text-third-light">
|
||||
<Arrow class="rotate-90 size-12 inline".to_string() />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Arrow(class: String) -> impl IntoView {
|
||||
view! {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" class=format!("{}", class)>
|
||||
<path fill="currentColor" d="M6.23 20.23L8 22l10-10L8 2L6.23 3.77L14.46 12z"/>
|
||||
</svg>
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
use leptos::*;
|
||||
use leptos_meta::*;
|
||||
use leptos_router::*;
|
||||
|
||||
use crate::models::OPTIONS;
|
||||
|
||||
#[server(ValueAction, "/api")]
|
||||
pub async fn add_value(device: String, value: String) -> Result<(), ServerFnError> {
|
||||
crate::models::Value::insert(device, value)
|
||||
.await
|
||||
.map(|_| ())
|
||||
.map_err(|x| {
|
||||
let err = format!("Error while posting a comment: {x:?}");
|
||||
tracing::error!("{err}");
|
||||
ServerFnError::ServerError("Could not post a comment, try again later".into())
|
||||
})
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn FormValues() -> impl IntoView {
|
||||
let value_action = create_server_action::<ValueAction>();
|
||||
let result = value_action.version();
|
||||
let reset_value = create_rw_signal("");
|
||||
let _ = create_resource(
|
||||
move || (result.get()),
|
||||
move |_| async move {
|
||||
reset_value.set("");
|
||||
},
|
||||
);
|
||||
|
||||
view! {
|
||||
<Title text="Formulaire"/>
|
||||
|
||||
<div class="my-5 mx-auto w-72 p-6 bg-prim-light rounded-lg">
|
||||
<h2 class="pb-6 text-2xl text-center">"Formulaire"</h2>
|
||||
|
||||
<ActionForm action=value_action attr:class="">
|
||||
<div>
|
||||
<label class="block mt-3 mb-1">Capteur</label>
|
||||
<select name="device" class="text-center bg-prim border border-transparent rounded-lg focus:border-third px-2 py-2 w-60">
|
||||
{OPTIONS.into_iter()
|
||||
.map(|option| view! { <option value={option.value} class="px-2 py-1">{option.name}</option>})
|
||||
.collect::<Vec<_>>()}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block mt-3 mb-1">Valeur</label>
|
||||
<input name="value"
|
||||
type="number"
|
||||
step="0.01"
|
||||
prop:value=move || reset_value.get()
|
||||
class="text-center bg-prim border border-transparent rounded-lg focus:border-third px-2 py-2 w-60" />
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="bg-third hover:bg-third-light rounded-lg transition-colors px-2 py-1 w-60 my-5">Valider</button>
|
||||
</div>
|
||||
</ActionForm>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -21,10 +21,16 @@ pub async fn init_app(configuration_path: Option<&str>) {
|
||||
let leptos_options = conf.leptos_options;
|
||||
let serve_dir = tower_http::services::ServeDir::new(&leptos_options.site_root)
|
||||
.append_index_html_on_directories(false);
|
||||
|
||||
let cors = tower_http::cors::CorsLayer::new()
|
||||
.allow_methods([axum::http::Method::GET, axum::http::Method::POST])
|
||||
.allow_origin(tower_http::cors::Any);
|
||||
|
||||
logging::log!("listening on http://{}", &addr);
|
||||
let app = axum::Router::new()
|
||||
.leptos_routes(&leptos_options, routes, || view! { <App/> })
|
||||
.fallback_service(serve_dir)
|
||||
.layer(cors)
|
||||
.layer(
|
||||
tower_http::trace::TraceLayer::new_for_http()
|
||||
.make_span_with(
|
||||
|
||||
530
style/output.css
530
style/output.css
File diff suppressed because one or more lines are too long
@@ -1,34 +1,12 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: {
|
||||
files: ["*.html", "./src/**/*.rs"],
|
||||
},
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
prim: {
|
||||
lightest: "#2E3235",
|
||||
light: "#2B2F33",
|
||||
DEFAULT: "#26292D",
|
||||
},
|
||||
second: {
|
||||
DEFAULT: "#FEFEFE",
|
||||
dark: "#929496",
|
||||
},
|
||||
third: {
|
||||
light: "#F96662",
|
||||
DEFAULT: "#FC443D",
|
||||
},
|
||||
fourth: {
|
||||
light: "#FFD885",
|
||||
DEFAULT: "#FEBB2E",
|
||||
},
|
||||
green: "#00DA00",
|
||||
module.exports = {
|
||||
content: {
|
||||
relative: true,
|
||||
files: ["*.html", "./src/**/*.rs"],
|
||||
},
|
||||
fontSize: {
|
||||
"4xl": ["4rem", "1"],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user