На всякий случай. MVC почти доделан!!!

This commit is contained in:
Programmist73 2023-05-15 12:24:26 +04:00
parent 8803176103
commit d1b53d51b6
14 changed files with 104 additions and 61 deletions

View File

@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import premium_store.model.GameClient; import premium_store.model.GameClient;
import premium_store.model.UserRole; import premium_store.model.UserRole;
import java.util.ArrayList;
import java.util.List; import java.util.List;
//класс, который соединяет танки клиента в одну строчку (нам так захотелось) //класс, который соединяет танки клиента в одну строчку (нам так захотелось)
@ -24,13 +25,13 @@ public class ClientDTO {
this.password = gameClient.getPassword(); this.password = gameClient.getPassword();
this.email = gameClient.getEmail(); this.email = gameClient.getEmail();
this.balance = gameClient.getBalance(); this.balance = gameClient.getBalance();
if(gameClient.getTanks() != null){
if(gameClient.getTanks() != null && gameClient.getTanks().size() > 0){
this.tanks = gameClient.getTanks().stream() this.tanks = gameClient.getTanks().stream()
.map(TankDTO::new) .map(TankDTO::new)
.toList(); .toList();
} else {
this.tanks = null;
} }
this.role = gameClient.getRole(); this.role = gameClient.getRole();
} }
@ -80,7 +81,11 @@ public class ClientDTO {
} }
public Long getIdLastTanks(){ public Long getIdLastTanks(){
return tanks.get(tanks.size() - 1).getId(); if(tanks.size() > 0){
return tanks.get(tanks.size() - 1).getId();
} else {
return null;
}
} }
public void setTanks(List<TankDTO> tanks) { public void setTanks(List<TankDTO> tanks) {

View File

@ -17,7 +17,7 @@ import java.util.List;
import java.util.stream.IntStream; import java.util.stream.IntStream;
@Controller @Controller
@RequestMapping("/client") @RequestMapping("/clients")
public class GameClientMvcController { public class GameClientMvcController {
private final GameClientService gameClientService; private final GameClientService gameClientService;
private final TankService tankService; private final TankService tankService;
@ -34,7 +34,7 @@ public class GameClientMvcController {
return "client-edit"; return "client-edit";
} }
@GetMapping({"/getClients"}) @GetMapping
@Secured({UserRole.AsString.ADMIN}) @Secured({UserRole.AsString.ADMIN})
public String getClients(@RequestParam(defaultValue = "1") int page, public String getClients(@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "5") int size, @RequestParam(defaultValue = "5") int size,
@ -57,15 +57,13 @@ public class GameClientMvcController {
} }
@GetMapping(value = {"/edit", "/edit/{id}"}) @GetMapping(value = {"/edit", "/edit/{id}"})
public String editClient(@ModelAttribute @Valid ClientDTO userDto, public String editClient(@PathVariable(required = false) Long id, Model model) {
BindingResult bindingResult, if(id == null || id <= 0){
Model model) {
if(userDto.getId() <= 0){
model.addAttribute("supportClientDTO", new SupportClientDTO()); model.addAttribute("supportClientDTO", new SupportClientDTO());
} }
else { else {
model.addAttribute("clientId", userDto.getId()); model.addAttribute("clientId", id);
model.addAttribute("supportClientDTO", new SupportClientDTO(gameClientService.findClient(userDto.getId()))); model.addAttribute("supportClientDTO", new SupportClientDTO(gameClientService.findClient(id)));
} }
List<TankDTO> tanks = tankService.findAllTanks().stream() List<TankDTO> tanks = tankService.findAllTanks().stream()
@ -114,8 +112,9 @@ public class GameClientMvcController {
} }
@PostMapping(value = {"", "/{id}"}) @PostMapping(value = {"", "/{id}"})
@Secured({UserRole.AsString.ADMIN})
public String saveClient(@PathVariable(required = false) Long id, public String saveClient(@PathVariable(required = false) Long id,
@ModelAttribute @Valid ClientDTO clientDTO, @ModelAttribute @Valid SupportClientDTO clientDTO,
BindingResult bindingResult, BindingResult bindingResult,
Model model){ Model model){
if(bindingResult.hasErrors()){ if(bindingResult.hasErrors()){
@ -130,7 +129,7 @@ public class GameClientMvcController {
gameClientService.updateClient(clientDTO); gameClientService.updateClient(clientDTO);
} }
return "redirect:/client"; return "redirect:/clients";
} }
@PostMapping("/delete/{id}") @PostMapping("/delete/{id}")
@ -138,6 +137,6 @@ public class GameClientMvcController {
public String deleteClient(Principal principal, Model model, public String deleteClient(Principal principal, Model model,
@PathVariable Long id){ @PathVariable Long id){
gameClientService.deleteClient(id); gameClientService.deleteClient(id);
return "redirect:/tank"; return "redirect:/clients";
} }
} }

View File

@ -34,14 +34,14 @@ public class UserSignupMvcController {
} }
@PostMapping @PostMapping
public String signup(@ModelAttribute("clientDto") @Valid UserSignupDto userSignupDto, public String signup(@ModelAttribute("clientDTO") @Valid UserSignupDto userSignupDto,
BindingResult bindingResult, Model model) { BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) { if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors()); model.addAttribute("errors", bindingResult.getAllErrors());
return "signup"; return "signup";
} }
try { try {
final GameClient client = clientService.addClient(userSignupDto.getLogin(), userSignupDto.getEmail(), userSignupDto.getPassword(), Integer.parseInt(userSignupDto.getBalance()), userSignupDto.getPasswordConfirm()); final GameClient client = clientService.addClient(userSignupDto.getLogin(), userSignupDto.getEmail(), userSignupDto.getPassword(), Integer.parseInt(userSignupDto.getBalance()), userSignupDto.getPasswordConfirm(), UserRole.USER);
return "redirect:/login?created=" + client.getLogin(); return "redirect:/login?created=" + client.getLogin();
} catch (ValidationException e) { } catch (ValidationException e) {
model.addAttribute("errors", e.getMessage()); model.addAttribute("errors", e.getMessage());

View File

@ -30,7 +30,7 @@ public class GameClient {
@Column(name = "balance") @Column(name = "balance")
private Integer balance; private Integer balance;
@OneToMany(fetch = FetchType.EAGER) @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
private List<Tank> tanks = new ArrayList<>(); private List<Tank> tanks = new ArrayList<>();
private UserRole role; private UserRole role;
@ -89,7 +89,7 @@ public class GameClient {
return tanks; return tanks;
} }
public void setTanks(Tank tank){ public void setTank(Tank tank){
this.tanks.add(tank); this.tanks.add(tank);
} }

View File

@ -1,7 +1,5 @@
package premium_store.model; package premium_store.model;
import premium_store.controller.DTO.TankDTO;
import javax.persistence.*; import javax.persistence.*;
import java.util.Objects; import java.util.Objects;

View File

@ -113,33 +113,33 @@ public class GameClientService implements UserDetailsService {
} }
if(newTank != null){ if(newTank != null){
currentGameClient.setTanks(newTank); currentGameClient.setTank(newTank);
} }
return gameClientRepository.save(currentGameClient); return gameClientRepository.save(currentGameClient);
} }
@Transactional @Transactional
public GameClient updateClient(ClientDTO clientDTO) { public GameClient updateClient(SupportClientDTO clientDTO) {
if (clientDTO.getId() <= 0) { if (clientDTO.getId() <= 0) {
throw new IllegalArgumentException("Invalid id"); throw new IllegalArgumentException("Invalid id");
} }
final GameClient currentGameClient = findClient(clientDTO.getId()); final GameClient currentGameClient = findClient(clientDTO.getId());
final GameClient sameClient = findByLogin(clientDTO.getLogin()); //final GameClient sameClient = findByLogin(clientDTO.getLogin());
//проверка логина и пароля //проверка логина и пароля
if (sameClient != null && !Objects.equals(sameClient.getId(), currentGameClient.getId())) { /*if (sameClient != null && !Objects.equals(sameClient.getId(), currentGameClient.getId())) {
throw new ValidationException(String.format("User '%s' already exists", clientDTO.getLogin())); throw new ValidationException(String.format("User '%s' already exists", clientDTO.getLogin()));
} }*/
currentGameClient.setLogin(clientDTO.getLogin()); currentGameClient.setLogin(clientDTO.getLogin());
currentGameClient.setEmail(clientDTO.getEmail()); currentGameClient.setEmail(clientDTO.getEmail());
currentGameClient.setBalance(clientDTO.getBalance()); currentGameClient.setBalance(clientDTO.getBalance());
/*if(clientDTO.getTankId() != null){ if(clientDTO.getTankId() != null){
currentGameClient.setTanks(tankRepository.getById(clientDTO.getTankId())); currentGameClient.setTank(tankRepository.getById(clientDTO.getTankId()));
}*/ }
return gameClientRepository.save(currentGameClient); return gameClientRepository.save(currentGameClient);
} }

View File

@ -11,7 +11,7 @@
<div class="Group_create_level"> <div class="Group_create_level">
<h1>Генератор клиентов</h1> <h1>Генератор клиентов</h1>
</div> </div>
<form action="#" th:action="@{/client/{id}(id=${id})}" th:object="${supportClientDTO}" method="post"> <form action="#" th:action="@{/clients/{id}(id=${id})}" th:object="${supportClientDTO}" method="post">
<div class="myModalContent"> <div class="myModalContent">
<label for="name" class="form-label">Логин: </label> <label for="name" class="form-label">Логин: </label>
<input <input
@ -46,7 +46,7 @@
required="true" required="true"
/> />
<label for="name" class="form-label">Танк: </label> <label for="name" class="form-label">Танк: </label>
<select id="level" class="form-select" th:field="${supportClientDTO.tankId}" required="true"> <select id="tank" class="form-select" th:field="${supportClientDTO.tankId}" required="true">
<option th:each="value: ${tanks}" <option th:each="value: ${tanks}"
th:value="${value.id}" th:value="${value.id}"
th:text="${value.name}"> th:text="${value.name}">

View File

@ -14,7 +14,8 @@
<h1>Генератор клиентов</h1> <h1>Генератор клиентов</h1>
<h2> <h2>
<a class="add-level-button text-dark" type="button" <a class="add-level-button text-dark" type="button"
th:href="@{/client/edit/}"> th:href="@{/clients/edit/}"
>
Создать клиента Создать клиента
</a> </a>
</h2> </h2>
@ -24,39 +25,41 @@
Список существующих клиентов: Список существующих клиентов:
</h1> </h1>
</div> </div>
<div th:each="client, iterator: ${users}"> <div th:each="user, iterator: ${users}">
<div class="client-card"> <div class="client-card">
<p class="client-attribute" th:text="'Номер: ' + ${client.id}"/> <p class="client-attribute" th:text="'Номер: ' + ${user.id}"/>
<p class="client-attribute" th:text="'Никнейм: ' + ${client.nickName}"/> <p class="client-attribute" th:text="'Никнейм (логин): ' + ${user.login}"/>
<p class="client-attribute" th:text="'Баланс: ' + ${client.balance}"/> <p class="client-attribute" th:text="'Баланс: ' + ${user.balance}"/>
<div class='client-button-group'> <div class='client-button-group'>
<form th:action="@{/client/edit/{id}(id=${client.id})}" method="get"> <form th:action="@{/clients/edit/{id}(id=${user.id})}" method="get">
<button class="client-button" type="submit" <button class="client-button" type="submit"
th:id="'edit-' + ${client.id}" th:id="'edit-' + ${user.id}"
> >
Редактировать Редактировать
</button> </button>
</form> </form>
<form th:action="@{/client/delete/{id}(id=${client.id})}" method="post"> <form th:action="@{/clients/delete/{id}(id=${user.id})}" method="post">
<button th:id="'remove-' + ${client.id}" class="client-button" type="submit"> <button th:id="'remove-' + ${user.id}" class="client-button" type="submit"
>
Удалить Удалить
</button> </button>
</form> </form>
<form th:action="@{/client/tanksOfClient/{id}(id=${client.id})}" method="get"> <form th:action="@{/clients/tanksOfClient/{id}(id=${user.id})}" method="get">
<button th:id="'list-tank-' + ${client.id}" class="client-button" type="submit"> <button th:id="'list-tank-' + ${user.id}" class="client-button" type="submit"
>
Список танков Список танков
</button> </button>
</form> </form>
</div> </div>
</div> </div>
<div th:if="${totalPages > 0}" class="pagination"> </div>
<span style="float: left; padding: 5px 5px;">Страницы:</span> <div th:if="${totalPages > 0}" class="pagination">
<a th:each="page : ${pages}" <span style="float: left; padding: 5px 5px;">Страницы:</span>
th:href="@{/users(page=${page}, size=${users.size})}" <a th:each="page : ${pages}"
th:text="${page}" th:href="@{/clients(page=${page}, size=${users.size})}"
th:class="${page == users.number + 1} ? active"> th:text="${page}"
</a> th:class="${page == users.number + 1} ? active">
</div> </a>
</div> </div>
</div> </div>
</body> </body>

View File

@ -7,7 +7,6 @@
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<title>Премиум магазин</title> <title>Премиум магазин</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="icon" href="/favicon.svg">
<script type="text/javascript" src="/webjars/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script> <script type="text/javascript" src="/webjars/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="/webjars/bootstrap/5.1.3/css/bootstrap.min.css"/> <link rel="stylesheet" href="/webjars/bootstrap/5.1.3/css/bootstrap.min.css"/>
<link rel="stylesheet" href="/webjars/font-awesome/6.1.0/css/all.min.css"/> <link rel="stylesheet" href="/webjars/font-awesome/6.1.0/css/all.min.css"/>
@ -26,7 +25,7 @@
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
<div class="collapse navbar-collapse justify-content-around" id="navbarNav"> <div class="collapse navbar-collapse justify-content-around" id="navbarNav">
<ul class="Main_head navbar-nav align-items-center" th:with="activeLink=${#request.requestURI}" sec:authorize="isAuthenticated()">> <ul class="Main_head navbar-nav align-items-center" th:with="activeLink=${#request.requestURI}" sec:authorize="isAuthenticated()">
<a class="nav-link btn border border-3 border-dark fs-4 lh-15 Button_Main_Group text-dark" href="/level" <a class="nav-link btn border border-3 border-dark fs-4 lh-15 Button_Main_Group text-dark" href="/level"
th:classappend="${#strings.equals(activeLink, '/level')} ? 'active' : ''">Обзор уровней th:classappend="${#strings.equals(activeLink, '/level')} ? 'active' : ''">Обзор уровней
</a> </a>
@ -36,8 +35,8 @@
<a class="nav-link btn border border-3 border-dark fs-4 lh-15 Button_Main_Group text-dark" href="/nation" <a class="nav-link btn border border-3 border-dark fs-4 lh-15 Button_Main_Group text-dark" href="/nation"
th:classappend="${#strings.equals(activeLink, '/nation')} ? 'active' : ''">Обзор наций th:classappend="${#strings.equals(activeLink, '/nation')} ? 'active' : ''">Обзор наций
</a> </a>
<a class="nav-link btn border border-3 border-dark fs-4 lh-15 Button_Main_Group text-dark" href="/client" <a class="nav-link btn border border-3 border-dark fs-4 lh-15 Button_Main_Group text-dark" href="/clients"
th:classappend="${#strings.equals(activeLink, '/clients')} ? 'active' : ''">Обзор клиентов th:classappend="${#strings.equals(activeLink, '/clients')} ? 'active' : ''" sec:authorize="hasRole('ROLE_ADMIN')">Обзор клиентов
</a> </a>
<a class="nav-link btn border border-3 border-dark fs-4 lh-15 Button_Main_Group text-dark" href="/logout"> <a class="nav-link btn border border-3 border-dark fs-4 lh-15 Button_Main_Group text-dark" href="/logout">
Выход(<span th:text="${#authentication.name}"></span>) Выход(<span th:text="${#authentication.name}"></span>)

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
<link rel="stylesheet" href="/css/style.css"/>
</head>
<body>
<div class="container" layout:fragment="content">
<div>
<h1 class="Main-label">Авторизация прошла успешно!</h1>
</div>
<a href="123">ERROR</a>
</div>
</body>
</html>

View File

@ -14,10 +14,17 @@
<h1>Генератор уровней</h1> <h1>Генератор уровней</h1>
<h2> <h2>
<a class="add-level-button text-dark" type="button" <a class="add-level-button text-dark" type="button"
th:href="@{/level/edit/}"> th:href="@{/level/edit/}"
sec:authorize="hasRole('ROLE_ADMIN')"
>
Создать уровень Создать уровень
</a> </a>
</h2> </h2>
<h2
sec:authorize="hasRole('ROLE_USER')"
>
Режим просмотра
</h2>
</div> </div>
<div> <div>
<h1 style="text-align: center; font-family: courier, monospace; background: #FF652F; border-radius: 10px"> <h1 style="text-align: center; font-family: courier, monospace; background: #FF652F; border-radius: 10px">
@ -28,7 +35,7 @@
<div class="level-card"> <div class="level-card">
<p class="level-attribute" th:text="'Номер: ' + ${level.id}"/> <p class="level-attribute" th:text="'Номер: ' + ${level.id}"/>
<p class="level-attribute" th:text="'Уровень: ' + ${level.level}"/> <p class="level-attribute" th:text="'Уровень: ' + ${level.level}"/>
<div class='level-button-group'> <div class='level-button-group' sec:authorize="hasRole('ROLE_ADMIN')">
<form th:action="@{/level/edit/{id}(id=${level.id})}" method="get"> <form th:action="@{/level/edit/{id}(id=${level.id})}" method="get">
<button class="level-button" type="submit" <button class="level-button" type="submit"
th:id="'edit-' + ${level.id}" th:id="'edit-' + ${level.id}"

View File

@ -14,10 +14,17 @@
<h1>Генератор наций</h1> <h1>Генератор наций</h1>
<h2> <h2>
<a class="add-level-button text-dark" type="button" <a class="add-level-button text-dark" type="button"
th:href="@{/nation/edit/}"> th:href="@{/nation/edit/}"
sec:authorize="hasRole('ROLE_ADMIN')"
>
Создать нацию Создать нацию
</a> </a>
</h2> </h2>
<h2
sec:authorize="hasRole('ROLE_USER')"
>
Режим просмотра
</h2>
</div> </div>
<div> <div>
<h1 style="text-align: center; font-family: courier, monospace; background: #FF652F; border-radius: 10px"> <h1 style="text-align: center; font-family: courier, monospace; background: #FF652F; border-radius: 10px">
@ -32,12 +39,14 @@
<form th:action="@{/nation/edit/{id}(id=${nation.id})}" method="get"> <form th:action="@{/nation/edit/{id}(id=${nation.id})}" method="get">
<button class="nation-button" type="submit" <button class="nation-button" type="submit"
th:id="'edit-' + ${nation.id}" th:id="'edit-' + ${nation.id}"
sec:authorize="hasRole('ROLE_ADMIN')"
> >
Редактировать Редактировать
</button> </button>
</form> </form>
<form th:action="@{/nation/delete/{id}(id=${nation.id})}" method="post"> <form th:action="@{/nation/delete/{id}(id=${nation.id})}" method="post">
<button th:id="'remove-' + ${nation.id}" class="nation-button" type="submit"> <button th:id="'remove-' + ${nation.id}" class="nation-button" type="submit"
sec:authorize="hasRole('ROLE_ADMIN')">
Удалить Удалить
</button> </button>
</form> </form>

View File

@ -14,10 +14,17 @@
<h1>Генератор танков</h1> <h1>Генератор танков</h1>
<h2> <h2>
<a class="add-tank-button text-dark" type="button" <a class="add-tank-button text-dark" type="button"
th:href="@{/tank/edit/}"> th:href="@{/tank/edit/}"
sec:authorize="hasRole('ROLE_ADMIN')"
>
Создать танк Создать танк
</a> </a>
</h2> </h2>
<h2
sec:authorize="hasRole('ROLE_USER')"
>
Режим просмотра
</h2>
<form id="filterForm" th:action="@{/tank/filteredList}" th:object="${sortDTO}" method="get"> <form id="filterForm" th:action="@{/tank/filteredList}" th:object="${sortDTO}" method="get">
<button class="tank-button" type="submit" <button class="tank-button" type="submit"
th:id="filterStart" th:id="filterStart"
@ -56,7 +63,7 @@
<p class="tank-attribute" th:text="'Нация: ' + ${tank.nation.getNation()}"/> <p class="tank-attribute" th:text="'Нация: ' + ${tank.nation.getNation()}"/>
<p class="tank-attribute" th:text="'Уровень: ' + ${tank.level.getLevel()}"/> <p class="tank-attribute" th:text="'Уровень: ' + ${tank.level.getLevel()}"/>
<p class="tank-attribute" th:text="'Стоимость: ' + ${tank.cost}"/> <p class="tank-attribute" th:text="'Стоимость: ' + ${tank.cost}"/>
<div class='tank-button-group'> <div class='tank-button-group' sec:authorize="hasRole('ROLE_ADMIN')">
<form th:action="@{/tank/edit/{id}(id=${tank.id})}" method="get"> <form th:action="@{/tank/edit/{id}(id=${tank.id})}" method="get">
<button class="tank-button" type="submit" <button class="tank-button" type="submit"
th:id="'edit-' + ${tank.id}" th:id="'edit-' + ${tank.id}"

View File

@ -8,7 +8,7 @@
</head> </head>
<body> <body>
<div layout:fragment="content"> <div layout:fragment="content">
<form action="#" th:action="@{/client/{id}(id=${id})}" th:object="${clientDTO}" method="get"> <form action="#" th:action="@{/clients/{id}(id=${id})}" th:object="${clientDTO}" method="get">
<div th:each="tank, iterator: ${clientDTO.tanks}"> <div th:each="tank, iterator: ${clientDTO.tanks}">
<div class="tank-card"> <div class="tank-card">
<p class="tank-attribute" th:text="'Номер: ' + ${tank.id}"/> <p class="tank-attribute" th:text="'Номер: ' + ${tank.id}"/>