mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-12-27 19:07:28 +00:00
Paing Update
This commit is contained in:
parent
6feeae0f13
commit
3eef14eef4
12 changed files with 280 additions and 73 deletions
|
|
@ -15,9 +15,11 @@
|
|||
*/
|
||||
package org.springframework.samples.petclinic.owner;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
|
@ -51,6 +53,12 @@ class OwnerController {
|
|||
|
||||
private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm";
|
||||
|
||||
private static final String DEFAULT_PAGE_SIZE_VALUE = "10";
|
||||
|
||||
private static final int DEFAULT_PAGE_SIZE = Integer.parseInt(DEFAULT_PAGE_SIZE_VALUE);
|
||||
|
||||
private static final List<Integer> PAGE_SIZE_OPTIONS = List.of(DEFAULT_PAGE_SIZE, 20, 30, 40, 50);
|
||||
|
||||
private final OwnerRepository owners;
|
||||
|
||||
public OwnerController(OwnerRepository owners) {
|
||||
|
|
@ -94,15 +102,20 @@ class OwnerController {
|
|||
|
||||
@GetMapping("/owners")
|
||||
public String processFindForm(@RequestParam(defaultValue = "1") int page, Owner owner, BindingResult result,
|
||||
Model model) {
|
||||
Model model, @RequestParam(name = "size", defaultValue = DEFAULT_PAGE_SIZE_VALUE) int size) {
|
||||
// allow parameterless GET request for /owners to return all records
|
||||
String lastName = owner.getLastName();
|
||||
if (lastName == null) {
|
||||
lastName = ""; // empty string signifies broadest possible search
|
||||
}
|
||||
|
||||
owner.setLastName(lastName);
|
||||
|
||||
int resolvedPage = Math.max(page, 1);
|
||||
int pageSize = resolvePageSize(size);
|
||||
|
||||
// find owners by last name
|
||||
Page<Owner> ownersResults = findPaginatedForOwnersLastName(page, lastName);
|
||||
Page<Owner> ownersResults = findPaginatedForOwnersLastName(resolvedPage, pageSize, lastName);
|
||||
if (ownersResults.isEmpty()) {
|
||||
// no owners found
|
||||
result.rejectValue("lastName", "notFound", "not found");
|
||||
|
|
@ -116,24 +129,56 @@ class OwnerController {
|
|||
}
|
||||
|
||||
// multiple owners found
|
||||
return addPaginationModel(page, model, ownersResults);
|
||||
return addPaginationModel(resolvedPage, pageSize, owner, model, ownersResults);
|
||||
}
|
||||
|
||||
private String addPaginationModel(int page, Model model, Page<Owner> paginated) {
|
||||
private String addPaginationModel(int page, int pageSize, Owner owner, Model model, Page<Owner> paginated) {
|
||||
List<Owner> listOwners = paginated.getContent();
|
||||
long totalItems = paginated.getTotalElements();
|
||||
int currentItemCount = paginated.getNumberOfElements();
|
||||
long startItem = totalItems == 0 ? 0L : (long) ((page - 1L) * pageSize) + 1L;
|
||||
long endItem = currentItemCount == 0 ? startItem : Math.min(startItem + currentItemCount - 1L, totalItems);
|
||||
int totalPages = paginated.getTotalPages();
|
||||
int windowSize = 10;
|
||||
int windowStart = 1;
|
||||
int windowEnd = 0;
|
||||
List<Integer> pageNumbers = Collections.emptyList();
|
||||
boolean showLeadingGap = false;
|
||||
boolean showTrailingGap = false;
|
||||
if (totalPages > 0) {
|
||||
int maxWindowStart = Math.max(1, totalPages - windowSize + 1);
|
||||
windowStart = Math.max(1, Math.min(page, maxWindowStart));
|
||||
windowEnd = Math.min(windowStart + windowSize - 1, totalPages);
|
||||
pageNumbers = IntStream.rangeClosed(windowStart, windowEnd).boxed().toList();
|
||||
int leadingHiddenCount = windowStart - 1;
|
||||
int trailingHiddenCount = totalPages - windowEnd;
|
||||
showLeadingGap = leadingHiddenCount > 0;
|
||||
showTrailingGap = trailingHiddenCount > 0;
|
||||
}
|
||||
model.addAttribute("currentPage", page);
|
||||
model.addAttribute("totalPages", paginated.getTotalPages());
|
||||
model.addAttribute("totalItems", paginated.getTotalElements());
|
||||
model.addAttribute("pageSize", pageSize);
|
||||
model.addAttribute("pageSizeOptions", PAGE_SIZE_OPTIONS);
|
||||
model.addAttribute("totalPages", totalPages);
|
||||
model.addAttribute("totalItems", totalItems);
|
||||
model.addAttribute("startItem", startItem);
|
||||
model.addAttribute("endItem", endItem);
|
||||
model.addAttribute("listOwners", listOwners);
|
||||
model.addAttribute("owner", owner);
|
||||
model.addAttribute("pageNumbers", pageNumbers);
|
||||
model.addAttribute("showLeadingGap", showLeadingGap);
|
||||
model.addAttribute("showTrailingGap", showTrailingGap);
|
||||
return "owners/ownersList";
|
||||
}
|
||||
|
||||
private Page<Owner> findPaginatedForOwnersLastName(int page, String lastname) {
|
||||
int pageSize = 5;
|
||||
private Page<Owner> findPaginatedForOwnersLastName(int page, int pageSize, String lastname) {
|
||||
Pageable pageable = PageRequest.of(page - 1, pageSize);
|
||||
return owners.findByLastNameStartingWith(lastname, pageable);
|
||||
}
|
||||
|
||||
private int resolvePageSize(int requestedSize) {
|
||||
return PAGE_SIZE_OPTIONS.contains(requestedSize) ? requestedSize : DEFAULT_PAGE_SIZE;
|
||||
}
|
||||
|
||||
@GetMapping("/owners/{ownerId}/edit")
|
||||
public String initUpdateOwnerForm() {
|
||||
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@
|
|||
*/
|
||||
package org.springframework.samples.petclinic.vet;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
|
@ -35,6 +37,14 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||
@Controller
|
||||
class VetController {
|
||||
|
||||
private static final String DEFAULT_PAGE_SIZE_VALUE = "10";
|
||||
|
||||
private static final int DEFAULT_PAGE_SIZE = Integer.parseInt(DEFAULT_PAGE_SIZE_VALUE);
|
||||
|
||||
private static final List<Integer> PAGE_SIZE_OPTIONS = List.of(DEFAULT_PAGE_SIZE, 20, 30, 40, 50);
|
||||
|
||||
private static final int PAGINATION_WINDOW_SIZE = 10;
|
||||
|
||||
private final VetRepository vetRepository;
|
||||
|
||||
public VetController(VetRepository vetRepository) {
|
||||
|
|
@ -42,30 +52,63 @@ class VetController {
|
|||
}
|
||||
|
||||
@GetMapping("/vets.html")
|
||||
public String showVetList(@RequestParam(defaultValue = "1") int page, Model model) {
|
||||
public String showVetList(@RequestParam(defaultValue = "1") int page, Model model,
|
||||
@RequestParam(name = "size", defaultValue = DEFAULT_PAGE_SIZE_VALUE) int size) {
|
||||
// Here we are returning an object of type 'Vets' rather than a collection of Vet
|
||||
// objects so it is simpler for Object-Xml mapping
|
||||
Vets vets = new Vets();
|
||||
Page<Vet> paginated = findPaginated(page);
|
||||
int resolvedPage = Math.max(page, 1);
|
||||
int pageSize = resolvePageSize(size);
|
||||
Page<Vet> paginated = findPaginated(resolvedPage, pageSize);
|
||||
vets.getVetList().addAll(paginated.toList());
|
||||
return addPaginationModel(page, paginated, model);
|
||||
return addPaginationModel(resolvedPage, pageSize, paginated, model);
|
||||
}
|
||||
|
||||
private String addPaginationModel(int page, Page<Vet> paginated, Model model) {
|
||||
private String addPaginationModel(int page, int pageSize, Page<Vet> paginated, Model model) {
|
||||
List<Vet> listVets = paginated.getContent();
|
||||
long totalItems = paginated.getTotalElements();
|
||||
int currentItemCount = paginated.getNumberOfElements();
|
||||
long startItem = totalItems == 0 ? 0L : (long) ((page - 1L) * pageSize) + 1L;
|
||||
long endItem = currentItemCount == 0 ? startItem : Math.min(startItem + currentItemCount - 1L, totalItems);
|
||||
int totalPages = paginated.getTotalPages();
|
||||
int windowStart = 1;
|
||||
int windowEnd = 0;
|
||||
List<Integer> pageNumbers = Collections.emptyList();
|
||||
boolean showLeadingGap = false;
|
||||
boolean showTrailingGap = false;
|
||||
if (totalPages > 0) {
|
||||
int maxWindowStart = Math.max(1, totalPages - PAGINATION_WINDOW_SIZE + 1);
|
||||
windowStart = Math.max(1, Math.min(page, maxWindowStart));
|
||||
windowEnd = Math.min(windowStart + PAGINATION_WINDOW_SIZE - 1, totalPages);
|
||||
pageNumbers = IntStream.rangeClosed(windowStart, windowEnd).boxed().toList();
|
||||
int leadingHiddenCount = windowStart - 1;
|
||||
int trailingHiddenCount = totalPages - windowEnd;
|
||||
showLeadingGap = leadingHiddenCount > 0;
|
||||
showTrailingGap = trailingHiddenCount > 0;
|
||||
}
|
||||
model.addAttribute("currentPage", page);
|
||||
model.addAttribute("totalPages", paginated.getTotalPages());
|
||||
model.addAttribute("totalItems", paginated.getTotalElements());
|
||||
model.addAttribute("pageSize", pageSize);
|
||||
model.addAttribute("pageSizeOptions", PAGE_SIZE_OPTIONS);
|
||||
model.addAttribute("totalPages", totalPages);
|
||||
model.addAttribute("totalItems", totalItems);
|
||||
model.addAttribute("startItem", startItem);
|
||||
model.addAttribute("endItem", endItem);
|
||||
model.addAttribute("listVets", listVets);
|
||||
model.addAttribute("pageNumbers", pageNumbers);
|
||||
model.addAttribute("showLeadingGap", showLeadingGap);
|
||||
model.addAttribute("showTrailingGap", showTrailingGap);
|
||||
return "vets/vetList";
|
||||
}
|
||||
|
||||
private Page<Vet> findPaginated(int page) {
|
||||
int pageSize = 5;
|
||||
private Page<Vet> findPaginated(int page, int pageSize) {
|
||||
Pageable pageable = PageRequest.of(page - 1, pageSize);
|
||||
return vetRepository.findAll(pageable);
|
||||
}
|
||||
|
||||
private int resolvePageSize(int requestedSize) {
|
||||
return PAGE_SIZE_OPTIONS.contains(requestedSize) ? requestedSize : DEFAULT_PAGE_SIZE;
|
||||
}
|
||||
|
||||
@GetMapping({ "/vets" })
|
||||
public @ResponseBody Vets showResourcesVetList() {
|
||||
// Here we are returning an object of type 'Vets' rather than a collection of Vet
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@ address=Address
|
|||
city=City
|
||||
telephone=Telephone
|
||||
owners=Owners
|
||||
owners.pageSize.label=Page Row
|
||||
owners.pageSize.submit=Apply
|
||||
owners.pagination.summary=Showing {0}-{1} of {2}
|
||||
owners.pagination.ellipsis=...
|
||||
addOwner=Add Owner
|
||||
findOwner=Find Owner
|
||||
findOwners=Find Owners
|
||||
|
|
|
|||
|
|
@ -49,3 +49,9 @@ petsAndVisits=Haustiere und Besuche
|
|||
error.404=Die angeforderte Seite wurde nicht gefunden.
|
||||
error.500=Ein interner Serverfehler ist aufgetreten.
|
||||
error.general=Ein unerwarteter Fehler ist aufgetreten.
|
||||
|
||||
owners.pageSize.label=Page Row
|
||||
owners.pageSize.submit=Apply
|
||||
owners.pagination.summary=Showing {0}-{1} of {2}
|
||||
|
||||
owners.pagination.ellipsis=...
|
||||
|
|
|
|||
|
|
@ -49,3 +49,9 @@ petsAndVisits=Mascotas y visitas
|
|||
error.404=La página solicitada no fue encontrada.
|
||||
error.500=Ocurrió un error interno del servidor.
|
||||
error.general=Ocurrió un error inesperado.
|
||||
|
||||
owners.pageSize.label=Page Row
|
||||
owners.pageSize.submit=Apply
|
||||
owners.pagination.summary=Showing {0}-{1} of {2}
|
||||
|
||||
owners.pagination.ellipsis=...
|
||||
|
|
|
|||
|
|
@ -49,3 +49,9 @@ petsAndVisits=حیوانات و ویزیتها
|
|||
error.404=صفحه درخواستی پیدا نشد.
|
||||
error.500=خطای داخلی سرور رخ داد.
|
||||
error.general=خطای غیرمنتظرهای رخ داد.
|
||||
|
||||
owners.pageSize.label=Page Row
|
||||
owners.pageSize.submit=Apply
|
||||
owners.pagination.summary=Showing {0}-{1} of {2}
|
||||
|
||||
owners.pagination.ellipsis=...
|
||||
|
|
|
|||
|
|
@ -49,3 +49,9 @@ petsAndVisits=반려동물 및 방문
|
|||
error.404=요청하신 페이지를 찾을 수 없습니다.
|
||||
error.500=서버 내부 오류가 발생했습니다.
|
||||
error.general=알 수 없는 오류가 발생했습니다.
|
||||
|
||||
owners.pageSize.label=Page Row
|
||||
owners.pageSize.submit=Apply
|
||||
owners.pagination.summary=Showing {0}-{1} of {2}
|
||||
|
||||
owners.pagination.ellipsis=...
|
||||
|
|
|
|||
|
|
@ -49,3 +49,9 @@ petsAndVisits=Animais e visitas
|
|||
error.404=A página solicitada não foi encontrada.
|
||||
error.500=Ocorreu um erro interno no servidor.
|
||||
error.general=Ocorreu um erro inesperado.
|
||||
|
||||
owners.pageSize.label=Page Row
|
||||
owners.pageSize.submit=Apply
|
||||
owners.pagination.summary=Showing {0}-{1} of {2}
|
||||
|
||||
owners.pagination.ellipsis=...
|
||||
|
|
|
|||
|
|
@ -49,3 +49,9 @@ petsAndVisits=Питомцы и визиты
|
|||
error.404=Запрашиваемая страница не найдена.
|
||||
error.500=Произошла внутренняя ошибка сервера.
|
||||
error.general=Произошла непредвиденная ошибка.
|
||||
|
||||
owners.pageSize.label=Page Row
|
||||
owners.pageSize.submit=Apply
|
||||
owners.pagination.summary=Showing {0}-{1} of {2}
|
||||
|
||||
owners.pagination.ellipsis=...
|
||||
|
|
|
|||
|
|
@ -49,3 +49,9 @@ petsAndVisits=Evcil Hayvanlar ve Ziyaretler
|
|||
error.404=İstenen sayfa bulunamadı.
|
||||
error.500=Sunucuda dahili bir hata oluştu.
|
||||
error.general=Beklenmeyen bir hata oluştu.
|
||||
|
||||
owners.pageSize.label=Page Row
|
||||
owners.pageSize.submit=Apply
|
||||
owners.pagination.summary=Showing {0}-{1} of {2}
|
||||
|
||||
owners.pagination.ellipsis=...
|
||||
|
|
|
|||
|
|
@ -6,6 +6,23 @@
|
|||
|
||||
<h2 th:text="#{owners}">Owners</h2>
|
||||
|
||||
<div class="owner-list-toolbar d-flex flex-column flex-lg-row align-items-lg-center justify-content-between gap-3 mb-3">
|
||||
<div class="text-muted small" th:if="${totalItems > 0}"
|
||||
th:text="#{owners.pagination.summary(${startItem}, ${endItem}, ${totalItems})}">Showing 1-10 of 42</div>
|
||||
<form class="d-flex align-items-center gap-2" th:action="@{/owners}" method="get">
|
||||
<input type="hidden" name="page" value="1" />
|
||||
<input type="hidden" name="lastName" th:value="${owner.lastName}" />
|
||||
<label class="form-label mb-0 small" for="pageSize" th:text="#{owners.pageSize.label}">Page Row</label>
|
||||
<select id="pageSize" name="size" class="form-select form-select-sm" onchange="this.form.submit()">
|
||||
<option th:each="option : ${pageSizeOptions}" th:value="${option}" th:selected="${option == pageSize}"
|
||||
th:text="${option}">10</option>
|
||||
</select>
|
||||
<noscript>
|
||||
<button type="submit" class="btn btn-primary btn-sm" th:text="#{owners.pageSize.submit}">Apply</button>
|
||||
</noscript>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<table id="owners" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
@ -28,34 +45,56 @@
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div th:if="${totalPages > 1}">
|
||||
<span th:text="#{pages}">Pages:</span>
|
||||
<span>[</span>
|
||||
<span th:each="i: ${#numbers.sequence(1, totalPages)}">
|
||||
<a th:if="${currentPage != i}" th:href="@{'/owners?page=' + ${i}}">[[${i}]]</a>
|
||||
<span th:unless="${currentPage != i}">[[${i}]]</span>
|
||||
</span>
|
||||
<span>] </span>
|
||||
<span>
|
||||
<a th:if="${currentPage > 1}" th:href="@{'/owners?page=1'}" th:title="#{first}" class="fa fa-fast-backward"></a>
|
||||
<span th:unless="${currentPage > 1}" th:title="#{first}" class="fa fa-fast-backward"></span>
|
||||
</span>
|
||||
<span>
|
||||
<a th:if="${currentPage > 1}" th:href="@{'/owners?page=__${currentPage - 1}__'}" th:title="#{previous}"
|
||||
class="fa fa-step-backward"></a>
|
||||
<span th:unless="${currentPage > 1}" th:title="#{previous}" class="fa fa-step-backward"></span>
|
||||
</span>
|
||||
<span>
|
||||
<a th:if="${currentPage < totalPages}" th:href="@{'/owners?page=__${currentPage + 1}__'}" th:title="#{next}"
|
||||
class="fa fa-step-forward"></a>
|
||||
<span th:unless="${currentPage < totalPages}" th:title="#{next}" class="fa fa-step-forward"></span>
|
||||
</span>
|
||||
<span>
|
||||
<a th:if="${currentPage < totalPages}" th:href="@{'/owners?page=__${totalPages}__'}" th:title="#{last}"
|
||||
class="fa fa-fast-forward"></a>
|
||||
<span th:unless="${currentPage < totalPages}" th:title="#{last}" class="fa fa-fast-forward"></span>
|
||||
</span>
|
||||
<div class="owner-list-pagination d-flex flex-column flex-lg-row align-items-lg-center justify-content-lg-between gap-3 mt-4"
|
||||
th:if="${totalPages > 1}">
|
||||
<div class="text-muted small" th:text="#{owners.pagination.summary(${startItem}, ${endItem}, ${totalItems})}">
|
||||
Showing 1-10 of 42
|
||||
</div>
|
||||
<nav class="flex-grow-1" aria-label="Owners pagination">
|
||||
<ul class="pagination justify-content-lg-end justify-content-center mb-0">
|
||||
<li class="page-item" th:classappend="${currentPage == 1} ? ' disabled'">
|
||||
<a class="page-link" th:href="@{/owners(page=1, size=${pageSize}, lastName=${owner.lastName})}"
|
||||
th:title="#{first}" aria-label="First">
|
||||
<span class="fa fa-fast-backward" aria-hidden="true"></span>
|
||||
<span class="visually-hidden" th:text="#{first}">First</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item" th:classappend="${currentPage == 1} ? ' disabled'">
|
||||
<a class="page-link"
|
||||
th:href="@{/owners(page=${currentPage - 1}, size=${pageSize}, lastName=${owner.lastName})}"
|
||||
th:title="#{previous}" aria-label="Previous">
|
||||
<span class="fa fa-step-backward" aria-hidden="true"></span>
|
||||
<span class="visually-hidden" th:text="#{previous}">Previous</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item disabled" th:if="${showLeadingGap}">
|
||||
<span class="page-link" aria-hidden="true" th:text="#{owners.pagination.ellipsis}"></span>
|
||||
</li>
|
||||
<li class="page-item" th:each="i : ${pageNumbers}" th:classappend="${currentPage == i} ? ' active'">
|
||||
<a class="page-link" th:href="@{/owners(page=${i}, size=${pageSize}, lastName=${owner.lastName})}"
|
||||
th:text="${i}" th:aria-current="${currentPage == i} ? 'page' : null"></a>
|
||||
</li>
|
||||
<li class="page-item disabled" th:if="${showTrailingGap}">
|
||||
<span class="page-link" aria-hidden="true" th:text="#{owners.pagination.ellipsis}"></span>
|
||||
</li>
|
||||
<li class="page-item" th:classappend="${currentPage == totalPages} ? ' disabled'">
|
||||
<a class="page-link"
|
||||
th:href="@{/owners(page=${currentPage + 1}, size=${pageSize}, lastName=${owner.lastName})}" th:title="#{next}"
|
||||
aria-label="Next">
|
||||
<span class="fa fa-step-forward" aria-hidden="true"></span>
|
||||
<span class="visually-hidden" th:text="#{next}">Next</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item" th:classappend="${currentPage == totalPages} ? ' disabled'">
|
||||
<a class="page-link" th:href="@{/owners(page=${totalPages}, size=${pageSize}, lastName=${owner.lastName})}"
|
||||
th:title="#{last}" aria-label="Last">
|
||||
<span class="fa fa-fast-forward" aria-hidden="true"></span>
|
||||
<span class="visually-hidden" th:text="#{last}">Last</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,22 @@
|
|||
|
||||
<h2 th:text="#{vets}">Veterinarians</h2>
|
||||
|
||||
<div class="vet-list-toolbar d-flex flex-column flex-lg-row align-items-lg-center justify-content-between gap-3 mb-3">
|
||||
<div class="text-muted small" th:if="${totalItems > 0}"
|
||||
th:text="#{owners.pagination.summary(${startItem}, ${endItem}, ${totalItems})}">Showing 1-10 of 42</div>
|
||||
<form class="d-flex align-items-center gap-2" th:action="@{/vets.html}" method="get">
|
||||
<input type="hidden" name="page" value="1" />
|
||||
<label class="form-label mb-0 small" for="vetsPageSize" th:text="#{owners.pageSize.label}">Page Row</label>
|
||||
<select id="vetsPageSize" name="size" class="form-select form-select-sm" onchange="this.form.submit()">
|
||||
<option th:each="option : ${pageSizeOptions}" th:value="${option}" th:selected="${option == pageSize}"
|
||||
th:text="${option}">10</option>
|
||||
</select>
|
||||
<noscript>
|
||||
<button type="submit" class="btn btn-primary btn-sm" th:text="#{owners.pageSize.submit}">Apply</button>
|
||||
</noscript>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<table id="vets" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
@ -23,35 +39,53 @@
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div th:if="${totalPages > 1}">
|
||||
<span th:text="#{pages}">Pages:</span>
|
||||
<span>[</span>
|
||||
<span th:each="i: ${#numbers.sequence(1, totalPages)}">
|
||||
<a th:if="${currentPage != i}" th:href="@{'/vets.html?page=__${i}__'}">[[${i}]]</a>
|
||||
<span th:unless="${currentPage != i}">[[${i}]]</span>
|
||||
</span>
|
||||
<span>] </span>
|
||||
<span>
|
||||
<a th:if="${currentPage > 1}" th:href="@{'/vets.html?page=1'}" th:title="#{first}"
|
||||
class="fa fa-fast-backward"></a>
|
||||
<span th:unless="${currentPage > 1}" th:title="#{first}" class="fa fa-fast-backward"></span>
|
||||
</span>
|
||||
<span>
|
||||
<a th:if="${currentPage > 1}" th:href="@{'/vets.html?page=__${currentPage - 1}__'}" th:title="#{previous}"
|
||||
class="fa fa-step-backward"></a>
|
||||
<span th:unless="${currentPage > 1}" th:title="#{previous}" class="fa fa-step-backward"></span>
|
||||
</span>
|
||||
<span>
|
||||
<a th:if="${currentPage < totalPages}" th:href="@{'/vets.html?page=__${currentPage + 1}__'}" th:title="#{next}"
|
||||
class="fa fa-step-forward"></a>
|
||||
<span th:unless="${currentPage < totalPages}" th:title="#{next}" class="fa fa-step-forward"></span>
|
||||
</span>
|
||||
<span>
|
||||
<a th:if="${currentPage < totalPages}" th:href="@{'/vets.html?page=__${totalPages}__'}" th:title="#{last}"
|
||||
class="fa fa-fast-forward"></a>
|
||||
<span th:unless="${currentPage < totalPages}" th:title="#{last}" class="fa fa-fast-forward"></span>
|
||||
</span>
|
||||
<div class="vet-list-pagination d-flex flex-column flex-lg-row align-items-lg-center justify-content-lg-between gap-3 mt-4"
|
||||
th:if="${totalPages > 1}">
|
||||
<div class="text-muted small" th:text="#{owners.pagination.summary(${startItem}, ${endItem}, ${totalItems})}">
|
||||
Showing 1-10 of 42
|
||||
</div>
|
||||
<nav class="flex-grow-1" aria-label="Veterinarians pagination">
|
||||
<ul class="pagination justify-content-lg-end justify-content-center mb-0">
|
||||
<li class="page-item" th:classappend="${currentPage == 1} ? ' disabled'">
|
||||
<a class="page-link" th:href="@{/vets.html(page=1, size=${pageSize})}" th:title="#{first}" aria-label="First">
|
||||
<span class="fa fa-fast-backward" aria-hidden="true"></span>
|
||||
<span class="visually-hidden" th:text="#{first}">First</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item" th:classappend="${currentPage == 1} ? ' disabled'">
|
||||
<a class="page-link" th:href="@{/vets.html(page=${currentPage - 1}, size=${pageSize})}"
|
||||
th:title="#{previous}" aria-label="Previous">
|
||||
<span class="fa fa-step-backward" aria-hidden="true"></span>
|
||||
<span class="visually-hidden" th:text="#{previous}">Previous</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item disabled" th:if="${showLeadingGap}">
|
||||
<span class="page-link" aria-hidden="true" th:text="#{owners.pagination.ellipsis}"></span>
|
||||
</li>
|
||||
<li class="page-item" th:each="i : ${pageNumbers}" th:classappend="${currentPage == i} ? ' active'">
|
||||
<a class="page-link" th:href="@{/vets.html(page=${i}, size=${pageSize})}" th:text="${i}"
|
||||
th:aria-current="${currentPage == i} ? 'page' : null"></a>
|
||||
</li>
|
||||
<li class="page-item disabled" th:if="${showTrailingGap}">
|
||||
<span class="page-link" aria-hidden="true" th:text="#{owners.pagination.ellipsis}"></span>
|
||||
</li>
|
||||
<li class="page-item" th:classappend="${currentPage == totalPages} ? ' disabled'">
|
||||
<a class="page-link" th:href="@{/vets.html(page=${currentPage + 1}, size=${pageSize})}" th:title="#{next}"
|
||||
aria-label="Next">
|
||||
<span class="fa fa-step-forward" aria-hidden="true"></span>
|
||||
<span class="visually-hidden" th:text="#{next}">Next</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item" th:classappend="${currentPage == totalPages} ? ' disabled'">
|
||||
<a class="page-link" th:href="@{/vets.html(page=${totalPages}, size=${pageSize})}" th:title="#{last}"
|
||||
aria-label="Last">
|
||||
<span class="fa fa-fast-forward" aria-hidden="true"></span>
|
||||
<span class="visually-hidden" th:text="#{last}">Last</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue