Add some API, update few pages

master
Dmitry Isaenko 2024-03-05 18:46:51 +03:00
parent 762bb8b97f
commit 67eb755b2b
8 changed files with 93 additions and 16 deletions

View File

@ -2,6 +2,7 @@ package ru.redrise.marinesco.data;
import java.util.Optional;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@ -12,4 +13,5 @@ import java.util.List;
public interface AuthorRepository extends JpaRepository<Author, Long>{
Optional<Author> findByAuthorName(String authorName);
List<Author> findByAuthorNameContainingIgnoreCase(String authorName);
List<Author> findByAuthorNameContainingIgnoreCase(String authorName, PageRequest pageRequest);
}

View File

@ -2,6 +2,7 @@ package ru.redrise.marinesco.data;
import java.util.List;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@ -10,5 +11,7 @@ import ru.redrise.marinesco.library.Book;
@Repository
public interface BookRepository extends JpaRepository<Book, Integer>{
List<Book> findBySeriesContainingIgnoreCase(String title);
List<Book> findBySeriesContainingIgnoreCase(String title, PageRequest page);
List<Book> findByTitleContainingIgnoreCase(String title);
List<Book> findByTitleContainingIgnoreCase(String title, PageRequest page);
}

View File

@ -3,6 +3,7 @@ package ru.redrise.marinesco.library.api;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@ -29,4 +30,20 @@ public class AuthorsApiController {
return authorRepository.findAll(pageRequest).getContent();
}
@GetMapping("/by/name/{name}")
public Iterable<Author> getAuthorId(
@PathVariable("name") String authorName,
@RequestParam(value = "page", required = false, defaultValue = "0") Integer page){
PageRequest pageRequest = PageRequest.of(page, 10);
return authorRepository.findByAuthorNameContainingIgnoreCase(authorName, pageRequest);
}
@GetMapping("/by/id/{id}")
public Author getAuthorId(@PathVariable("id") Long authorId){
return authorRepository.findById(authorId).get();
}
}

View File

@ -1,8 +1,11 @@
package ru.redrise.marinesco.library.api;
import java.util.Optional;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@ -27,12 +30,38 @@ public class BooksApiController {
}
@GetMapping(params = "page")
public Iterable<Book> getBooks(@RequestParam(value = "page", required = true) Integer page,
public Iterable<Book> getBooks(
@RequestParam(value = "page", required = true) Integer page,
@RequestParam(value = "sort", required = false, defaultValue = "title") String sortBy){
PageRequest pageRequest = PageRequest.of(
page, 10, Sort.by(sortBy).descending());
return bookRepository.findAll(pageRequest).getContent();
}
@GetMapping("/by/title/{title}")
public Iterable<Book> getBooksByName(
@PathVariable("title") String title,
@RequestParam(value = "page", required = false, defaultValue = "0") Integer page){
PageRequest pageRequest = PageRequest.of(page, 10);
return bookRepository.findByTitleContainingIgnoreCase(title, pageRequest);
}
@GetMapping("/by/series/{series}")
public Iterable<Book> getBooksBySeries(
@PathVariable("series") String series,
@RequestParam(value = "page", required = false, defaultValue = "0") Integer page){
PageRequest pageRequest = PageRequest.of(page, 10);
return bookRepository.findBySeriesContainingIgnoreCase(series, pageRequest);
}
@GetMapping("/by/id/{id}")
public Book getBooksById(@PathVariable("id") Integer id){
return bookRepository.findById(id).get();
}
}

View File

@ -1,19 +1,26 @@
package ru.redrise.marinesco.library.api;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import lombok.extern.slf4j.Slf4j;
import ru.redrise.marinesco.data.GenreRepository;
import ru.redrise.marinesco.library.Author;
import ru.redrise.marinesco.library.Genre;
@Slf4j
@RestController
@RequestMapping(path = "/api/genres", produces = "application/json")
public class GenresApiController {
@ -27,16 +34,36 @@ public class GenresApiController {
public Iterable<Genre> getGenres(
@RequestParam(value = "page", required = false, defaultValue = "0") Integer page,
@RequestParam(value = "sort", required = false, defaultValue = "genreId") String sortBy) {
PageRequest pageRequest = PageRequest.of(
page, 10, Sort.by(sortBy).descending());
PageRequest pageRequest = PageRequest.of(page, 10, Sort.by(sortBy).descending());
return genreRepository.findAll(pageRequest).getContent();
}
@GetMapping("/by/id/{id}")
public Genre getAuthorId(@PathVariable("id") String id){
return genreRepository.findById(id).get();
}
@PostMapping(consumes = "application/json")
@ResponseStatus(HttpStatus.CREATED)
public Genre postGenre(@RequestBody Genre genre) {
log.info("{}", genre);
return genreRepository.save(genre);
}
@PutMapping(path = "/{genreId}", consumes = "application/json")
public Genre putGenre(@PathVariable("genreId") String genreId,
@RequestBody Genre genre){
genre.setGenreId(genreId);
return genreRepository.save(genre);
}
@DeleteMapping("/{genreId}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteGenre(@PathVariable("genreId") String genreId){
try{
genreRepository.deleteById(genreId);
}
catch(EmptyResultDataAccessException ignore){}
}
}

View File

@ -51,8 +51,7 @@
<span class="header_entry">|</span>
</li>
<li class="li_header_block">
<a class="header_entry header_entry_link" href="/logout">Logout</a>
<form style="visibility: hidden" id="form" method="post" action="#" th:action="@{/logout}"></form>
<a id="logout" class="header_entry header_entry_link" href="/logout">Logout</a>
</li>
</ul>
</div>

View File

@ -15,38 +15,38 @@
<div class="container base">
<h1>Register</h1>
<form class="regForm" method="POST" th:action="@{/register}" th:object="${registrationForm}">
<span class="validationError" th:if="${loginOccupied} != null"
<span id="duplicate_error" class="validationError" th:if="${loginOccupied} != null"
th:text="${loginOccupied}">pew</span>
<span class="validationError" th:if="${#fields.hasErrors('username')}"
<span id="username_error" class="validationError" th:if="${#fields.hasErrors('username')}"
th:errors="*{username}">Error</span>
<br />
<label for="username">Username: </label>
<br />
<input type="text" name="username" id="username" size="50%" /><br />
<span class="validationError" th:if="${#fields.hasErrors('password')}"
<span id="password_error" class="validationError" th:if="${#fields.hasErrors('password')}"
th:errors="*{password}">Error</span>
<br />
<label for="password">Password: </label>
<br />
<input type="password" name="password" id="password" size="50%" /><br />
<span class="validationError" th:if="${passwordsMismatch} != null"
<span id="password_dup_error" class="validationError" th:if="${passwordsMismatch} != null"
th:text="${passwordsMismatch}">false</span>
<br />
<label for="confirm">Confirm password: </label>
<br />
<input type="password" name="passwordConfirm" id="passwordConfirm" size="50%" /><br />
<span class="validationError" th:if="${#fields.hasErrors('displayname')}"
<span id="displayname_error" class="validationError" th:if="${#fields.hasErrors('displayname')}"
th:errors="*{displayname}">Error</span>
<br />
<label for="displayname">Displayed name: </label>
<br />
<input type="text" name="displayname" id="displayname" size="50%" /><br />
<p>
<button class="sign" type="submit">Register</button>
<button id="register_submit" class="sign" type="submit">Register</button>
</p>
</form>
</div>

View File

@ -14,27 +14,27 @@
<div class="container base">
<span
th:text="${'New users registration is now ' + (allowRegistration ? 'enabled. ' : 'disabled. ' )}"></span>
<a th:href="${'/settings/allow_registration/' + !allowRegistration }"
<a id="registration" th:href="${'/settings/allow_registration/' + !allowRegistration }"
th:text="${'Click here to ' + (allowRegistration ? 'disable' : 'enable' )}"></a>
<br />
<br />
<a href="/settings/manage_users">Manage users</a>
<a id="manage_users" href="/settings/manage_users">Manage users</a>
<br />
<br />
<span class="validationError" th:if="${rescanError} != null" th:text="${rescanError}"></span>
<span class="validationPass" th:if="${rescanOk} != null" th:text="${rescanOk}"></span>
<br />
<a href="/settings/rescan" >Click to rescan library</a>
<a id="rescan_library" href="/settings/rescan" >Click to rescan library</a>
<br />
<br />
<span class="validationPass" th:if="${repack} != null" th:text="${repack}"></span>
<span class="validationPass" th:if="${repack_lastrun} != null" th:text="${repack_lastrun}"></span>
<br />
<a href="/settings/repack" >Click to repack library zip archives</a>
<a id="repack_library" href="/settings/repack" >Click to repack library zip archives</a>
<br />
<span class="validationError" th:if="${lastScanErrors} != ''" th:text="${lastScanErrors}"></span>
</p>
<a href="/settings/genres">Edit genre descriptions</a>
<a id="edit_genres" href="/settings/genres">Edit genre descriptions</a>
</div>
</div>
<div th:replace="~{fragments/footer :: 'footer'}"></div>