Improve layout, fix navbar

This commit is contained in:
eraden 2023-08-14 22:23:18 +02:00
parent 749ce35ab9
commit c9fd7128f3
12 changed files with 178 additions and 134 deletions

View File

@ -1,5 +1,5 @@
use actix_web::web::{scope, Data, Form, ServiceConfig};
use actix_web::{get, post, HttpResponse};
use actix_web::{get, post, HttpRequest, HttpResponse};
use askama_actix::Template;
use oswilno_contract::accounts;
use oswilno_contract::parking_space_rents;
@ -10,7 +10,7 @@ use std::collections::HashMap;
use std::sync::Arc;
use oswilno_session::{Authenticated, Claims};
use oswilno_view::{Layout, LayoutOptions};
use oswilno_view::{is_partial, Layout, LayoutOptions, Main};
pub fn mount(config: &mut ServiceConfig) {
config.service(
@ -31,15 +31,27 @@ struct AllPartialParkingSpace {
#[get("/all")]
async fn all_parking_spaces(
req: HttpRequest,
db: Data<sea_orm::DatabaseConnection>,
) -> Layout<AllPartialParkingSpace> {
) -> HttpResponse {
let db = db.into_inner();
let main = load_parking_spaces(db).await;
oswilno_view::Layout {
main,
opts: LayoutOptions::default(),
}
let parking_spaces = load_parking_spaces(db).await;
HttpResponse::Ok().body(
if is_partial(&req) {
parking_spaces.render()
} else {
Layout {
main: Main {
body: parking_spaces,
opts: LayoutOptions::default(),
},
}
.render()
}
.unwrap(),
)
}
#[get("/all-partial")]

View File

@ -9,7 +9,7 @@ use askama_actix::Template;
use autometrics::autometrics;
use garde::Validate;
use jsonwebtoken::*;
use oswilno_view::{Errors, Lang, Layout, LayoutOptions, TranslationStorage};
use oswilno_view::{Errors, Lang, Layout, LayoutOptions, Main, TranslationStorage};
use ring::rand::SystemRandom;
use ring::signature::{Ed25519KeyPair, KeyPair};
use sea_orm::DatabaseConnection;
@ -157,22 +157,34 @@ pub struct SignInPayload {
async fn login_view(req: HttpRequest, t: Data<TranslationStorage>) -> HttpResponse {
HttpResponse::Ok().body(
if oswilno_view::is_partial(&req) {
SignInPartialTemplate {
form: SignInPayload::default(),
lang: Lang::Pl,
t: t.into_inner(),
errors: Errors::default(),
}
.render()
} else {
oswilno_view::Layout {
main: SignInPartialTemplate {
Main {
body: SignInPartialTemplate {
form: SignInPayload::default(),
lang: Lang::Pl,
t: t.into_inner(),
errors: Errors::default(),
},
opts: LayoutOptions { show: true, ..Default::default() },
opts: LayoutOptions {
show: true,
search: None,
session: None,
},
}
.render()
} else {
Layout {
main: Main {
body: SignInPartialTemplate {
form: SignInPayload::default(),
lang: Lang::Pl,
t: t.into_inner(),
errors: Errors::default(),
},
opts: LayoutOptions {
show: true,
..Default::default()
},
},
}
.render()
}
@ -313,22 +325,31 @@ struct AccountInfo {
async fn register_view(req: HttpRequest, t: Data<TranslationStorage>) -> HttpResponse {
HttpResponse::Ok().body(
if oswilno_view::is_partial(&req) {
RegisterPartialTemplate {
form: AccountInfo::default(),
t: t.into_inner(),
lang: Lang::Pl,
errors: oswilno_view::Errors::default(),
}
.render()
} else {
Layout {
main: RegisterPartialTemplate {
Main {
body: RegisterPartialTemplate {
form: AccountInfo::default(),
t: t.into_inner(),
lang: Lang::Pl,
errors: oswilno_view::Errors::default(),
},
opts: LayoutOptions::default(),
opts: LayoutOptions {
show: true,
search: None,
session: None,
},
}
.render()
} else {
Layout {
main: Main {
body: RegisterPartialTemplate {
form: AccountInfo::default(),
t: t.into_inner(),
lang: Lang::Pl,
errors: oswilno_view::Errors::default(),
},
opts: LayoutOptions::default(),
},
}
.render()
}

View File

@ -54,7 +54,7 @@
</div>
</form>
<div>
<a href="/login" hx-get="/login" hx-replace-url="true" hx-target="#main-view" hx-headers='{"Accept":"text/html-partial"}'>{{"Sign in"|t(lang,t)}}</a>
<a href="/login" hx-get="/login" hx-replace-url="true" hx-target="main" hx-headers='{"Accept":"text/html-partial"}'>{{"Sign in"|t(lang,t)}}</a>
</div>
</section>
</section>

View File

@ -26,7 +26,7 @@
</div>
</form>
<div>
<a href="/register" hx-get="/register" hx-replace-url="true" hx-target="#main-view" hx-headers='{"Accept":"text/html-partial"}'>{{"Register"|t(lang,t)}}</a>
<a href="/register" hx-get="/register" hx-replace-url="true" hx-target="main" hx-headers='{"Accept":"text/html-partial"}'>{{"Register"|t(lang,t)}}</a>
</div>
</section>
</section>

View File

@ -33,11 +33,17 @@ pub struct LayoutOptions {
pub session: Option<SessionOpts>,
}
#[derive(Debug, askama_actix::Template)]
#[template(path = "../templates/main.html")]
pub struct Main<BodyTemplate: askama::Template> {
pub body: BodyTemplate,
pub opts: LayoutOptions,
}
#[derive(Debug, askama_actix::Template)]
#[template(path = "../templates/base.html")]
pub struct Layout<BodyTemplate: askama::Template> {
pub main: BodyTemplate,
pub opts: LayoutOptions,
pub main: Main<BodyTemplate>,
}
#[derive(Debug, Clone, Default)]

View File

@ -11,9 +11,6 @@
</head>
<body>
<base url="/" />
{% include "navbar.html" %}
<main>
{{ main|safe }}
</main>
{{ main|safe }}
</body>
</html>

View File

@ -0,0 +1,4 @@
<main>
{% include "navbar.html" %}
{{ body|safe }}
</main>

View File

@ -0,0 +1,14 @@
<ul class="py-2" aria-labelledby="user-menu-button">
<li>
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Dashboard</a>
</li>
<li>
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Settings</a>
</li>
<li>
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Earnings</a>
</li>
<li>
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Sign out</a>
</li>
</ul>

View File

@ -0,0 +1,19 @@
<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:flex-row md:space-x-8 md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700">
<li>
<a href="#" class="block py-2 pl-3 pr-4 text-white bg-blue-700 rounded md:bg-transparent md:text-blue-700 md:p-0 md:dark:text-blue-500" aria-current="page">Home</a>
</li>
<li>
<a href="#" class="block py-2 pl-3 pr-4 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">About</a>
</li>
<li>
<a href="#" class="block py-2 pl-3 pr-4 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">Services</a>
</li>
<li>
<a href="#" class="block py-2 pl-3 pr-4 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">Pricing</a>
</li>
<li>
<a href="#" class="block py-2 pl-3 pr-4 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">Contact</a>
</li>
</ul>
</div>

View File

@ -0,0 +1,19 @@
{% match opts.search %}
{% when Some with (search) %}
<div class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1" id="main-search">
<div class="relative mt-3 xs:hidden">
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"/>
</svg>
</div>
<input
type="search"
id="search-navbar"
class="block w-full min-w-[35rem] p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Search..."
>
</div>
</div>
{% when None %}
{% endmatch %}

View File

@ -0,0 +1,44 @@
{% match opts.session %}
{% when Some with (session) %}
<div class="flex items-center md:order-2">
<button
type="button"
class="flex mr-3 text-sm bg-gray-800 rounded-full md:mr-0 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"
id="user-menu-button"
aria-expanded="false"
data-dropdown-toggle="user-dropdown"
data-dropdown-placement="bottom"
>
<span class="sr-only">Open user menu</span>
{% match session.profile_image_url %}
{% when Some with (url) %}
<img class="w-8 h-8 rounded-full" src="{{ url }}" alt="user photo">
{% when None %}
<span>{{ session.login }}</span>
{% endmatch %}
</button>
<!-- Dropdown menu -->
<div class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded-lg shadow dark:bg-gray-700 dark:divide-gray-600" id="user-dropdown">
<div class="px-4 py-3">
<span class="block text-sm text-gray-900 dark:text-white">session.login</span>
<span class="block text-sm text-gray-500 truncate dark:text-gray-400">session.login</span>
</div>
{% include "nav/account-options.html" %}
</div>
<button
data-collapse-toggle="navbar-user"
type="button"
class="inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600"
aria-controls="navbar-user"
aria-expanded="false"
>
<span class="sr-only">Open main menu</span>
<svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15"/>
</svg>
</button>
</div>
{% when None %}
{% endmatch %}

View File

@ -5,102 +5,10 @@
<span class="self-center text-2xl font-semibold whitespace-nowrap dark:text-white">Flowbite</span>
</a>
<div class="flex items-center md:order-2">
{% include "nav/session-menu.html" %}
{% include "nav/search.html" %}
{% include "nav/links-large.html" %}
{% match opts.session %}
{% when Some with (session) %}
<button type="button" class="flex mr-3 text-sm bg-gray-800 rounded-full md:mr-0 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600" id="user-menu-button" aria-expanded="false" data-dropdown-toggle="user-dropdown" data-dropdown-placement="bottom">
<span class="sr-only">Open user menu</span>
{% match session.profile_image_url %}
{% when Some with (url) %}
<img class="w-8 h-8 rounded-full" src="{{ url }}" alt="user photo">
{% when None %}
<span>{{ session.login }}</span>
{% endmatch %}
</button>
{% when None %}
{% endmatch %}
{% match opts.session %}
{% when Some with (session) %}
<!-- Dropdown menu -->
<div class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded-lg shadow dark:bg-gray-700 dark:divide-gray-600" id="user-dropdown">
<div class="px-4 py-3">
<span class="block text-sm text-gray-900 dark:text-white">session.login</span>
<span class="block text-sm text-gray-500 truncate dark:text-gray-400">session.login</span>
</div>
<ul class="py-2" aria-labelledby="user-menu-button">
<li>
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Dashboard</a>
</li>
<li>
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Settings</a>
</li>
<li>
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Earnings</a>
</li>
<li>
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Sign out</a>
</li>
</ul>
</div>
<button
data-collapse-toggle="navbar-user"
type="button"
class="inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600"
aria-controls="navbar-user" aria-expanded="false"
>
<span class="sr-only">Open main menu</span>
<svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15"/>
</svg>
</button>
{% when None %}
{% endmatch %}
</div>
{% match opts.search %}
{% when Some with (search) %}
<div class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1" id="main-search">
<div class="relative mt-3 xs:hidden">
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"/>
</svg>
</div>
<input
type="search"
id="search-navbar"
class="block w-full min-w-[35rem] p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Search..."
>
</div>
</div>
{% when None %}
{% endmatch %}
<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:flex-row md:space-x-8 md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700">
<li>
<a href="#" class="block py-2 pl-3 pr-4 text-white bg-blue-700 rounded md:bg-transparent md:text-blue-700 md:p-0 md:dark:text-blue-500" aria-current="page">Home</a>
</li>
<li>
<a href="#" class="block py-2 pl-3 pr-4 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">About</a>
</li>
<li>
<a href="#" class="block py-2 pl-3 pr-4 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">Services</a>
</li>
<li>
<a href="#" class="block py-2 pl-3 pr-4 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">Pricing</a>
</li>
<li>
<a href="#" class="block py-2 pl-3 pr-4 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">Contact</a>
</li>
</ul>
</div>
</div>
</nav>