From f12ab66d55fa3a0bd53bac75fcb40e8f82624736 Mon Sep 17 00:00:00 2001 From: Romulus21 Date: Fri, 6 Dec 2024 23:58:13 +0100 Subject: [PATCH] add sensor values --- Makefile | 2 +- rustfmt.toml | 1 + src/app.rs | 4 ++ src/models/value.rs | 45 +++++++++++++++++++++- src/routes/data.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++ src/routes/link.rs | 3 +- src/routes/mod.rs | 2 + src/routes/value.rs | 4 +- style/output.css | 45 ++++++++++++++++++++++ tailwind.config.js | 4 ++ 10 files changed, 199 insertions(+), 5 deletions(-) create mode 100644 rustfmt.toml create mode 100644 src/routes/data.rs diff --git a/Makefile b/Makefile index 76ade1f..2fac671 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ deploy: - npx tailwindcss -i ./input.css -o ./style/output.css + 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 cargo leptos build --release diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..3a26366 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +edition = "2021" diff --git a/src/app.rs b/src/app.rs index b7332a4..48c52af 100644 --- a/src/app.rs +++ b/src/app.rs @@ -21,6 +21,7 @@ pub fn App() -> impl IntoView { }/> }/> }/> + }/> // }/> @@ -45,6 +46,9 @@ pub fn Navigation() -> impl IntoView { Formulaire + Données } } diff --git a/src/models/value.rs b/src/models/value.rs index 09b680c..85d2816 100644 --- a/src/models/value.rs +++ b/src/models/value.rs @@ -42,11 +42,12 @@ pub const OPTIONS: &[Option] = &[ #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Value { - id: u16, + id: i32, service: String, capteur: String, type_donnee: String, - donnee: String, + pub donnee: String, + pub date_donnee: String, } impl Value { @@ -71,6 +72,46 @@ impl Value { .execute(crate::database::get_db()) .await } + + #[cfg(feature = "ssr")] + pub async fn get_one(topic: String) -> Result { + 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 = ?", + 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> { diff --git a/src/routes/data.rs b/src/routes/data.rs new file mode 100644 index 0000000..81c17e9 --- /dev/null +++ b/src/routes/data.rs @@ -0,0 +1,94 @@ +use leptos::*; +use leptos_meta::*; + +use crate::models::Value; + +#[component] +pub fn Data() -> impl IntoView { + view! { + + + <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> + } +} diff --git a/src/routes/link.rs b/src/routes/link.rs index a52ff97..39113cf 100644 --- a/src/routes/link.rs +++ b/src/routes/link.rs @@ -1,5 +1,5 @@ use leptos::*; -//use leptos_meta::*; +use leptos_meta::*; use leptos_router::*; #[server(GetLinksAction, "/api", "GetJson")] @@ -70,6 +70,7 @@ pub fn Links() -> impl IntoView { }; view! { + <Title text="Liens"/> <ul class="flex flex-wrap gap-5 m-5 justify-center"> <Suspense fallback=move || view! {<p>"Loading Comments from the article"</p> }> <ErrorBoundary fallback=|_| { diff --git a/src/routes/mod.rs b/src/routes/mod.rs index d4af40c..69202d2 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,5 +1,7 @@ +mod data; mod link; mod value; +pub use data::*; pub use link::*; pub use value::*; diff --git a/src/routes/value.rs b/src/routes/value.rs index 78f407b..09f66f8 100644 --- a/src/routes/value.rs +++ b/src/routes/value.rs @@ -1,5 +1,5 @@ use leptos::*; -//use leptos_meta::*; +use leptos_meta::*; use leptos_router::*; use crate::models::OPTIONS; @@ -29,6 +29,8 @@ pub fn FormValues() -> impl IntoView { ); 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> diff --git a/style/output.css b/style/output.css index a287823..b4b0747 100644 --- a/style/output.css +++ b/style/output.css @@ -556,6 +556,16 @@ video { margin: 1.25rem; } +.-my-2 { + margin-top: -0.5rem; + margin-bottom: -0.5rem; +} + +.mx-5 { + margin-left: 1.25rem; + margin-right: 1.25rem; +} + .mx-auto { margin-left: auto; margin-right: auto; @@ -575,6 +585,10 @@ video { margin-bottom: 0.25rem; } +.ml-5 { + margin-left: 1.25rem; +} + .mt-3 { margin-top: 0.75rem; } @@ -615,6 +629,10 @@ video { width: 18rem; } +.w-80 { + width: 20rem; +} + .min-w-60 { min-width: 15rem; } @@ -668,6 +686,10 @@ video { border-width: 1px; } +.border-b { + border-bottom-width: 1px; +} + .border-third { --tw-border-opacity: 1; border-color: rgb(252 68 61 / var(--tw-border-opacity)); @@ -692,6 +714,10 @@ video { background-color: rgb(252 68 61 / var(--tw-bg-opacity)); } +.p-3 { + padding: 0.75rem; +} + .p-6 { padding: 1.5rem; } @@ -739,11 +765,20 @@ video { line-height: 2rem; } +.text-\[4rem\] { + font-size: 4rem; +} + .text-lg { font-size: 1.125rem; line-height: 1.75rem; } +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} + .text-xl { font-size: 1.25rem; line-height: 1.75rem; @@ -754,6 +789,11 @@ video { color: rgb(146 148 150 / var(--tw-text-opacity)); } +.text-third { + --tw-text-opacity: 1; + color: rgb(252 68 61 / var(--tw-text-opacity)); +} + .transition-colors { transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); @@ -770,6 +810,11 @@ video { border-bottom-width: 1px; } +.hover\:border-third:hover { + --tw-border-opacity: 1; + border-color: rgb(252 68 61 / var(--tw-border-opacity)); +} + .hover\:bg-prim-lightest:hover { --tw-bg-opacity: 1; background-color: rgb(46 50 53 / var(--tw-bg-opacity)); diff --git a/tailwind.config.js b/tailwind.config.js index 235d7cd..12e90af 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -23,6 +23,10 @@ module.exports = { light: "#FFD885", DEFAULT: "#FEBB2E", }, + green: "#00DA00", + }, + fontSize: { + "4xl": ["4rem", "1"], }, }, },