Постепенно идём к истине
This commit is contained in:
parent
1820b567a6
commit
53911bccf8
8469
front/premium_store/package-lock.json
generated
8469
front/premium_store/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/index.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,45 +1,64 @@
|
||||
import React, {useState} from 'react';
|
||||
import { useRoutes, Outlet, BrowserRouter } from 'react-router-dom';
|
||||
import { Routes, BrowserRouter, Route } from 'react-router-dom';
|
||||
|
||||
import PrivateRoutes from "./components/items/Pages/PrivateRoutes";
|
||||
|
||||
import AddLevel from './components/AddLevel';
|
||||
import MainHead from './components/MainHead';
|
||||
import AddNation from './components/AddNation';
|
||||
import AddTank from './components/AddTank';
|
||||
import AddClient from './components/AddClient';
|
||||
import PageForChecking from './components/PageForChecking';
|
||||
import SingupPage from './components/items/Pages/SingupPage';
|
||||
import LoginPage from './components/items/Pages/LoginPage';
|
||||
import MyNavBar from './components/items/Pages/MyNavbar';
|
||||
|
||||
function Router(props) {
|
||||
/*function Router(props) {
|
||||
return useRoutes(props.rootRoute);
|
||||
}
|
||||
}*/
|
||||
|
||||
function App() {
|
||||
const routes = [
|
||||
{ index: true, element: <AddLevel /> },
|
||||
{ path: 'levels', element: <AddLevel />, label: 'Обзор уровней' },
|
||||
{ path: 'nations', element: <AddNation />, label: 'Обзор наций' },
|
||||
{ path: 'tanks', element: <AddTank />, label: 'Обзор танков'},
|
||||
{ path: 'clients', element: <AddClient />, label: 'Обзор клиентов'},
|
||||
{ path: 'checkPage', element: <PageForChecking />, label: 'Фильтр по танкам'}
|
||||
{ index: true, element: <AddLevel />, userGroup: "AUTH"},
|
||||
{ path: 'levels', element: <AddLevel />, label: 'Обзор уровней', userGroup: "AUTH" },
|
||||
{ path: 'nations', element: <AddNation />, label: 'Обзор наций', userGroup: "AUTH" },
|
||||
{ path: 'tanks', element: <AddTank />, label: 'Обзор танков', userGroup: "AUTH"},
|
||||
{ path: 'clients', element: <AddClient />, label: 'Обзор клиентов', userGroup: "AUTH"},
|
||||
{ path: 'checkPage', element: <PageForChecking />, label: 'Фильтр по танкам', userGroup: "AUTH"}
|
||||
];
|
||||
|
||||
const links = routes.filter(route => route.hasOwnProperty('label'));
|
||||
|
||||
const rootRoute = [
|
||||
/*const rootRoute = [
|
||||
{ path: '/', element: render(links), children: routes }
|
||||
];
|
||||
|
||||
function render(links) {
|
||||
return (
|
||||
<div className="App">
|
||||
<MainHead links={links}/>
|
||||
<Outlet/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
];*/
|
||||
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Router rootRoute={ rootRoute } />
|
||||
</BrowserRouter>
|
||||
<>
|
||||
<BrowserRouter>
|
||||
<MyNavBar links={routes}></MyNavBar>
|
||||
<div className="content-div">
|
||||
<Routes>
|
||||
<Route element={<LoginPage />} path="/login" />
|
||||
<Route element={<SingupPage />} path="/singup" />
|
||||
<Route element={<PrivateRoutes userGroup="AUTH" />}>
|
||||
<Route element={<AddTank />} path="/tanks" />
|
||||
<Route element={<PageForChecking />} path="/checkPage" />
|
||||
<Route element={<AddNation />} path="/nations" exact />
|
||||
<Route element={<AddNation />} path="*" />
|
||||
</Route>
|
||||
<Route element={<PrivateRoutes userGroup="USER" />}>
|
||||
<Route element={<AddLevel />} path="/levels" />
|
||||
</Route>
|
||||
<Route element={<PrivateRoutes userGroup="ADMIN" />}>
|
||||
<Route element={<AddClient />} path="/clients" />
|
||||
</Route>
|
||||
</Routes>
|
||||
</div>
|
||||
<footer className="border-top">
|
||||
Footer
|
||||
</footer>
|
||||
</BrowserRouter>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ export default function AddClient() {
|
||||
//загрузка всех имеющихся уровней при старте
|
||||
useEffect(() => {
|
||||
console.log('Обращение к БД');
|
||||
axios.get('http://localhost:8080/client/')
|
||||
axios.get('http://localhost:8080/api/1.0/client/')
|
||||
.then((responce) => {
|
||||
console.log(responce.data);
|
||||
setClientItems(responce.data)
|
||||
@ -28,7 +28,7 @@ export default function AddClient() {
|
||||
//обновить список уровней
|
||||
function CheckArray(){
|
||||
console.log('Обращение к БД');
|
||||
axios.get('http://localhost:8080/client/')
|
||||
axios.get('http://localhost:8080/api/1.0/client/')
|
||||
.then((responce) => {
|
||||
console.log(responce.data);
|
||||
setClientItems(responce.data)
|
||||
@ -44,8 +44,8 @@ export default function AddClient() {
|
||||
if(clientNickName === ''){
|
||||
return;
|
||||
}
|
||||
else {//http://localhost:8080/client/?nickName=11&email=11&balance=11
|
||||
axios.post('http://localhost:8080/client/?nickName=' + clientNickName + '&email=' + clientEmail + '&balance=' + clientBalance)
|
||||
else {
|
||||
axios.post('http://localhost:8080/api/1.0/client/?nickName=' + clientNickName + '&email=' + clientEmail + '&balance=' + clientBalance)
|
||||
.then((response) => {
|
||||
CheckArray();
|
||||
setClientNickName('');
|
||||
|
@ -0,0 +1,8 @@
|
||||
export default class UserSignupDto {
|
||||
constructor(args) {
|
||||
this.login = args.login;
|
||||
this.email = args.email;
|
||||
this.password = args.password;
|
||||
this.passwordConfirm = args.passwordConfirm;
|
||||
}
|
||||
}
|
148
front/premium_store/src/components/items/Pages/AccountPage.jsx
Normal file
148
front/premium_store/src/components/items/Pages/AccountPage.jsx
Normal file
@ -0,0 +1,148 @@
|
||||
import { useEffect, useState, useRef } from "react";
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
const hostURL = "http://localhost:8080";
|
||||
const host = hostURL + "/api/1.0";
|
||||
|
||||
const AccountPage = function () {
|
||||
|
||||
const [currentUser, setCurrentUser] = useState({});
|
||||
|
||||
const loginInput = useRef();
|
||||
const emailInput = useRef();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
getUser().then(user => setCurrentUser(user));
|
||||
}, []);
|
||||
|
||||
const getTokenForHeader = function () {
|
||||
return "Bearer " + localStorage.getItem("token");
|
||||
}
|
||||
|
||||
const login = async function () {
|
||||
const requestParams = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(currentUser),
|
||||
};
|
||||
const requestUrl = hostURL + "/jwt/login";
|
||||
const response = await fetch(requestUrl, requestParams);
|
||||
const result = await response.text();
|
||||
if (response.status === 200) {
|
||||
localStorage.setItem("token", result);
|
||||
localStorage.setItem("user", currentUser.login);
|
||||
getRole(result);
|
||||
} else {
|
||||
localStorage.removeItem("token");
|
||||
localStorage.removeItem("user");
|
||||
localStorage.removeItem("role");
|
||||
}
|
||||
}
|
||||
|
||||
const getRole = async function (token) {
|
||||
const requestParams = {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
};
|
||||
const requestUrl = hostURL + `/who_am_i?token=${token}`;
|
||||
const response = await fetch(requestUrl, requestParams);
|
||||
const result = await response.text();
|
||||
localStorage.setItem("role", result);
|
||||
window.dispatchEvent(new Event("storage"));
|
||||
}
|
||||
|
||||
const updateUser = async function () {
|
||||
const requestParams = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": getTokenForHeader(),
|
||||
},
|
||||
body: JSON.stringify(currentUser),
|
||||
};
|
||||
const requestUrl = host + `/user`;
|
||||
const response = await fetch(requestUrl, requestParams);
|
||||
const result = await response.text();
|
||||
return result;
|
||||
}
|
||||
|
||||
const getUser = async function () {
|
||||
const requestParams = {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Authorization": getTokenForHeader(),
|
||||
}
|
||||
};
|
||||
let login = localStorage.getItem("user");
|
||||
const requestUrl = host + `/user?login=${login}`;
|
||||
const response = await fetch(requestUrl, requestParams);
|
||||
const user = await response.json();
|
||||
return user;
|
||||
}
|
||||
|
||||
const onSubmit = function (event) {
|
||||
event.preventDefault();
|
||||
updateUser().then((result) => {
|
||||
alert(result);
|
||||
if (result === "Profile updated") {
|
||||
login();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const onInput = function (event, fieldName) {
|
||||
setCurrentUser(oldUser => ({
|
||||
...oldUser, [fieldName]: event.target.value
|
||||
}));
|
||||
}
|
||||
|
||||
const logoutButtonOnClick = function () {
|
||||
localStorage.removeItem("token");
|
||||
localStorage.removeItem("user");
|
||||
localStorage.removeItem("role");
|
||||
window.dispatchEvent(new Event("storage"));
|
||||
navigate("/login");
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div class="border-bottom pb-3 mb-3">
|
||||
<button class="btn btn-primary"
|
||||
onClick={logoutButtonOnClick}>
|
||||
Log Out
|
||||
</button>
|
||||
</div>
|
||||
<h4 className="mb-4">Update profile</h4>
|
||||
<form onSubmit={onSubmit}>
|
||||
<div className="mb-3">
|
||||
<p className="mb-1">New Login</p>
|
||||
<input className="form-control" type="text" required
|
||||
ref={loginInput} value={currentUser.login}
|
||||
onInput={(event) => onInput(event, "login")} />
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<p className="mb-1">New Email</p>
|
||||
<input className="form-control" type="text" required
|
||||
ref={emailInput} value={currentUser.email}
|
||||
onInput={(event) => onInput(event, "email")} />
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<p className="mb-1">Enter password</p>
|
||||
<input className="form-control" type="password" required
|
||||
ref={emailInput}
|
||||
onInput={(event) => onInput(event, "password")} />
|
||||
</div>
|
||||
<button type="submit" className="btn btn-primary">
|
||||
Save
|
||||
</button>
|
||||
</form>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default AccountPage;
|
90
front/premium_store/src/components/items/Pages/LoginPage.jsx
Normal file
90
front/premium_store/src/components/items/Pages/LoginPage.jsx
Normal file
@ -0,0 +1,90 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { useRef } from "react";
|
||||
|
||||
const hostURL = "http://localhost:8080";
|
||||
|
||||
const LoginPage = function () {
|
||||
|
||||
const loginInput = useRef();
|
||||
const passwordInput = useRef();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
}, []);
|
||||
|
||||
const login = async function (login, password) {
|
||||
const requestParams = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({login: login, password: password}),
|
||||
};
|
||||
const response = await fetch(hostURL + "/jwt/login", requestParams);
|
||||
const result = await response.text();
|
||||
if (response.status === 200) {
|
||||
localStorage.setItem("token", result);
|
||||
localStorage.setItem("user", login);
|
||||
getRole(result);
|
||||
} else {
|
||||
localStorage.removeItem("token");
|
||||
localStorage.removeItem("user");
|
||||
localStorage.removeItem("role");
|
||||
}
|
||||
}
|
||||
|
||||
const getRole = async function (token) {
|
||||
const requestParams = {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
};
|
||||
const requestUrl = hostURL + `/who_am_i?token=${token}`;
|
||||
const response = await fetch(requestUrl, requestParams);
|
||||
const result = await response.text();
|
||||
localStorage.setItem("role", result);
|
||||
window.dispatchEvent(new Event("storage"));
|
||||
navigate("/main");
|
||||
}
|
||||
|
||||
const loginFormOnSubmit = function (event) {
|
||||
event.preventDefault();
|
||||
login(loginInput.current.value, passwordInput.current.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<form onSubmit={(event) => loginFormOnSubmit(event)}>
|
||||
<div className="mb-3">
|
||||
<p className="mb-1">Login</p>
|
||||
<input className="form-control"
|
||||
type="text" required autofocus
|
||||
ref={loginInput} />
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<p className="mb-1">Password</p>
|
||||
<input className="form-control"
|
||||
type="password" required
|
||||
ref={passwordInput} />
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<button type="submit" className="btn btn-success">
|
||||
Sing in
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<span>Not a member yet? </span>
|
||||
<Link to="/singup">Sing Up here</Link>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default LoginPage;
|
56
front/premium_store/src/components/items/Pages/MyNavbar.jsx
Normal file
56
front/premium_store/src/components/items/Pages/MyNavbar.jsx
Normal file
@ -0,0 +1,56 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const MyNavBar = function (props) {
|
||||
|
||||
const [userRole, setUserRole] = useState("NONE");
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("storage", () => {
|
||||
getUserRole();
|
||||
});
|
||||
getUserRole();
|
||||
}, [])
|
||||
|
||||
const getUserRole = function () {
|
||||
const role = localStorage.getItem("role") || "NONE";
|
||||
setUserRole(role);
|
||||
}
|
||||
|
||||
const validate = function (userGroup) {
|
||||
if ((userGroup === "AUTH" && userRole !== "NONE") ||
|
||||
(userGroup === userRole)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
<nav className="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<div className="container-fluid">
|
||||
<Link className="navbar-brand fw-bold" to="main">Logo</Link>
|
||||
<button className="navbar-toggler" data-bs-toggle="collapse"
|
||||
data-bs-target="#navbar" aria-controls="navbar"
|
||||
aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span className="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div className="collapse navbar-collapse" id="navbar">
|
||||
<div className="navbar-nav">
|
||||
{props.links.map(route => {
|
||||
if (validate(route.userGroup)) {
|
||||
return (
|
||||
<li key={route.path} className="nav-item">
|
||||
<Link className="nav-link" to={route.path}>
|
||||
{route.label}
|
||||
</Link>
|
||||
</li> );
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
export default MyNavBar;
|
@ -0,0 +1,47 @@
|
||||
import { Outlet, Navigate, useNavigate } from 'react-router-dom';
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const PrivateRoutes = (props) => {
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("storage", () => {
|
||||
let token = localStorage.getItem("token");
|
||||
if (token) {
|
||||
getRole(token).then((role) => {
|
||||
if (localStorage.getItem("role") != role) {
|
||||
localStorage.removeItem("token");
|
||||
localStorage.removeItem("user");
|
||||
localStorage.removeItem("role");
|
||||
window.dispatchEvent(new Event("storage"));
|
||||
navigate("/main");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [])
|
||||
|
||||
const getRole = async function (token) {
|
||||
const requestParams = {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
};
|
||||
const requestUrl = `http://localhost:8080/who_am_i?token=${token}`;
|
||||
const response = await fetch(requestUrl, requestParams);
|
||||
const result = await response.text();
|
||||
return result;
|
||||
}
|
||||
|
||||
let isAllowed = false;
|
||||
let userRole = localStorage.getItem("role");
|
||||
if ((props.userGroup === "AUTH" && userRole) || (props.userGroup === userRole)) {
|
||||
isAllowed = true;
|
||||
}
|
||||
|
||||
return isAllowed ? <Outlet /> : <Navigate to="/login" />;
|
||||
}
|
||||
|
||||
export default PrivateRoutes;
|
@ -0,0 +1,86 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useRef } from "react";
|
||||
|
||||
const hostURL = "http://localhost:8080";
|
||||
|
||||
const SingupPage = function () {
|
||||
|
||||
const loginInput = useRef();
|
||||
const emailInput = useRef();
|
||||
const passwordInput = useRef();
|
||||
const passwordConfirmInput = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
}, []);
|
||||
|
||||
const singup = async function (userSinginDto) {
|
||||
const requestParams = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(userSinginDto),
|
||||
};
|
||||
const response = await fetch(hostURL + "/sing_up", requestParams);
|
||||
const result = await response.text();
|
||||
alert(result);
|
||||
}
|
||||
|
||||
const singupFormOnSubmit = function (event) {
|
||||
event.preventDefault();
|
||||
const userSinginDto = {
|
||||
login: loginInput.current.value,
|
||||
email: emailInput.current.value,
|
||||
password: passwordInput.current.value,
|
||||
passwordConfirm: passwordConfirmInput.current.value
|
||||
}
|
||||
singup(userSinginDto);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<form onSubmit={(event) => singupFormOnSubmit(event)}>
|
||||
<div className="mb-3">
|
||||
<p className="mb-1">Login</p>
|
||||
<input className="form-control"
|
||||
type="text" required maxlength="64"
|
||||
ref={loginInput} />
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<p className="mb-1">Email</p>
|
||||
<input className="form-control"
|
||||
type="text" required
|
||||
ref={emailInput} />
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<p className="mb-1">Password</p>
|
||||
<input className="form-control"
|
||||
type="password" required minlength="3" maxlength="64"
|
||||
ref={passwordInput} />
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<p className="mb-1">Confirm Password</p>
|
||||
<input className="form-control"
|
||||
type="password" required minlength="3" maxlength="64"
|
||||
ref={passwordConfirmInput} />
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<button type="submit" className="btn btn-success">
|
||||
Create account
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<span>Already have an account? </span>
|
||||
<Link to="/login">Sing In here</Link>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default SingupPage;
|
@ -2,7 +2,6 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
ReactDOM.createRoot(document.getElementById('app')).render(
|
||||
<App />
|
||||
);
|
||||
)
|
||||
|
7
front/premium_store/src/vite.config.js
Normal file
7
front/premium_store/src/vite.config.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()]
|
||||
})
|
@ -24,10 +24,6 @@ dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'com.h2database:h2:2.1.210'
|
||||
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
||||
implementation 'org.springframework.boot:spring-boot-devtools'
|
||||
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
|
||||
|
||||
implementation 'org.webjars:bootstrap:5.1.3'
|
||||
implementation 'org.webjars:jquery:3.6.0'
|
||||
implementation 'org.webjars:font-awesome:6.1.0'
|
||||
|
@ -1,7 +1,5 @@
|
||||
package premium_store.controller.controller;
|
||||
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import premium_store.configuration.OpenAPI30Configuration;
|
||||
import premium_store.controller.DTO.ClientDTO;
|
||||
import premium_store.controller.DTO.UserSignupDto;
|
||||
@ -10,9 +8,15 @@ import premium_store.model.UserRole;
|
||||
import premium_store.service.GameClientService;
|
||||
import premium_store.service.TankService;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.ValidationException;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@RestController
|
||||
@CrossOrigin
|
||||
@ -86,4 +90,27 @@ public class GameClientController {
|
||||
public ClientDTO deleteClient(@PathVariable Long id) {
|
||||
return new ClientDTO(gameClientService.deleteClient(id));
|
||||
}
|
||||
|
||||
@GetMapping(OpenAPI30Configuration.API_PREFIX + "/users")
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public Pair<Page<ClientDTO>, List<Integer>> getUsers(@RequestParam(defaultValue = "1") int page,
|
||||
@RequestParam(defaultValue = "5") int size) {
|
||||
final Page<ClientDTO> users = gameClientService.findAllPages(page, size)
|
||||
.map(ClientDTO::new);
|
||||
|
||||
final int totalPages = users.getTotalPages();
|
||||
|
||||
final List<Integer> pageNumbers = IntStream.rangeClosed(1, totalPages)
|
||||
.boxed()
|
||||
.toList();
|
||||
|
||||
return new Pair<>(users, pageNumbers);
|
||||
}
|
||||
|
||||
@GetMapping(URL_WHO_AM_I)
|
||||
public String whoAmI(@RequestParam("token") String token) {
|
||||
UserDetails userDetails = gameClientService.loadUserByToken(token);
|
||||
GameClient user = gameClientService.findByLogin(userDetails.getUsername());
|
||||
return user.getRole().toString();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
package premium_store.controller.controller;
|
||||
|
||||
public class Pair<F, S> {
|
||||
private final F first;
|
||||
private final S second;
|
||||
|
||||
public Pair(F first, S second) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
public F getFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public S getSecond() {
|
||||
return second;
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
spring.main.banner-mode=off
|
||||
server.port=8080
|
||||
#JPA
|
||||
server.tomcat.relaxed-query-chars=|,{,},[,]
|
||||
spring.datasource.url=jdbc:h2:file:./data
|
||||
spring.datasource.driverClassName=org.h2.Driver
|
||||
spring.datasource.username=sa
|
||||
@ -12,3 +11,5 @@ spring.jpa.hibernate.ddl-auto=update
|
||||
spring.h2.console.enabled=true
|
||||
spring.h2.console.settings.trace=false
|
||||
spring.h2.console.settings.web-allow-others=false
|
||||
jwt.dev-token=my-secret-jwt
|
||||
jwt.dev=true
|
||||
|
@ -1,91 +0,0 @@
|
||||
.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;
|
||||
}
|
||||
|
||||
|
||||
.client-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;
|
||||
}
|
||||
|
||||
.client-attribute{
|
||||
padding: 5px;
|
||||
border-radius: 10px;
|
||||
background-color: #FF652F;
|
||||
font-family: Courier, monospace;
|
||||
font-weight: 900;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.client-button-group{
|
||||
display: flex;
|
||||
width: 20%;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.client-button{
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
background-color: #FF652F;
|
||||
font-family: Courier, monospace;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.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: inline-block;
|
||||
padding: 15px;
|
||||
width: 100%;
|
||||
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;
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
.add-level-button{
|
||||
border-radius: 10px;
|
||||
border-color: #505050;
|
||||
background-color: #FFE430;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.level-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;
|
||||
}
|
||||
|
||||
.level-attribute{
|
||||
padding: 5px;
|
||||
border-radius: 10px;
|
||||
background-color: #FF652F;
|
||||
font-family: Courier, monospace;
|
||||
font-weight: 900;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.level-button-group{
|
||||
display: flex;
|
||||
width: 20%;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.level-button{
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
background-color: #FF652F;
|
||||
font-family: Courier, monospace;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.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;
|
||||
width: 100%;
|
||||
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;
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
.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;
|
||||
width: 100%;
|
||||
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;
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
.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;
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
* {
|
||||
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;
|
||||
width: 80%;
|
||||
margin: 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;
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
.add-nation-input{
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border: 3px solid;
|
||||
border-radius: 10px;
|
||||
border-color: #505050;
|
||||
}
|
||||
|
||||
.add-tank-button{
|
||||
border-radius: 10px;
|
||||
border-color: #505050;
|
||||
background-color: #FFE430;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.tank-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;
|
||||
}
|
||||
|
||||
.tank-attribute{
|
||||
padding: 5px;
|
||||
border-radius: 10px;
|
||||
background-color: #FF652F;
|
||||
font-family: Courier, monospace;
|
||||
font-weight: 900;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tank-button-group{
|
||||
display: flex;
|
||||
width: 20%;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tank-button{
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
background-color: #FF652F;
|
||||
font-family: Courier, monospace;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.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: inline-block;
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
background: #FF652F;
|
||||
border-radius: 16px;
|
||||
min-width: 300px;
|
||||
min-height: 100px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modalButton{
|
||||
padding: 5px;
|
||||
border-radius: 10px;
|
||||
background-color: #FFE430;
|
||||
font-family: Courier, monospace;
|
||||
font-weight: 900;
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 474 KiB |
@ -1,73 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}">
|
||||
<head>
|
||||
<link rel="stylesheet" href="/css/client.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
<div class="Group_create_level">
|
||||
<h1>Генератор клиентов</h1>
|
||||
</div>
|
||||
<form action="#" th:action="@{/clients/{id}(id=${id})}" th:object="${supportClientDTO}" method="post">
|
||||
<div class="myModalContent">
|
||||
<label for="name" class="form-label">Логин: </label>
|
||||
<input
|
||||
type='text'
|
||||
class="add-nation-input form-control"
|
||||
id="name"
|
||||
th:field="${supportClientDTO.login}"
|
||||
required="true"
|
||||
/>
|
||||
<label for="password" class="form-label">Пароль: </label>
|
||||
<input
|
||||
type='text'
|
||||
class="add-nation-input form-control"
|
||||
id="password"
|
||||
th:field="${supportClientDTO.password}"
|
||||
required="true"
|
||||
/>
|
||||
<label for="email" class="form-label">Почта: </label>
|
||||
<input
|
||||
type='text'
|
||||
class="add-nation-input form-control"
|
||||
id="email"
|
||||
th:field="${supportClientDTO.email}"
|
||||
required="true"
|
||||
/>
|
||||
<label for="balance" class="form-label">Баланс: </label>
|
||||
<input
|
||||
type='text'
|
||||
class="add-nation-input form-control"
|
||||
id="balance"
|
||||
th:field="${supportClientDTO.balance}"
|
||||
required="true"
|
||||
/>
|
||||
<label for="name" class="form-label">Танк: </label>
|
||||
<select id="level" class="form-select" th:field="${supportClientDTO.tankId}" required="true">
|
||||
<option th:each="value: ${tanks}"
|
||||
th:value="${value.id}"
|
||||
th:text="${value.name}">
|
||||
</option>
|
||||
</select>
|
||||
<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="@{/clients}"
|
||||
>
|
||||
Назад
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,68 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
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/client.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>
|
||||
<h2>
|
||||
<a class="add-level-button text-dark" type="button"
|
||||
th:href="@{/clients/edit/}"
|
||||
>
|
||||
Создать клиента
|
||||
</a>
|
||||
</h2>
|
||||
</div>
|
||||
<div>
|
||||
<h1 style="text-align: center; font-family: courier, monospace; background: #FF652F; border-radius: 10px">
|
||||
Список существующих клиентов:
|
||||
</h1>
|
||||
</div>
|
||||
<div th:each="user, iterator: ${users}">
|
||||
<div class="client-card">
|
||||
<p class="client-attribute" th:text="'Номер: ' + ${user.id}"/>
|
||||
<p class="client-attribute" th:text="'Никнейм (логин): ' + ${user.login}"/>
|
||||
<p class="client-attribute" th:text="'Баланс: ' + ${user.balance}"/>
|
||||
<div class='client-button-group'>
|
||||
<form th:action="@{/clients/edit/{id}(id=${user.id})}" method="get">
|
||||
<button class="client-button" type="submit"
|
||||
th:id="'edit-' + ${user.id}"
|
||||
>
|
||||
Редактировать
|
||||
</button>
|
||||
</form>
|
||||
<form th:action="@{/clients/delete/{id}(id=${user.id})}" method="post">
|
||||
<button th:id="'remove-' + ${user.id}" class="client-button" type="submit"
|
||||
>
|
||||
Удалить
|
||||
</button>
|
||||
</form>
|
||||
<form th:action="@{/clients/tanksOfClient/{id}(id=${user.id})}" method="get">
|
||||
<button th:id="'list-tank-' + ${user.id}" class="client-button" type="submit"
|
||||
>
|
||||
Список танков
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:if="${totalPages > 0}" class="pagination">
|
||||
<span style="float: left; padding: 5px 5px;">Страницы:</span>
|
||||
<a th:each="page : ${pages}"
|
||||
th:href="@{/clients(page=${page}, size=${users.size})}"
|
||||
th:text="${page}"
|
||||
th:class="${page == users.number + 1} ? active">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<th:block layout:fragment="scripts">
|
||||
</th:block>
|
||||
</html>
|
@ -1,55 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>Премиум магазин</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<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/font-awesome/6.1.0/css/all.min.css"/>
|
||||
<link rel="stylesheet" href="/css/style.css"/>
|
||||
</head>
|
||||
<body class="body">
|
||||
<div>
|
||||
<h1 class="Main-label">Мир танков</h1>
|
||||
</div>
|
||||
<div class="justify-content-around">
|
||||
<div>
|
||||
<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 justify-content-around" id="navbarNav">
|
||||
<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"
|
||||
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 text-dark" 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 text-dark" 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 text-dark" href="/clients"
|
||||
th:classappend="${#strings.equals(activeLink, '/clients')} ? 'active' : ''" sec:authorize="hasRole('ROLE_ADMIN')">Обзор клиентов
|
||||
</a>
|
||||
<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>)
|
||||
</a>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid body">
|
||||
<div class="container container-padding" layout:fragment="content"></div>
|
||||
</div>
|
||||
</body>
|
||||
<th:block layout:fragment="scripts">
|
||||
</th:block>
|
||||
</html>
|
@ -1,20 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
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">
|
||||
<div th:each="tank, iterator: ${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>
|
||||
</div>
|
@ -1,16 +0,0 @@
|
||||
<!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>
|
@ -1,41 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}">
|
||||
<head>
|
||||
<link rel="stylesheet" href="/css/level.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
<div class="Group_create_level">
|
||||
<h1>Генератор уровней</h1>
|
||||
</div>
|
||||
<form action="#" th:action="@{/level/{id}(id=${id})}" th:object="${levelDTO}" method="post">
|
||||
<div class="myModalContent">
|
||||
<input
|
||||
type='text'
|
||||
class="add-level-input form-control"
|
||||
id="level"
|
||||
th:field="${levelDTO.level}"
|
||||
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="@{/level}"
|
||||
>
|
||||
Назад
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,58 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
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/level.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>
|
||||
<h2>
|
||||
<a class="add-level-button text-dark" type="button"
|
||||
th:href="@{/level/edit/}"
|
||||
sec:authorize="hasRole('ROLE_ADMIN')"
|
||||
>
|
||||
Создать уровень
|
||||
</a>
|
||||
</h2>
|
||||
<h2
|
||||
sec:authorize="hasRole('ROLE_USER')"
|
||||
>
|
||||
Режим просмотра
|
||||
</h2>
|
||||
</div>
|
||||
<div>
|
||||
<h1 style="text-align: center; font-family: courier, monospace; background: #FF652F; border-radius: 10px">
|
||||
Список существующих уровней:
|
||||
</h1>
|
||||
</div>
|
||||
<div th:each="level, iterator: ${levels}">
|
||||
<div class="level-card">
|
||||
<p class="level-attribute" th:text="'Номер: ' + ${level.id}"/>
|
||||
<p class="level-attribute" th:text="'Уровень: ' + ${level.level}"/>
|
||||
<div class='level-button-group' sec:authorize="hasRole('ROLE_ADMIN')">
|
||||
<form th:action="@{/level/edit/{id}(id=${level.id})}" method="get">
|
||||
<button class="level-button" type="submit"
|
||||
th:id="'edit-' + ${level.id}"
|
||||
>
|
||||
Редактировать
|
||||
</button>
|
||||
</form>
|
||||
<form th:action="@{/level/delete/{id}(id=${level.id})}" method="post">
|
||||
<button th:id="'remove-' + ${level.id}" class="level-button" type="submit">
|
||||
Удалить
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<th:block layout:fragment="scripts">
|
||||
</th:block>
|
||||
</html>
|
@ -1,34 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}">
|
||||
<head>
|
||||
<script type="text/javascript" src="/webjars/jquery/3.6.0/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container" layout:fragment="content">
|
||||
<div th:if="${param.error}" class="alert alert-danger margin-bottom">
|
||||
Пользователь не найден или пароль указан не верно
|
||||
</div>
|
||||
<div th:if="${param.logout}" class="alert alert-success margin-bottom">
|
||||
Выход успешно произведен
|
||||
</div>
|
||||
<div th:if="${param.created}" class="alert alert-success margin-bottom">
|
||||
Пользователь '<span th:text="${param.created}"></span>' успешно создан
|
||||
</div>
|
||||
<form th:action="@{/login}" method="post" class="container-padding">
|
||||
<div class="mb-3">
|
||||
<input type="text" name="username" id="username" class="form-control"
|
||||
placeholder="Логин" required="true" autofocus="true"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="password" name="password" id="password" class="form-control"
|
||||
placeholder="Пароль" required="true"/>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success button-fixed">Войти</button>
|
||||
<a class="btn btn-primary button-fixed" href="/signup">Регистрация</a>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,64 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
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">
|
||||
<div class="Group_create_level">
|
||||
<h1>Генератор наций</h1>
|
||||
</div>
|
||||
<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>
|
@ -1,46 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
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>
|
@ -1,65 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
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>
|
||||
<h2>
|
||||
<a class="add-level-button text-dark" type="button"
|
||||
th:href="@{/nation/edit/}"
|
||||
sec:authorize="hasRole('ROLE_ADMIN')"
|
||||
>
|
||||
Создать нацию
|
||||
</a>
|
||||
</h2>
|
||||
<h2
|
||||
sec:authorize="hasRole('ROLE_USER')"
|
||||
>
|
||||
Режим просмотра
|
||||
</h2>
|
||||
</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}"
|
||||
sec:authorize="hasRole('ROLE_ADMIN')"
|
||||
>
|
||||
Редактировать
|
||||
</button>
|
||||
</form>
|
||||
<form th:action="@{/nation/delete/{id}(id=${nation.id})}" method="post">
|
||||
<button th:id="'remove-' + ${nation.id}" class="nation-button" type="submit"
|
||||
sec:authorize="hasRole('ROLE_ADMIN')">
|
||||
Удалить
|
||||
</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>
|
||||
</body>
|
||||
<th:block layout:fragment="scripts">
|
||||
</th:block>
|
||||
</html>
|
@ -1,40 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}">
|
||||
<head>
|
||||
<script type="text/javascript" src="/webjars/jquery/3.6.0/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container container-padding" layout:fragment="content">
|
||||
<div th:if="${errors}" th:text="${errors}" class="margin-bottom alert alert-danger"></div>
|
||||
<form action="#" th:action="@{/signup}" th:object="${clientDTO}" method="post">
|
||||
<div class="mb-3">
|
||||
<input type="text" class="form-control" th:field="${clientDTO.login}"
|
||||
placeholder="Логин" required="true" autofocus="true" maxlength="64"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="text" class="form-control" th:field="${clientDTO.email}"
|
||||
placeholder="Почта" required="true" autofocus="true" maxlength="64"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="text" class="form-control" th:field="${clientDTO.balance}"
|
||||
placeholder="Балланс" maxlength="64"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="password" class="form-control" th:field="${clientDTO.password}"
|
||||
placeholder="Пароль" required="true" minlength="6" maxlength="64"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="password" class="form-control" th:field="${clientDTO.passwordConfirm}"
|
||||
placeholder="Пароль (подтверждение)" required="true" minlength="6" maxlength="64"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<button type="submit" class="btn btn-success button-fixed">Создать</button>
|
||||
<a class="btn btn-primary button-fixed" href="/login">Назад</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,64 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}">
|
||||
<head>
|
||||
<link rel="stylesheet" href="/css/tank.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
<div class="Group_create_level">
|
||||
<h1>Генератор танков</h1>
|
||||
</div>
|
||||
<form class="justify-content-around" action="#" th:action="@{/tank/{id}(id=${id})}" th:object="${supportTankDTO}" method="post">
|
||||
<div class="myModalContent">
|
||||
<label for="name" class="form-label">Название: </label>
|
||||
<input
|
||||
type='text'
|
||||
class="add-nation-input form-control"
|
||||
id="name"
|
||||
th:field="${supportTankDTO.name}"
|
||||
required="true"
|
||||
/>
|
||||
<label for="name" class="form-label">Нация: </label>
|
||||
<select id="nation" class="form-select" th:field="${supportTankDTO.nationId}" required="true">
|
||||
<option th:each="value: ${nations}"
|
||||
th:value="${value.id}"
|
||||
th:text="${value.nation}">
|
||||
</option>
|
||||
</select>
|
||||
<label for="name" class="form-label">Уровень: </label>
|
||||
<select id="level" class="form-select" th:field="${supportTankDTO.levelId}" required="true">
|
||||
<option th:each="value: ${levels}"
|
||||
th:value="${value.id}"
|
||||
th:text="${value.level}">
|
||||
</option>
|
||||
</select>
|
||||
<label for="name" class="form-label">Стоимость: </label>
|
||||
<input
|
||||
type='text'
|
||||
class="add-nation-input form-control"
|
||||
id="cost"
|
||||
th:field="${supportTankDTO.cost}"
|
||||
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="@{/tank}"
|
||||
>
|
||||
Назад
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,104 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
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/tank.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>
|
||||
<h2>
|
||||
<a class="add-tank-button text-dark" type="button"
|
||||
th:href="@{/tank/edit/}"
|
||||
sec:authorize="hasRole('ROLE_ADMIN')"
|
||||
>
|
||||
Создать танк
|
||||
</a>
|
||||
</h2>
|
||||
<h2
|
||||
sec:authorize="hasRole('ROLE_USER')"
|
||||
>
|
||||
Режим просмотра
|
||||
</h2>
|
||||
<form id="filterForm" th:action="@{/tank/filteredList}" th:object="${sortDTO}" method="get">
|
||||
<button class="tank-button" type="submit"
|
||||
th:id="filterStart"
|
||||
>
|
||||
Фильтрация
|
||||
</button>
|
||||
<select id="nation" class="form-select" required="true" th:field="*{nation}">
|
||||
<option th:each="value: ${nations}"
|
||||
th:value="${value.nation}"
|
||||
th:text="${value.nation}">
|
||||
</option>
|
||||
</select>
|
||||
<select id="firstLevel" class="form-select" required="true" th:field="*{firstLevel}">
|
||||
<option th:each="value: ${levels}"
|
||||
th:value="${value.level}"
|
||||
th:text="${value.level}">
|
||||
</option>
|
||||
</select>
|
||||
<select id="secondLevel" class="form-select" required="true" th:field="*{secondLevel}">
|
||||
<option th:each="value: ${levels}"
|
||||
th:value="${value.level}"
|
||||
th:text="${value.level}">
|
||||
</option>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
<div>
|
||||
<h1 style="text-align: center; font-family: courier, monospace; background: #FF652F; border-radius: 10px">
|
||||
Список существующих танков:
|
||||
</h1>
|
||||
</div>
|
||||
<div th:each="tank, iterator: ${tanks}">
|
||||
<div class="tank-card">
|
||||
<p class="tank-attribute" th:text="'Номер: ' + ${tank.id}"/>
|
||||
<p class="tank-attribute" th:text="'Название: ' + ${tank.name}"/>
|
||||
<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.cost}"/>
|
||||
<div class='tank-button-group' sec:authorize="hasRole('ROLE_ADMIN')">
|
||||
<form th:action="@{/tank/edit/{id}(id=${tank.id})}" method="get">
|
||||
<button class="tank-button" type="submit"
|
||||
th:id="'edit-' + ${tank.id}"
|
||||
>
|
||||
Редактировать
|
||||
</button>
|
||||
</form>
|
||||
<form th:action="@{/tank/delete/{id}(id=${tank.id})}" method="post">
|
||||
<button th:id="'remove-' + ${tank.id}" class="tank-button" type="submit">
|
||||
Удалить
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#filterStart').on('click', function() {
|
||||
$.ajax({
|
||||
url: "http://localhost:8080/api/tank/filteredList/?nation='
|
||||
+escape(document.forms['filterForm'].elements['nation'].value)&
|
||||
+escape(document.forms['filterForm'].elements['firstLevel'].value)&
|
||||
+escape(document.forms['filterForm'].elements['secondLevel'].value)"
|
||||
}).then(function (data) {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
|
||||
<!--
|
||||
|
||||
-->
|
||||
|
||||
<!--th:action="@{/tank/filteredList/{nation}(nation=${document.elements['nation'].value}){firstLevel}(firstLevel=${document.elements['firstLevel'].value}){secondLevel}(secondLevel=${document.elements['secondLevel'].value})}"-->
|
@ -1,24 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}">
|
||||
<head>
|
||||
<link rel="stylesheet" href="/css/tank.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
<form action="#" th:action="@{/clients/{id}(id=${id})}" th:object="${clientDTO}" method="get">
|
||||
<div th:each="tank, iterator: ${clientDTO.tanks}">
|
||||
<div class="tank-card">
|
||||
<p class="tank-attribute" th:text="'Номер: ' + ${tank.id}"/>
|
||||
<p class="tank-attribute" th:text="'Название: ' + ${tank.name}"/>
|
||||
<p class="tank-attribute" th:text="'Стоимость: ' + ${tank.cost}"/>
|
||||
<p class="tank-attribute" th:text="'Нация: ' + ${tank.nation.nation}"/>
|
||||
<p class="tank-attribute" th:text="'Уровень: ' + ${tank.level.level}"/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user