Implémentation "HATEOAS" de l'interface pour HTMX et update des URLs qui fonctionne ! #57
30
Cargo.lock
generated
30
Cargo.lock
generated
@ -87,6 +87,7 @@ dependencies = [
|
|||||||
"askama",
|
"askama",
|
||||||
"askama_axum",
|
"askama_axum",
|
||||||
"axum",
|
"axum",
|
||||||
|
"axum-htmx",
|
||||||
"cargo-watch",
|
"cargo-watch",
|
||||||
"listenfd",
|
"listenfd",
|
||||||
"notify 6.1.1",
|
"notify 6.1.1",
|
||||||
@ -398,6 +399,20 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "axum-htmx"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36cdb6062317f732ed3acf4e9c28c3824092e226726616f46ebdd8cd32c82a41"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"axum-core",
|
||||||
|
"futures",
|
||||||
|
"http",
|
||||||
|
"tokio",
|
||||||
|
"tower",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
version = "0.3.73"
|
version = "0.3.73"
|
||||||
@ -1470,6 +1485,20 @@ dependencies = [
|
|||||||
"new_debug_unreachable",
|
"new_debug_unreachable",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.30"
|
version = "0.3.30"
|
||||||
@ -1477,6 +1506,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
|
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
askama = "0.12.1"
|
askama = "0.12.1"
|
||||||
askama_axum = "0.4.0"
|
askama_axum = "0.4.0"
|
||||||
axum = "0.7.5"
|
axum = "0.7.5"
|
||||||
|
axum-htmx = { version = "0.6", features = ["auto-vary"] }
|
||||||
listenfd = "1.0.1"
|
listenfd = "1.0.1"
|
||||||
notify = "6.1.1"
|
notify = "6.1.1"
|
||||||
serde = { version = "1.0.204", features = ["derive"] }
|
serde = { version = "1.0.204", features = ["derive"] }
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
{% if hx_request %}
|
||||||
|
<title>{% block title %}{{ title }}{% endblock %}</title>
|
||||||
|
{% block body %}{% endblock %}
|
||||||
|
{% else %}
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="fr" class="h-full">
|
<html lang="fr" class="h-full">
|
||||||
<head>
|
<head>
|
||||||
@ -17,3 +21,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
{% endif %}
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
{% else -%}
|
{% else -%}
|
||||||
class="block py-2 px-3 text-gray-900 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700"
|
class="block py-2 px-3 text-gray-900 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700"
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
|
hx-get="{{ item.href }}"
|
||||||
|
hx-push-url="true"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
hx-select-oob="#menu-items,#page-header,#page-main"
|
||||||
>
|
>
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</a>
|
</a>
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1" id="navbar-user">
|
<div class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1" id="navbar-user">
|
||||||
<ul class="flex flex-col font-medium p-4 md:p-0 mt-4 border border-gray-100 rounded-lg bg-gray-50 md:space-x-8 rtl:space-x-reverse md:flex-row md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700">
|
<ul id="menu-items" class="flex flex-col font-medium p-4 md:p-0 mt-4 border border-gray-100 rounded-lg bg-gray-50 md:space-x-8 rtl:space-x-reverse md:flex-row md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700">
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
{% include "navbar/menu-item.html" %}
|
{% include "navbar/menu-item.html" %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -2,6 +2,7 @@ use std::path::Path;
|
|||||||
|
|
||||||
use askama_axum::Template;
|
use askama_axum::Template;
|
||||||
use axum::http::{StatusCode, Uri};
|
use axum::http::{StatusCode, Uri};
|
||||||
|
use axum_htmx::{AutoVaryLayer, HxRequest};
|
||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
|
|
||||||
mod menu;
|
mod menu;
|
||||||
@ -13,10 +14,12 @@ async fn fallback(uri: Uri) -> (StatusCode, String) {
|
|||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "index.html")]
|
#[template(path = "index.html")]
|
||||||
pub struct GetIndexTemplate;
|
pub struct GetIndexTemplate {
|
||||||
|
hx_request: bool,
|
||||||
|
}
|
||||||
|
|
||||||
async fn root() -> GetIndexTemplate {
|
async fn root(HxRequest(hx_request): HxRequest) -> GetIndexTemplate {
|
||||||
GetIndexTemplate {}
|
GetIndexTemplate { hx_request }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_router(assets_path: &Path) -> axum::Router {
|
pub fn get_router(assets_path: &Path) -> axum::Router {
|
||||||
@ -25,4 +28,5 @@ pub fn get_router(assets_path: &Path) -> axum::Router {
|
|||||||
.route("/", axum::routing::get(root))
|
.route("/", axum::routing::get(root))
|
||||||
.merge(pages::get_routes())
|
.merge(pages::get_routes())
|
||||||
.fallback(fallback)
|
.fallback(fallback)
|
||||||
|
.layer(AutoVaryLayer)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
{% block body %}
|
{% block body %}
|
||||||
{% call navbar::navbar(current="cps") %}
|
{% call navbar::navbar(current="cps") %}
|
||||||
<div class="py-10">
|
<div class="py-10">
|
||||||
<header>
|
<header id="page-header">
|
||||||
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||||
<h1
|
<h1
|
||||||
id="page-title"
|
id="page-title"
|
||||||
@ -16,17 +16,16 @@
|
|||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main id="page-main">
|
||||||
<div
|
<div
|
||||||
id="main-container"
|
|
||||||
class="mx-auto max-w-7xl px-4 py-8 sm:px-6 lg:px-8"
|
class="mx-auto max-w-7xl px-4 py-8 sm:px-6 lg:px-8"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
class="border-2 border-dashed rounded-lg border-gray-300 dark:border-gray-600 h-96 mb-4"
|
||||||
|
>A</div>
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-4">
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-4">
|
||||||
<div
|
<div
|
||||||
class="border-2 border-dashed border-gray-300 rounded-lg dark:border-gray-600 h-32 md:h-64"
|
class="border-2 border-dashed border-gray-300 rounded-lg dark:border-gray-600 h-32 md:h-64"
|
||||||
>A</div>
|
|
||||||
<div
|
|
||||||
class="border-2 border-dashed rounded-lg border-gray-300 dark:border-gray-600 h-32 md:h-64"
|
|
||||||
>B</div>
|
>B</div>
|
||||||
<div
|
<div
|
||||||
class="border-2 border-dashed rounded-lg border-gray-300 dark:border-gray-600 h-32 md:h-64"
|
class="border-2 border-dashed rounded-lg border-gray-300 dark:border-gray-600 h-32 md:h-64"
|
||||||
@ -34,11 +33,11 @@
|
|||||||
<div
|
<div
|
||||||
class="border-2 border-dashed rounded-lg border-gray-300 dark:border-gray-600 h-32 md:h-64"
|
class="border-2 border-dashed rounded-lg border-gray-300 dark:border-gray-600 h-32 md:h-64"
|
||||||
>D</div>
|
>D</div>
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
class="border-2 border-dashed rounded-lg border-gray-300 dark:border-gray-600 h-96 mb-4"
|
class="border-2 border-dashed rounded-lg border-gray-300 dark:border-gray-600 h-32 md:h-64"
|
||||||
>E</div>
|
>E</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,34 +1,12 @@
|
|||||||
use askama_axum::Template;
|
use askama_axum::Template;
|
||||||
use axum::{
|
use axum_htmx::HxRequest;
|
||||||
async_trait,
|
|
||||||
extract::FromRequestParts,
|
|
||||||
http::{request::Parts, HeaderMap, StatusCode},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "cps.html")]
|
#[template(path = "cps.html")]
|
||||||
pub struct CpsTemplate;
|
pub struct CpsTemplate {
|
||||||
|
hx_request: bool,
|
||||||
pub struct ExtractHxRequest(bool);
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl<S> FromRequestParts<S> for ExtractHxRequest
|
|
||||||
where
|
|
||||||
S: Send + Sync,
|
|
||||||
{
|
|
||||||
type Rejection = (StatusCode, &'static str);
|
|
||||||
|
|
||||||
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
|
|
||||||
if parts.headers.get("HX-Request").is_some() {
|
|
||||||
Ok(ExtractHxRequest(true))
|
|
||||||
} else {
|
|
||||||
Ok(ExtractHxRequest(false))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn cps(headers: HeaderMap, hx_request: ExtractHxRequest) -> CpsTemplate {
|
pub async fn cps(HxRequest(hx_request): HxRequest) -> CpsTemplate {
|
||||||
println!("{:#?}", headers);
|
CpsTemplate { hx_request }
|
||||||
println!("{:#?}", hx_request.0);
|
|
||||||
CpsTemplate
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
{% block body %}
|
{% block body %}
|
||||||
{% call navbar::navbar(current="home") %}
|
{% call navbar::navbar(current="home") %}
|
||||||
<div class="py-10">
|
<div class="py-10">
|
||||||
<header>
|
<header id="page-header">
|
||||||
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||||
<h1
|
<h1
|
||||||
id="page-title"
|
id="page-title"
|
||||||
@ -16,9 +16,8 @@
|
|||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main id="page-main">
|
||||||
<div
|
<div
|
||||||
id="main-container"
|
|
||||||
class="mx-auto max-w-7xl px-4 py-8 sm:px-6 lg:px-8"
|
class="mx-auto max-w-7xl px-4 py-8 sm:px-6 lg:px-8"
|
||||||
>
|
>
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-4">
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-4">
|
||||||
|
Loading…
Reference in New Issue
Block a user