Server: Start work on better nav bar
This commit is contained in:
parent
0387e09959
commit
1e62b11a01
|
@ -25,6 +25,26 @@ picture {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.profile-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.bar-icon {
|
||||
margin-right: 0;
|
||||
margin-left: 16px;
|
||||
}
|
||||
.toolkit-icon--link .toolkit-icon {
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.notification-bell {
|
||||
.toolkit-link,
|
||||
i {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.narrow-nav {
|
||||
display: none;
|
||||
}
|
||||
|
|
99
src/nav.rs
99
src/nav.rs
|
@ -1,15 +1,19 @@
|
|||
use crate::{
|
||||
admin::Admin, extensions::ProfileExt, middleware::UserProfile,
|
||||
notifications::total_for_profile, ActixLoader, State,
|
||||
admin::Admin,
|
||||
error::Error,
|
||||
extensions::ProfileExt,
|
||||
middleware::UserProfile,
|
||||
notifications::total_for_profile,
|
||||
views::{OwnedProfileView, ProfileView},
|
||||
ActixLoader, State,
|
||||
};
|
||||
use actix_web::{
|
||||
dev::Payload,
|
||||
web::{Data, Query},
|
||||
web::{self, Data, Query},
|
||||
FromRequest, HttpRequest,
|
||||
};
|
||||
use futures::future::LocalBoxFuture;
|
||||
use hyaenidae_accounts::LogoutState;
|
||||
use hyaenidae_profiles::store::Profile;
|
||||
use hyaenidae_toolkit::Button;
|
||||
use i18n_embed_fl::fl;
|
||||
|
||||
|
@ -66,6 +70,29 @@ impl FromRequest for NavState {
|
|||
None
|
||||
};
|
||||
|
||||
let store = state.profiles.clone();
|
||||
|
||||
let profile = if let Some(profile) = profile {
|
||||
let profile = web::block(move || {
|
||||
let icon = if let Some(file_id) = profile.icon() {
|
||||
store.store.files.by_id(file_id)?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(OwnedProfileView {
|
||||
profile,
|
||||
icon,
|
||||
banner: None,
|
||||
}) as Result<_, Error>
|
||||
})
|
||||
.await?;
|
||||
|
||||
Some(profile)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(NavState {
|
||||
profile,
|
||||
notification_count,
|
||||
|
@ -73,14 +100,14 @@ impl FromRequest for NavState {
|
|||
admin,
|
||||
href,
|
||||
is_open,
|
||||
dark: false,
|
||||
dark: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NavState {
|
||||
profile: Option<Profile>,
|
||||
profile: Option<OwnedProfileView>,
|
||||
notification_count: Option<u64>,
|
||||
logout_state: Option<LogoutState>,
|
||||
admin: Option<Admin>,
|
||||
|
@ -94,50 +121,70 @@ impl NavState {
|
|||
&self.href
|
||||
}
|
||||
|
||||
fn submission_button(&self, loader: &ActixLoader) -> Button {
|
||||
Button::primary(&fl!(loader, "nav-submission-button")).href("/submissions/create")
|
||||
pub(crate) fn profile<'a>(&'a self) -> Option<ProfileView<'a>> {
|
||||
self.profile.as_ref().map(|p| ProfileView {
|
||||
profile: &p.profile,
|
||||
icon: p.icon.as_ref(),
|
||||
banner: p.banner.as_ref(),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn submission_button(&self, loader: &ActixLoader) -> Button {
|
||||
Button::primary_link(&fl!(loader, "nav-submission-button")).href("/submissions/create")
|
||||
}
|
||||
|
||||
fn nav_button(&self, loader: &ActixLoader) -> Button {
|
||||
Button::secondary(&fl!(loader, "nav-text"))
|
||||
Button::link(&fl!(loader, "nav-text"))
|
||||
.href(&self.href)
|
||||
.class("nav-link")
|
||||
}
|
||||
|
||||
fn browse_button(&self, loader: &ActixLoader) -> Button {
|
||||
Button::secondary(&fl!(loader, "nav-browse-button")).href("/browse")
|
||||
pub(crate) fn browse_button(&self, loader: &ActixLoader) -> Button {
|
||||
Button::link(&fl!(loader, "nav-browse-button")).href("/browse")
|
||||
}
|
||||
|
||||
fn profile_button(&self, loader: &ActixLoader) -> Button {
|
||||
if let Some(profile) = self.profile.as_ref() {
|
||||
Button::secondary(&fl!(loader, "nav-profile-button")).href(&profile.view_path())
|
||||
if let Some(view) = self.profile.as_ref() {
|
||||
Button::link(&fl!(loader, "nav-profile-button")).href(&view.profile.view_path())
|
||||
} else {
|
||||
Button::secondary(&fl!(loader, "nav-switch-profile-button")).href("/profiles/change")
|
||||
Button::link(&fl!(loader, "nav-switch-profile-button")).href("/profiles/change")
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn notifications_path(&self) -> &'static str {
|
||||
"/notifications"
|
||||
}
|
||||
|
||||
fn notifications_button(&self, loader: &ActixLoader) -> Button {
|
||||
Button::secondary(&fl!(loader, "nav-notifications-button")).href("/notifications")
|
||||
Button::link(&fl!(loader, "nav-notifications-button")).href(self.notifications_path())
|
||||
}
|
||||
|
||||
fn admin_button(&self, loader: &ActixLoader) -> Button {
|
||||
Button::secondary(&fl!(loader, "nav-admin-button")).href("/admin")
|
||||
Button::link(&fl!(loader, "nav-admin-button")).href("/admin")
|
||||
}
|
||||
|
||||
fn account_button(&self, loader: &ActixLoader) -> Button {
|
||||
Button::secondary(&fl!(loader, "nav-account-button")).href("/session/account")
|
||||
Button::link(&fl!(loader, "nav-account-button")).href("/session/account")
|
||||
}
|
||||
|
||||
fn login_button(&self, loader: &ActixLoader) -> Button {
|
||||
Button::primary_outline(&fl!(loader, "nav-login-button")).href("/session/auth/login")
|
||||
Button::primary_link(&fl!(loader, "nav-login-button")).href("/session/auth/login")
|
||||
}
|
||||
|
||||
fn register_button(&self, loader: &ActixLoader) -> Button {
|
||||
Button::primary_outline(&fl!(loader, "nav-register-button")).href("/session/auth/register")
|
||||
Button::primary_link(&fl!(loader, "nav-register-button")).href("/session/auth/register")
|
||||
}
|
||||
|
||||
fn logout_button(&self, logout_state: &LogoutState, loader: &ActixLoader) -> Button {
|
||||
Button::primary_outline(&fl!(loader, "nav-logout-button")).form(&logout_state.logout_path())
|
||||
Button::primary_link(&fl!(loader, "nav-logout-button")).form(&logout_state.logout_path())
|
||||
}
|
||||
|
||||
pub(crate) fn has_notifications(&self) -> bool {
|
||||
if let Some(count) = self.notification_count {
|
||||
count > 0
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn buttons(&self, loader: &ActixLoader) -> Vec<Button> {
|
||||
|
@ -148,10 +195,8 @@ impl NavState {
|
|||
nav.push(self.browse_button(loader));
|
||||
nav.push(self.profile_button(loader));
|
||||
|
||||
if let Some(count) = self.notification_count {
|
||||
if count > 0 {
|
||||
nav.push(self.notifications_button(loader));
|
||||
}
|
||||
if self.has_notifications() {
|
||||
nav.push(self.notifications_button(loader));
|
||||
}
|
||||
|
||||
nav.push(self.account_button(loader));
|
||||
|
@ -189,10 +234,8 @@ impl NavState {
|
|||
site_nav.push(self.browse_button(loader));
|
||||
site_nav.push(self.profile_button(loader));
|
||||
|
||||
if let Some(count) = self.notification_count {
|
||||
if count > 0 {
|
||||
site_nav.push(self.notifications_button(loader));
|
||||
}
|
||||
if self.has_notifications() {
|
||||
site_nav.push(self.notifications_button(loader));
|
||||
}
|
||||
|
||||
if self.admin.is_some() {
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
@use hyaenidae_toolkit::templates::bbcode;
|
||||
@use hyaenidae_toolkit::templates::{card_body, card_section};
|
||||
@use hyaenidae_toolkit::{templates::link, Link};
|
||||
@use hyaenidae_toolkit::templates::icon;
|
||||
@use hyaenidae_toolkit::{templates::icon, Size};
|
||||
@use hyaenidae_toolkit::{templates::{tile, tiles}, Tiles};
|
||||
|
||||
@(loader: &ActixLoader, sub_view: &OwnedSubmissionView, pro_view: &OwnedProfileView, dark: bool)
|
||||
|
||||
@:card_body({
|
||||
<div class="profile-box">
|
||||
@:icon(&pro_view.icon(loader).small(true).dark(dark))
|
||||
@:icon(&pro_view.icon(loader).size(Size::Small).dark(dark))
|
||||
<div class="profile-box--content">
|
||||
<div class="profile-box--all-meta">
|
||||
<div>
|
||||
|
|
53
templates/bar.rs.html
Normal file
53
templates/bar.rs.html
Normal file
|
@ -0,0 +1,53 @@
|
|||
@use crate::ActixLoader;
|
||||
@use crate::nav::NavState;
|
||||
@use hyaenidae_toolkit::templates::bar;
|
||||
@use hyaenidae_toolkit::templates::{button, button_group};
|
||||
@use hyaenidae_toolkit::{templates::icon, Size};
|
||||
@use hyaenidae_toolkit::{templates::link, Link};
|
||||
@use i18n_embed_fl::fl;
|
||||
|
||||
@(loader: &ActixLoader, nav_state: &NavState)
|
||||
|
||||
@:bar(nav_state.dark(), "desktop-bar", {
|
||||
<div>
|
||||
@:link(&Link::current_tab("/").plain(true), {
|
||||
<h2>@fl!(loader, "site-name")</h2>
|
||||
})
|
||||
</div>
|
||||
<nav>
|
||||
@if let Some(profile) = nav_state.profile() {
|
||||
<div class="profile-nav">
|
||||
<div class="toolkit-button-group">
|
||||
@:button(&nav_state.submission_button(loader))
|
||||
@:button(&nav_state.browse_button(loader))
|
||||
@if nav_state.has_notifications() {
|
||||
<div class="toolkit-button toolkit-button__link">
|
||||
<span><i class="fa fa-bell"></i></span>
|
||||
@:link(&Link::current_tab(nav_state.notifications_path()).plain(true).class("toolkit-button--action"), {
|
||||
<i class="fa fa-bell"></i>
|
||||
})
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@:icon(&profile.icon(loader).size(Size::Tiny).class("bar-icon").dark(true))
|
||||
</div>
|
||||
} else {
|
||||
<div class="narrow-nav">
|
||||
@:button_group(&nav_state.narrow_buttons(loader))
|
||||
</div>
|
||||
<div class="wide-nav">
|
||||
@:button_group(&nav_state.buttons(loader))
|
||||
</div>
|
||||
}
|
||||
</nav>
|
||||
})
|
||||
@:bar(nav_state.dark(), "mobile-bar", {
|
||||
@:link(&Link::current_tab("/").plain(true), {
|
||||
<h2>@fl!(loader, "site-name")</h2>
|
||||
})
|
||||
<h3 class="nav-link">
|
||||
@:link(&Link::current_tab(nav_state.href()).plain(true), {
|
||||
@fl!(loader, "nav-text")
|
||||
})
|
||||
</h3>
|
||||
})
|
|
@ -5,13 +5,13 @@
|
|||
@use crate::views::OwnedProfileView;
|
||||
@use chrono::{DateTime, Utc};
|
||||
@use hyaenidae_toolkit::{templates::link, Link};
|
||||
@use hyaenidae_toolkit::templates::icon;
|
||||
@use hyaenidae_toolkit::{templates::icon, Size};
|
||||
@use i18n_embed_fl::fl;
|
||||
|
||||
@(loader: &ActixLoader, view: &OwnedProfileView, published: DateTime<Utc>, parent: &CommentNode, cache: &Cache, dark: bool, meta: Content, body: Content)
|
||||
|
||||
<div class="profile-box">
|
||||
@:icon(&view.icon(loader).small(true).dark(dark))
|
||||
@:icon(&view.icon(loader).size(Size::Small).dark(dark))
|
||||
<div class="profile-box--content">
|
||||
<div class="profile-box--all-meta">
|
||||
<div>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
@use crate::ActixLoader;
|
||||
@use crate::{templates::layouts::root, nav::NavState};
|
||||
@use crate::nav::NavState;
|
||||
@use crate::templates::bar;
|
||||
@use crate::templates::layouts::root;
|
||||
@use crate::templates::statics::nav_js;
|
||||
@use hyaenidae_toolkit::templates::{bar, centered};
|
||||
@use hyaenidae_toolkit::templates::centered;
|
||||
@use hyaenidae_toolkit::{templates::{card, card_body}, Card};
|
||||
@use hyaenidae_toolkit::{templates::link, Link};
|
||||
@use hyaenidae_toolkit::{templates::button_group, Button};
|
||||
|
@ -13,31 +15,7 @@
|
|||
<script src="@crate::statics_path(nav_js.name)"></script>
|
||||
@:head()
|
||||
}, {
|
||||
@:bar(nav_state.dark(), "desktop-bar", {
|
||||
<div>
|
||||
@:link(&Link::current_tab("/").plain(true), {
|
||||
<h2>@fl!(loader, "site-name")</h2>
|
||||
})
|
||||
</div>
|
||||
<nav>
|
||||
<div class="narrow-nav">
|
||||
@:button_group(&nav_state.narrow_buttons(loader))
|
||||
</div>
|
||||
<div class="wide-nav">
|
||||
@:button_group(&nav_state.buttons(loader))
|
||||
</div>
|
||||
</nav>
|
||||
})
|
||||
@:bar(nav_state.dark(), "mobile-bar", {
|
||||
@:link(&Link::current_tab("/").plain(true), {
|
||||
<h2>@fl!(loader, "site-name")</h2>
|
||||
})
|
||||
<h3 class="nav-link">
|
||||
@:link(&Link::current_tab(nav_state.href()).plain(true), {
|
||||
@fl!(loader, "nav-text")
|
||||
})
|
||||
</h3>
|
||||
})
|
||||
@:bar(loader, nav_state)
|
||||
<div class="home-content">
|
||||
@:body()
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
@use hyaenidae_toolkit::{templates::button_group, Button};
|
||||
@use hyaenidae_toolkit::{templates::{card, card_body, card_section}, Card};
|
||||
@use hyaenidae_toolkit::templates::centered;
|
||||
@use hyaenidae_toolkit::templates::{icon, image};
|
||||
@use hyaenidae_toolkit::{templates::{icon, image}, Size};
|
||||
@use hyaenidae_toolkit::{templates::link, Link};
|
||||
@use hyaenidae_toolkit::templates::search;
|
||||
@use hyaenidae_toolkit::{templates::{tab, tab_group}, Tab};
|
||||
|
@ -42,7 +42,7 @@
|
|||
}
|
||||
<div class="profile-result--left">
|
||||
<div class="profile-result--icon">
|
||||
@:icon(&pview.icon(loader).small(true).dark(nav_state.dark()))
|
||||
@:icon(&pview.icon(loader).size(Size::Small).dark(nav_state.dark()))
|
||||
</div>
|
||||
<div class="profile-result--meta">
|
||||
<div class="profile-result--display-name">
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
@use crate::views::OwnedProfileView;
|
||||
@use hyaenidae_toolkit::{templates::button_group, Button};
|
||||
@use hyaenidae_toolkit::{templates::{card, card_body, card_section, card_title}, Card};
|
||||
@use hyaenidae_toolkit::templates::{icon, image};
|
||||
@use hyaenidae_toolkit::{templates::{icon, image}, Size};
|
||||
@use hyaenidae_toolkit::{templates::link, Link};
|
||||
@use i18n_embed_fl::fl;
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
|||
}
|
||||
<div class="profile-result--left">
|
||||
<div class="profile-result--icon">
|
||||
@:icon(&pview.icon(loader).small(true).dark(nav_state.dark()))
|
||||
@:icon(&pview.icon(loader).size(Size::Small).dark(nav_state.dark()))
|
||||
</div>
|
||||
<div class="profile-result--meta">
|
||||
<div class="profile-result--display-name">
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
@use crate::views::OwnedProfileView;
|
||||
@use chrono::{DateTime, Utc};
|
||||
@use hyaenidae_toolkit::{templates::link, Link};
|
||||
@use hyaenidae_toolkit::templates::icon;
|
||||
@use hyaenidae_toolkit::{templates::icon, Size};
|
||||
|
||||
@(loader: &ActixLoader, view: &OwnedProfileView, published: Option<DateTime<Utc>>, dark: bool, body: Content)
|
||||
|
||||
<div class="profile-box">
|
||||
@:icon(&view.icon(loader).small(true).dark(dark))
|
||||
@:icon(&view.icon(loader).size(Size::Small).dark(dark))
|
||||
<div class="profile-box--content">
|
||||
<div class="profile-box--all-meta">
|
||||
<div class="profile-box--meta">
|
||||
|
|
Loading…
Reference in a new issue