@ -1,5 +1,6 @@
use std ::rc ::Rc ;
use perseus ::prelude ::* ;
use serde ::Deserialize ;
use sycamore ::prelude ::* ;
@ -11,7 +12,7 @@ use crate::{
} ,
} ;
#[ derive( Clone )]
#[ derive( Prop )]
pub struct PaginatedTableStateRx < M , F , C >
where
M : ' static ,
@ -33,99 +34,100 @@ where
}
}
#[ component(PaginatedTable<G>) ]
pub fn component < M , F , C > ( state : PaginatedTableStateRx < M , F , C > ) -> View < G >
#[ component ]
pub fn PaginatedTable < ' a , G , M , F , C > (
cx : Scope < ' a > ,
props : PaginatedTableStateRx < M , F , C > ,
) -> View < G >
where
G : Html ,
M : ' static + Clone ,
PaginatedResponse < M > : IntoTableData < G > ,
for < ' de > M : Deserialize < ' de > ,
C : Fn ( Option < String > , i64 , i64 ) -> F + ' static ,
F : std ::future ::Future < Output = Result < PaginatedResponse < M > , ( ) > > + ' static ,
{
let paginated_data : Signal < Option < PaginatedResponse < M > > > = Signal ::new ( None ) ;
let paginated_data = create_signal ( cx , None ) ;
let table_prop : TableContentRx < G > = TableContentRx {
headers_view : Signal::new ( vec! [ ] ) ,
data_view : Signal::new ( vec! [ vec! [ ] ] ) ,
headers_view : create_signal( cx , vec! [ ] ) ,
data_view : create_signal( cx , vec! [ vec! [ ] ] ) ,
} ;
let table_prop2 = table_prop . clone ( ) ;
let page : Signal < i64 > = Signal ::new ( 0 ) ;
let n_page : Signal < i64 > = Signal ::new ( 1 ) ;
let n_rows : Signal < i64 > = Signal ::new ( 0 ) ;
let page = create_signal ( cx , 0 ) ;
let n_page = create_signal ( cx , 1 ) ;
let n_rows = create_signal ( cx , 0 ) ;
let page_up = cloned ! ( ( page , paginated_data , n_page ) = > move | _ | {
n_page . set ( ( * paginated_data . get ( ) ) . as_ref ( ) . map_or ( 0 , | t | t . num_pages ) ) ;
let page_up = move | _ | {
n_page . set (
( * paginated_data . get ( ) )
. clone ( )
. map_or ( 0 , | t : PaginatedResponse < M > | t . num_pages ) ,
) ;
if * page . get ( ) + 1 < * n_page . get ( ) {
page . set ( ( * page . get ( ) ) . min ( * n_page . get ( ) - 1 ) + 1 )
}
} ) ;
let page_down = cloned ! ( ( page ) = > move | _ | {
} ;
let page_down = | _ | {
if * page . get ( ) > 0 {
page . set ( ( * page . get ( ) - 1 ) . max ( 0 ) ) ;
page . set ( ( * page . get ( ) - 1 ) . max ( 0 ) ) ;
}
} ) ;
} ;
let page_size_string = Signal::new ( "20" . to_string ( ) ) ;
let page_size_string = create_signal( cx , "20" . to_string ( ) ) ;
let page_size_string2 = page_size_string . clone ( ) ;
let state_rc = Rc ::new ( state ) ;
create_effect (
cloned ! ( ( page_size_string , paginated_data , page , n_page , n_rows , state_rc ) = > move | | {
let page = * page . get ( ) ;
let page_size_s = page_size_string . get ( ) ;
let page_size = page_size_s . parse ( ) . unwrap_or ( 20 ) ;
if G ::IS_BROWSER {
perseus ::spawn_local (
cloned ! ( ( table_prop2 , page , paginated_data , n_page , n_rows , state_rc ) = > async move {
let res = state_rc . get_data ( page , page_size ) . await . unwrap ( ) ;
paginated_data . set ( Some ( res . clone ( ) ) ) ;
n_rows . set ( res . count ) ;
let table_content = res . into_table_data ( ) ;
table_prop2 . data_view . set ( table_content . data_view ) ;
table_prop2 . headers_view . set ( table_content . headers_view ) ;
n_page . set ( ( * paginated_data . get ( ) ) . as_ref ( ) . map_or ( 0 , | t | t . num_pages ) ) ;
} ) ,
) ;
}
} ) ,
) ;
view ! {
( cloned ! ( ( n_rows , page_size_string , page_down , page_up , page , n_page , page_size_string2 ) = >
view ! {
p ( class = "text-right" ) { ( format! ( "{} transactions" , n_rows . get ( ) ) ) }
div ( class = "flex flex-row justify-between" ) {
select ( bind :value = page_size_string ,
class = "p-2 justify-end text-slate-700 dark:text-slate-100 bg-slate-200 dark:bg-slate-800 rounded-md" ,
id = "size-select" ,
) {
option ( value = "20" ) { "20" }
option ( value = "10" ) { "10" }
option ( value = "30" , selected = page_size_string2 . get ( ) . eq ( & Rc ::new ( "30" . to_string ( ) ) ) ) { "30" }
option ( value = "40" ) { "40" }
option ( value = "50" ) { "50" }
}
div ( class = "flex flex-row p-2 bg-slate-200 dark:bg-slate-800 rounded-md" ) {
button ( on :click = page_down , class = "m-1 hover:font-bold" ) {
"<<"
}
div ( class = "m-1 align-middle text-center" ) {
( format! ( "{}/{}" , * page . get ( ) + 1 , * n_page . get ( ) ) )
}
button ( on :click = page_up , class = "m-1 hover:font-bold" ) {
">>"
}
}
}
} ) )
( if paginated_data . get ( ) . is_some ( ) {
view ! {
BaseTable ( table_prop . clone ( ) )
//let props_ref = Rc::new(props);
let props_sig = create_signal ( cx , props ) ;
create_effect ( cx , move | | {
let page = * page . get ( ) ;
let page_size_s = page_size_string . get ( ) ;
let page_size = page_size_s . parse ( ) . unwrap_or ( 20 ) ;
#[ cfg(client) ]
spawn_local_scoped ( cx , async move {
let res = props_sig . get ( ) . get_data ( page , page_size ) . await . unwrap ( ) ;
paginated_data . set ( Some ( res . clone ( ) ) ) ;
n_rows . set ( res . count ) ;
let table_content = res . into_table_data ( cx ) ;
table_prop . data_view . set ( table_content . data_view ) ;
table_prop . headers_view . set ( table_content . headers_view ) ;
n_page . set ( ( * paginated_data . get ( ) ) . as_ref ( ) . map_or ( 0 , | t | t . num_pages ) ) ;
} ) ;
} ) ;
view ! { cx ,
( if paginated_data . get ( ) . is_some ( ) {
view ! { cx ,
p ( class = "text-right" ) { ( format! ( "{} transactions" , n_rows . get ( ) ) ) }
div ( class = "flex flex-row justify-between" ) {
select ( bind :value = page_size_string ,
class = "p-2 justify-end text-slate-700 dark:text-slate-100 bg-slate-200 dark:bg-slate-800 rounded-md" ,
id = "size-select" ,
) {
option ( value = "20" ) { "20" }
option ( value = "10" ) { "10" }
option ( value = "30" , selected = page_size_string2 . get ( ) . eq ( & Rc ::new ( "30" . to_string ( ) ) ) ) { "30" }
option ( value = "40" ) { "40" }
option ( value = "50" ) { "50" }
}
} else {
view ! {
div ( class = "flex flex-row justify-center" ) {
Loading ( )
div ( class = "flex flex-row p-2 bg-slate-200 dark:bg-slate-800 rounded-md" ) {
button ( on :click = page_down , class = "m-1 hover:font-bold" ) {
"<<"
}
div ( class = "m-1 align-middle text-center" ) {
( format! ( "{}/{}" , * page . get ( ) + 1 , * n_page . get ( ) ) )
}
button ( on :click = page_up , class = "m-1 hover:font-bold" ) {
">>"
}
}
} )
}
BaseTable ( headers_view = table_prop . headers_view , data_view = table_prop . data_view )
}
} else {
view ! { cx ,
div ( class = "flex flex-row justify-center" ) {
Loading ( )
}
}
} )
}
}