From 9317484deb62c1dbe5376d591f50770a43c99f35 Mon Sep 17 00:00:00 2001 From: gabatxo1312 Date: Fri, 30 Jan 2026 18:40:49 +0100 Subject: [PATCH 1/6] Add empty state on table --- locales/en.yml | 1 + locales/fr.yml | 1 + src/routes/user.rs | 4 +- templates/index.html | 119 ++++++++++++++++++++----------------- templates/users/index.html | 56 ++++++++++------- 5 files changed, 102 insertions(+), 79 deletions(-) diff --git a/locales/en.yml b/locales/en.yml index c6cb27c..2bc8531 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -11,6 +11,7 @@ common: search: Search reset: Reset show: Show + no_result: No results close: Close confirmation: Confirmation are_you_sure: Are you sure? diff --git a/locales/fr.yml b/locales/fr.yml index b3f6b34..4411bcc 100644 --- a/locales/fr.yml +++ b/locales/fr.yml @@ -11,6 +11,7 @@ common: search: Filtrer reset: Réini. show: Voir + no_result: Aucun résultat close: Fermer confirmation: Confirmation are_you_sure: Êtes-vous sûr ? diff --git a/src/routes/user.rs b/src/routes/user.rs index 3c81570..e4458eb 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -25,7 +25,7 @@ use crate::{ #[derive(Template, WebTemplate)] #[template(path = "users/index.html")] struct UsersIndexTemplate { - user_with_books_number: Vec, + users_with_books_number: Vec, query: IndexQuery, } @@ -84,7 +84,7 @@ pub async fn index( } Ok(UsersIndexTemplate { - user_with_books_number: result, + users_with_books_number: result, query, }) } diff --git a/templates/index.html b/templates/index.html index 82b28b9..4dc9640 100644 --- a/templates/index.html +++ b/templates/index.html @@ -90,62 +90,73 @@ {% endcall %} {% call cards::card() %} - - - - - - - - - - - - - {% for book_user in books_with_user %} - - - - - - - - - {% endfor %} - -
#{{ t!("book.attributes.title") }}{{ t!("book.attributes.authors") }}{{ t!("book.attributes.owner") }}{{ t!("book.attributes.current_holder") }}{{ t!("common.actions") }}
{{ book_user.book.id }}{{ book_user.book.title }}{{ book_user.book.authors }}{{ book_user.owner.name }} - {% match book_user.current_holder %} - {% when Some with (current_holder) %} - {{ current_holder.name }} - {% when None %} - - - {% endmatch %} - - {{ dropdown::crud_dropdown_button(book_user.book, t!("common.actions"), "books") }} -
+ {% if books_with_user.is_empty() %} +
+

{{ t!("common.no_result") }}

- {% if total_page > 1 %} -
- + + {{ t!("book.new.button_short") }} +
+ {% else %} + + + + + + + + + + + + + {% for book_user in books_with_user %} + + + + + + + + + {% endfor %} + +
#{{ t!("book.attributes.title") }}{{ t!("book.attributes.authors") }}{{ t!("book.attributes.owner") }}{{ t!("book.attributes.current_holder") }}{{ t!("common.actions") }}
{{ book_user.book.id }}{{ book_user.book.title }}{{ book_user.book.authors }}{{ book_user.owner.name }} + {% match book_user.current_holder %} + {% when Some with (current_holder) %} + {{ current_holder.name }} + {% when None %} + - + {% endmatch %} + + {{ dropdown::crud_dropdown_button(book_user.book, t!("common.actions"), "books") }} +
+ + {% if total_page > 1 %} +
+ +
+ {% endif %} + {% endif %} {% endcall %} {% endblock %} diff --git a/templates/users/index.html b/templates/users/index.html index e235dae..6ee5e3d 100644 --- a/templates/users/index.html +++ b/templates/users/index.html @@ -34,29 +34,39 @@ {% endcall %} {% call cards::card() %} - - - - - - - - - - - - {% for user_information in user_with_books_number %} - - - - - - + {% if users_with_books_number.is_empty() %} +
+

{{ t!("common.no_result") }}

+ + + {{ t!("user.index.button") }} + +
+ {% else %} +
#{{ t!("user.attributes.name") }}{{ t!("user.attributes.owner_books") }}{{ t!("user.attributes.borrowed_books") }}{{ t!("common.actions") }}
{{ user_information.user.id }}{{ user_information.user.name }}{{ user_information.owner_book_number }}{{ user_information.borrowed_book_number }} - {{ dropdown::crud_dropdown_button(user_information.user, t!("common.actions"), "users", show = false) }} -
+ + + + + + + - {% endfor %} - -
#{{ t!("user.attributes.name") }}{{ t!("user.attributes.owner_books") }}{{ t!("user.attributes.borrowed_books") }}{{ t!("common.actions") }}
+ + + {% for user_information in users_with_books_number %} + + {{ user_information.user.id }} + {{ user_information.user.name }} + {{ user_information.owner_book_number }} + {{ user_information.borrowed_book_number }} + + {{ dropdown::crud_dropdown_button(user_information.user, t!("common.actions"), "users", show = false) }} + + + {% endfor %} + + + {% endif %} {% endcall %} {% endblock %} From 09429080b19577e8d6fe18902c4b8335987c9622 Mon Sep 17 00:00:00 2001 From: gabatxo1312 Date: Fri, 30 Jan 2026 19:16:51 +0100 Subject: [PATCH 2/6] Add favicon and title --- .gitignore | 2 ++ assets/images/favicon.png | Bin 0 -> 2727 bytes locales/fr.yml | 21 +++++++++++++++------ templates/404.html | 5 +++++ templates/base.html | 1 + templates/books/edit.html | 4 ++++ templates/books/new.html | 4 ++++ templates/books/show.html | 12 ++++++++---- templates/error.html | 5 +++++ templates/index.html | 4 ++++ templates/users/edit.html | 6 +++++- templates/users/index.html | 4 ++++ templates/users/new.html | 6 +++++- 13 files changed, 62 insertions(+), 12 deletions(-) create mode 100644 assets/images/favicon.png diff --git a/.gitignore b/.gitignore index ea8c4bf..bcd5559 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target + +.DS_Store diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..5dbbdbe9e842fbd1113ad3f0a000c8a76c93df4d GIT binary patch literal 2727 zcmY*b2{=@38y+i5Yvw+R$&wzRiqfFt!MhP{imXqR7rjwvc@Z z$&wO<8H!|&WcQE0{=WZz&-I+=exGwc_wzpQd#-bx1oUOS)2srl007{$fxfOe&4W*j znUQu62o2q$Il2IIy-R?~*Pun(B-RyU;AUb1fYLBC07%CLU^t=BE&!bX0QeIF0ETpe zzp*);#4ip#01)p9IQ5HTOYYKQB+a3jW1Z$$eD!St z006eLCq@Uz%I2r3*?3xF2pAJ%HD^2)cFhIv5_Mro}gST*3kw++F1&YsFdJNzpKy4sc)mWnGOXwo>( zv8M3AS>Z&9CRSExVxCHg(bb$0xor;jQfF;BzY>e{oQg@D$vjL+2B?Y(r!r|*v&2Zt zirIo>H4AJZiy=r>4K*Cq#*hw`kfyO*IC3jpMbd*F2Xl4;*@A$p_ zFz$VPSzjM*V`KC6V0RO$d|pqi+&JZ#MbYIFZ=}PU$vhR|+ho47=xBP?upd)zzY>r9 z0;wH9Qflg>*}2)}gE2~;TIg1BxS)^_PcNzK+qcgHPYDyW_Yn1mf&#akoS8@D#7(}6 zp}vbzt*s&wRkF?~X$i95(z|-ftCs@P8*BMvJia@x zethndS=JEt1GYNV6fa+Nd^_^q6Wtpc7s708&OL^RKK+_wCEJvF6LzmboZY9kHV@!4)W{{PibYR(s1%eF zl{9gh9hEPdWO?o!rq3)N^@qF^o42I>U$}+WIgsq3u+XqwSEdL2?^gz+C%6QR3(bnj zWIc=rzcEaFXK(MeqOENfb!~w>a;vBD6W5?;H?Ne8Ond4UAsZ1PUpkjs>8rZe>eW`ogfzPhfr!fRTO3`Fi+H)+Tw3q?mTyejGnVT*xFvmd26_gh@BYAjC2AIl z^pN!BktImpjh#_KF*BF3-9_w(Ot1UWk21R)`yw}-HJHQH(#q;leGwB77}=gF?{0>{ z=+{EHkVs@ln$#S+exvYczO;Bex_r=Qe>hj^yN@tcB}!2(*Q{pfcvs_Ft31r1#ke~k zgtu7tW5IfPaVbet;`ayM-Qp-K)0gIandKshV9OXgaccQNtOUBIIJe1<2MqGNfAJ&gKs*2diYU|j~F5gsq%QPXig z><1V-WKY$@@}Iw)of3#fr^u$k-0m0hS-oL!L?KTK zf1W?g%~b2&oxS+)`X>7rdf(n{mqpH3*ZR{Xw=9X;$iA4X^BUQvq zZuZA(A$7E!Me^8~WrKP9=)@na?8D8xXXS-5vII_rOUueS*Uo_QM!nN*JCMmY7J3lXb&NcM>J~XF zA@}x)iMJ1W8@>T|I>CncY>zmLYe2vvM8E@1!Aev~L~%F?+!@$A;{pE*P0 zGa?L!5guU^sLp71qB6N9g0d#YJ`H{M}JttlrDbM_%!q~<&7MoWoK~D!Ds*xPTbk)_V~9RKQV9R zkw1bfsW|E#`mBG1teIkf{DUV0iwEx(G>obZ)Fs3ln;JdMtIt5gk6N1*lCwu*@;6A} z=ca!(?mZ}33kwM~)TU16O^Fe^l1C{djdRy@*_wI33trrVKVa6SuJuT^ocygBATR4y IUUH274-QJSVgLXD literal 0 HcmV?d00001 diff --git a/locales/fr.yml b/locales/fr.yml index 4411bcc..22b0675 100644 --- a/locales/fr.yml +++ b/locales/fr.yml @@ -28,14 +28,17 @@ user: owner_books: Livres possédés borrowed_books: Livres empruntés index: - title: Tous les utilisateurs - button: Ajouter un utilisateur + title_tag: Liste des utilisateur.ice.s | BookForge + title: Tous les utilisateur.ice.s + button: Ajouter un.e utilisateur.ice edit: + title_tag: Modifier l'utilisateur.ice | BookForge title: Modifier - button: Modifier l'utilisateur + button: Modifier l'utilisateur.ice new: - title: Nouvel utilisateur - button: Créer l'utilisateur + title_tag: Nouvel utilisateur.ice | BookForge + title: Nouvel utilisateur.ice + button: Créer l'utilisateur.ice book: attributes: title: Titre @@ -45,24 +48,30 @@ book: current_holder: Détenteur.ice actuel.le comment: Commentaire index: + title_tag: Liste des livres | BookForge title: Tous les livres new: + title_tag: Nouveau livre | BookForge title: Nouveau livre button: Créer le livre button_short: Ajouter un livre edit: + title_tag: Modifier le livre | BookForge title: Modifier le livre button: Modifier le livre show: + title_tag: Details | BookForge book_details: Détails du livre - user_details: Détails de l'utilisateur + user_details: Détails de l'utilisateur.ice more_informations: Plus d'informations footer: message: Fait avec amour & Nique les fachos ! error: error_404: + title_tag: Erreur 404 | BookForge title: Oups ! Cette page n'existe pas subtitle: 404 NOT FOUND button: Retour à l'accueil generic: + title_tag: Erreur | BookForge title: Oups ! Une erreur s'est produite diff --git a/templates/404.html b/templates/404.html index 289eb9e..e76f185 100644 --- a/templates/404.html +++ b/templates/404.html @@ -1,4 +1,9 @@ {% extends "base.html" %} + +{% block title %} + {{ t!("error.error_404.title_tag") }} +{% endblock %} + {% block main %}

{{ t!("error.error_404.title") }}

diff --git a/templates/base.html b/templates/base.html index dcbe412..8e7f371 100644 --- a/templates/base.html +++ b/templates/base.html @@ -6,6 +6,7 @@ + diff --git a/templates/books/edit.html b/templates/books/edit.html index 462dbd1..ecb8734 100644 --- a/templates/books/edit.html +++ b/templates/books/edit.html @@ -2,6 +2,10 @@ {% import "components/typography.html" as typography %} {% import "components/cards.html" as cards %} +{% block title %} + {{ t!("book.edit.title_tag") }} +{% endblock %} + {% block main %} {{ typography::heading(t!("book.edit.title")) }} diff --git a/templates/books/new.html b/templates/books/new.html index 294aa03..719c9e4 100644 --- a/templates/books/new.html +++ b/templates/books/new.html @@ -3,6 +3,10 @@ {% import "components/cards.html" as cards %} {% import "components/inputs.html" as form_helpers %} +{% block title %} + {{ t!("book.new.title_tag") }} +{% endblock %} + {% block main %} {{ typography::heading(t!("book.new.title")) }} diff --git a/templates/books/show.html b/templates/books/show.html index 88f8603..61042f2 100644 --- a/templates/books/show.html +++ b/templates/books/show.html @@ -4,12 +4,16 @@ {% import "components/fields.html" as fields %} {% import "components/cards.html" as cards %} +{% block title %} + {{ t!("book.show.title_tag") }} +{% endblock %} + {% block main %} {{ typography::book_heading(book.title, book, show = false) }} {% call cards::card() %} -
-
{{ t!("book.show.book_details") }}
+
+
{{ t!("book.show.book_details") }}
{{ fields::field(t!("book.attributes.title"), book.title) }} {{ fields::field(t!("book.attributes.authors"), book.authors) }} @@ -20,7 +24,7 @@ {{ fields::field(t!("book.attributes.description"), "-") }} {% endmatch %} -
{{ t!("book.show.user_details") }}
+
{{ t!("book.show.user_details") }}
{{ fields::field(t!("book.attributes.owner"), owner.name) }} {% match current_holder %} @@ -31,7 +35,7 @@ {% endmatch %} -
{{ t!("book.show.more_informations") }}
+
{{ t!("book.show.more_informations") }}
{% match book.comment %} {% when Some with (comment) %} {{ fields::field(t!("book.attributes.comment"), comment) }} diff --git a/templates/error.html b/templates/error.html index eba937a..abc0eee 100644 --- a/templates/error.html +++ b/templates/error.html @@ -1,4 +1,9 @@ {% extends "base.html" %} + +{% block title %} + {{ t!("error.generic.title_tag") }} +{% endblock %} + {% block main %}

{{ t!("error.generic.title") }}

diff --git a/templates/index.html b/templates/index.html index 4dc9640..641f7a7 100644 --- a/templates/index.html +++ b/templates/index.html @@ -3,6 +3,10 @@ {% import "components/dropdown.html" as dropdown %} {% import "components/cards.html" as cards %} +{% block title %} + {{ t!("book.index.title_tag") }} +{% endblock %} + {% block main %} {% call typography::heading(t!("book.index.title")) %} diff --git a/templates/users/edit.html b/templates/users/edit.html index 856f149..7d5d9b2 100644 --- a/templates/users/edit.html +++ b/templates/users/edit.html @@ -1,7 +1,11 @@ {% extends "base.html" %} {% import "components/typography.html" as typography %} {% import "components/cards.html" as cards %} -o{% import "components/inputs.html" as form_helpers %} +{% import "components/inputs.html" as form_helpers %} + +{% block title %} + {{ t!("book.edit.title_tag") }} +{% endblock %} {% block main %} {{ typography::heading(t!("user.edit.title")) }} diff --git a/templates/users/index.html b/templates/users/index.html index 6ee5e3d..ec3eb08 100644 --- a/templates/users/index.html +++ b/templates/users/index.html @@ -4,6 +4,10 @@ {% import "components/cards.html" as cards %} {% import "components/inputs.html" as form_helpers %} +{% block title %} + {{ t!("user.index.title_tag") }} +{% endblock %} + {% block main %} {% call typography::heading(t!("user.index.title")) %} {{ t!("user.index.button") }} diff --git a/templates/users/new.html b/templates/users/new.html index bdbc639..4e028af 100644 --- a/templates/users/new.html +++ b/templates/users/new.html @@ -1,7 +1,11 @@ {% extends "base.html" %} {% import "components/typography.html" as typography %} {% import "components/cards.html" as cards %} -o{% import "components/inputs.html" as form_helpers %} +{% import "components/inputs.html" as form_helpers %} + +{% block title %} + {{ t!("user.new.title_tag") }} +{% endblock %} {% block main %} {{ typography::heading(t!("user.new.title")) }} From 4eb913e7a13e64cff59a069ec410ffe49ee2854f Mon Sep 17 00:00:00 2001 From: gabatxo1312 Date: Fri, 30 Jan 2026 19:28:21 +0100 Subject: [PATCH 3/6] Harmonize english --- locales/en.yml | 52 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/locales/en.yml b/locales/en.yml index 2bc8531..5e258e0 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -1,12 +1,13 @@ _version: 1 name: "BookForge" + common: download: Download create: Create edit: Edit delete: Delete next: Next - previous: Prev + previous: Previous actions: Actions search: Search reset: Reset @@ -15,54 +16,77 @@ common: close: Close confirmation: Confirmation are_you_sure: Are you sure? + nav: toggle: Toggle navigation books: Books users: Users + theme: light: Light dark: Dark + user: attributes: name: Name - owner_books: Owner books + owner_books: Owned books borrowed_books: Borrowed books + index: + title_tag: Users list | BookForge title: All Users - button: Add User + button: Add a user + edit: + title_tag: Edit user | BookForge title: Edit button: Edit user + new: - title: New User - button: Create User + title_tag: New user | BookForge + title: New user + button: Create user + book: attributes: title: Title authors: Author(s) description: Description owner: Owner - current_holder: Current Holder + current_holder: Current holder comment: Comment + index: + title_tag: Books list | BookForge title: All Books + new: + title_tag: New book | BookForge title: New Book - button: Create Book + button: Create book button_short: Add book + edit: - title: Edit Book - button: Edit Book + title_tag: Edit book | BookForge + title: Edit book + button: Edit book + show: - book_details: Book Details - user_details: User Details - more_informations: More Informations + title_tag: Details | BookForge + book_details: Book details + user_details: User details + more_informations: More information + footer: - message: Made with Love & Fuck a Fascist! + message: Made with love & Fuck fascists! + error: error_404: - title: Oops ! This page does not exist + title_tag: Error 404 | BookForge + title: Oops! This page does not exist subtitle: 404 NOT FOUND button: Back to home + generic: + title_tag: Error | BookForge title: Oops! An error occurred From f6d4e7c55611b916b91befffef041b46f6d076df Mon Sep 17 00:00:00 2001 From: gabatxo1312 Date: Sat, 31 Jan 2026 00:05:53 +0100 Subject: [PATCH 4/6] Add Base Path --- BookForge.toml | 1 + src/lib.rs | 17 ++++++++++++----- src/routes/book.rs | 38 ++++++++++++++++++++++++++++++++------ src/routes/mod.rs | 1 + src/routes/template_ctx.rs | 14 ++++++++++++++ src/routes/user.rs | 29 +++++++++++++++++++++++------ src/state/config.rs | 6 ++++++ src/state/error.rs | 5 +++++ templates/base.html | 12 ++++++------ 9 files changed, 100 insertions(+), 23 deletions(-) create mode 100644 src/routes/template_ctx.rs diff --git a/BookForge.toml b/BookForge.toml index 57033f1..0ac7cc8 100644 --- a/BookForge.toml +++ b/BookForge.toml @@ -1,5 +1,6 @@ database_path = "" locale = "fr" +base_url = "" [listener] port = 8000 diff --git a/src/lib.rs b/src/lib.rs index 9c1f01d..52757e1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,11 +2,12 @@ use askama::Template; use askama_web::WebTemplate; use axum::{ Router, + extract::State, routing::{get, post}, }; use static_serve::embed_assets; -use crate::state::AppState; +use crate::{routes::template_ctx::TemplateCtx, state::AppState}; mod migrations; mod models; @@ -44,8 +45,14 @@ pub fn build_app(state: AppState) -> Router { #[derive(Template, WebTemplate)] #[template(path = "404.html")] -struct NotFoundTemplate {} - -pub async fn error_handler() -> impl axum::response::IntoResponse { - NotFoundTemplate {} +struct NotFoundTemplate { + pub ctx: TemplateCtx, +} + +pub async fn error_handler(State(state): State) -> impl axum::response::IntoResponse { + NotFoundTemplate { + ctx: TemplateCtx { + base_path: state.config.base_path, + }, + } } diff --git a/src/routes/book.rs b/src/routes/book.rs index 124a44f..1b1dbfc 100644 --- a/src/routes/book.rs +++ b/src/routes/book.rs @@ -13,7 +13,9 @@ use serde::Deserialize; use serde_with::{NoneAsEmptyString, serde_as}; use snafu::prelude::*; -use crate::{models::book::Model as BookModel, state::error::CSVSnafu}; +use crate::{ + models::book::Model as BookModel, routes::template_ctx::TemplateCtx, state::error::CSVSnafu, +}; use crate::{models::user::Model as UserModel, state::error::IOSnafu}; use crate::{ @@ -55,6 +57,7 @@ struct BookIndexTemplate { current_page: u64, total_page: u64, base_query: String, + ctx: TemplateCtx, } pub async fn index( @@ -73,7 +76,7 @@ pub async fn index( .context(UserSnafu)?; // Get all Book filtered with query - let books_paginate = BookOperator::new(state) + let books_paginate = BookOperator::new(state.clone()) .all_paginate(page, Some(query.clone())) .await .context(BookSnafu)?; @@ -127,6 +130,9 @@ pub async fn index( current_page: books_paginate.current_page, total_page: books_paginate.total_page, base_query, + ctx: TemplateCtx { + base_path: state.config.base_path, + }, }) } @@ -136,6 +142,7 @@ struct ShowBookTemplate { book: BookModel, owner: UserModel, current_holder: Option, + ctx: TemplateCtx, } pub async fn show( @@ -168,6 +175,9 @@ pub async fn show( book, owner, current_holder, + ctx: TemplateCtx { + base_path: state.config.base_path, + }, }) } @@ -200,14 +210,23 @@ pub async fn create( #[template(path = "books/new.html")] struct NewBookTemplate { users: Vec, + ctx: TemplateCtx, } pub async fn new( State(state): State, ) -> Result { - let users = UserOperator::new(state).all().await.context(UserSnafu)?; + let users = UserOperator::new(state.clone()) + .all() + .await + .context(UserSnafu)?; - Ok(NewBookTemplate { users }) + Ok(NewBookTemplate { + users, + ctx: TemplateCtx { + base_path: state.config.base_path, + }, + }) } #[derive(Template, WebTemplate)] @@ -215,6 +234,7 @@ pub async fn new( struct EditBookTemplate { users: Vec, book: BookModel, + ctx: TemplateCtx, } pub async fn edit( @@ -225,12 +245,18 @@ pub async fn edit( .all() .await .context(UserSnafu)?; - let book = BookOperator::new(state) + let book = BookOperator::new(state.clone()) .find_by_id(id) .await .context(BookSnafu)?; - Ok(EditBookTemplate { users, book }) + Ok(EditBookTemplate { + users, + book, + ctx: TemplateCtx { + base_path: state.config.base_path, + }, + }) } pub async fn update( diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 011ff79..b8d18ab 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,2 +1,3 @@ pub mod book; +pub mod template_ctx; pub mod user; diff --git a/src/routes/template_ctx.rs b/src/routes/template_ctx.rs new file mode 100644 index 0000000..43c09b6 --- /dev/null +++ b/src/routes/template_ctx.rs @@ -0,0 +1,14 @@ +#[derive(Clone)] +pub struct TemplateCtx { + pub base_path: String, +} + +impl TemplateCtx { + pub fn asset(&self, path: &str) -> String { + if self.base_path.is_empty() || self.base_path == "/" { + format!("/{}", path) + } else { + format!("{}/{}", self.base_path.trim_end_matches('/'), path) + } + } +} diff --git a/src/routes/user.rs b/src/routes/user.rs index e4458eb..d870ed7 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -16,6 +16,7 @@ use crate::{ book::BookOperator, user::{self, UserOperator}, }, + routes::template_ctx::TemplateCtx, state::{ AppState, error::{AppStateError, BookSnafu, UserSnafu}, @@ -27,6 +28,7 @@ use crate::{ struct UsersIndexTemplate { users_with_books_number: Vec, query: IndexQuery, + ctx: TemplateCtx, } pub struct UserWithBookNumber { @@ -86,6 +88,9 @@ pub async fn index( Ok(UsersIndexTemplate { users_with_books_number: result, query, + ctx: TemplateCtx { + base_path: state.config.base_path, + }, }) } @@ -135,24 +140,36 @@ pub async fn delete( #[template(path = "users/edit.html")] struct EditTemplate { user: user::Model, + ctx: TemplateCtx, } pub async fn edit( State(state): State, Path(id): Path, ) -> Result { - let user = UserOperator::new(state) + let user = UserOperator::new(state.clone()) .find_by_id(id) .await .context(UserSnafu)?; - Ok(EditTemplate { user }) + Ok(EditTemplate { + user, + ctx: TemplateCtx { + base_path: state.config.base_path, + }, + }) } #[derive(Template, WebTemplate)] #[template(path = "users/new.html")] -struct NewTemplate {} - -pub async fn new() -> impl axum::response::IntoResponse { - NewTemplate {} +struct NewTemplate { + ctx: TemplateCtx, +} + +pub async fn new(State(state): State) -> impl axum::response::IntoResponse { + NewTemplate { + ctx: TemplateCtx { + base_path: state.config.base_path, + }, + } } diff --git a/src/state/config.rs b/src/state/config.rs index 3686711..f137f8a 100644 --- a/src/state/config.rs +++ b/src/state/config.rs @@ -33,6 +33,7 @@ pub struct AppConfig { #[serde(default = "AppConfig::default_sqlite_path")] pub database_path: Utf8PathBuf, pub locale: String, + pub base_path: String, pub listener: Listener, } @@ -40,6 +41,7 @@ impl Default for AppConfig { fn default() -> Self { AppConfig { database_path: Self::default_sqlite_path(), + base_path: Self::default_base_path(), locale: Self::default_locale(), listener: Listener::default(), } @@ -98,6 +100,10 @@ impl AppConfig { "en".to_string() } + fn default_base_path() -> String { + "".to_string() + } + pub fn default_sqlite_path() -> Utf8PathBuf { Self::config_path().join("db.sqlite") } diff --git a/src/state/error.rs b/src/state/error.rs index 59d8232..3a9a1f4 100644 --- a/src/state/error.rs +++ b/src/state/error.rs @@ -6,6 +6,7 @@ use snafu::prelude::*; use crate::{ models::{book::BookError, user::UserError}, + routes::template_ctx::TemplateCtx, state::config::ConfigError, }; @@ -47,6 +48,7 @@ pub enum AppStateError { #[template(path = "error.html")] struct ErrorTemplate { state: AppStateErrorContext, + ctx: TemplateCtx, } struct AppStateErrorContext { @@ -66,6 +68,9 @@ impl IntoResponse for AppStateError { let error_context = AppStateErrorContext::from(self); ErrorTemplate { state: error_context, + ctx: TemplateCtx { + base_path: "".to_string(), + }, } .into_response() } diff --git a/templates/base.html b/templates/base.html index 8e7f371..dd8aa4f 100644 --- a/templates/base.html +++ b/templates/base.html @@ -4,12 +4,12 @@ {% block title %}{{ t!("name") }}{% endblock %} - - + + - - + + {% block extra_head %}{% endblock extra_head %} @@ -26,7 +26,7 @@ {% endblock %} - - + + From 8c94eb5252152d4184111ae1ad338dd04b89d780 Mon Sep 17 00:00:00 2001 From: gabatxo1312 Date: Sat, 31 Jan 2026 18:21:28 +0100 Subject: [PATCH 5/6] Add router --- src/lib.rs | 7 ++-- src/routes/book.rs | 20 +++++------ src/routes/mod.rs | 2 +- src/routes/router.rs | 54 ++++++++++++++++++++++++++++++ src/routes/template_ctx.rs | 14 -------- src/routes/user.rs | 14 ++++---- src/state/error.rs | 6 ++-- templates/404.html | 2 +- templates/base.html | 12 +++---- templates/books/edit.html | 2 +- templates/books/new.html | 2 +- templates/components/dropdown.html | 6 ++-- templates/error.html | 2 +- templates/index.html | 12 +++---- templates/layout/footer.html | 2 +- templates/layout/header.html | 8 ++--- templates/users/edit.html | 2 +- templates/users/index.html | 4 +-- templates/users/new.html | 2 +- 19 files changed, 106 insertions(+), 67 deletions(-) create mode 100644 src/routes/router.rs delete mode 100644 src/routes/template_ctx.rs diff --git a/src/lib.rs b/src/lib.rs index 52757e1..6c3de23 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,8 @@ use axum::{ }; use static_serve::embed_assets; -use crate::{routes::template_ctx::TemplateCtx, state::AppState}; +use crate::routes::router::Router as InternalRouter; +use crate::state::AppState; mod migrations; mod models; @@ -46,12 +47,12 @@ pub fn build_app(state: AppState) -> Router { #[derive(Template, WebTemplate)] #[template(path = "404.html")] struct NotFoundTemplate { - pub ctx: TemplateCtx, + pub router: InternalRouter, } pub async fn error_handler(State(state): State) -> impl axum::response::IntoResponse { NotFoundTemplate { - ctx: TemplateCtx { + router: InternalRouter { base_path: state.config.base_path, }, } diff --git a/src/routes/book.rs b/src/routes/book.rs index 1b1dbfc..8d4fa03 100644 --- a/src/routes/book.rs +++ b/src/routes/book.rs @@ -13,9 +13,7 @@ use serde::Deserialize; use serde_with::{NoneAsEmptyString, serde_as}; use snafu::prelude::*; -use crate::{ - models::book::Model as BookModel, routes::template_ctx::TemplateCtx, state::error::CSVSnafu, -}; +use crate::{models::book::Model as BookModel, routes::router::Router, state::error::CSVSnafu}; use crate::{models::user::Model as UserModel, state::error::IOSnafu}; use crate::{ @@ -57,7 +55,7 @@ struct BookIndexTemplate { current_page: u64, total_page: u64, base_query: String, - ctx: TemplateCtx, + router: Router, } pub async fn index( @@ -130,7 +128,7 @@ pub async fn index( current_page: books_paginate.current_page, total_page: books_paginate.total_page, base_query, - ctx: TemplateCtx { + router: Router { base_path: state.config.base_path, }, }) @@ -142,7 +140,7 @@ struct ShowBookTemplate { book: BookModel, owner: UserModel, current_holder: Option, - ctx: TemplateCtx, + router: Router, } pub async fn show( @@ -175,7 +173,7 @@ pub async fn show( book, owner, current_holder, - ctx: TemplateCtx { + router: Router { base_path: state.config.base_path, }, }) @@ -210,7 +208,7 @@ pub async fn create( #[template(path = "books/new.html")] struct NewBookTemplate { users: Vec, - ctx: TemplateCtx, + router: Router, } pub async fn new( @@ -223,7 +221,7 @@ pub async fn new( Ok(NewBookTemplate { users, - ctx: TemplateCtx { + router: Router { base_path: state.config.base_path, }, }) @@ -234,7 +232,7 @@ pub async fn new( struct EditBookTemplate { users: Vec, book: BookModel, - ctx: TemplateCtx, + router: Router, } pub async fn edit( @@ -253,7 +251,7 @@ pub async fn edit( Ok(EditBookTemplate { users, book, - ctx: TemplateCtx { + router: Router { base_path: state.config.base_path, }, }) diff --git a/src/routes/mod.rs b/src/routes/mod.rs index b8d18ab..2bbba56 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,3 +1,3 @@ pub mod book; -pub mod template_ctx; +pub mod router; pub mod user; diff --git a/src/routes/router.rs b/src/routes/router.rs new file mode 100644 index 0000000..52bcd0b --- /dev/null +++ b/src/routes/router.rs @@ -0,0 +1,54 @@ +#[derive(Clone)] +pub struct Router { + pub base_path: String, +} + +impl Router { + pub fn assets(&self, path: &str) -> String { + if self.base_path.is_empty() || self.base_path == "/" { + format!("/{}", path) + } else { + format!("{}/{}", self.base_path.trim_end_matches('/'), path) + } + } + + pub fn root_path(&self) -> String { + format!("{}/", &self.base_path) + } + + // BOOKS ROUTES + + pub fn new_book_path(&self) -> String { + format!("{}/books/new", &self.base_path) + } + + pub fn create_book_path(&self) -> String { + format!("{}/books", &self.base_path) + } + + pub fn update_book_path(&self, id: &i32) -> String { + format!("{}/books/{}", &self.base_path, id) + } + + pub fn download_csv_book_path(&self) -> String { + format!("{}/books/download_csv", &self.base_path) + } + + // USERS + + pub fn index_user_path(&self) -> String { + format!("{}/users", &self.base_path) + } + + pub fn new_user_path(&self) -> String { + format!("{}/users/new", &self.base_path) + } + + pub fn create_user_path(&self) -> String { + format!("{}/users", &self.base_path) + } + + pub fn update_user_path(&self, id: &i32) -> String { + format!("{}/users/{}", &self.base_path, id) + } +} diff --git a/src/routes/template_ctx.rs b/src/routes/template_ctx.rs deleted file mode 100644 index 43c09b6..0000000 --- a/src/routes/template_ctx.rs +++ /dev/null @@ -1,14 +0,0 @@ -#[derive(Clone)] -pub struct TemplateCtx { - pub base_path: String, -} - -impl TemplateCtx { - pub fn asset(&self, path: &str) -> String { - if self.base_path.is_empty() || self.base_path == "/" { - format!("/{}", path) - } else { - format!("{}/{}", self.base_path.trim_end_matches('/'), path) - } - } -} diff --git a/src/routes/user.rs b/src/routes/user.rs index d870ed7..04eed56 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -16,7 +16,7 @@ use crate::{ book::BookOperator, user::{self, UserOperator}, }, - routes::template_ctx::TemplateCtx, + routes::router::Router, state::{ AppState, error::{AppStateError, BookSnafu, UserSnafu}, @@ -28,7 +28,7 @@ use crate::{ struct UsersIndexTemplate { users_with_books_number: Vec, query: IndexQuery, - ctx: TemplateCtx, + router: Router, } pub struct UserWithBookNumber { @@ -88,7 +88,7 @@ pub async fn index( Ok(UsersIndexTemplate { users_with_books_number: result, query, - ctx: TemplateCtx { + router: Router { base_path: state.config.base_path, }, }) @@ -140,7 +140,7 @@ pub async fn delete( #[template(path = "users/edit.html")] struct EditTemplate { user: user::Model, - ctx: TemplateCtx, + router: Router, } pub async fn edit( @@ -154,7 +154,7 @@ pub async fn edit( Ok(EditTemplate { user, - ctx: TemplateCtx { + router: Router { base_path: state.config.base_path, }, }) @@ -163,12 +163,12 @@ pub async fn edit( #[derive(Template, WebTemplate)] #[template(path = "users/new.html")] struct NewTemplate { - ctx: TemplateCtx, + router: Router, } pub async fn new(State(state): State) -> impl axum::response::IntoResponse { NewTemplate { - ctx: TemplateCtx { + router: Router { base_path: state.config.base_path, }, } diff --git a/src/state/error.rs b/src/state/error.rs index 3a9a1f4..6a031b6 100644 --- a/src/state/error.rs +++ b/src/state/error.rs @@ -6,7 +6,7 @@ use snafu::prelude::*; use crate::{ models::{book::BookError, user::UserError}, - routes::template_ctx::TemplateCtx, + routes::router::Router, state::config::ConfigError, }; @@ -48,7 +48,7 @@ pub enum AppStateError { #[template(path = "error.html")] struct ErrorTemplate { state: AppStateErrorContext, - ctx: TemplateCtx, + router: Router, } struct AppStateErrorContext { @@ -68,7 +68,7 @@ impl IntoResponse for AppStateError { let error_context = AppStateErrorContext::from(self); ErrorTemplate { state: error_context, - ctx: TemplateCtx { + router: Router { base_path: "".to_string(), }, } diff --git a/templates/404.html b/templates/404.html index e76f185..6f35ef6 100644 --- a/templates/404.html +++ b/templates/404.html @@ -8,6 +8,6 @@

{{ t!("error.error_404.title") }}

{{ t!("error.error_404.subtitle") }}

- {{ t!("error.error_404.button") }} + {{ t!("error.error_404.button") }}
{% endblock %} diff --git a/templates/base.html b/templates/base.html index dd8aa4f..5c50fb4 100644 --- a/templates/base.html +++ b/templates/base.html @@ -4,12 +4,12 @@ {% block title %}{{ t!("name") }}{% endblock %} - - + + - - + + {% block extra_head %}{% endblock extra_head %} @@ -26,7 +26,7 @@ {% endblock %} - - + + diff --git a/templates/books/edit.html b/templates/books/edit.html index ecb8734..f80be6a 100644 --- a/templates/books/edit.html +++ b/templates/books/edit.html @@ -10,7 +10,7 @@ {{ typography::heading(t!("book.edit.title")) }} {% call cards::card() %} -
+
diff --git a/templates/books/new.html b/templates/books/new.html index 719c9e4..30deb91 100644 --- a/templates/books/new.html +++ b/templates/books/new.html @@ -11,7 +11,7 @@ {{ typography::heading(t!("book.new.title")) }} {% call cards::card() %} - + {{ form_helpers::input("title", t!("book.attributes.title"), is_required = true, placeholder = "Ex: La Petite Dernière") }} {{ form_helpers::input("authors", t!("book.attributes.authors"), is_required = true, placeholder = "Ex: Fatima Daas") }} diff --git a/templates/components/dropdown.html b/templates/components/dropdown.html index 29c0841..7b0e55d 100644 --- a/templates/components/dropdown.html +++ b/templates/components/dropdown.html @@ -18,9 +18,9 @@
diff --git a/templates/error.html b/templates/error.html index abc0eee..09e125b 100644 --- a/templates/error.html +++ b/templates/error.html @@ -12,6 +12,6 @@

{{ error }}

{% endfor %}
- {{ t!("error.error_404.button") }} + {{ t!("error.error_404.button") }}
{% endblock %} diff --git a/templates/index.html b/templates/index.html index 641f7a7..2701d7b 100644 --- a/templates/index.html +++ b/templates/index.html @@ -9,7 +9,7 @@ {% block main %} {% call typography::heading(t!("book.index.title")) %} - + {{ t!("common.download") }} (csv) {% endcall %} @@ -87,7 +87,7 @@
@@ -98,7 +98,7 @@

{{ t!("common.no_result") }}

- + {{ t!("book.new.button_short") }}
@@ -142,19 +142,19 @@ diff --git a/templates/layout/footer.html b/templates/layout/footer.html index 0cafa82..3f29c8b 100644 --- a/templates/layout/footer.html +++ b/templates/layout/footer.html @@ -2,4 +2,4 @@

{{ t!("footer.message") }}

-
\ No newline at end of file + diff --git a/templates/layout/header.html b/templates/layout/header.html index dd9ecbc..114aa1f 100644 --- a/templates/layout/header.html +++ b/templates/layout/header.html @@ -1,6 +1,6 @@