Лаба готова
This commit is contained in:
parent
46732e4a2a
commit
cb2828e0a9
@ -22,4 +22,9 @@ public class AuthorDto {
|
|||||||
public String getFirstname(){return firstname;}
|
public String getFirstname(){return firstname;}
|
||||||
public String getLastname(){return lastname;}
|
public String getLastname(){return lastname;}
|
||||||
public String getPhoto(){return photo;}
|
public String getPhoto(){return photo;}
|
||||||
|
|
||||||
|
public void setId(Long id){this.id = id;}
|
||||||
|
public void setFirstname(String firstname){this.firstname = firstname;}
|
||||||
|
public void setLastname(String lastname){this.lastname = lastname;}
|
||||||
|
public void setPhoto(String photo){this.photo = photo;}
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,22 @@ import org.springframework.stereotype.Controller;
|
|||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import ru.ip.labworks.labworks.bookshop.service.AuthorService;
|
import ru.ip.labworks.labworks.bookshop.service.AuthorService;
|
||||||
|
import ru.ip.labworks.labworks.bookshop.service.BookService;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@RequestMapping("/author")
|
@RequestMapping("/author")
|
||||||
public class AuthorMvcController {
|
public class AuthorMvcController {
|
||||||
private final AuthorService authorService;
|
private final AuthorService authorService;
|
||||||
public AuthorMvcController(AuthorService authorService)
|
private final BookService bookService;
|
||||||
|
public AuthorMvcController(AuthorService authorService, BookService bookService)
|
||||||
{
|
{
|
||||||
this.authorService = authorService;
|
this.authorService = authorService;
|
||||||
|
this.bookService = bookService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
@ -39,14 +44,16 @@ public class AuthorMvcController {
|
|||||||
|
|
||||||
@PostMapping(value = {"/", "/{id}"})
|
@PostMapping(value = {"/", "/{id}"})
|
||||||
public String saveAuthor(@PathVariable(required = false) Long id,
|
public String saveAuthor(@PathVariable(required = false) Long id,
|
||||||
@ModelAttribute("authorDto") AuthorDto authorDto,
|
@RequestParam(value = "multipartFile") MultipartFile multipartFile,
|
||||||
BindingResult bindingResult,
|
@ModelAttribute("authorDto") AuthorDto authorDto,
|
||||||
Model model) throws IOException {
|
BindingResult bindingResult,
|
||||||
|
Model model) throws IOException {
|
||||||
if (bindingResult.hasErrors()) {
|
if (bindingResult.hasErrors()) {
|
||||||
model.addAttribute("errors",
|
model.addAttribute("errors",
|
||||||
bindingResult.getAllErrors());
|
bindingResult.getAllErrors());
|
||||||
return "author-update";
|
return "author-update";
|
||||||
}
|
}
|
||||||
|
authorDto.setPhoto("data:" + multipartFile.getContentType() + ";base64," + Base64.getEncoder().encodeToString(multipartFile.getBytes()));
|
||||||
if (id == null || id <= 0) {
|
if (id == null || id <= 0) {
|
||||||
authorService.addAuthor(authorDto);
|
authorService.addAuthor(authorDto);
|
||||||
} else {
|
} else {
|
||||||
@ -60,4 +67,31 @@ public class AuthorMvcController {
|
|||||||
authorService.deleteAuthor(id);
|
authorService.deleteAuthor(id);
|
||||||
return "redirect:/author";
|
return "redirect:/author";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}/books")
|
||||||
|
public String getAuthorBooks(@PathVariable Long id, Model model){
|
||||||
|
model.addAttribute("author",
|
||||||
|
new AuthorDto(authorService.findAuthor(id)));
|
||||||
|
model.addAttribute("authorbooks",
|
||||||
|
authorService.authorBooks(id).stream()
|
||||||
|
.map(BookDto::new)
|
||||||
|
.toList());
|
||||||
|
model.addAttribute("books",
|
||||||
|
bookService.findAllBooks().stream()
|
||||||
|
.map(BookDto::new)
|
||||||
|
.toList());
|
||||||
|
return "author-mtm";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{id}/books")
|
||||||
|
public String addBookToAuthor(@PathVariable Long id, @RequestParam(value = "bookid") Long bookid){
|
||||||
|
authorService.addBookToAuthor(id, bookid);
|
||||||
|
return "redirect:/author/" + id.toString() + "/books";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{id}/books/{bookid}")
|
||||||
|
public String removeBookFromAuthor(@PathVariable Long id, @PathVariable Long bookid){
|
||||||
|
authorService.removeBookFromAuthor(id, bookid);
|
||||||
|
return "redirect:/author/" + id.toString() + "/books";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,4 +23,9 @@ public class BookDto {
|
|||||||
public String getName(){return name;}
|
public String getName(){return name;}
|
||||||
public Date getRelease(){return release;}
|
public Date getRelease(){return release;}
|
||||||
public String getCover(){return cover;}
|
public String getCover(){return cover;}
|
||||||
|
|
||||||
|
public void setId(Long id){this.id = id;}
|
||||||
|
public void setName(String name){this.name = name;}
|
||||||
|
public void setRelease(Date release){this.release = release;}
|
||||||
|
public void setCover(String cover){this.cover = cover;}
|
||||||
}
|
}
|
||||||
|
@ -3,16 +3,21 @@ import org.springframework.stereotype.Controller;
|
|||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import ru.ip.labworks.labworks.bookshop.service.BookService;
|
import ru.ip.labworks.labworks.bookshop.service.BookService;
|
||||||
|
import ru.ip.labworks.labworks.bookshop.service.GenreService;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@RequestMapping("/book")
|
@RequestMapping("/book")
|
||||||
public class BookMvcController {
|
public class BookMvcController {
|
||||||
private final BookService bookService;
|
private final BookService bookService;
|
||||||
public BookMvcController(BookService bookService){
|
private final GenreService genreService;
|
||||||
|
public BookMvcController(BookService bookService, GenreService genreService){
|
||||||
this.bookService = bookService;
|
this.bookService = bookService;
|
||||||
|
this.genreService = genreService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
@ -38,14 +43,16 @@ public class BookMvcController {
|
|||||||
|
|
||||||
@PostMapping(value = {"/", "/{id}"})
|
@PostMapping(value = {"/", "/{id}"})
|
||||||
public String saveBook(@PathVariable(required = false) Long id,
|
public String saveBook(@PathVariable(required = false) Long id,
|
||||||
@ModelAttribute("bookDto") BookDto bookDto,
|
@RequestParam(value = "multipartFile") MultipartFile multipartFile,
|
||||||
BindingResult bindingResult,
|
@ModelAttribute("bookDto") BookDto bookDto,
|
||||||
Model model) throws IOException {
|
BindingResult bindingResult,
|
||||||
|
Model model) throws IOException {
|
||||||
if (bindingResult.hasErrors()) {
|
if (bindingResult.hasErrors()) {
|
||||||
model.addAttribute("errors",
|
model.addAttribute("errors",
|
||||||
bindingResult.getAllErrors());
|
bindingResult.getAllErrors());
|
||||||
return "book-update";
|
return "book-update";
|
||||||
}
|
}
|
||||||
|
bookDto.setCover("data:" + multipartFile.getContentType() + ";base64," + Base64.getEncoder().encodeToString(multipartFile.getBytes()));
|
||||||
if (id == null || id <= 0) {
|
if (id == null || id <= 0) {
|
||||||
bookService.addBook(bookDto);
|
bookService.addBook(bookDto);
|
||||||
} else {
|
} else {
|
||||||
@ -59,4 +66,31 @@ public class BookMvcController {
|
|||||||
bookService.deleteBook(id);
|
bookService.deleteBook(id);
|
||||||
return "redirect:/book";
|
return "redirect:/book";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}/genres")
|
||||||
|
public String getBookGenres(@PathVariable Long id, Model model){
|
||||||
|
model.addAttribute("book",
|
||||||
|
new BookDto(bookService.findBook(id)));
|
||||||
|
model.addAttribute("bookgenres",
|
||||||
|
bookService.bookGenres(id).stream()
|
||||||
|
.map(GenreDto::new)
|
||||||
|
.toList());
|
||||||
|
model.addAttribute("genres",
|
||||||
|
genreService.findAllGenres().stream()
|
||||||
|
.map(GenreDto::new)
|
||||||
|
.toList());
|
||||||
|
return "book-mtm";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{id}/genres")
|
||||||
|
public String addGenreToBook(@PathVariable Long id, @RequestParam(value = "genreid") Long genreid){
|
||||||
|
bookService.addGenreToBook(id, genreid);
|
||||||
|
return "redirect:/book/" + id.toString() + "/genres";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{id}/genres/{genreid}")
|
||||||
|
public String removeGenreFromBook(@PathVariable Long id, @PathVariable Long genreid){
|
||||||
|
bookService.removeGenreFromBook(id, genreid);
|
||||||
|
return "redirect:/book/" + id.toString() + "/genres";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,4 +14,7 @@ public class GenreDto {
|
|||||||
|
|
||||||
public Long getId(){return id;}
|
public Long getId(){return id;}
|
||||||
public String getName(){return name;}
|
public String getName(){return name;}
|
||||||
|
|
||||||
|
public void setId(Long id){this.id = id;}
|
||||||
|
public void setName(String name){this.name = name;}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ public class GenreMvcController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/delete/{id}")
|
@PostMapping("/delete/{id}")
|
||||||
public String deleteBook(@PathVariable Long id) {
|
public String deleteGenre(@PathVariable Long id) {
|
||||||
genreService.deleteGenre(id);
|
genreService.deleteGenre(id);
|
||||||
return "redirect:/genre";
|
return "redirect:/genre";
|
||||||
}
|
}
|
||||||
|
54
src/main/resources/templates/author-mtm.html
Normal file
54
src/main/resources/templates/author-mtm.html
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{default}">
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div layout:fragment="content">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Название</th>
|
||||||
|
<th scope="col">Дата релиза</th>
|
||||||
|
<th scope="col">Фото</th>
|
||||||
|
<th scope="col">Редактировать запись</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="ab, iterator: ${authorbooks}">
|
||||||
|
<td th:text="${ab.name}" style="width: 25%"/>
|
||||||
|
<td th:text="${ab.release}" style="width: 25%"/>
|
||||||
|
<td><img th:src="${ab.cover}" class="img-thumbnail mw-50 mh-50"/></td>
|
||||||
|
<td style="width: 10%">
|
||||||
|
<div class="btn-group" role="group" aria-label="Basic example">
|
||||||
|
<button type="button" class="btn btn-danger button-fixed button-sm"
|
||||||
|
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${ab.id}').click()|">
|
||||||
|
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<form th:action="@{/author/{id}/books/{bookid}(id=${author.id}, bookid=${ab.id})}" method="post">
|
||||||
|
<button th:id="'remove-' + ${ab.id}" type="submit" style="display: none">
|
||||||
|
Удалить
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<form th:action="@{/author/{id}/books(id=${author.id})}" enctype="bookid/form-data" method="post">
|
||||||
|
<div class="input-group mb-3">
|
||||||
|
<select class="form-select" th:name="bookid">
|
||||||
|
<option th:each="book, iterator: ${books}" th:value="${book.id}" th:text="${book.name}"></option>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-outline-secondary" type="submit">Добавить</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div>
|
||||||
|
<a class="btn btn-secondary" th:href="@{/author}">Закрыть</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,40 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{default}">
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div layout:fragment="content">
|
||||||
|
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
|
||||||
|
<form action="#" th:action="@{/author/{id}(id=${id})}" th:object="${authorDto}" method="post" enctype="multipart/form-data">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="firstname" class="form-label">Имя</label>
|
||||||
|
<input type="text" class="form-control" id="firstname" th:field="${authorDto.firstname}" required="true">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="lastname" class="form-label">Фамилия</label>
|
||||||
|
<input type="text" class="form-control" id="lastname" th:field="${authorDto.lastname}" required="true">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="photo" class="form-label">Фото</label>
|
||||||
|
<input type="file" class="form-control" id="photo" th:name="multipartFile" required="true">
|
||||||
|
<img th:src="${authorDto.photo}" class="img-thumbnail mw-50 mh-50"/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<button type="submit" class="btn btn-success button-fixed">
|
||||||
|
<span th:if="${id == null}">
|
||||||
|
<i class="fa-solid fa-plus"></i> Добавить
|
||||||
|
</span>
|
||||||
|
<span th:if="${id != null}">
|
||||||
|
<i class="fa fa-pencil" aria-hidden="true"></i> Сохранить
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<a class="btn btn-secondary button-fixed" th:href="@{/author}">
|
||||||
|
Назад
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,57 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{default}">
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div layout:fragment="content">
|
||||||
|
<div>
|
||||||
|
<a class="btn btn-success button-fixed"
|
||||||
|
th:href="@{/author/update/}">
|
||||||
|
<i class="fa-solid fa-plus"></i> Добавить
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Имя</th>
|
||||||
|
<th scope="col">Фамилия</th>
|
||||||
|
<th scope="col">Фото</th>
|
||||||
|
<th scope="col">Редактировать запись</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="author, iterator: ${authors}">
|
||||||
|
<td th:text="${author.firstname}" style="width: 25%"/>
|
||||||
|
<td th:text="${author.lastname}" style="width: 25%"/>
|
||||||
|
<td><img th:src="${author.photo}" class="img-thumbnail mw-50 mh-50"/></td>
|
||||||
|
<td style="width: 10%">
|
||||||
|
<div class="btn-group" role="group" aria-label="Basic example">
|
||||||
|
<a class="btn btn-warning button-fixed button-sm"
|
||||||
|
th:href="@{/author/update/{id}(id=${author.id})}">
|
||||||
|
<i class="fa fa-pencil" aria-hidden="true"></i> Изменить
|
||||||
|
</a>
|
||||||
|
<button type="button" class="btn btn-danger button-fixed button-sm"
|
||||||
|
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${author.id}').click()|">
|
||||||
|
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
|
||||||
|
</button>
|
||||||
|
<a class="btn btn-primary button-fixed button-sm"
|
||||||
|
th:href="@{/author/{id}/books(id=${author.id})}">
|
||||||
|
<i class="fa fa-pencil" aria-hidden="true"></i> Книга
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<form th:action="@{/author/delete/{id}(id=${author.id})}" method="post">
|
||||||
|
<button th:id="'remove-' + ${author.id}" type="submit" style="display: none">
|
||||||
|
Удалить
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
50
src/main/resources/templates/book-mtm.html
Normal file
50
src/main/resources/templates/book-mtm.html
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{default}">
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div layout:fragment="content">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Название</th>
|
||||||
|
<th scope="col">Редактировать запись</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="bg, iterator: ${bookgenres}">
|
||||||
|
<td th:text="${bg.name}" style="width: 25%"/>
|
||||||
|
<td style="width: 10%">
|
||||||
|
<div class="btn-group" role="group" aria-label="Basic example">
|
||||||
|
<button type="button" class="btn btn-danger button-fixed button-sm"
|
||||||
|
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${bg.id}').click()|">
|
||||||
|
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<form th:action="@{/book/{id}/genres/{genreid}(id=${book.id}, genreid=${bg.id})}" method="post">
|
||||||
|
<button th:id="'remove-' + ${bg.id}" type="submit" style="display: none">
|
||||||
|
Удалить
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<form th:action="@{/book/{id}/genres(id=${book.id})}" enctype="genreid/form-data" method="post">
|
||||||
|
<div class="input-group mb-3">
|
||||||
|
<select class="form-select" th:name="genreid">
|
||||||
|
<option th:each="genre, iterator: ${genres}" th:value="${genre.id}" th:text="${genre.name}"></option>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-outline-secondary" type="submit">Добавить</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div>
|
||||||
|
<a class="btn btn-secondary" th:href="@{/book}">Закрыть</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,40 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{default}">
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div layout:fragment="content">
|
||||||
|
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
|
||||||
|
<form action="#" th:action="@{/book/{id}(id=${id})}" th:object="${bookDto}" method="post" enctype="multipart/form-data">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="name" class="form-label">Название</label>
|
||||||
|
<input type="text" class="form-control" id="name" th:field="${bookDto.name}" required="true">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="release" class="form-label">Дата релиза</label>
|
||||||
|
<input type="date" class="form-control" id="release" th:field="${bookDto.release}" required="true">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="cover" class="form-label">Обложка</label>
|
||||||
|
<input type="file" class="form-control" id="cover" th:name="multipartFile" required="true">
|
||||||
|
<img th:src="${bookDto.cover}" class="img-thumbnail mw-50 mh-50"/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<button type="submit" class="btn btn-success button-fixed">
|
||||||
|
<span th:if="${id == null}">
|
||||||
|
<i class="fa-solid fa-plus"></i> Добавить
|
||||||
|
</span>
|
||||||
|
<span th:if="${id != null}">
|
||||||
|
<i class="fa fa-pencil" aria-hidden="true"></i> Сохранить
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<a class="btn btn-secondary button-fixed" th:href="@{/book}">
|
||||||
|
Назад
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,57 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{default}">
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div layout:fragment="content">
|
||||||
|
<div>
|
||||||
|
<a class="btn btn-success button-fixed"
|
||||||
|
th:href="@{/book/update/}">
|
||||||
|
<i class="fa-solid fa-plus"></i> Добавить
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Название</th>
|
||||||
|
<th scope="col">Дата релиза</th>
|
||||||
|
<th scope="col">Фото</th>
|
||||||
|
<th scope="col">Редактировать запись</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="book, iterator: ${books}">
|
||||||
|
<td th:text="${book.name}" style="width: 25%"/>
|
||||||
|
<td th:text="${book.release}" style="width: 25%"/>
|
||||||
|
<td><img th:src="${book.cover}" class="img-thumbnail mw-50 mh-50"/></td>
|
||||||
|
<td style="width: 10%">
|
||||||
|
<div class="btn-group" role="group" aria-label="Basic example">
|
||||||
|
<a class="btn btn-warning button-fixed button-sm"
|
||||||
|
th:href="@{/book/update/{id}(id=${book.id})}">
|
||||||
|
<i class="fa fa-pencil" aria-hidden="true"></i> Изменить
|
||||||
|
</a>
|
||||||
|
<button type="button" class="btn btn-danger button-fixed button-sm"
|
||||||
|
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${book.id}').click()|">
|
||||||
|
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
|
||||||
|
</button>
|
||||||
|
<a class="btn btn-primary button-fixed button-sm"
|
||||||
|
th:href="@{/book/{id}/genres(id=${book.id})}">
|
||||||
|
<i class="fa fa-pencil" aria-hidden="true"></i> Жанры
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<form th:action="@{/book/delete/{id}(id=${book.id})}" method="post">
|
||||||
|
<button th:id="'remove-' + ${book.id}" type="submit" style="display: none">
|
||||||
|
Удалить
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -16,21 +16,25 @@
|
|||||||
<nav class="navbar navbar-expand-lg bg-success" data-bs-theme="dark">
|
<nav class="navbar navbar-expand-lg bg-success" data-bs-theme="dark">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="navbar-brand" href="#">
|
<a class="navbar-brand" href="#">
|
||||||
<strong>{ OBS } Online Book Service</strong>
|
<strong class="text-white">{ OBS } Online Book Service</strong>
|
||||||
</a>
|
</a>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
|
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
|
||||||
<div class="navbar-nav">
|
<div class="navbar-nav" th:with="activeLink=${#request.requestURI}">
|
||||||
<a class="nav-link active" aria-current="page" href="/authors">Authors</a>
|
<a class="nav-link active text-white" aria-current="page" href="/author" th:classappend="${#strings.equals(activeLink, '/author')} ? 'active' : ''">Authors</a>
|
||||||
<a class="nav-link active" href="/books">Books</a>
|
<a class="nav-link active text-white" href="/book" th:classappend="${#strings.equals(activeLink, '/book')} ? 'active' : ''">Books</a>
|
||||||
<a class="nav-link active" href="/genres">Genres</a>
|
<a class="nav-link active text-white" href="/genre" th:classappend="${#strings.equals(activeLink, '/genre')} ? 'active' : ''">Genres</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
<div class="container-fluid" style="margin-top: 50pt;">
|
||||||
|
<div class="container container-padding" layout:fragment="content">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<footer class="container pt-4 my-md-5 pt-md-5 text-center border-top">
|
<footer class="container pt-4 my-md-5 pt-md-5 text-center border-top">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-md">
|
<div class="col-12 col-md">
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{default}">
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div layout:fragment="content">
|
||||||
|
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
|
||||||
|
<form action="#" th:action="@{/genre/{id}(id=${id})}" th:object="${genreDto}" method="post">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="name" class="form-label">Название</label>
|
||||||
|
<input type="text" class="form-control" id="name" th:field="${genreDto.name}" required="true">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<button type="submit" class="btn btn-success button-fixed">
|
||||||
|
<span th:if="${id == null}">
|
||||||
|
<i class="fa-solid fa-plus"></i> Добавить
|
||||||
|
</span>
|
||||||
|
<span th:if="${id != null}">
|
||||||
|
<i class="fa fa-pencil" aria-hidden="true"></i> Сохранить
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<a class="btn btn-secondary button-fixed" th:href="@{/genre}">
|
||||||
|
Назад
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,49 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{default}">
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div layout:fragment="content">
|
||||||
|
<div>
|
||||||
|
<a class="btn btn-success button-fixed"
|
||||||
|
th:href="@{/genre/update/}">
|
||||||
|
<i class="fa-solid fa-plus"></i> Добавить
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Название</th>
|
||||||
|
<th scope="col">Редактировать запись</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="genre, iterator: ${genres}">
|
||||||
|
<td th:text="${genre.name}" style="width: 60%"/>
|
||||||
|
<td style="width: 10%">
|
||||||
|
<div class="btn-group" role="group" aria-label="Basic example">
|
||||||
|
<a class="btn btn-warning button-fixed button-sm"
|
||||||
|
th:href="@{/genre/update/{id}(id=${genre.id})}">
|
||||||
|
<i class="fa fa-pencil" aria-hidden="true"></i> Изменить
|
||||||
|
</a>
|
||||||
|
<button type="button" class="btn btn-danger button-fixed button-sm"
|
||||||
|
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${genre.id}').click()|">
|
||||||
|
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<form th:action="@{/genre/delete/{id}(id=${genre.id})}" method="post">
|
||||||
|
<button th:id="'remove-' + ${genre.id}" type="submit" style="display: none">
|
||||||
|
Удалить
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user