pagination and likes #4
@ -22,6 +22,10 @@ public class BookDto {
|
||||
private Long typeId;
|
||||
@NotNull
|
||||
private List<Long> authorsId;
|
||||
@NotNull
|
||||
private boolean isChosen = false;
|
||||
@Min(0)
|
||||
private int fansNumber = 0;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
@ -70,4 +74,20 @@ public class BookDto {
|
||||
public void setAuthorsId(List<Long> authorsId) {
|
||||
this.authorsId = authorsId;
|
||||
}
|
||||
|
||||
public boolean getIsChosen() {
|
||||
return isChosen;
|
||||
}
|
||||
|
||||
public void setIsChosen(boolean isChosen) {
|
||||
this.isChosen = isChosen;
|
||||
}
|
||||
|
||||
public int getFansNumber() {
|
||||
return fansNumber;
|
||||
}
|
||||
|
||||
public void setFansNumber(int fansNumber) {
|
||||
this.fansNumber = fansNumber;
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,11 @@ import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.OrderBy;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Transient;
|
||||
|
||||
import com.ip.library.controllers.authors.AuthorEntity;
|
||||
import com.ip.library.controllers.authors_books.AuthorsBooksEntity;
|
||||
import com.ip.library.controllers.favorites.FavoriteEntity;
|
||||
import com.ip.library.controllers.types.TypeEntity;
|
||||
|
||||
@Entity
|
||||
@ -32,6 +34,13 @@ public class BookEntity extends BaseEntity {
|
||||
@OneToMany(mappedBy = "book", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
@OrderBy("id ASC")
|
||||
private Set<AuthorsBooksEntity> authorsBooks = new HashSet<>();
|
||||
@OneToMany(mappedBy = "book", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
@OrderBy("id ASC")
|
||||
private Set<FavoriteEntity> fans = new HashSet<>();
|
||||
@Transient
|
||||
private boolean isChosen = false;
|
||||
@Transient
|
||||
private int fansNumber = 0;
|
||||
|
||||
public BookEntity() {
|
||||
super();
|
||||
@ -42,14 +51,6 @@ public class BookEntity extends BaseEntity {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public TypeEntity getType() {
|
||||
return type;
|
||||
}
|
||||
@ -66,6 +67,38 @@ public class BookEntity extends BaseEntity {
|
||||
this.authorsBooks = authorsBooks;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean getIsChosen() {
|
||||
return isChosen;
|
||||
}
|
||||
|
||||
public void setIsChosen(boolean isChosen) {
|
||||
this.isChosen = isChosen;
|
||||
}
|
||||
|
||||
public int getFansNumber() {
|
||||
return fansNumber;
|
||||
}
|
||||
|
||||
public void setFansNumber(int fansNumber) {
|
||||
this.fansNumber = fansNumber;
|
||||
}
|
||||
|
||||
public Set<FavoriteEntity> getFans() {
|
||||
return fans;
|
||||
}
|
||||
|
||||
public void setFans(Set<FavoriteEntity> fans) {
|
||||
this.fans = fans;
|
||||
}
|
||||
|
||||
public boolean addAuthor(AuthorEntity author) {
|
||||
AuthorsBooksEntity entity = new AuthorsBooksEntity(author, this);
|
||||
return authorsBooks.add(entity);
|
||||
|
@ -13,6 +13,7 @@ import com.ip.library.controllers.authors.AuthorService;
|
||||
import com.ip.library.controllers.authors_books.AuthorsBooksEntity;
|
||||
import com.ip.library.controllers.authors_books.AuthorsBooksId;
|
||||
import com.ip.library.controllers.authors_books.AuthorsBooksRepository;
|
||||
import com.ip.library.controllers.users.UserRepository;
|
||||
import com.ip.library.core.error.NotFoundException;
|
||||
|
||||
@Service
|
||||
@ -20,14 +21,17 @@ public class BookService {
|
||||
private final AuthorsBooksRepository authorsBooksRepository;
|
||||
private final BookRepository bookRepository;
|
||||
private final AuthorService authorService;
|
||||
private final UserRepository userRepository;
|
||||
|
||||
public BookService(
|
||||
BookRepository bookRepository,
|
||||
AuthorService authorService,
|
||||
AuthorsBooksRepository authorsBooksRepository) {
|
||||
AuthorsBooksRepository authorsBooksRepository,
|
||||
UserRepository userRepository) {
|
||||
this.bookRepository = bookRepository;
|
||||
this.authorService = authorService;
|
||||
this.authorsBooksRepository = authorsBooksRepository;
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
private void checkNameUniqueness(String name){
|
||||
@ -55,6 +59,32 @@ public class BookService {
|
||||
return bookRepository.findByAuthorIdAndTypeId(authorId, typeId, pageRequest);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Page<BookEntity> getAll(long typeId, long authorId, long userId, int page, int size) {
|
||||
PageRequest pageRequest = PageRequest.of(page, size);
|
||||
Page<BookEntity> result = null;
|
||||
if (typeId <= 0L && authorId <= 0L) {
|
||||
result = bookRepository.findAll(pageRequest);
|
||||
}
|
||||
else if (authorId <= 0L){
|
||||
result = bookRepository.findByTypeId(typeId, pageRequest);
|
||||
}
|
||||
else if (typeId <= 0L) {
|
||||
result = bookRepository.findByAuthorId(authorId, pageRequest);
|
||||
}
|
||||
else {
|
||||
result = bookRepository.findByAuthorIdAndTypeId(authorId, typeId, pageRequest);
|
||||
}
|
||||
List<BookEntity> favorites = getUserFavorities(userId);
|
||||
for (BookEntity book : result.getContent()) {
|
||||
if (favorites.contains(book)) {
|
||||
book.setIsChosen(true);
|
||||
}
|
||||
book.setFansNumber(book.getFans().size());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<BookEntity> getAll(long typeId, long authorId) {
|
||||
if (typeId <= 0L && authorId <= 0L)
|
||||
@ -122,6 +152,11 @@ public class BookService {
|
||||
return bookRepository.getBookSubscribersNumber(bookId);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<BookEntity> getUserFavorities (long userId) {
|
||||
return userRepository.getUserFavorities(userId);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<AuthorEntity> getAuthors(long bookId) {
|
||||
return bookRepository.getAuthors(bookId);
|
||||
|
@ -32,6 +32,7 @@ public class UserBookController {
|
||||
private static final String AUTHORS_ATTRIBUTE = "authors";
|
||||
private static final String TYPE_ATTRIBUTE = "typeId";
|
||||
private static final String TYPES_ATTRIBUTE = "types";
|
||||
private static final String PARAMS_ATTRIBUTE = "searchParams";
|
||||
|
||||
private final UserService userService;
|
||||
private final BookService bookService;
|
||||
@ -70,7 +71,7 @@ public class UserBookController {
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public String getFavorites(
|
||||
public String favorites(
|
||||
@RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page,
|
||||
Model model,
|
||||
@AuthenticationPrincipal UserPrincipal principal) {
|
||||
@ -94,19 +95,21 @@ public class UserBookController {
|
||||
}
|
||||
|
||||
@GetMapping(Constants.API_URL + "/search")
|
||||
public String getAll(
|
||||
public String search(
|
||||
@RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page,
|
||||
@RequestParam(name = TYPE_ATTRIBUTE, defaultValue = "-1") Long typeId,
|
||||
@RequestParam(name = AUTHOR_ATTRIBUTE, defaultValue = "-1") Long authorId,
|
||||
Model model) {
|
||||
Model model,
|
||||
@AuthenticationPrincipal UserPrincipal principal) {
|
||||
final Map<String, Object> attributes = PageAttributesMapper.toAttributes(
|
||||
bookService.getAll(typeId, authorId, page, Constants.DEFUALT_PAGE_SIZE),
|
||||
bookService.getAll(typeId, authorId, principal.getId(), page, Constants.DEFUALT_PAGE_SIZE),
|
||||
this::toBookDto);
|
||||
model.addAllAttributes(attributes);
|
||||
model.addAttribute(TYPE_ATTRIBUTE, typeId);
|
||||
model.addAttribute(AUTHOR_ATTRIBUTE, authorId);
|
||||
model.addAttribute(TYPES_ATTRIBUTE, typeService.getAll());
|
||||
model.addAttribute(AUTHORS_ATTRIBUTE, authorService.getAll());
|
||||
model.addAttribute(PARAMS_ATTRIBUTE, "typeId="+typeId+"&authorId="+authorId);
|
||||
model.addAttribute(PAGE_ATTRIBUTE, page);
|
||||
return BOOK_SEARCH_VIEW;
|
||||
}
|
||||
|
@ -42,6 +42,7 @@
|
||||
<th scope="col" class="w-auto">Название</th>
|
||||
<th scope="col" class="w-auto">Жанр</th>
|
||||
<th scope="col" class="w-auto">Автор</th>
|
||||
<th scope="col" class="w-auto">Добавили в избранное</th>
|
||||
<th scope="col" class="w-10"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -51,10 +52,12 @@
|
||||
<td th:text="${book.name}"></td>
|
||||
<td th:text="${book.typeName}"></td>
|
||||
<td th:text="${book.authorName}"></td>
|
||||
<td th:text="${book.fansNumber}"></td>
|
||||
<td>
|
||||
<form th:action="@{/api/1.0/addFavorite/{id}(id=${book.id})}" method="post">
|
||||
<input type="hidden" th:name="page" th:value="${page}">
|
||||
<button type="submit" class="btn btn-link button-link">В избранное</button>
|
||||
<button type="submit" class="btn btn-link button-link"
|
||||
th:hidden="${book.isChosen}">В избранное</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
@ -65,10 +68,8 @@
|
||||
url=${'api/1.0/search'},
|
||||
totalPages=${totalPages},
|
||||
currentPage=${currentPage},
|
||||
param1name=${'typeId'},
|
||||
param1value=${typeId},
|
||||
param2name=${'authorId'},
|
||||
param2value=${authorId}) }" />
|
||||
searchParams=${searchParams}
|
||||
)}" />
|
||||
</th:block>
|
||||
</main>
|
||||
</body>
|
||||
|
@ -48,7 +48,7 @@
|
||||
</nav>
|
||||
</th:block>
|
||||
|
||||
<th:block th:fragment="pagination-with-params (url, totalPages, currentPage, param1name, param1value, param2name, param2value)">
|
||||
<th:block th:fragment="pagination-with-params (url, totalPages, currentPage, searchParams)">
|
||||
<nav th:if="${totalPages > 1}" th:with="
|
||||
maxPage=2,
|
||||
currentPage=${currentPage + 1}">
|
||||
@ -59,10 +59,7 @@
|
||||
<th:block th:if="${currentPage > maxPage + 1}">
|
||||
<li class="page-item">
|
||||
<a class="page-link" aria-label="Previous"
|
||||
th:href="@{/{url}?page=0&{param1name}={param1value}&{param2name}={param2value}
|
||||
(url=${url},
|
||||
param1name=${param1name},param1value=${param1value},
|
||||
param2name=${param2name},param2value=${param2value})}">
|
||||
th:href="@{/{url}?page=0&(url=${url})} + ${searchParams}">
|
||||
<span aria-hidden="true">«</span>
|
||||
</a>
|
||||
</li>
|
||||
@ -75,10 +72,7 @@
|
||||
<li class="page-item" th:each="page : ${#numbers.sequence(seqFrom, seqTo)}"
|
||||
th:classappend="${page == currentPage} ? 'active' : ''">
|
||||
<a class=" page-link"
|
||||
th:href="@{/{url}?page={page}&{param1name}={param1value}&{param2name}={param2value}
|
||||
(url=${url},page=${page - 1},
|
||||
param1name=${param1name},param1value=${param1value},
|
||||
param2name=${param2name},param2value=${param2value})}">
|
||||
th:href="@{/{url}?page={page}&(url=${url},page=${page - 1})} + ${searchParams}">
|
||||
<span th:text="${page}" />
|
||||
</a>
|
||||
</li>
|
||||
@ -90,10 +84,7 @@
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" aria-label="Next"
|
||||
th:href="@{/{url}?page={page}&{param1name}={param1value}&{param2name}={param2value}
|
||||
(url=${url},page=${totalPages - 1},
|
||||
param1name=${param1name},param1value=${param1value},
|
||||
param2name=${param2name},param2value=${param2value})}">
|
||||
th:href="@{/{url}?page={page}&(url=${url},page=${totalPages - 1})} + ${searchParams}">
|
||||
<span aria-hidden="true">»</span>
|
||||
</a>
|
||||
</li>
|
||||
|
Loading…
Reference in New Issue
Block a user