#5 -- add pagination, styles and footer

This commit is contained in:
Anton Romanov 2022-03-11 14:26:24 +04:00
parent c9a6f559f2
commit 458011644c
9 changed files with 160 additions and 4 deletions

Binary file not shown.

View File

@ -6,6 +6,7 @@
package ru.ulstu.controller;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
@ -14,14 +15,21 @@ import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.model.News;
import ru.ulstu.model.OffsetablePageRequest;
import ru.ulstu.service.NewsService;
import javax.validation.Valid;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@Controller
@RequestMapping("news")
public class NewsController {
private final static int DEFAULT_PAGE_SIZE = 10;
private final NewsService newsService;
public NewsController(NewsService newsService) {
@ -29,8 +37,21 @@ public class NewsController {
}
@GetMapping("/news")
public String index(Model model) {
model.addAttribute("news", newsService.getAll());
public String listNews(Model model,
@RequestParam Optional<Integer> page,
@RequestParam Optional<Integer> size) {
int currentPage = page.orElse(1);
int pageSize = size.orElse(DEFAULT_PAGE_SIZE);
Page<News> newsPage = newsService.getNews(new OffsetablePageRequest(currentPage - 1, pageSize));
model.addAttribute("news", newsPage);
int totalPages = newsPage.getTotalPages();
if (totalPages > 0) {
List<Integer> pageNumbers = IntStream.rangeClosed(1, totalPages)
.boxed()
.collect(Collectors.toList());
model.addAttribute("pageNumbers", pageNumbers);
}
return "news";
}

View File

@ -0,0 +1,93 @@
package ru.ulstu.model;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import java.io.Serializable;
public class OffsetablePageRequest implements Pageable, Serializable {
private final int offset;
private final int count;
private final Sort sort;
public OffsetablePageRequest(int page, long pageSize) {
this(pageSize * page, pageSize, Sort.by("id"));
}
public OffsetablePageRequest(long offset, long count, Sort sort) {
if (offset < 0) {
throw new IllegalArgumentException("Offset value must not be less than zero!");
}
if (count < 1) {
throw new IllegalArgumentException("Count value must not be less than one!");
}
this.offset = (int) offset;
this.count = (int) count;
this.sort = sort;
}
@Override
public Sort getSort() {
return sort;
}
@Override
public int getPageSize() {
return count;
}
@Override
public int getPageNumber() {
return offset / count;
}
@Override
public long getOffset() {
return offset;
}
@Override
public boolean hasPrevious() {
return offset > 0;
}
@Override
public Pageable next() {
return new OffsetablePageRequest(getOffset() + getPageSize(), getPageSize(), getSort());
}
@Override
public Pageable previousOrFirst() {
return hasPrevious() ? previous() : first();
}
public Pageable previous() {
return getOffset() == 0 ? this : new OffsetablePageRequest(getOffset() - getPageSize(), getPageSize(), getSort());
}
@Override
public Pageable first() {
return new OffsetablePageRequest(0, getPageSize(), getSort());
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final OffsetablePageRequest other = (OffsetablePageRequest) obj;
return this.offset == other.offset && this.count == other.count;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + offset;
result = prime * result + count;
return result;
}
}

View File

@ -1,5 +1,7 @@
package ru.ulstu.repository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import ru.ulstu.model.News;
@ -7,4 +9,6 @@ import java.util.List;
public interface NewsRepository extends JpaRepository<News, Integer> {
List<News> findFirst3ByOrderByDateDesc();
Page<News> findByOrderByDateDesc(Pageable pageable);
}

View File

@ -1,5 +1,7 @@
package ru.ulstu.service;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import ru.ulstu.model.News;
import ru.ulstu.repository.NewsRepository;
@ -50,4 +52,8 @@ public class NewsService {
public List<News> getLast() {
return newsRepository.findFirst3ByOrderByDateDesc();
}
public Page<News> getNews(Pageable pageable) {
return newsRepository.findByOrderByDateDesc(pageable);
}
}

View File

@ -32,3 +32,24 @@
.link-dark, .link-dark:visited, .link-dark:focus, .link-dark:any-link {
color: black;
}
.pagination {
display: inline-block;
}
.pagination a {
color: black;
float: left;
padding: 5px 5px;
text-decoration: none;
}
.pagination a.active {
background-color: gray;
color: white;
border-radius: 2px;
}
footer {
height: 50px;
}

View File

@ -7,7 +7,7 @@
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
<div class="container" layout:fragment="content">
<a href="/editNews/0" class="btn btn-outline-dark">
<a href="/news/editNews/0" class="btn btn-outline-dark">
<i class="fa fa-plus-square" aria-hidden="true">Добавить новость</i>
</a>
</div>

View File

@ -64,6 +64,7 @@
<div layout:fragment="content">
</div>
</div>
<footer></footer>
</div>
</body>
</html>

View File

@ -36,5 +36,15 @@
class="news-date"></div>
<hr/>
</div>
<div th:if="${news.totalPages > 0}" class="pagination">
<span style="float: left; padding: 5px 5px;">Страницы:</span>
</div>
<div th:if="${news.totalPages > 0}" class="pagination"
th:each="pageNumber : ${pageNumbers}">
<a th:href="@{/news/news(size=${news.size}, page=${pageNumber})}"
th:text=${pageNumber}
th:class="${pageNumber == news.number+1} ? active"></a>
</div>
</div>
</html>