✨ push changes
This commit is contained in:
213
src/pages/blog/navigation.rs
Normal file
213
src/pages/blog/navigation.rs
Normal file
@@ -0,0 +1,213 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yew::prelude::*;
|
||||
use yew_router::components::Link;
|
||||
|
||||
use crate::Route;
|
||||
|
||||
const ELLIPSIS: &str = "\u{02026}";
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
|
||||
pub struct PageQuery {
|
||||
pub page: u8,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Properties)]
|
||||
pub struct PropsNavigation {
|
||||
pub page: u8,
|
||||
pub total_pages: u8,
|
||||
pub route_to_page: Route,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn RelNavButtons(props: &PropsNavigation) -> Html {
|
||||
let PropsNavigation {
|
||||
page,
|
||||
total_pages,
|
||||
route_to_page: to,
|
||||
} = props.clone();
|
||||
|
||||
html! {
|
||||
<>
|
||||
<Link<Route, PageQuery>
|
||||
classes={classes!("pagination-previous")}
|
||||
disabled={page==1}
|
||||
query={Some(PageQuery{page: page - 1})}
|
||||
to={to.clone()}
|
||||
>
|
||||
{ "Previous" }
|
||||
</Link<Route, PageQuery>>
|
||||
<Link<Route, PageQuery>
|
||||
classes={classes!("pagination-next")}
|
||||
disabled={page==total_pages}
|
||||
query={Some(PageQuery{page: page + 1})}
|
||||
{to}
|
||||
>
|
||||
{ "Next page" }
|
||||
</Link<Route, PageQuery>>
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Properties, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct RenderLinksProps {
|
||||
range: Range<u8>,
|
||||
len: usize,
|
||||
max_links: usize,
|
||||
props: PropsNavigation,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn RenderLinks(props: &RenderLinksProps) -> Html {
|
||||
let RenderLinksProps {
|
||||
range,
|
||||
len,
|
||||
max_links,
|
||||
props,
|
||||
} = props.clone();
|
||||
|
||||
let mut range = range;
|
||||
|
||||
if len > max_links {
|
||||
let last_link =
|
||||
html! {<RenderLink to_page={range.next_back().unwrap()} props={props.clone()} />};
|
||||
let links = range
|
||||
.take(max_links - 2)
|
||||
.map(|page| html! {<RenderLink to_page={page} props={props.clone()} />});
|
||||
html! {
|
||||
<>
|
||||
{ for links }
|
||||
<li><span class="pagination-ellipsis">{ ELLIPSIS }</span></li>
|
||||
{ last_link }
|
||||
</>
|
||||
}
|
||||
} else {
|
||||
html! {
|
||||
for page in range {
|
||||
<RenderLink to_page={page} props={props.clone()} />
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Properties, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct RenderLinkProps {
|
||||
to_page: u8,
|
||||
props: PropsNavigation,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn RenderLink(props: &RenderLinkProps) -> Html {
|
||||
let RenderLinkProps { to_page, props } = props.clone();
|
||||
|
||||
let PropsNavigation {
|
||||
page,
|
||||
route_to_page,
|
||||
..
|
||||
} = props;
|
||||
|
||||
let is_current_class = if to_page == page { "is-current" } else { "" };
|
||||
|
||||
html! {
|
||||
<li>
|
||||
<Link<Route, PageQuery>
|
||||
classes={classes!("pagination-link", is_current_class)}
|
||||
to={route_to_page}
|
||||
query={Some(PageQuery{page: to_page})}
|
||||
>
|
||||
{ to_page }
|
||||
</Link<Route, PageQuery>>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn Links(props: &PropsNavigation) -> Html {
|
||||
const LINKS_PER_SIDE: usize = 3;
|
||||
|
||||
let PropsNavigation {
|
||||
page, total_pages, ..
|
||||
} = *props;
|
||||
|
||||
let pages_prev = page.checked_sub(1).unwrap_or_default() as usize;
|
||||
let pages_next = (total_pages - page) as usize;
|
||||
|
||||
let links_left = LINKS_PER_SIDE.min(pages_prev)
|
||||
// if there are less than `LINKS_PER_SIDE` to the right, we add some more on the left.
|
||||
+ LINKS_PER_SIDE.checked_sub(pages_next).unwrap_or_default();
|
||||
let links_right = 2 * LINKS_PER_SIDE - links_left;
|
||||
|
||||
html! {
|
||||
<>
|
||||
<RenderLinks range={ 1..page } len={pages_prev} max_links={links_left} props={props.clone()} />
|
||||
<RenderLink to_page={page} props={props.clone()} />
|
||||
<RenderLinks range={ page + 1..total_pages + 1 } len={pages_next} max_links={links_right} props={props.clone()} />
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn Pagination(props: &PropsNavigation) -> Html {
|
||||
html! {
|
||||
<nav class="pagination is-right" role="navigation" aria-label="pagination">
|
||||
<RelNavButtons ..{props.clone()} />
|
||||
<ul class="pagination-list">
|
||||
<Links ..{props.clone()} />
|
||||
</ul>
|
||||
</nav>
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn Nav() -> Html {
|
||||
let navbar_active = use_state_eq(|| false);
|
||||
|
||||
let toggle_navbar = {
|
||||
let navbar_active = navbar_active.clone();
|
||||
|
||||
Callback::from(move |_| {
|
||||
navbar_active.set(!*navbar_active);
|
||||
})
|
||||
};
|
||||
|
||||
let active_class = if !*navbar_active { "is-active" } else { "" };
|
||||
|
||||
html! {
|
||||
<nav class="navbar is-primary" role="navigation" aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<h1 class="navbar-item is-size-3">{ "Yew Blog" }</h1>
|
||||
|
||||
<button class={classes!("navbar-burger", "burger", active_class)}
|
||||
aria-label="menu" aria-expanded="false"
|
||||
onclick={toggle_navbar}
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class={classes!("navbar-menu", active_class)}>
|
||||
<div class="navbar-start">
|
||||
<Link<Route> classes={classes!("navbar-item")} to={Route::Entries}> // TODO: ...
|
||||
{ "Home" }
|
||||
</Link<Route>>
|
||||
<Link<Route> classes={classes!("navbar-item")} to={Route::Entries}>
|
||||
{ "Posts" }
|
||||
</Link<Route>>
|
||||
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<div class="navbar-link">
|
||||
{ "More" }
|
||||
</div>
|
||||
<div class="navbar-dropdown">
|
||||
<Link<Route> classes={classes!("navbar-item")} to={Route::Authors}>
|
||||
{ "Meet the authors" }
|
||||
</Link<Route>>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user