kayrx_ui/widget/
pagination.rs1use crate::fabric::prelude::*;
2
3pub enum Msg {
4 TablePageChange(u32),
5 TablePageUp,
6 TablePageDown,
7}
8
9#[derive(Properties, Clone)]
10pub struct Props {
11 pub onupdate: Callback<u32>,
12 pub total_pages: u32,
13 pub current_page: u32,
14}
15
16pub struct Pagination {
17 link: ComponentLink<Self>,
18 onupdate: Callback<u32>,
19 total_pages: u32,
20 current_page: u32,
21}
22
23impl Component for Pagination {
24 type Message = Msg;
25 type Properties = Props;
26
27 fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
28 Pagination {
29 link,
30 onupdate: props.onupdate,
31 total_pages: props.total_pages,
32 current_page: props.current_page,
33 }
34 }
35
36 fn change(&mut self, props: Self::Properties) -> ShouldRender {
37 self.total_pages = props.total_pages;
38 self.current_page = props.current_page;
39 true
40 }
41
42 fn update(&mut self, msg: Self::Message) -> ShouldRender {
43 match msg {
44 Msg::TablePageChange(n) => self.onupdate.emit(n),
45 Msg::TablePageUp => {
46 if self.current_page < self.total_pages {
47 self.onupdate.emit(self.current_page + 1)
48 }
49 }
50 Msg::TablePageDown => {
51 if self.current_page > 1 {
52 self.onupdate.emit(self.current_page - 1)
53 }
54 }
55 }
56 true
57 }
58
59 fn view(&self) -> Html {
60 html! {
61 <div class="table-paging">
62 <button class="table-paging__btn" onclick=self.link.callback(|_| Msg::TablePageDown)
63 disabled={ self.current_page==1 }>{ "«" }</button>
64 { self.view_pagination_button_first() }
65 { self.view_pagination_buttons_first() }
66 { self.view_pagination_delimiter_first() }
67 { self.view_pagination_button_middle() }
68 { self.view_pagination_delimiter_last() }
69 { self.view_pagination_buttons_last() }
70 { self.view_pagination_button_last() }
71 <button class="table-paging__btn" onclick=self.link.callback(|_| Msg::TablePageUp)
72 disabled={ self.current_page==self.total_pages }>{ "»" }</button>
73 </div>
74 }
75 }
76}
77
78impl Pagination {
79 fn view_pagination_button_is_active(&self, page: u32) -> &str {
80 let current_page = self.current_page;
81
82 if current_page == page {
83 "table-paging__btn--active"
84 } else {
85 "table-paging__btn"
86 }
87 }
88
89 fn view_pagination_button(&self, page: u32) -> Html {
90 html! {
91 <button class={ self.view_pagination_button_is_active(page) }
92 onclick=self.link.callback(move |_| Msg::TablePageChange(page))>{ page }</button>
93 }
94 }
95
96 fn view_pagination_button_first(&self) -> Html {
97 self.view_pagination_button(1)
98 }
99
100 fn view_pagination_delimiter_first(&self) -> Html {
101 let total_pages = self.total_pages;
102 let current_page = self.current_page;
103
104 if total_pages > 5 && current_page > 3 {
105 html! {
106 <button class="table-paging__btn">{ "..." }</button>
107 }
108 } else {
109 html! {}
110 }
111 }
112
113 fn view_pagination_delimiter_last(&self) -> Html {
114 let total_pages = self.total_pages;
115 let current_page = self.current_page;
116
117 if total_pages > 5 && total_pages - current_page > 2 {
118 html! {
119 <button class="table-paging__btn">{ "..." }</button>
120 }
121 } else {
122 html! {}
123 }
124 }
125
126 fn view_pagination_button_last(&self) -> Html {
127 let total_pages = self.total_pages;
128
129 if total_pages > 5 {
130 self.view_pagination_button(total_pages)
131 } else {
132 html! {}
133 }
134 }
135
136 fn view_pagination_button_middle(&self) -> Html {
137 let total_pages = self.total_pages;
138 let current_page = self.current_page;
139 let total_pages_safe = if total_pages < 2 { 2 } else { total_pages };
140
141 if total_pages > 5 && current_page > 3 && current_page < total_pages_safe - 2 {
142 self.view_pagination_button(current_page)
143 } else {
144 html! {}
145 }
146 }
147
148 fn view_pagination_buttons_first(&self) -> Html {
149 let total_pages = self.total_pages;
150 let current_page = self.current_page;
151
152 let max = if total_pages > 5 { 3 } else { 5 };
153 let through = if total_pages > 5 { 4 } else { 6 };
154
155 html! {
156 { for (2..through).filter_map(|page| {
157 if current_page <= max && total_pages >= page {
158 Some(self.view_pagination_button(page))
159 } else {
160 None
161 }
162 }) }
163 }
164 }
165
166 fn view_pagination_buttons_last(&self) -> Html {
167 let total_pages = self.total_pages;
168 let current_page = self.current_page;
169 let total_pages_safe = if total_pages < 2 { 2 } else { total_pages };
170
171 html! {
172 {
173 for (total_pages_safe-2..total_pages_safe).filter_map(|page| {
174 if total_pages > 5 && current_page > 3 && current_page >= total_pages_safe - 2 {
175 Some(self.view_pagination_button(page))
176 } else {
177 None
178 }
179 })
180 }
181 }
182 }
183}