Add Base Path
This commit is contained in:
parent
4eb913e7a1
commit
f6d4e7c556
@ -1,5 +1,6 @@
|
||||
database_path = ""
|
||||
locale = "fr"
|
||||
base_url = ""
|
||||
|
||||
[listener]
|
||||
port = 8000
|
||||
|
||||
17
src/lib.rs
17
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<AppState>) -> impl axum::response::IntoResponse {
|
||||
NotFoundTemplate {
|
||||
ctx: TemplateCtx {
|
||||
base_path: state.config.base_path,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<UserModel>,
|
||||
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<UserModel>,
|
||||
ctx: TemplateCtx,
|
||||
}
|
||||
|
||||
pub async fn new(
|
||||
State(state): State<AppState>,
|
||||
) -> Result<impl axum::response::IntoResponse, AppStateError> {
|
||||
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<UserModel>,
|
||||
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(
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
pub mod book;
|
||||
pub mod template_ctx;
|
||||
pub mod user;
|
||||
|
||||
14
src/routes/template_ctx.rs
Normal file
14
src/routes/template_ctx.rs
Normal file
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<UserWithBookNumber>,
|
||||
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<AppState>,
|
||||
Path(id): Path<i32>,
|
||||
) -> Result<impl axum::response::IntoResponse, AppStateError> {
|
||||
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<AppState>) -> impl axum::response::IntoResponse {
|
||||
NewTemplate {
|
||||
ctx: TemplateCtx {
|
||||
base_path: state.config.base_path,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -4,12 +4,12 @@
|
||||
<meta charset="utf-8">
|
||||
<title>{% block title %}{{ t!("name") }}{% endblock %}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="/assets/css/bootstrap.css">
|
||||
<link rel="stylesheet" href="/assets/css/main.css">
|
||||
<link rel="stylesheet" href='{{ ctx.asset("assets/css/bootstrap.css") }}'>
|
||||
<link rel="stylesheet" href='{{ ctx.asset("assets/css/main.css") }}'>
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/assets/images/favicon.png">
|
||||
|
||||
<link rel="stylesheet" href="/assets/css/fork-awesome.min.css">
|
||||
<link rel="icon" type="image/x-icon" href="/assets/images/favicon.ico">
|
||||
<link rel="stylesheet" href='{{ ctx.asset("assets/css/fork-awesome.min.css") }}'>
|
||||
<link rel="icon" type="image/x-icon" href='{{ ctx.asset("assets/images/favicon.ico") }}'>
|
||||
{% block extra_head %}{% endblock extra_head %}
|
||||
</head>
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
{% endblock %}
|
||||
</footer>
|
||||
|
||||
<script src="/assets/js/bootstrap.min.js"></script>
|
||||
<script src="/assets/js/script.js"></script>
|
||||
<script src='{{ ctx.asset("assets/js/bootstrap.min.js") }}'></script>
|
||||
<script src='{{ ctx.asset("assets/js/script.js") }}'></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user