add sensor values
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,5 +1,5 @@
|
|||||||
deploy:
|
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
|
tac Cargo.toml | sed '1s/^.//' | tac > fichier_temp.txt && mv fichier_temp.txt Cargo.toml
|
||||||
#cargo leptos build
|
#cargo leptos build
|
||||||
cargo leptos build --release
|
cargo leptos build --release
|
||||||
|
|||||||
1
rustfmt.toml
Normal file
1
rustfmt.toml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
edition = "2021"
|
||||||
@@ -21,6 +21,7 @@ pub fn App() -> impl IntoView {
|
|||||||
<Route path="/" view=move || view! { <Home/> }/>
|
<Route path="/" view=move || view! { <Home/> }/>
|
||||||
<Route path="/liens" view=move || view! { <Links/> }/>
|
<Route path="/liens" view=move || view! { <Links/> }/>
|
||||||
<Route path="/formulaire" view=move || view! { <FormValues/> }/>
|
<Route path="/formulaire" view=move || view! { <FormValues/> }/>
|
||||||
|
<Route path="/donnees" view=move || view! { <Data/> }/>
|
||||||
//<Route path="/*any" view=move || view! { <NotFound/> }/>
|
//<Route path="/*any" view=move || view! { <NotFound/> }/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</main>
|
</main>
|
||||||
@@ -45,6 +46,9 @@ pub fn Navigation() -> impl IntoView {
|
|||||||
<a href="/formulaire"
|
<a href="/formulaire"
|
||||||
class="hover:text-third hover:border-b border-third inline-block transition-colors"
|
class="hover:text-third hover:border-b border-third inline-block transition-colors"
|
||||||
class:active-link=move || location.pathname.get() == "/formulaire">Formulaire</a>
|
class:active-link=move || location.pathname.get() == "/formulaire">Formulaire</a>
|
||||||
|
<a href="/donnees"
|
||||||
|
class="hover:text-third hover:border-b border-third inline-block transition-colors"
|
||||||
|
class:active-link=move || location.pathname.get() == "/donnees">Données</a>
|
||||||
</nav>
|
</nav>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,11 +42,12 @@ pub const OPTIONS: &[Option] = &[
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct Value {
|
pub struct Value {
|
||||||
id: u16,
|
id: i32,
|
||||||
service: String,
|
service: String,
|
||||||
capteur: String,
|
capteur: String,
|
||||||
type_donnee: String,
|
type_donnee: String,
|
||||||
donnee: String,
|
pub donnee: String,
|
||||||
|
pub date_donnee: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
@@ -71,6 +72,46 @@ impl Value {
|
|||||||
.execute(crate::database::get_db())
|
.execute(crate::database::get_db())
|
||||||
.await
|
.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 = ?",
|
||||||
|
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> {
|
fn find_option(value: &str) -> Result<&Option, &str> {
|
||||||
|
|||||||
94
src/routes/data.rs
Normal file
94
src/routes/data.rs
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
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>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
use leptos::*;
|
use leptos::*;
|
||||||
//use leptos_meta::*;
|
use leptos_meta::*;
|
||||||
use leptos_router::*;
|
use leptos_router::*;
|
||||||
|
|
||||||
#[server(GetLinksAction, "/api", "GetJson")]
|
#[server(GetLinksAction, "/api", "GetJson")]
|
||||||
@@ -70,6 +70,7 @@ pub fn Links() -> impl IntoView {
|
|||||||
};
|
};
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
|
<Title text="Liens"/>
|
||||||
<ul class="flex flex-wrap gap-5 m-5 justify-center">
|
<ul class="flex flex-wrap gap-5 m-5 justify-center">
|
||||||
<Suspense fallback=move || view! {<p>"Loading Comments from the article"</p> }>
|
<Suspense fallback=move || view! {<p>"Loading Comments from the article"</p> }>
|
||||||
<ErrorBoundary fallback=|_| {
|
<ErrorBoundary fallback=|_| {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
mod data;
|
||||||
mod link;
|
mod link;
|
||||||
mod value;
|
mod value;
|
||||||
|
|
||||||
|
pub use data::*;
|
||||||
pub use link::*;
|
pub use link::*;
|
||||||
pub use value::*;
|
pub use value::*;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use leptos::*;
|
use leptos::*;
|
||||||
//use leptos_meta::*;
|
use leptos_meta::*;
|
||||||
use leptos_router::*;
|
use leptos_router::*;
|
||||||
|
|
||||||
use crate::models::OPTIONS;
|
use crate::models::OPTIONS;
|
||||||
@@ -29,6 +29,8 @@ pub fn FormValues() -> impl IntoView {
|
|||||||
);
|
);
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
|
<Title text="Formulaire"/>
|
||||||
|
|
||||||
<div class="my-5 mx-auto w-72 p-6 bg-prim-light rounded-lg">
|
<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>
|
<h2 class="pb-6 text-2xl text-center">"Formulaire"</h2>
|
||||||
|
|
||||||
|
|||||||
@@ -556,6 +556,16 @@ video {
|
|||||||
margin: 1.25rem;
|
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 {
|
.mx-auto {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
@@ -575,6 +585,10 @@ video {
|
|||||||
margin-bottom: 0.25rem;
|
margin-bottom: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ml-5 {
|
||||||
|
margin-left: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.mt-3 {
|
.mt-3 {
|
||||||
margin-top: 0.75rem;
|
margin-top: 0.75rem;
|
||||||
}
|
}
|
||||||
@@ -615,6 +629,10 @@ video {
|
|||||||
width: 18rem;
|
width: 18rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-80 {
|
||||||
|
width: 20rem;
|
||||||
|
}
|
||||||
|
|
||||||
.min-w-60 {
|
.min-w-60 {
|
||||||
min-width: 15rem;
|
min-width: 15rem;
|
||||||
}
|
}
|
||||||
@@ -668,6 +686,10 @@ video {
|
|||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.border-b {
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
.border-third {
|
.border-third {
|
||||||
--tw-border-opacity: 1;
|
--tw-border-opacity: 1;
|
||||||
border-color: rgb(252 68 61 / var(--tw-border-opacity));
|
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));
|
background-color: rgb(252 68 61 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.p-3 {
|
||||||
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.p-6 {
|
.p-6 {
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
}
|
}
|
||||||
@@ -739,11 +765,20 @@ video {
|
|||||||
line-height: 2rem;
|
line-height: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-\[4rem\] {
|
||||||
|
font-size: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
.text-lg {
|
.text-lg {
|
||||||
font-size: 1.125rem;
|
font-size: 1.125rem;
|
||||||
line-height: 1.75rem;
|
line-height: 1.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-sm {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.text-xl {
|
.text-xl {
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
line-height: 1.75rem;
|
line-height: 1.75rem;
|
||||||
@@ -754,6 +789,11 @@ video {
|
|||||||
color: rgb(146 148 150 / var(--tw-text-opacity));
|
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-colors {
|
||||||
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
||||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
@@ -770,6 +810,11 @@ video {
|
|||||||
border-bottom-width: 1px;
|
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 {
|
.hover\:bg-prim-lightest:hover {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(46 50 53 / var(--tw-bg-opacity));
|
background-color: rgb(46 50 53 / var(--tw-bg-opacity));
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ module.exports = {
|
|||||||
light: "#FFD885",
|
light: "#FFD885",
|
||||||
DEFAULT: "#FEBB2E",
|
DEFAULT: "#FEBB2E",
|
||||||
},
|
},
|
||||||
|
green: "#00DA00",
|
||||||
|
},
|
||||||
|
fontSize: {
|
||||||
|
"4xl": ["4rem", "1"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user