Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 41aa78b672 | |||
| 21163b277d | |||
| 7a0d3b7f40 | |||
| 6d2b8c77b2 |
1961
AobaClient/Cargo.lock
generated
1961
AobaClient/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ edition = "2024"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dioxus = { version = "0.6.0", features = ["router"] }
|
||||
dioxus = { version = "0.7.2", features = ["router"] }
|
||||
serde = "1.0.219"
|
||||
serde_repr = "0.1.20"
|
||||
tonic = { version = "*", default-features = false, features = [
|
||||
|
||||
@@ -195,3 +195,24 @@ form {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 5;
|
||||
padding: 2px;
|
||||
|
||||
a {
|
||||
transition: all 0.25s ease-out;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding: 5px 10px;
|
||||
background-color: $featureColor;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
background-color: $focusColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ use crate::{
|
||||
#[derive(PartialEq, Clone, Props)]
|
||||
pub struct MediaGridProps {
|
||||
pub query: Option<String>,
|
||||
pub max_page: Signal<i32>,
|
||||
pub total_items: Signal<i32>,
|
||||
#[props(default = Some(1))]
|
||||
pub page: Option<i32>,
|
||||
#[props(default = Some(100))]
|
||||
@@ -33,12 +35,13 @@ impl Into<PageFilter> for MediaGridProps {
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn MediaGrid(props: MediaGridProps) -> Element {
|
||||
pub fn MediaGrid(mut props: MediaGridProps) -> Element {
|
||||
let media_result = use_resource(use_reactive!(|(props)| async move {
|
||||
let mut client = get_rpc_client();
|
||||
let result = client.list_media(props.into_request()).await;
|
||||
if let Ok(items) = result {
|
||||
return Ok(items.into_inner());
|
||||
let res = items.into_inner();
|
||||
return Ok(res);
|
||||
} else {
|
||||
let err = result.err().unwrap();
|
||||
let message = err.message();
|
||||
@@ -48,7 +51,13 @@ pub fn MediaGrid(props: MediaGridProps) -> Element {
|
||||
|
||||
match media_result.cloned() {
|
||||
Some(value) => match value {
|
||||
Ok(result) => rsx! {
|
||||
Ok(result) => {
|
||||
let pagination = result.pagination.unwrap();
|
||||
let total_pages = pagination.total_pages;
|
||||
let total_items = pagination.total_items;
|
||||
props.max_page.set(total_pages.max(1));
|
||||
props.total_items.set(total_items.max(1));
|
||||
return rsx! {
|
||||
div {
|
||||
class: "mediaGrid",
|
||||
// oncontextmenu: oncontext,
|
||||
@@ -58,7 +67,8 @@ pub fn MediaGrid(props: MediaGridProps) -> Element {
|
||||
}
|
||||
})},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
Err(msg) => rsx! {
|
||||
div {
|
||||
class: "mediaGrid",
|
||||
|
||||
@@ -5,6 +5,7 @@ mod media_item;
|
||||
mod metrics_token;
|
||||
mod navbar;
|
||||
mod notif;
|
||||
mod pagination;
|
||||
mod search;
|
||||
pub use context_menu::*;
|
||||
pub use media_grid::*;
|
||||
@@ -12,5 +13,6 @@ pub use media_item::*;
|
||||
pub use metrics_token::*;
|
||||
pub use navbar::*;
|
||||
pub use notif::*;
|
||||
pub use pagination::*;
|
||||
pub use search::*;
|
||||
mod icons;
|
||||
|
||||
@@ -22,7 +22,7 @@ pub fn Navbar() -> Element {
|
||||
pub fn MainNaviagation() -> Element {
|
||||
rsx! {
|
||||
div { class: "mainNav",
|
||||
Link { class: "navItem", to: Route::Home {}, "Home" }
|
||||
Link { class: "navItem", to: Route::Home { }, "Home" }
|
||||
Link { class: "navItem", to: Route::Settings {}, "Settings" }
|
||||
}
|
||||
}
|
||||
|
||||
30
AobaClient/src/components/pagination.rs
Normal file
30
AobaClient/src/components/pagination.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn Pagination(page: Signal<i32>, max_page: Signal<i32>, item_count: Signal<i32>) -> Element {
|
||||
let cur_page_val = page.cloned();
|
||||
let max_page_val = max_page.cloned();
|
||||
let item_count_val = item_count.cloned();
|
||||
rsx! {
|
||||
div {
|
||||
class: "pagination",
|
||||
a {
|
||||
onclick: move|_| page.set(1),
|
||||
"First"
|
||||
}
|
||||
a {
|
||||
onclick: move|_| page.set((cur_page_val - 1).max(1)),
|
||||
"Prev"
|
||||
}
|
||||
div { "Page {cur_page_val} of {max_page_val} ({item_count_val} Media Items)" }
|
||||
a {
|
||||
onclick: move|_| page.set((cur_page_val + 1).min(max_page_val)),
|
||||
"Next"
|
||||
}
|
||||
a {
|
||||
onclick: move|_| page.set(max_page_val),
|
||||
"Last"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn Search(query: Signal<String>) -> Element {
|
||||
pub fn Search(query: Signal<String>, page: Signal<i32>) -> Element {
|
||||
rsx! {
|
||||
div { class: "searchBar stickyTop",
|
||||
input {
|
||||
r#type: "search",
|
||||
placeholder: "Search Files",
|
||||
value: query,
|
||||
oninput: move |event| query.set(event.value()),
|
||||
oninput: move |event| {query.set(event.value()); page.set(1);},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use dioxus::signals::{Signal, Writable};
|
||||
use dioxus::signals::{Signal, WritableExt};
|
||||
use web_sys::window;
|
||||
|
||||
use crate::rpc::{login, logout};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
layouts::MainLayout,
|
||||
views::{Home, Settings},
|
||||
views::{Home, Media, Settings},
|
||||
};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
@@ -8,8 +8,11 @@ use dioxus::prelude::*;
|
||||
#[rustfmt::skip]
|
||||
pub enum Route {
|
||||
#[layout(MainLayout)]
|
||||
|
||||
#[route("/")]
|
||||
Home {},
|
||||
Home { },
|
||||
#[route("/media/:id")]
|
||||
Media { id: String },
|
||||
#[route("/settings")]
|
||||
Settings {},
|
||||
// #[end_layout]
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
use crate::components::{MediaGrid, Search};
|
||||
use crate::components::{MediaGrid, Pagination, Search};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn Home() -> Element {
|
||||
let query = use_signal(|| "".to_string());
|
||||
|
||||
let page = use_signal(|| 1 as i32);
|
||||
let max_page = use_signal(|| 1 as i32);
|
||||
let item_count = use_signal(|| 0 as i32);
|
||||
rsx! {
|
||||
Search { query }
|
||||
MediaGrid { query: query.cloned() }
|
||||
Search { query, page },
|
||||
Pagination { page, max_page, item_count },
|
||||
MediaGrid { query: query.cloned(), page: page.cloned(), max_page, total_items: item_count }
|
||||
}
|
||||
}
|
||||
|
||||
8
AobaClient/src/views/media.rs
Normal file
8
AobaClient/src/views/media.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn Media(id: String) -> Element {
|
||||
rsx! {
|
||||
{id}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
mod home;
|
||||
mod login;
|
||||
mod media;
|
||||
pub use home::*;
|
||||
pub use login::*;
|
||||
pub use media::*;
|
||||
|
||||
mod settings;
|
||||
pub use settings::Settings;
|
||||
|
||||
@@ -5,13 +5,13 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AobaCore.Models;
|
||||
public class PagedResult<T>(List<T> items, int page, int pageSize, long totalItems)
|
||||
public class PagedResult<T>(List<T> items, int page, int pageSize, int totalItems)
|
||||
{
|
||||
public List<T> Items { get; set; } = items;
|
||||
public int Page { get; set; } = page;
|
||||
public int PageSize { get; set; } = pageSize;
|
||||
public long TotalItems { get; set; } = totalItems;
|
||||
public long TotalPages { get; set; } = totalItems / pageSize;
|
||||
public int TotalItems { get; set; } = totalItems;
|
||||
public int TotalPages { get; set; } = (totalItems / pageSize) + 1;
|
||||
public string? Query { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class AobaService(IMongoDatabase db)
|
||||
var total = await find.CountDocumentsAsync();
|
||||
page -= 1;
|
||||
var items = await find.Sort(sort).Skip(page * pageSize).Limit(pageSize).ToListAsync();
|
||||
return new PagedResult<Media>(items, page, pageSize, total);
|
||||
return new PagedResult<Media>(items, page, pageSize, (int)total);
|
||||
}
|
||||
|
||||
public async Task<List<Media>> FindMediaWithExtAsync(string ext, CancellationToken cancellationToken = default)
|
||||
|
||||
@@ -22,12 +22,12 @@ RUN apt install -y protobuf-compiler libprotobuf-dev ffmpeg
|
||||
|
||||
# Install `dx`
|
||||
RUN curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
|
||||
RUN cargo binstall dioxus-cli@0.6.3 --root /.cargo -y --force
|
||||
RUN cargo binstall dioxus-cli@0.7.2 --root /.cargo -y --force
|
||||
ENV PATH="/.cargo/bin:$PATH"
|
||||
ARG VERSION
|
||||
ENV APP_VERSION=$VERSION
|
||||
# Create the final bundle folder. Bundle always executes in release mode with optimizations enabled
|
||||
RUN dx bundle --platform web
|
||||
RUN dx bundle --release --platform web
|
||||
|
||||
# Server Build
|
||||
# This stage is used when running from VS in fast mode (Default for Debug configuration)
|
||||
|
||||
@@ -54,8 +54,8 @@ message ListResponse {
|
||||
message Pagination {
|
||||
int32 page = 1;
|
||||
int32 pageSize = 2;
|
||||
int64 totalPages = 3;
|
||||
int64 totalItems = 4;
|
||||
int32 totalPages = 3;
|
||||
int32 totalItems = 4;
|
||||
optional string query = 5;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user