работает регистрация, разграничение прав доступа, отображаются, удаляются, редактируются пользоатели)) (всё для админа)
This commit is contained in:
parent
b04eacffd1
commit
8ce978e9cb
@ -29,8 +29,37 @@ public class BackendApplication implements CommandLineRunner {
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
final var admin = new UserEntity(null, "elena", "1234");
|
||||
final var vasya = new UserEntity(null, "vasya", "1234");
|
||||
|
||||
final var u1 = new UserEntity(null, "1", "1234");
|
||||
final var u2 = new UserEntity(null, "2", "1234");
|
||||
final var u3 = new UserEntity(null, "3", "1234");
|
||||
final var u4 = new UserEntity(null, "4", "1234");
|
||||
final var u5 = new UserEntity(null, "5", "1234");
|
||||
final var u6 = new UserEntity(null, "6", "1234");
|
||||
final var u7 = new UserEntity(null, "7", "1234");
|
||||
|
||||
admin.setRole(UserRole.ADMIN);
|
||||
vasya.setRole(UserRole.USER);
|
||||
|
||||
u1.setRole(UserRole.USER);
|
||||
u2.setRole(UserRole.USER);
|
||||
u3.setRole(UserRole.USER);
|
||||
u4.setRole(UserRole.USER);
|
||||
u5.setRole(UserRole.USER);
|
||||
u6.setRole(UserRole.USER);
|
||||
u7.setRole(UserRole.USER);
|
||||
|
||||
userService.create(admin);
|
||||
userService.create(vasya);
|
||||
userService.create(u1);
|
||||
userService.create(u2);
|
||||
userService.create(u3);
|
||||
userService.create(u4);
|
||||
userService.create(u5);
|
||||
userService.create(u6);
|
||||
userService.create(u7);
|
||||
|
||||
_logger.info("Admin user added");
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ public class CategorieService {
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public CategorieEntity get(Integer id) {
|
||||
return repository.findById(id).orElseThrow(() -> new NotFoundException(id));
|
||||
return repository.findById(id).orElseThrow(() -> new NotFoundException(CategorieEntity.class, id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.example.backend.core.errors;
|
||||
|
||||
public class NotFoundException extends RuntimeException {
|
||||
public NotFoundException(Integer id) {
|
||||
super(String.format("Сущность с айдишником <[%s]> не найден, либо его не существует", id));
|
||||
public <T> NotFoundException(Class<T> clazz, Integer id) {
|
||||
super(String.format("%s with id [%s] is not found or not exists", clazz.getSimpleName(), id));
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public class FavoriteService {
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public FavoriteEntity get(Integer id) {
|
||||
return repository.findById(id).orElseThrow(() -> new NotFoundException(id));
|
||||
return repository.findById(id).orElseThrow(() -> new NotFoundException(FavoriteEntity.class, id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
@ -37,7 +37,7 @@ public class MovieService {
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public MovieEntity get(Integer id) {
|
||||
return repository.findById(id).orElseThrow(() -> new NotFoundException(id));
|
||||
return repository.findById(id).orElseThrow(() -> new NotFoundException(MovieEntity.class, id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
@ -1,28 +1,33 @@
|
||||
package com.example.backend.users.api;
|
||||
|
||||
import java.util.Map;
|
||||
import org.modelmapper.ModelMapper;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
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.RestController;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import com.example.backend.core.api.PageAttributesMapper;
|
||||
import com.example.backend.core.configurations.Constants;
|
||||
import com.example.backend.users.model.UserEntity;
|
||||
import com.example.backend.users.service.UserService;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
@Controller
|
||||
// @RequestMapping(Constants.API_URL + "/user")
|
||||
@RequestMapping(UserController.URL)
|
||||
public class UserController {
|
||||
|
||||
private static final String CATEGORIES_VIEW = "categories";
|
||||
private static final String LOGIN_VIEW = "login";
|
||||
public static final String URL = Constants.ADMIN_PREFIX + "/user";
|
||||
private static final String USER_VIEW = "user";
|
||||
private static final String USER_EDIT_VIEW = "user-edit";
|
||||
private static final String PAGE_ATTRIBUTE = "page";
|
||||
private static final String USER_ATTRIBUTE = "user";
|
||||
|
||||
private final UserService userService;
|
||||
@ -41,21 +46,81 @@ public class UserController {
|
||||
return modelMapper.map(entity, UserDTO.class);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public String getAll(
|
||||
@RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page,
|
||||
Model model) {
|
||||
final Map<String, Object> attributes = PageAttributesMapper.toAttributes(
|
||||
userService.getAll(page, Constants.DEFUALT_PAGE_SIZE), this::toDto);
|
||||
model.addAllAttributes(attributes);
|
||||
model.addAttribute(PAGE_ATTRIBUTE, page);
|
||||
return USER_VIEW;
|
||||
}
|
||||
|
||||
@GetMapping("/edit/")
|
||||
public String create(Model model) {
|
||||
model.addAttribute(CATEGORIES_VIEW, new UserDTO());
|
||||
return LOGIN_VIEW;
|
||||
public String create(@RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page,
|
||||
Model model) {
|
||||
model.addAttribute(USER_ATTRIBUTE, new UserDTO());
|
||||
model.addAttribute(PAGE_ATTRIBUTE, page);
|
||||
return USER_EDIT_VIEW;
|
||||
}
|
||||
|
||||
@PostMapping("/edit/")
|
||||
public String create(
|
||||
@ModelAttribute(name = USER_ATTRIBUTE) @Valid UserDTO userDTO,
|
||||
@RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page,
|
||||
@ModelAttribute(name = USER_ATTRIBUTE) @Valid UserDTO user,
|
||||
BindingResult bindingResult,
|
||||
Model model) {
|
||||
Model model,
|
||||
RedirectAttributes redirectAttributes) {
|
||||
if (bindingResult.hasErrors()) {
|
||||
return LOGIN_VIEW + "/login";
|
||||
model.addAttribute(PAGE_ATTRIBUTE, page);
|
||||
return USER_EDIT_VIEW;
|
||||
}
|
||||
userService.create(toEntity(userDTO));
|
||||
return Constants.REDIRECT_VIEW + "/user";
|
||||
redirectAttributes.addAttribute(PAGE_ATTRIBUTE, page);
|
||||
userService.create(toEntity(user));
|
||||
return Constants.REDIRECT_VIEW + URL;
|
||||
}
|
||||
|
||||
@GetMapping("/edit/{id}")
|
||||
public String update(
|
||||
@PathVariable(name = "id") Integer id,
|
||||
@RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page,
|
||||
Model model) {
|
||||
if (id <= 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
model.addAttribute(USER_ATTRIBUTE, toDto(userService.get(id)));
|
||||
model.addAttribute(PAGE_ATTRIBUTE, page);
|
||||
return USER_EDIT_VIEW;
|
||||
}
|
||||
|
||||
@PostMapping("/edit/{id}")
|
||||
public String update(
|
||||
@PathVariable(name = "id") Integer id,
|
||||
@RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page,
|
||||
@ModelAttribute(name = USER_ATTRIBUTE) @Valid UserDTO user,
|
||||
BindingResult bindingResult,
|
||||
Model model,
|
||||
RedirectAttributes redirectAttributes) {
|
||||
if (bindingResult.hasErrors()) {
|
||||
model.addAttribute(PAGE_ATTRIBUTE, page);
|
||||
return USER_EDIT_VIEW;
|
||||
}
|
||||
if (id <= 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
redirectAttributes.addAttribute(PAGE_ATTRIBUTE, page);
|
||||
userService.update(id, toEntity(user));
|
||||
return Constants.REDIRECT_VIEW + URL;
|
||||
}
|
||||
|
||||
@PostMapping("/delete/{id}")
|
||||
public String delete(
|
||||
@PathVariable(name = "id") Integer id,
|
||||
@RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page,
|
||||
RedirectAttributes redirectAttributes) {
|
||||
redirectAttributes.addAttribute(PAGE_ATTRIBUTE, page);
|
||||
userService.delete(id);
|
||||
return Constants.REDIRECT_VIEW + URL;
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,15 @@ package com.example.backend.users.service;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@ -43,9 +47,14 @@ public class UserService implements UserDetailsService {
|
||||
return StreamSupport.stream(repository.findAll().spliterator(), false).toList();
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Page<UserEntity> getAll(int page, int size) {
|
||||
return repository.findAll(PageRequest.of(page, size, Sort.by("id")));
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public UserEntity get(Integer id) {
|
||||
return repository.findById(id).orElseThrow(() -> new NotFoundException(id));
|
||||
return repository.findById(id).orElseThrow(() -> new NotFoundException(UserEntity.class, id));
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
|
@ -28,7 +28,7 @@ public class ViewedService {
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public ViewedEntity get(Integer id) {
|
||||
return repository.findById(id).orElseThrow(() -> new NotFoundException(id));
|
||||
return repository.findById(id).orElseThrow(() -> new NotFoundException(ViewedEntity.class, id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@ -50,10 +50,4 @@ public class ViewedService {
|
||||
repository.delete(exisEntity);
|
||||
return exisEntity;
|
||||
}
|
||||
|
||||
// @Transactional
|
||||
// public Integer countViewed(Integer movieId) {
|
||||
// return repository.getCountViews(movieId);
|
||||
// }
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{index}">
|
||||
|
||||
<head>
|
||||
<title>Вход</title>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- <!DOCTYPE html>
|
||||
<html lang="ru" data-bs-theme="dark" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity6">
|
||||
@ -32,8 +32,8 @@
|
||||
<div class="collapse navbar-collapse" id="main-navbar">
|
||||
<ul class="navbar-nav me-auto link" th:with="activeLink=${#objects.nullSafe(servletPath, '')}">
|
||||
<th:block sec:authorize="hasRole('ADMIN')">
|
||||
<a class="nav-link" href="/admin/users"
|
||||
th:classappend="${activeLink.startsWith('/admin/users')? 'active' : '' }">Пользователи</a>
|
||||
<a class="nav-link" href="/admin/user"
|
||||
th:classappend="${activeLink.startsWith('/admin/user')? 'active' : '' }">Пользователи</a>
|
||||
<a class="nav-link" href="/admin/categories"
|
||||
th:classappend="${activeLink.startsWith('/admin/categories')? 'active' : '' }">Категории</a>
|
||||
<a class="nav-link" href="/admin/movies"
|
||||
@ -73,4 +73,4 @@
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html> -->
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{index}">
|
||||
|
||||
<head>
|
||||
<title>Ошибка</title>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{index}">
|
||||
|
||||
|
||||
<head>
|
||||
|
76
backend/src/main/resources/templates/index.html
Normal file
76
backend/src/main/resources/templates/index.html
Normal file
@ -0,0 +1,76 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" data-bs-theme="dark" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity6">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image" src="/images/logo_livecinema.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">LiveCinema</title>
|
||||
<script type="text/javascript" src="/webjars/bootstrap/5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<link rel="stylesheet" href="/webjars/bootstrap/5.3.3/dist/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="/webjars/bootstrap-icons/1.11.3/font/bootstrap-icons.min.css" />
|
||||
<link rel="stylesheet" href="/css/style.css" />
|
||||
<meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate">
|
||||
<meta http-equiv="Pragma" content="no-cache">
|
||||
<meta http-equiv="Expires" content="0">
|
||||
</head>
|
||||
|
||||
<body class="d-flex flex-column flex-fill h-100">
|
||||
<nav expand="md" data-bs-theme="dark" class="navbar my-navbar navbar-expand-md">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/">
|
||||
<img src="/images/logo_livecinema.png" class="logo" style="height: 2vh;" />
|
||||
LiveCinema
|
||||
</a>
|
||||
<th:block sec:authorize="isAuthenticated()" th:with="userName=${#authentication.name}">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#main-navbar"
|
||||
aria-controls="main-navbar" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="main-navbar">
|
||||
<ul class="navbar-nav me-auto link" th:with="activeLink=${#objects.nullSafe(servletPath, '')}">
|
||||
<th:block sec:authorize="hasRole('ADMIN')">
|
||||
<a class="nav-link" href="/admin/user"
|
||||
th:classappend="${activeLink.startsWith('/admin/user')? 'active' : '' }">Пользователи</a>
|
||||
<a class="nav-link" href="/admin/categories"
|
||||
th:classappend="${activeLink.startsWith('/admin/categories')? 'active' : '' }">Категории</a>
|
||||
<a class="nav-link" href="/admin/movies"
|
||||
th:classappend="${activeLink.startsWith('/admin/movies') ? 'active' : '' }">Фильмы</a>
|
||||
<a class="nav-link" href="/admin/favorites"
|
||||
th:classappend="${activeLink.startsWith('/admin/favorites') ? 'active' : '' }">Избранные</a>
|
||||
<a class="nav-link" href="/admin/viewed"
|
||||
th:classappend="${activeLink.startsWith('/admin/viewed') ? 'active' : '' }">Просмотренные</a>
|
||||
<a class="nav-link" href="/h2-console/" target="_blank">Консоль H2</a>
|
||||
</th:block>
|
||||
<th:block sec:authorize="hasRole('USER')">
|
||||
<a class="nav-link" href="/categories"
|
||||
th:classappend="${activeLink.startsWith('/categories') ? 'active' : '' }">Категории</a>
|
||||
<a class="nav-link" href="/movies"
|
||||
th:classappend="${activeLink.startsWith('/movies') ? 'active' : '' }">Фильмы</a>
|
||||
<a class="nav-link" href="/favorites"
|
||||
th:classappend="${activeLink.startsWith('/favorites') ? 'active' : '' }">Избранные</a>
|
||||
<a class="nav-link" href="/viewed"
|
||||
th:classappend="${activeLink.startsWith('/viewed') ? 'active' : '' }">Просмотренные</a>
|
||||
</th:block>
|
||||
</ul>
|
||||
<ul class="navbar-nav" th:if="${not #strings.isEmpty(userName)}">
|
||||
<form th:action="@{/logout}" method="post">
|
||||
<button type="submit" class="navbar-brand nav-link" onclick="return confirm('Вы уверены?')">
|
||||
Выход ([[${userName}]])
|
||||
</button>
|
||||
</form>
|
||||
</ul>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
</nav>
|
||||
<main layout:fragment="content" class="d-flex flex-column flex-fill">
|
||||
</main>
|
||||
<footer class="my-footer mt-auto d-flex flex-shrink-0 justify-content-center">
|
||||
Бакальская Е.Д. (@)LiveCinema [[${#dates.year(#dates.createNow())}]]. Все права защищены
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{index}">
|
||||
|
||||
<head>
|
||||
<title>Вход</title>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{index}">
|
||||
|
||||
<head>
|
||||
<title>Вход</title>
|
||||
|
51
backend/src/main/resources/templates/pagination.html
Normal file
51
backend/src/main/resources/templates/pagination.html
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<body>
|
||||
|
||||
<th:block th:fragment="pagination (url, totalPages, currentPage)">
|
||||
<nav th:if="${totalPages > 1}" th:with="
|
||||
maxPage=2,
|
||||
currentPage=${currentPage + 1}">
|
||||
<ul class="pagination justify-content-center"
|
||||
th:with="
|
||||
seqFrom=${currentPage - maxPage < 1 ? 1 : currentPage - maxPage},
|
||||
seqTo=${currentPage + maxPage > totalPages ? totalPages : currentPage + maxPage}">
|
||||
<th:block th:if="${currentPage > maxPage + 1}">
|
||||
<li class="page-item">
|
||||
<a class="page-link" aria-label="Previous" th:href="@{/{url}?page=0(url=${url})}">
|
||||
<span aria-hidden="true">«</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item disabled">
|
||||
<span class="page-link" aria-label="Previous">
|
||||
<span aria-hidden="true">…</span>
|
||||
</span>
|
||||
</li>
|
||||
</th:block>
|
||||
<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}(url=${url},page=${page - 1})}">
|
||||
<span th:text="${page}" />
|
||||
</a>
|
||||
</li>
|
||||
<th:block th:if="${currentPage < totalPages - maxPage}">
|
||||
<li class="page-item disabled">
|
||||
<span class="page-link" aria-label="Previous">
|
||||
<span aria-hidden="true">…</span>
|
||||
</span>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" aria-label="Next"
|
||||
th:href="@{/{url}?page={page}(url=${url},page=${totalPages - 1})}">
|
||||
<span aria-hidden="true">»</span>
|
||||
</a>
|
||||
</li>
|
||||
</th:block>
|
||||
</ul>
|
||||
</nav>
|
||||
</th:block>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{index}">
|
||||
|
||||
<head>
|
||||
<title>Регистрация</title>
|
||||
|
36
backend/src/main/resources/templates/user-edit.html
Normal file
36
backend/src/main/resources/templates/user-edit.html
Normal file
@ -0,0 +1,36 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{index}">
|
||||
|
||||
<head>
|
||||
<title>Редакторовать пользователя</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main layout:fragment="content">
|
||||
<form action="#" th:action="@{/admin/user/edit/{id}(id=${user.id},page=${page})}" th:object="${user}"
|
||||
method="post">
|
||||
<div class="mb-3">
|
||||
<label for="id" class="form-label">ID</label>
|
||||
<input type="text" th:value="*{id}" id="id" class="form-control" readonly disabled>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="login" class="form-label">Имя пользователя</label>
|
||||
<input type="text" th:field="*{login}" id="login" class="form-control">
|
||||
<div th:if="${#fields.hasErrors('login')}" th:errors="*{login}" class="invalid-feedback"></div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Имя пользователя</label>
|
||||
<input type="text" th:field="*{password}" id="password" class="form-control">
|
||||
<div th:if="${#fields.hasErrors('password')}" th:errors="*{password}" class="invalid-feedback"></div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 d-flex flex-row">
|
||||
<button class="btn btn-primary me-2 button-fixed-width" type="submit">Сохранить</button>
|
||||
<a class="btn btn-secondary button-fixed-width" th:href="@{/admin/user(page=${page})}">Отмена</a>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
56
backend/src/main/resources/templates/user.html
Normal file
56
backend/src/main/resources/templates/user.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{index}">
|
||||
|
||||
<head>
|
||||
<title>Пользователи</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main layout:fragment="content">
|
||||
<th:block th:switch="${items.size()}">
|
||||
<h2 th:case="0">Данные отсутствуют</h2>
|
||||
<th:block th:case="*">
|
||||
<h2>Пользователи</h2>
|
||||
<div>
|
||||
<a th:href="@{/admin/user/edit/(page=${page})}" class="btn btn-primary">Добавить пользователя</a>
|
||||
</div>
|
||||
<table class="table">
|
||||
<caption></caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="w-10">ID</th>
|
||||
<th scope="col" class="w-auto">Имя пользователя</th>
|
||||
<th scope="col" class="w-10"></th>
|
||||
<th scope="col" class="w-10"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="user : ${items}">
|
||||
<th scope="row" th:text="${user.id}"></th>
|
||||
<td th:text="${user.login}"></td>
|
||||
<td>
|
||||
<form th:action="@{/admin/user/edit/{id}(id=${user.id})}" method="get">
|
||||
<input type="hidden" th:name="page" th:value="${page}">
|
||||
<button type="submit" class="btn btn-link button-link">Редактировать</button>
|
||||
</form>
|
||||
</td>
|
||||
<td>
|
||||
<form th:action="@{/admin/user/delete/{id}(id=${user.id})}" method="post">
|
||||
<input type="hidden" th:name="page" th:value="${page}">
|
||||
<button type="submit" class="btn btn-link button-link"
|
||||
onclick="return confirm('Вы уверены?')">Удалить</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</th:block>
|
||||
<th:block th:replace="~{ pagination :: pagination (
|
||||
url=${'admin/user'},
|
||||
totalPages=${totalPages},
|
||||
currentPage=${currentPage}) }" />
|
||||
</th:block>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
BIN
data.mv.db
BIN
data.mv.db
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user