From 3bf77add88987f354da5bce7905bd46d2c0e8518 Mon Sep 17 00:00:00 2001 From: Romulus21 Date: Wed, 8 Oct 2025 14:16:27 +0200 Subject: [PATCH] remove unused pages & update links --- README.md | 8 ++- src/app.rs | 14 +++-- src/models/link.rs | 18 +++++++ src/models/mod.rs | 4 +- src/models/value.rs | 122 -------------------------------------------- src/routes/data.rs | 94 ---------------------------------- src/routes/link.rs | 90 +++++++++++++++++++++++++++++++- src/routes/mod.rs | 4 -- src/routes/value.rs | 60 ---------------------- 9 files changed, 120 insertions(+), 294 deletions(-) delete mode 100644 src/models/value.rs delete mode 100644 src/routes/data.rs delete mode 100644 src/routes/value.rs diff --git a/README.md b/README.md index 644d56d..d12a3aa 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,18 @@ +# 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 diff --git a/src/app.rs b/src/app.rs index e09a42d..e86ac80 100644 --- a/src/app.rs +++ b/src/app.rs @@ -20,8 +20,6 @@ pub fn App() -> impl IntoView { }/> }/> - }/> - }/> }/> // }/> @@ -54,12 +52,12 @@ pub fn Navigation() -> impl IntoView { Liens - Formulaire - Données + //Formulaire + //Données Volets diff --git a/src/models/link.rs b/src/models/link.rs index 4aac25f..452c19f 100644 --- a/src/models/link.rs +++ b/src/models/link.rs @@ -94,6 +94,24 @@ impl Link { } } + #[cfg(feature = "ssr")] + pub async fn update( + id: String, + name: String, + link: String, + icon: String, + ) -> Result { + 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::query!("DELETE FROM links WHERE id = ? ", id,) diff --git a/src/models/mod.rs b/src/models/mod.rs index 8bbe6d3..0e58b92 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,5 +1,3 @@ mod link; -mod value; + pub use link::Link; -pub use value::Value; -pub use value::OPTIONS; diff --git a/src/models/value.rs b/src/models/value.rs deleted file mode 100644 index 3885c5c..0000000 --- a/src/models/value.rs +++ /dev/null @@ -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: i64, - 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 { - 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 { - 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") -} diff --git a/src/routes/data.rs b/src/routes/data.rs deleted file mode 100644 index 34ea5e8..0000000 --- a/src/routes/data.rs +++ /dev/null @@ -1,94 +0,0 @@ -use leptos::*; -use leptos_meta::*; - -use crate::models::Value; - -#[component] -pub fn Data() -> impl IntoView { - view! { - - - <ul class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-3 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 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(); - let value_class = ["text-4xl flex ml-5 -my-2 text-center ", color.as_str()].join(" "); - 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=value_class> - <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 bd20148..5d0f125 100644 --- a/src/routes/link.rs +++ b/src/routes/link.rs @@ -45,7 +45,7 @@ pub fn Links() -> impl IntoView { 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=""> + <ActionForm action=link_action> <div> <label class="block mt-3 mb-1">"Nom"</label> <input type="text" @@ -130,6 +130,8 @@ fn Link<T: 'static + Clone, S: 'static>( edit: ReadSignal<bool>, links: Resource<T, S>, ) -> impl IntoView { + let (show_edit, set_show_edit) = create_signal(false); + view! { <li class="mx-auto w-44 lg:w-60"> <a class="bg-prim-light w-full 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 inline-block" @@ -148,13 +150,18 @@ fn Link<T: 'static + Clone, S: 'static>( 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_show_edit.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 /> </div> } }) }} + {move || { + show_edit.get().then(|| { + view! { <EditLinkForm link=link set_show=set_show_edit links=links /> } + }) + }} </li> } } @@ -213,3 +220,82 @@ 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 EditLinkForm<T: 'static + Clone, S: 'static>( + link: RwSignal<crate::models::Link>, + set_show: WriteSignal<bool>, + links: Resource<T, S>, +) -> impl IntoView { + let update_action = create_server_action::<UpdateLinkAction>(); + + let (name, set_name) = create_signal(link.with(|x| x.name.clone())); + let (link_url, set_link_url) = create_signal(link.with(|x| x.link.clone())); + let (icon, set_icon) = create_signal(link.with(|x| x.icon.clone())); + + create_effect(move |_| { + if update_action.value().get().is_some() { + links.refetch(); + set_show.set(false); + } + }); + + 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">"Édition du lien"</h2> + <ActionForm action=update_action> + <input name="id" type="hidden" value={move || link.with(|x| x.id.to_string())} /> + + <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" + 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> + + <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> + </ActionForm> + </div> + </div> + } +} \ No newline at end of file diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 8656e30..e98346e 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,9 +1,5 @@ -mod data; mod link; -mod value; mod shutters; -pub use data::*; pub use link::*; -pub use value::*; pub use shutters::*; diff --git a/src/routes/value.rs b/src/routes/value.rs deleted file mode 100644 index 09f66f8..0000000 --- a/src/routes/value.rs +++ /dev/null @@ -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> - } -}