Первое глобальное промежуточное сохранение.

This commit is contained in:
Programmist73 2023-04-24 01:03:24 +04:00
parent 9560588d41
commit 843ec51b8c
20 changed files with 613 additions and 59 deletions

View File

@ -0,0 +1,15 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myValues">
<value>
<list size="1">
<item index="0" class="java.lang.String" itemvalue="th:text" />
</list>
</value>
</option>
<option name="myCustomValuesEnabled" value="true" />
</inspection_tool>
</profile>
</component>

View File

@ -1,5 +1,5 @@
plugins {
id 'org.springframework.boot' version '2.6.3'
id 'org.springframework.boot' version '2.6.5'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'java'
}

View File

@ -1,16 +1,19 @@
package premium_store.controller.DTO;
import com.fasterxml.jackson.annotation.JsonProperty;
import premium_store.model.GameClient;
import java.util.List;
//класс, который соединяет танки клиента в одну строчку (нам так захотелось)
public class ClientDTO {
private final long id;
private final String nickName;
private final String email;
private final Integer balance;
private final List<TankDTO> tanks;
private long id;
private String nickName;
private String email;
private Integer balance;
private List<TankDTO> tanks;
public ClientDTO(){ }
public ClientDTO(GameClient gameClient){
this.id = gameClient.getId();
@ -22,23 +25,44 @@ public class ClientDTO {
.toList();
}
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public long getId(){
return id;
}
public void setId(long id) {
this.id = id;
}
public String getNickName(){
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getEmail(){
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getBalance(){
return balance;
}
public void setBalance(Integer balance) {
this.balance = balance;
}
public List<TankDTO> getTanks(){
return tanks;
}
public void setTanks(List<TankDTO> tanks) {
this.tanks = tanks;
}
}

View File

@ -1,13 +1,16 @@
package premium_store.controller.DTO;
import com.fasterxml.jackson.annotation.JsonProperty;
import premium_store.model.Nation;
import java.util.List;
public class FullNationDTO {
public final Long id;
public final String nation;
public final List<TankDTO> tanks;
public Long id;
public String nation;
public List<TankDTO> tanks;
public FullNationDTO(){ }
public FullNationDTO(Nation nation){
this.id = nation.getId();
@ -17,15 +20,28 @@ public class FullNationDTO {
.toList();
}
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNation() {
return nation;
}
public void setNation(String nation) {
this.nation = nation;
}
public List<TankDTO> getTanksOfThisNation() {
return tanks;
}
public void setTanks(List<TankDTO> tanks) {
this.tanks = tanks;
}
}

View File

@ -1,21 +1,33 @@
package premium_store.controller.DTO;
import com.fasterxml.jackson.annotation.JsonProperty;
import premium_store.model.TankLevel;
public class LevelDTO {
private final Long id;
private final int level;
private Long id;
private int level;
public LevelDTO(){}
public LevelDTO(TankLevel level){
this.id = level.getId();
this.level = level.getLevel();
}
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public Long getId(){
return id;
}
public void setId(Long id){
this.id = id;
}
public int getLevel(){
return level;
}
public void setLevel(int level) {
this.level = level;
}
}

View File

@ -1,21 +1,33 @@
package premium_store.controller.DTO;
import com.fasterxml.jackson.annotation.JsonProperty;
import premium_store.model.Nation;
public class SimpleNationDTO {
private final Long id;
private final String nation;
private Long id;
private String nation;
public SimpleNationDTO(){}
public SimpleNationDTO(Nation nation){
this.id = nation.getId();
this.nation = nation.getNation();
}
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public Long getId(){
return id;
}
public void setId(Long id){
this.id = id;
}
public String getNation(){
return nation;
}
public void setNation(String nation){
this.nation = nation;
}
}

View File

@ -1,13 +1,16 @@
package premium_store.controller.DTO;
import com.fasterxml.jackson.annotation.JsonProperty;
import premium_store.model.Tank;
public class TankDTO {
private final long id;
private final String name;
private final SimpleNationDTO nation;
private final LevelDTO level;
private final int cost;
private long id;
private String name;
private SimpleNationDTO nation;
private LevelDTO level;
private int cost;
public TankDTO(){}
public TankDTO(Tank tank){
this.id = tank.getId();
@ -17,23 +20,44 @@ public class TankDTO {
this.cost = tank.getCost();
}
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public long getId(){
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName(){
return name;
}
public void setName(String name) {
this.name = name;
}
public SimpleNationDTO getNation(){
return nation;
}
public void setNation(SimpleNationDTO nation) {
this.nation = nation;
}
public LevelDTO getLevel(){
return level;
}
public void setLevel(LevelDTO level) {
this.level = level;
}
public int getCost(){
return cost;
}
public void setCost(int cost) {
this.cost = cost;
}
}

View File

@ -0,0 +1,82 @@
package premium_store.controller.controller;
import net.bytebuddy.implementation.bind.MethodDelegationBinder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import premium_store.controller.DTO.FullNationDTO;
import premium_store.controller.DTO.SimpleNationDTO;
import premium_store.service.NationService;
import javax.validation.Valid;
@Controller
@RequestMapping("/nation")
public class NationMvcController {
private final NationService nationService;
public NationMvcController(NationService nationService){
this.nationService = nationService;
}
@GetMapping
public String getNations(Model model){
model.addAttribute("nations",
nationService.findAllNations().stream()
.map(FullNationDTO::new)
.toList());
return "nation";
}
@GetMapping(value = {"/edit", "/edit/{id}"})
public String editNation(@PathVariable(required = false) Long id, Model model){
if(id == null || id <= 0){
model.addAttribute("simpleNationDTO", new SimpleNationDTO());
}
else {
model.addAttribute("nationId", id);
model.addAttribute("simpleNationDTO", new SimpleNationDTO(nationService.findNation(id)));
}
return "nation-edit";
}
@GetMapping(value = {"/editTank", "/editTank/{id}"})
public String editTankNation(@PathVariable(required = false) Long id, Model model){
if(id == null || id <= 0){
model.addAttribute("fullNationDTO", new FullNationDTO());
}
else {
model.addAttribute("nationId", id);
model.addAttribute("fullNationDTO", new FullNationDTO(nationService.findNation(id)));
}
return "nation-tank-edit";
}
@PostMapping(value = {"", "/{id}"})
public String saveNation(@PathVariable(required = false) Long id,
@ModelAttribute @Valid SimpleNationDTO simpleNationDTO,
BindingResult bindingResult,
Model model){
if(bindingResult.hasErrors()){
model.addAttribute("errors", bindingResult.getAllErrors());
return "nation-edit";
}
if(id == null || id <= 0){
nationService.addNation(simpleNationDTO.getNation());
} else {
nationService.updateNation(id, simpleNationDTO.getNation(), null);
}
return "redirect:/nation";
}
@PostMapping("/delete/{id}")
public String deleteNation(@PathVariable Long id){
nationService.deleteNation(id);
return "redirect:/nation";
}
}

View File

@ -0,0 +1,34 @@
.myModal{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: none;
background: rgba(0, 0, 0, 0.8);
}
.myModal.active{
display: flex;
justify-content: center;
align-items: center;
}
.myModalContent{
display: flex;
padding: 15px;
background: #FF652F;
border-radius: 16px;
min-width: 300px;
min-height: 100px;
justify-content: space-between;
align-items: center;
}
.modalButton{
padding: 5px;
border-radius: 10px;
background-color: #FFE430;
font-family: Courier, monospace;
font-weight: 900;
}

View File

@ -0,0 +1,55 @@
.add-nation-input{
padding-left: 10px;
padding-right: 10px;
border: 3px solid;
border-radius: 10px;
border-color: #505050;
}
.add-level-button{
border-radius: 10px;
border-color: #505050;
background-color: #FFE430;
font-weight: 900;
}
.nation-card{
display: flex;
width: 100%;
padding: 15px;
margin-top: 5px;
border: 5px solid;
border-color: #14A76C;
border-radius: 10px;
opacity: 0.9;
background-color: #151719;
justify-content: space-around;
align-items: center;
font-family: Courier, monospace;
font-weight: 900;
}
.nation-attribute{
padding: 5px;
border-radius: 10px;
background-color: #FF652F;
font-family: Courier, monospace;
font-weight: 900;
align-items: center;
}
.nation-button-group{
display: flex;
margin: 10px;
width: 20%;
justify-content: space-around;
align-items: center;
}
.nation-button{
padding: 10px;
border-radius: 10px;
background-color: #FF652F;
font-family: Courier, monospace;
font-weight: 900;
}

View File

@ -0,0 +1,99 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/*#505050*/
#root{
display: flex;
justify-content: center;
background-color: #151719;
background-image: url("../images/wot-is-4.jpg");
background-size: cover;
background-attachment: fixed;
font-family: Courier, monospace;
font-weight: 900;
}
.body{
margin: 0; /* Убираем отступы */
height: 100%; /* Высота страницы */
justify-content: center;
background-color: #151719;
background-image: url("./wot-is-4.jpg");
background-size: cover;
background-attachment: fixed;
font-family: Courier, monospace;
font-weight: 900;
}
/*
.App{
width: 1200px;
}
*/
.Group_create_level{
display: flex;
padding: 15px;
background-color: #FFE430;
opacity: 0.8;
border-radius: 10px;
margin-top: 15px;
justify-content: space-around;
align-items: center;
}
.Card_list{
padding: 15px;
border: 5px solid;
border-color: #14A76C;
background-color: #151719;
opacity: 0.9;
border-radius: 10px;
margin-top: 15px;
align-items: center;
}
.Main_head{
display: flex;
padding: 15px;
margin-top: 30px;
border: 5px solid;
border-color: #FF652F;
border-radius: 10px;
background-color: #151719;
opacity: 0.9;
justify-content: space-between;
align-items: center;
}
.Button_Main_Group{
padding: 5px;
border-color: #FF652F;
border-radius: 10px;
background-color: #FF652F;
font-family: Courier, monospace;
font-weight: bold;
align-items: center;
}
.add-level-button{
padding: 10px;
margin-right: 15px;
}
.Main-label{
display: flex;
padding-top: 16px;
font-size: 7vw;
font-variant: small-caps;
font-stretch: ultra-expanded;
justify-content: space-around;
align-items: center;
color: #505050;
-webkit-text-stroke-width: 3.0px;
-webkit-text-stroke-color: #000000;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 KiB

View File

@ -12,37 +12,38 @@
<link rel="stylesheet" href="/webjars/font-awesome/6.1.0/css/all.min.css"/>
<link rel="stylesheet" href="/css/style.css"/>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<i class="fa-solid fa-font-awesome"></i>
Премиум магазин
</a>
<button class="navbar-toggler" type="button"
data-bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav" th:with="activeLink=${#request.requestURI}">
<a class="nav-link" href="/levels"
th:classappend="${#strings.equals(activeLink, '/levels')} ? 'active' : ''">Обзор уровней
</a>
<a class="nav-link" href="/tanks"
th:classappend="${#strings.equals(activeLink, '/tanks')} ? 'active' : ''">Обзор танков
</a>
<a class="nav-link" href="/nations"
th:classappend="${#strings.equals(activeLink, '/nations')} ? 'active' : ''">Обзор наций
</a>
<a class="nav-link" href="/clients"
th:classappend="${#strings.equals(activeLink, '/clients')} ? 'active' : ''">Обзор клиентов
</a>
</ul>
</div>
</div>
</nav>
<div class="container-fluid">
<body class="body">
<div>
<h1 class="Main-label">Мир танков</h1>
</div>
<div>
<form className="collapse navbar-collapse">
<nav class="navbar navbar-expand-lg justify-content-around">
<button class="navbar-toggler" type="button"
data-bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="Main_head navbar-nav me-auto align-items-center" th:with="activeLink=${#request.requestURI}">
<a class="nav-link btn border border-3 border-dark fs-4 lh-15 Button_Main_Group" href="/level"
th:classappend="${#strings.equals(activeLink, '/level')} ? 'active' : ''">Обзор уровней
</a>
<a class="nav-link btn border border-3 border-dark fs-4 lh-15 Button_Main_Group " href="/tank"
th:classappend="${#strings.equals(activeLink, '/tank')} ? 'active' : ''">Обзор танков
</a>
<a class="nav-link btn border border-3 border-dark fs-4 lh-15 Button_Main_Group " href="/nation"
th:classappend="${#strings.equals(activeLink, '/nation')} ? 'active' : ''">Обзор наций
</a>
<a class="nav-link btn border border-3 border-dark fs-4 lh-15 Button_Main_Group" href="/client"
th:classappend="${#strings.equals(activeLink, '/client')} ? 'active' : ''">Обзор клиентов
</a>
</ul>
</div>
</nav>
</form>
</div>
<div class="container-fluid body">
<div class="container container-padding" layout:fragment="content"></div>
</div>
</body>

View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
<link rel="stylesheet" href="/css/nation.css"/>
<link rel="stylesheet" href="/css/modal-nation.css"/>
</head>
<body>
<div layout:fragment="content">
<form action="#" th:action="@{/nation/{id}(id=${id})}" th:object="${simpleNationDTO}" method="post">
<div class="myModalContent">
<input
type='text'
class="add-nation-input form-control"
id="nation"
th:field="${simpleNationDTO.nation}"
required="true"
/>
<button
class="modalButton"
type="submit"
>
<span th:if="${id == null}">Добавить</span>
<span th:if="${id != null}">Сохранить</span>
</button>
<button
class="modalButton"
type="submit"
th:href="@{/nation}"
>
Назад
</button>
</div>
</form>
</div>
<!--<div layout:fragment="content">
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/student/{id}(id=${id})}" th:object="${studentDto}" method="post">
<div class="mb-3">
<label for="firstName" class="form-label">Имя</label>
<input type="text" class="form-control" id="firstName" th:field="${studentDto.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="${studentDto.lastName}" required="true">
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary button-fixed">
<span th:if="${id == null}">Добавить</span>
<span th:if="${id != null}">Обновить</span>
</button>
<a class="btn btn-secondary button-fixed" th:href="@{/student}">
Назад
</a>
</div>
</form>
</div>-->
</body>
</html>

View File

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
<link rel="stylesheet" href="/css/nation.css"/>
<link rel="stylesheet" href="/css/modal-nation.css"/>
</head>
<body>
<div layout:fragment="content">
<form action="#" th:action="@{/nation/{id}(id=${id})}" th:object="${fullNationDTO}" method="get">
<div th:each="tank, iterator: ${fullNationDTO.tanks}">
<div class="nation-card">
<p class="nation-attribute" th:text="'Номер: ' + ${tank.id}"/>
<p class="nation-attribute" th:text="'Название: ' + ${tank.name}"/>
<p class="nation-attribute" th:text="'Стоимость: ' + ${tank.cost}"/>
<p class="nation-attribute" th:text="'Уровень: ' + ${tank.level.level}"/>
</div>
</div>
</form>
</div>
<!--<div layout:fragment="content">
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/student/{id}(id=${id})}" th:object="${studentDto}" method="post">
<div class="mb-3">
<label for="firstName" class="form-label">Имя</label>
<input type="text" class="form-control" id="firstName" th:field="${studentDto.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="${studentDto.lastName}" required="true">
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary button-fixed">
<span th:if="${id == null}">Добавить</span>
<span th:if="${id != null}">Обновить</span>
</button>
<a class="btn btn-secondary button-fixed" th:href="@{/student}">
Назад
</a>
</div>
</form>
</div>-->
</body>
</html>

View File

@ -0,0 +1,85 @@
<!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"/>
<link rel="stylesheet" href="/css/nation.css"/>
<script type="text/javascript" src="/webjars/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<div layout:fragment="content">
<div class="Group_create_level">
<h1>Генератор наций</h1>
<a class="add-level-button" type="button"
th:href="@{/nation/edit/}">
Создать нацию
</a>
<button class='add-level-button'
>
Вывести все нации
</button>
</div>
<div>
<h1 style="text-align: center; font-family: courier, monospace; background: #FF652F; border-radius: 10px">
Список существующих наций:
</h1>
</div>
<div th:each="nation, iterator: ${nations}">
<div class="nation-card">
<p class="nation-attribute" th:text="${nation.id}"/>
<p class="nation-attribute" th:text="${nation.nation}"/>
<div class='nation-button-group'>
<form th:action="@{/nation/edit/{id}(id=${nation.id})}" method="get">
<button class="nation-button" type="submit"
th:id="'edit-' + ${nation.id}"
>
Редактировать
</button>
</form>
<form th:action="@{/nation/delete/{id}(id=${nation.id})}" method="post">
<button th:id="'remove-' + ${nation.id}" class="nation-button" type="submit">
Удалить
</button>
</form>
<form th:action="@{/nation/editTank/{id}(id=${nation.id})}" method="get">
<button th:id="'edit-tank-' + ${nation.id}" class="nation-button" type="submit">
Список танков
</button>
</form>
</div>
</div>
</div>
<div class="table-responsive">
<table class="table">
<tbody>
<tr th:each="nation, iterator: ${nations}">
<th scope="row" th:text="${iterator.index} + 1"/>
<td th:text="${nation.id}"/>
<td th:text="${nation.nation}" 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="@{/nation/edit/{id}(id=${nation.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-${nation.id}').click()|">
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
</div>
<form th:action="@{/nation/delete/{id}(id=${nation.id})}" method="post">
<button th:id="'remove-' + ${nation.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
<th:block layout:fragment="scripts">
</th:block>
</html>

View File

@ -1,10 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>