11 Commits

Author SHA1 Message Date
c3cb5ad7c6 фикс 2023-06-17 09:51:44 +04:00
04ede57e4b чистила бд 2023-06-16 23:03:00 +04:00
a379461483 почистила бд 2023-06-16 22:41:45 +04:00
b223ef36ab (для 6 лабы) почистила бд от старых записей и лишних таблиц 2023-06-14 18:49:34 +04:00
bb1bd8e543 теперь точно готово, сделала отдельную стр. для инфы о персонаже 2023-06-14 17:39:52 +04:00
9f15263643 готово, красота наведена! 2023-06-14 01:28:59 +04:00
1cb57c9c58 привязка редкостей и т.д. работает (сделала один метод вместо трех разных, чтобы использовали одну и ту же ссылку), осталось навести красоту 2023-06-14 00:05:18 +04:00
4d38a11886 странички (все работает, кроме привязки редкостей и т.д.) 2023-06-13 20:16:28 +04:00
7560b95c46 странички (редактирование персонажа, добавление персонажа и привязка к нему редкостей, ГБ и оружия пока не работает) 2023-06-12 16:54:47 +04:00
b8515d5acb странички 2023-06-11 20:52:56 +04:00
e1a7bf2b27 добавила зависимости, создала mvc-контроллеры 2023-06-07 18:42:00 +04:00
37 changed files with 1420 additions and 15 deletions

View File

@@ -14,6 +14,13 @@ repositories {
dependencies { dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-web'
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.4'
implementation 'org.webjars:font-awesome:6.3.0'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.h2database:h2:2.1.214' implementation 'com.h2database:h2:2.1.214'

Binary file not shown.

79
data.trace.db Normal file
View File

@@ -0,0 +1,79 @@
2023-06-14 17:50:12 jdbc[13]: exception
org.h2.jdbc.JdbcSQLSyntaxErrorException: Синтаксическая ошибка в выражении SQL "DELETE[*]* FROM CHARACTER_WEAPON"; ожидалось "identifier"
Syntax error in SQL statement "DELETE[*]* FROM CHARACTER_WEAPON"; expected "identifier"; SQL statement:
DELETE* FROM CHARACTER_WEAPON [42001-214]
2023-06-14 17:54:39 jdbc[13]: exception
org.h2.jdbc.JdbcSQLSyntaxErrorException: Невозможно удалить "TAB_CHARACTER", пока существует зависимый объект "FK7D4X8R6JREM5K74XFXERIN105, FKKXMV2OHBKM1U7EOUOBN81MLGG, FK8I006N3J8HIVUIVNPRJGKURUO"
Cannot drop "TAB_CHARACTER" because "FK7D4X8R6JREM5K74XFXERIN105, FKKXMV2OHBKM1U7EOUOBN81MLGG, FK8I006N3J8HIVUIVNPRJGKURUO" depends on it; SQL statement:
DROP TABLE IF EXISTS TAB_CHARACTER [90107-214]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:632)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:477)
at org.h2.message.DbException.get(DbException.java:223)
at org.h2.command.ddl.DropTable.prepareDrop(DropTable.java:97)
at org.h2.command.ddl.DropTable.update(DropTable.java:121)
at org.h2.command.CommandContainer.update(CommandContainer.java:169)
at org.h2.command.Command.executeUpdate(Command.java:252)
at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:252)
at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:223)
at org.h2.server.web.WebApp.getResult(WebApp.java:1339)
at org.h2.server.web.WebApp.query(WebApp.java:1137)
at org.h2.server.web.WebApp.query(WebApp.java:1113)
at org.h2.server.web.WebApp.process(WebApp.java:244)
at org.h2.server.web.WebApp.processRequest(WebApp.java:176)
at org.h2.server.web.JakartaWebServlet.doGet(JakartaWebServlet.java:129)
at org.h2.server.web.JakartaWebServlet.doPost(JakartaWebServlet.java:166)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:731)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:223)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:859)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1734)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:1589)
2023-06-14 17:55:42 jdbc[3]: exception
org.h2.jdbc.JdbcSQLSyntaxErrorException: Таблица "CHR_WEAPON" не найдена
Table "CHR_WEAPON" not found; SQL statement:
select w1_0.character_id,w2_0.id,w2_0.name from chr_weapon w1_0 join weapon w2_0 on w2_0.id=w1_0.weapon_id where w1_0.character_id=? [42102-214]
2023-06-14 17:55:45 jdbc[3]: exception
org.h2.jdbc.JdbcSQLSyntaxErrorException: Таблица "CHR_WEAPON" не найдена
Table "CHR_WEAPON" not found; SQL statement:
select w1_0.character_id,w2_0.id,w2_0.name from chr_weapon w1_0 join weapon w2_0 on w2_0.id=w1_0.weapon_id where w1_0.character_id=? [42102-214]
2023-06-14 17:56:03 jdbc[3]: exception
org.h2.jdbc.JdbcSQLSyntaxErrorException: Таблица "CHR_WEAPON" не найдена
Table "CHR_WEAPON" not found; SQL statement:
select w1_0.character_id,w2_0.id,w2_0.name from chr_weapon w1_0 join weapon w2_0 on w2_0.id=w1_0.weapon_id where w1_0.character_id=? [42102-214]
2023-06-14 17:56:05 jdbc[3]: exception
org.h2.jdbc.JdbcSQLSyntaxErrorException: Таблица "CHR_WEAPON" не найдена
Table "CHR_WEAPON" not found; SQL statement:
select w1_0.character_id,w2_0.id,w2_0.name from chr_weapon w1_0 join weapon w2_0 on w2_0.id=w1_0.weapon_id where w1_0.character_id=? [42102-214]
2023-06-16 22:40:04 jdbc[13]: exception
org.h2.jdbc.JdbcSQLSyntaxErrorException: Синтаксическая ошибка в выражении SQL "[*]CHARACTER_RARITY"; ожидалось "COMMIT, CREATE, CALL, CHECKPOINT, COMMENT"
Syntax error in SQL statement "[*]CHARACTER_RARITY"; expected "COMMIT, CREATE, CALL, CHECKPOINT, COMMENT"; SQL statement:
CHARACTER_RARITY [42001-214]

View File

@@ -13,21 +13,14 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration @Configuration
public class WebConfiguration implements WebMvcConfigurer { public class WebConfiguration implements WebMvcConfigurer {
public static final String REST_API = "/api";
@Override @Override
public void addCorsMappings(CorsRegistry registry){ public void addCorsMappings(CorsRegistry registry){
registry.addMapping("/**").allowedMethods("*"); registry.addMapping("/**").allowedMethods("*");
} }
@Override @Override
public void addViewControllers(ViewControllerRegistry registry) { public void addViewControllers(ViewControllerRegistry registry) {
ViewControllerRegistration registration = registry.addViewController("/notFound"); WebMvcConfigurer.super.addViewControllers(registry);
registration.setViewName("forward:/index.html");
registration.setStatusCode(HttpStatus.OK);
}
@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> containerCustomizer(){
return container -> {
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notFound"));
};
} }
} }

View File

@@ -2,12 +2,13 @@ package ru.ulstu.is.sbapp.student.controller;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.sbapp.WebConfiguration;
import ru.ulstu.is.sbapp.student.service.CharacterService; import ru.ulstu.is.sbapp.student.service.CharacterService;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/character") @RequestMapping( WebConfiguration.REST_API + "/character")
public class CharacterController { public class CharacterController {
private final CharacterService characterService; private final CharacterService characterService;

View File

@@ -54,6 +54,18 @@ public class CharacterDto {
public String getImage(){ return image; } public String getImage(){ return image; }
public void setId(long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setImage(String image) {
this.image = image;
}
public List<RarityDto> getRarities(){ return rarities; } public List<RarityDto> getRarities(){ return rarities; }
public List<VisionDto> getVisions(){ return visions; } public List<VisionDto> getVisions(){ return visions; }
public List<WeaponDto> getWeapons(){ return weapons; } public List<WeaponDto> getWeapons(){ return weapons; }

View File

@@ -0,0 +1,196 @@
package ru.ulstu.is.sbapp.student.controller;
import jakarta.validation.Valid;
import org.springframework.ui.Model;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import ru.ulstu.is.sbapp.student.model.*;
import ru.ulstu.is.sbapp.student.model.Character;
import ru.ulstu.is.sbapp.student.service.CharacterService;
import ru.ulstu.is.sbapp.student.service.RarityService;
import ru.ulstu.is.sbapp.student.service.VisionService;
import ru.ulstu.is.sbapp.student.service.WeaponService;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
@Controller
@RequestMapping("/character")
public class CharacterMvcController {
private final CharacterService characterService;
private final VisionService visionService;
private final WeaponService weaponService;
private final RarityService rarityService;
public CharacterMvcController(CharacterService characterService, VisionService visionService, WeaponService weaponService, RarityService rarityService){
this.characterService = characterService;
this.visionService = visionService;
this.weaponService = weaponService;
this.rarityService = rarityService;
}
@GetMapping
public String getCharacters(Model model){
model.addAttribute("characters", characterService.findAllCharacters()
.stream().map(CharacterDto::new).toList());
return "character";
}
@GetMapping(value = "/page/{id}")
public String getCharacter(@PathVariable Long id,
Model model){
Character character = characterService.findCharacter(id);
List<RarityDto> characterRarities = new ArrayList<>();
List<VisionDto> characterVisions = new ArrayList<>();
List<WeaponDto> characterWeapons = new ArrayList<>();
for (CharacterRarity cr : character.getRaritys()){
characterRarities.add(new RarityDto(cr.getRarity()));
}
for (CharacterVision cv : character.getVisions()){
characterVisions.add(new VisionDto(cv.getVision()));
}
for (CharacterWeapon cw : character.getWeapons()){
characterWeapons.add(new WeaponDto(cw.getWeapon()));
}
model.addAttribute("characterId", id);
model.addAttribute("characterDto", new CharacterDto(characterService.findCharacter(id)));
model.addAttribute("characterRarities", characterRarities);
model.addAttribute("characterVisions", characterVisions);
model.addAttribute("characterWeapons", characterWeapons);
return "character-page";
}
@GetMapping(value = {"/edit", "/edit/{id}"})
public String editCharacter(@PathVariable(required = false) Long id,
Model model){
if(id==null||id<=0){
model.addAttribute("characterDto", new CharacterDto());
return "character-edit";
}else{
Character character = characterService.findCharacter(id);
List<RarityDto> rarities = rarityService.findAllRarities()
.stream().map(RarityDto::new).toList();
List<VisionDto> visions = visionService.findAllVisions()
.stream().map(VisionDto::new).toList();
List<WeaponDto> weapons = weaponService.findAllWeapons()
.stream().map(WeaponDto::new).toList();
List<RarityDto> characterRarities = new ArrayList<>();
List<VisionDto> characterVisions = new ArrayList<>();
List<WeaponDto> characterWeapons = new ArrayList<>();
for (CharacterRarity cr : character.getRaritys()){
characterRarities.add(new RarityDto(cr.getRarity()));
}
for (CharacterVision cv : character.getVisions()){
characterVisions.add(new VisionDto(cv.getVision()));
}
for (CharacterWeapon cw : character.getWeapons()){
characterWeapons.add(new WeaponDto(cw.getWeapon()));
}
model.addAttribute("characterId", id);
model.addAttribute("characterDto", new CharacterDto(characterService.findCharacter(id)));
model.addAttribute("characterRarities", characterRarities);
model.addAttribute("characterVisions", characterVisions);
model.addAttribute("characterWeapons", characterWeapons);
model.addAttribute("rarities", rarities);
model.addAttribute("visions", visions);
model.addAttribute("weapons", weapons);
return "character-edit-elements";
}
}
@GetMapping(value = "/search/")
public String searchCharacter(@RequestParam String request, Model model){
List<CharacterDto> characters = characterService.findAllCharacters(request)
.stream().map(CharacterDto::new).toList();
model.addAttribute("characters", characters);
return "character";
}
@PostMapping(value = {"/"})
public String saveCharacter(@PathVariable(required = false) Long id,
@RequestParam("multipartFile") MultipartFile multipartFile,
@ModelAttribute @Valid CharacterDto characterDto,
BindingResult bindingResult,
Model model) throws IOException {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "character-edit";
}
if (id == null || id <= 0) {
characterDto.setImage("data:" + multipartFile.getContentType() + ";base64," + Base64.getEncoder().encodeToString(multipartFile.getBytes()));
characterService.addCharacter(characterDto);
} else {
characterDto.setId(id);
characterDto.setImage("data:" + multipartFile.getContentType() + ";base64," + Base64.getEncoder().encodeToString(multipartFile.getBytes()));
characterService.updateCharacter(characterDto);
}
return "redirect:/character";
}
@PostMapping(value = "/{id}")
public String editCharacter(@PathVariable Long id,
@RequestParam Long rarityId,
@RequestParam Long visionId,
@RequestParam Long weaponId,
Model model){
characterService.addRarity(id, rarityId);
characterService.addVision(id, visionId);
characterService.addWeapon(id, weaponId);
return "redirect:/character/edit/" +id;
}
@PostMapping(value = "/{id}/rarities/delete/{rarityId}")
public String deleteRarities(@PathVariable Long id, @PathVariable Long rarityId, Model model){
Character character = characterService.findCharacter(id);
characterService.removeRarity(id, rarityId);
List<RarityDto> rarities = new ArrayList<>();
for( CharacterRarity cr : character.getRaritys()){
rarities.add(new RarityDto(cr.getRarity()));
}
model.addAttribute("rarities", rarities);
return "redirect:/character";
}
@PostMapping(value = "/{id}/visions/delete/{visionId}")
public String deleteVisions(@PathVariable Long id, @PathVariable Long visionId, Model model){
Character character = characterService.findCharacter(id);
characterService.removeVision(id, visionId);
List<VisionDto> visions = new ArrayList<>();
for( CharacterVision cv : character.getVisions()){
visions.add(new VisionDto(cv.getVision()));
}
model.addAttribute("visions", visions);
return "redirect:/character";
}
@PostMapping(value = "/{id}/weapons/delete/{weaponId}")
public String deleteWeapons(@PathVariable Long id, @PathVariable Long weaponId, Model model){
Character character = characterService.findCharacter(id);
characterService.removeWeapon(id, weaponId);
List<WeaponDto> weapons = new ArrayList<>();
for( CharacterWeapon cw : character.getWeapons()){
weapons.add(new WeaponDto(cw.getWeapon()));
}
model.addAttribute("weapons", weapons);
return "redirect:/character";
}
@PostMapping("/delete/{id}")
public String deleteCharacter(@PathVariable Long id) {
characterService.deleteCharacter(id);
return "redirect:/character";
}
}

View File

@@ -10,6 +10,6 @@ public class CharacterVisionDto {
this.characterId = characterId; this.characterId = characterId;
this.visionId = visionId; this.visionId = visionId;
} }
private Long getCharacter(){ return characterId; } public Long getCharacter(){ return characterId; }
public Long getVision(){ return visionId; } public Long getVision(){ return visionId; }
} }

View File

@@ -1,12 +1,13 @@
package ru.ulstu.is.sbapp.student.controller; package ru.ulstu.is.sbapp.student.controller;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.sbapp.WebConfiguration;
import ru.ulstu.is.sbapp.student.service.RarityService; import ru.ulstu.is.sbapp.student.service.RarityService;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/rarity") @RequestMapping( WebConfiguration.REST_API + "/rarity")
public class RarityController { public class RarityController {
private final RarityService rarityService; private final RarityService rarityService;

View File

@@ -0,0 +1,67 @@
package ru.ulstu.is.sbapp.student.controller;
import jakarta.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.sbapp.student.service.RarityService;
import java.util.List;
@Controller
@RequestMapping("/rarity")
public class RarityMvcController {
private final RarityService rarityService;
public RarityMvcController(RarityService rarityService){
this.rarityService = rarityService;
}
@GetMapping
public String getRarities(Model model){
model.addAttribute("rarities", rarityService.findAllRarities()
.stream().map(RarityDto::new).toList());
return "rarity";
}
@GetMapping(value = {"/edit", "/edit/{id}"})
public String editRarity(@PathVariable(required = false) Long id, Model model){
if (id == null || id <= 0) {
List<RarityDto> rarities = rarityService.findAllRarities().stream()
.map(RarityDto::new)
.toList();
model.addAttribute("rarityDto", new RarityDto());
} else {
model.addAttribute("rarityId", id);
model.addAttribute("rarityDto", new RarityDto(rarityService.findRarity(id)));
}
return "rarity-edit";
}
@PostMapping(value = "/{id}")
public String editRarity(@PathVariable Long id,
@ModelAttribute @Valid RarityDto rarityDto,
BindingResult bindingResult,
Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "rarity-edit";
}
rarityService.updateRarity(id, rarityDto.getName());
return "redirect:/rarity";
}
@PostMapping(value = "/")
public String saveRarity(@RequestParam("name") String name, Model model){
rarityService.addRarity(name);
return "redirect:/rarity";
}
@PostMapping("/delete/{id}")
public String deleteRarity(@PathVariable Long id){
rarityService.deleteRarity(id);
return "redirect:/rarity";
}
}

View File

@@ -1,12 +1,13 @@
package ru.ulstu.is.sbapp.student.controller; package ru.ulstu.is.sbapp.student.controller;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.sbapp.WebConfiguration;
import ru.ulstu.is.sbapp.student.service.VisionService; import ru.ulstu.is.sbapp.student.service.VisionService;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/vision") @RequestMapping( WebConfiguration.REST_API + "/vision")
public class VisionController { public class VisionController {
private final VisionService visionService; private final VisionService visionService;
public VisionController(VisionService visionService) { this.visionService = visionService; } public VisionController(VisionService visionService) { this.visionService = visionService; }

View File

@@ -0,0 +1,67 @@
package ru.ulstu.is.sbapp.student.controller;
import jakarta.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.sbapp.student.service.VisionService;
import java.util.List;
@Controller
@RequestMapping("/vision")
public class VisionMvcController {
private final VisionService visionService;
public VisionMvcController(VisionService visionService){
this.visionService = visionService;
}
@GetMapping
public String getVisions(Model model){
model.addAttribute("visions", visionService.findAllVisions()
.stream().map(VisionDto::new).toList());
return "vision";
}
@GetMapping(value = {"/edit", "/edit/{id}"})
public String editVision(@PathVariable(required = false) Long id, Model model){
if (id == null || id <= 0) {
List<VisionDto> visions = visionService.findAllVisions().stream()
.map(VisionDto::new)
.toList();
model.addAttribute("visionDto", new VisionDto());
} else {
model.addAttribute("visionId", id);
model.addAttribute("visionDto", new VisionDto(visionService.findVision(id)));
}
return "vision-edit";
}
@PostMapping(value = "/{id}")
public String editVision(@PathVariable Long id,
@ModelAttribute @Valid VisionDto visionDto,
BindingResult bindingResult,
Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "vision-edit";
}
visionService.updateVision(id, visionDto.getName());
return "redirect:/vision";
}
@PostMapping(value = "/")
public String saveVision(@RequestParam("name") String name, Model model){
visionService.addVision(name);
return "redirect:/vision";
}
@PostMapping("/delete/{id}")
public String deleteVision(@PathVariable Long id){
visionService.deleteVision(id);
return "redirect:/vision";
}
}

View File

@@ -1,12 +1,13 @@
package ru.ulstu.is.sbapp.student.controller; package ru.ulstu.is.sbapp.student.controller;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.sbapp.WebConfiguration;
import ru.ulstu.is.sbapp.student.service.WeaponService; import ru.ulstu.is.sbapp.student.service.WeaponService;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/weapon") @RequestMapping( WebConfiguration.REST_API + "/weapon")
public class WeaponController { public class WeaponController {
private final WeaponService weaponService; private final WeaponService weaponService;

View File

@@ -0,0 +1,67 @@
package ru.ulstu.is.sbapp.student.controller;
import jakarta.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.sbapp.student.service.WeaponService;
import java.util.List;
@Controller
@RequestMapping("/weapon")
public class WeaponMvcController {
private final WeaponService weaponService;
public WeaponMvcController(WeaponService weaponService){
this.weaponService = weaponService;
}
@GetMapping
public String getWeapons(Model model){
model.addAttribute("weapons", weaponService.findAllWeapons()
.stream().map(WeaponDto::new).toList());
return "weapon";
}
@GetMapping(value = {"/edit", "/edit/{id}"})
public String editWeapon(@PathVariable(required = false) Long id, Model model){
if (id == null || id <= 0) {
List<WeaponDto> weapons = weaponService.findAllWeapons().stream()
.map(WeaponDto::new)
.toList();
model.addAttribute("weaponDto", new WeaponDto());
} else {
model.addAttribute("weaponId", id);
model.addAttribute("weaponDto", new WeaponDto(weaponService.findWeapon(id)));
}
return "weapon-edit";
}
@PostMapping(value = "/{id}")
public String editWeapon(@PathVariable Long id,
@ModelAttribute @Valid WeaponDto weaponDto,
BindingResult bindingResult,
Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "weapon-edit";
}
weaponService.updateWeapon(id, weaponDto.getName());
return "redirect:/weapon";
}
@PostMapping(value = "/")
public String saveWeapon(@RequestParam("name") String name, Model model){
weaponService.addWeapon(name);
return "redirect:/weapon";
}
@PostMapping("/delete/{id}")
public String deleteWeapon(@PathVariable Long id){
weaponService.deleteWeapon(id);
return "redirect:/weapon";
}
}

View File

@@ -0,0 +1,45 @@
package ru.ulstu.is.sbapp.util.error;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import ru.ulstu.is.sbapp.student.service.CharacterNotFoundException;
import ru.ulstu.is.sbapp.student.service.RarityNotFoundException;
import ru.ulstu.is.sbapp.student.service.VisionNotFoundException;
import ru.ulstu.is.sbapp.student.service.WeaponNotFoundException;
import ru.ulstu.is.sbapp.util.validation.ValidationException;
import java.util.stream.Collectors;
@ControllerAdvice
public class AdviceController {
@ExceptionHandler({
CharacterNotFoundException.class,
VisionNotFoundException.class,
WeaponNotFoundException.class,
RarityNotFoundException.class,
ValidationException.class,
IllegalArgumentException.class
})
public ResponseEntity<Object> handleException(Throwable e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler( MethodArgumentNotValidException.class)
public ResponseEntity<Object> handleBindException(MethodArgumentNotValidException e) {
final ValidationException validationException = new ValidationException(
e.getBindingResult().getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.toSet()));
return handleException(validationException);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleUnknownException(Throwable e) {
e.printStackTrace();
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}

View File

@@ -0,0 +1,88 @@
html, body {
background: #6173ab;
}
.btn {
width: 100px;
display: inline;
}
.pictureItem {
width: 150px;
height: 150px;
}
.content {
min-height: calc(100vh - 25.1vh);
background: #7d8eb4;
}
.content_header {
margin: -1.5em -1.5em 0em -1.5em;
background-color: #bdcce5;
}
form input {
max-width: 300px;
}
form select {
max-width: 300px;
}
table tbody tr td {
border: 0px !important;
}
.table {
margin: 0 auto;
}
header {
background: #1a1c20;
}
header a {
color: #c2c2c2;
text-decoration: none;
}
header a:hover {
color: white;
text-decoration: none;
}
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.logo {
width: 380px;
height: 130px;
position: relative; left: 80px;
position: relative; top: 10px;
}
.popular_p {
width: 120px;
height: 120px;
}
#weaponbtn{
width: fit-content;
}
#visionbtn {
width: fit-content;
}
#charbtn{
width: fit-content;
}
#raritybtn{
width: fit-content;
}

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 448 512"><!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->
<path d="M448 48V384c-63.09 22.54-82.34 32-119.5 32c-62.82 0-86.6-32-149.3-32C158.6 384 142.6 387.6 128 392.2v-64C142.6 323.6 158.6 320 179.2 320c62.73 0 86.51 32 149.3 32C348.9 352 364.1 349 384 342.7v-208C364.1 141 348.9 144 328.5 144c-62.82 0-86.6-32-149.3-32C128.4 112 104.3 132.6 64 140.7v307.3C64 465.7 49.67 480 32 480S0 465.7 0 448V63.1C0 46.33 14.33 32 31.1 32S64 46.33 64 63.1V76.66C104.3 68.63 128.4 48 179.2 48c62.73 0 86.51 32 149.3 32C365.7 80 384.9 70.54 448 48z"/>
</svg>

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -0,0 +1,143 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content_header" th:text="'Характеристики персонажа ' + ${id}"></div>
<div layout:fragment="content">
<form action="#" th:action="@{/character/{id}(id=${id})}" th:object="${characterDto}" enctype="multipart/form-data" method="post">
<div class="mb-3">
<label for="multipartFile" class="form-label">Фото</label>
<input type="file" class="form-control" id="multipartFile"
th:name="multipartFile" />
</div>
<div class="mb-3">
<label for="name" class="form-label">Имя</label>
<input type="text" class="form-control" id="name"
th:field="${characterDto.name}" />
</div>
<div class="mb-3">
<label for="rarityList" class="form-label">Редкость</label>
<select th:name="rarityId" id="rarityList" class="form-select">
<option th:each="rarity: ${rarities}"
th:value="${rarity.id}"
th:text="${rarity.name}">
</option>
</select>
</div>
<div class="mb-3">
<label for="visionList" class="form-label">Глаз бога</label>
<select th:name="visionId" id="visionList" class="form-select">
<option th:each="vision: ${visions}"
th:value="${vision.id}"
th:text="${vision.name}">
</option>
</select>
</div>
<div class="mb-3">
<label for="weaponList" class="form-label">Оружие</label>
<select th:name="weaponId" id="weaponList" class="form-select">
<option th:each="weapon: ${weapons}"
th:value="${weapon.id}"
th:text="${weapon.name}">
</option>
</select>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary button-fixed">
<span>Добавить</span>
</button>
<a class="btn btn-secondary button-fixed" th:href="@{/character}">
Назад
</a>
</div>
</form>
<table class="table text-white" id="tbl-rarities">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Редкость</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="item, iterator: ${characterRarities}">
<td th:text="${item.id}"/>
<td th:text="${item.name}"/>
<td>
<div>
<a type="button" class="m-1 btn btn-danger"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${item.id}').click()|">
Удалить
</a>
</div>
<form th:action="@{'/character/' + ${id} + '/rarities/delete/' + ${item.id}}" method="post">
<button th:id="'remove-' + ${item.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
<table class="table text-white" id="tbl-visions">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Глаз бога</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="item, iterator: ${characterVisions}">
<td th:text="${item.id}"/>
<td th:text="${item.name}"/>
<td>
<div>
<a type="button" class="m-1 btn btn-danger"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${item.id}').click()|">
Удалить
</a>
</div>
<form th:action="@{'/character/' + ${id} + '/visions/delete/' + ${item.id}}" method="post">
<button th:id="'remove-' + ${item.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
<table class="table text-white" id="tbl-weapons">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Оружие</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="item, iterator: ${characterWeapons}">
<td th:text="${item.id}"/>
<td th:text="${item.name}"/>
<td>
<div>
<a type="button" class="m-1 btn btn-danger"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${item.id}').click()|">
Удалить
</a>
</div>
<form th:action="@{'/character/' + ${id} + '/weapons/delete/' + ${item.id}}" method="post">
<button th:id="'remove-' + ${item.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content_header">Создание персонажа</div>
<div layout:fragment="content">
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/character/{id}(id=${id})}" th:object="${characterDto}"
enctype="multipart/form-data" method="post">
<div class="mb-3">
<label for="multipartFile" class="form-label">Фото</label>
<input type="file" class="form-control" id="multipartFile"
th:name="multipartFile" required="true"/>
</div>
<div class="mb-3">
<label for="name" class="form-label">Имя</label>
<input type="text" class="form-control" id="name"
th:field="${characterDto.name}" required="true" />
</div>
<div class="mb-3">
<label for="rarityid" class="invisible form-label">Редкость</label>
<select id="rarityid" class="invisible form-select" th:name="rarityid">
<option th:each="value: ${rarities}"
th:value="${value.id}"
th:text="${value.name}">
</option>
</select>
<label for="visionid" class="invisible form-label">ГБ</label>
<select id="visionid" class="invisible form-select" th:name="visionid">
<option th:each="value: ${visions}"
th:value="${value.id}"
th:text="${value.name}">
</option>
</select>
<label for="weaponid" class="invisible form-label">Оружие</label>
<select id="weaponid" class="invisible form-select" th:name="weaponid">
<option th:each="value: ${weapons}"
th:value="${value.id}"
th:text="${value.name}">
</option>
</select>
</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="@{/character}">
Назад
</a>
</div>
</form>
</div>
</body>
</html>

View File

@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en"
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 layout:fragment="content_header" th:text="'Информация о персонаже ' + ${id}"></div>
<div layout:fragment="content">
<div id="character-info-div" class="justify-content-center bg-light text-dark border border-0 rounded-2 container gap-5 d-flex flex-row">
<img id="character-image" th:src="${characterDto.image}" class="character m-5 d-flex ms-3 justify-content-center" />
<div class="p-5 text-center">
<p id="character-name" class="fw-bolder fs-5 ps-2" th:text="'Имя: ' + ${characterDto.name}"></p>
<p class="fw-bolder fs-5 ps-2">Какая-то информация о персонаже.</p>
<div class="mb-3">
<a class="btn btn-secondary button-fixed" th:href="@{/character}">
Назад
</a>
</div>
</div>
</div>
<div class="justify-content-center bg-light text-danger text-center border border-0 rounded-2 container gap-5 d-flex flex-column">
<table class="table w-50" id="tbl-rarities">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Редкость</th>
</tr>
</thead>
<tbody>
<tr th:each="item, iterator: ${characterRarities}">
<td th:text="${item.id}"/>
<td th:text="${item.name}"/>
</tr>
</tbody>
</table>
<table class="table w-50" id="tbl-visions">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Глаз бога</th>
</tr>
</thead>
<tbody>
<tr th:each="item, iterator: ${characterVisions}">
<td th:text="${item.id}"/>
<td th:text="${item.name}"/>
</tr>
</tbody>
</table>
<table class="table w-50" id="tbl-weapons">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Оружие</th>
</tr>
</thead>
<tbody>
<tr th:each="item, iterator: ${characterWeapons}">
<td th:text="${item.id}"/>
<td th:text="${item.name}"/>
</tr>
</tbody>
</table>
</div>
</div>
</body>
<th:block layout:fragment="scripts">
<script type="module">
</script>
</th:block>
</html>

View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content_header" th:text="'Редкости персонажа'"></div>
<div layout:fragment="content">
<form action="#" th:action="@{/character/{id}(id=${id})}" method="post">
<div class="mb-3">
<label for="rarity" class="form-label">Редкость</label>
<select id="rarity" class="form-select" th:name="rarity" required="true">
<option th:each="value: ${rarities}"
th:value="${value.id}"
th:text="${value.name}">
</option>
</select>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary button-fixed">
<span>Добавить</span>
</button>
<a class="btn btn-secondary button-fixed" th:href="@{/character}">
Назад
</a>
</div>
</form>
</div>
</body>
</html>

View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content_header" th:text="'ГБ персонажа'"></div>
<div layout:fragment="content">
<form action="#" th:action="@{/character/{id}(id=${id})}" method="post">
<div class="mb-3">
<label for="vision" class="form-label">Глаз бога</label>
<select id="vision" class="form-select" th:name="vision" required="true">
<option th:each="value: ${visions}"
th:value="${value.id}"
th:text="${value.name}">
</option>
</select>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary button-fixed">
<span>Добавить</span>
</button>
<a class="btn btn-secondary button-fixed" th:href="@{/character}">
Назад
</a>
</div>
</form>
</div>
</body>
</html>

View File

@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content_header" th:text="'Оружие персонажа'"></div>
<div layout:fragment="content">
<form action="#" th:action="@{/character/{id}(id=${id})}" method="post">
<div class="mb-3">
<label for="weapon" class="form-label">Оружие</label>
<select id="weapon" class="form-select" th:name="weapon" required="true">
<option th:each="value: ${weapons}"
th:value="${value.id}"
th:text="${value.name}">
</option>
</select>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary button-fixed">
<span>Добавить</span>
</button>
<a class="btn btn-secondary button-fixed" th:href="@{/character}">
Назад
</a>
</div>
</form>
<table class="table text-white" id="tbl-weapons">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Название</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="item, iterator: ${characterWeapons}">
<td th:text="${item.key.id}"/>
<td th:text="${item.key.name}"/>
<td th:text="${item.value}"/>
<td>
<div>
<a type="button" class="m-1 btn btn-danger"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${item.key.id}').click()|">
Удалить
</a>
</div>
<form th:action="@{'/character/' + ${id} + '/weapons/delete/' + ${item.key.id}}" method="post">
<button th:id="'remove-' + ${item.key.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div layout:fragment="content_header">Персонажи</div>
<div layout:fragment="content">
<div class="d-flex justify-content-between align-items-center">
<form action="#" th:action="@{/character/search/}" class="d-flex">
<input class="form-control m-1" type="text" name="request" placeholder="Введите имя..." required="true"/>
<button class="btn btn-primary m-1" type="submit">Найти</button>
</form>
<div class="d-flex justify-content-around">
<a type="button" class="btn btn-success m-1"
th:href="@{/character/edit}">
Добавить персонажа
</a>
</div>
</div>
<hr class="border border-0 bg-white"/>
<div class="m-3 container d-flex flex-wrap justify-content-around" id="tbl-items">
<div class="bg-white p-2 text-primary border border-0 rounded-4 mb-2 d-flex flex-wrap justify-content-around"
th:each="character, iterator: ${characters}">
<img class="pictureItem me-3 border border-0 rounded-2" th:src="${character.image}" alt="${character.name}" align="left"/>
<ul class="list-unstyled">
<li class="text-decoration-none" th:text="${character.id}"></li>
<li class="text-decoration-none">
<a class="text-primary" th:href="@{/character/page/{id}(id=${character.id})}" th:text="${character.name}"></a>
</li>
<li class="text-decoration-none">
<a type="button" class="m-1 btn btn-secondary" th:href="@{/character/edit/{id}(id=${character.id})}">
Изменить
</a>
</li>
<li>
<a type="button" class="m-1 btn btn-danger"
th:attr="onclick=|confirm('Удалить персонажа?') && document.getElementById('remove-${character.id}').click()|">
Удалить
</a>
<form th:action="@{/character/delete/{id}(id=${character.id})}" method="post">
<button th:id="'remove-' + ${character.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</li>
</ul>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="ru"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>Genshin Impact Wiki</title>
<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>
<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="d-flex flex-column h-100 text-white">
<header class="fw-bold fs-5">
<nav class="navbar navbar-expand-lg navbar-light bg-light" aria-label="Eleventh navbar example">
<div class="container-fluid">
<a class="navbar-brand" href="#">Genshin Impact Wiki</a>
<div class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="/">Главная</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Регистрация</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/h2-console/" target="_blank">Консоль H2</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container rounded my-5 p-4 content">
<div class="content_header rounded-top p-2 mb-2">
<h1 class="fs-1 fw-bold text-white ms-5">
<div layout:fragment="content_header">
</div>
</h1>
</div>
<div layout:fragment="content">
</div>
</div>
</body>
<th:block layout:fragment="scripts">
</th:block>
</html>

View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content">
<div><span th:text="${error}"></span></div>
<a href="/">На главную</a>
</div>
</body>
</html>

View File

@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content_header">Главная</div>
<div layout:fragment="content">
<div class="container d-grid gap-5 mt-1 d-flex flex-row justify-content-center" id="blocks">
<div class="container ms-5 mt-5 col-2 d-grid row-5 gap-2 bg-white fw-bold border border-0 rounded-4 justify-content-center" id="links">
<a id="weaponbtn" class="btn btn-primary bg-gradient opacity-75 btn-lg border border-0 rounded-4 align-self-center text-decoration-none text-white fw-bold h-50 w-100" href="/weapon">Оружие</a>
<a id="charbtn" class="btn btn-primary bg-gradient opacity-75 btn-lg border border-0 rounded-4 align-self-center text-decoration-none text-white fw-bold h-50 w-100" href="/character">Персонажи</a>
<a id="raritybtn" class="btn btn-primary bg-gradient opacity-75 btn-lg border border-0 rounded-4 align-self-center text-decoration-none text-white fw-bold h-50 w-100" href='/rarity'>Редкости</a>
<a id="visionbtn" class="btn btn-primary bg-gradient opacity-75 btn-lg border border-0 rounded-4 align-self-center text-decoration-none text-white fw-bold h-50 w-100" href='/vision'>Глаза бога</a>
</div>
<div class="col-5 mt-5 ms-5 me-5 bg-white border border-0 rounded-4" id="main_desc"><img class="logo" src="/logo.jpg" />
<p class="p-3 fw-bold text-primary pt-4 fs-4">Genshin Impact -- компьютерная игра в жанре action-adventure с открытым миром и элементами RPG, разработанная китайской компанией miHoYo Limited. Вас ждёт захватывающее однопользовательское приключение, где вы станете гостем из другого мира в поисках потерянного родного человека. Разгадайте тайны Тейвата и самого себя.</p>
</div>
<div class="col col-lg-2 ms-2 d-grid gap-2 col-2 mx-auto mt-5 offset-md-3 bg-white row row-cols-2 text-wrap text-center mx-5 px-3 border border-0 rounded-4" id="popular_pages">
<h2 class="float-center fs-4 fw-bold text-primary">Популярные страницы</h2>
<div class="text-wrap" id="popular_pics"><a href="/character"><img class="popular_p float-center" src="/xiao_wbgr.jpg" /></a><a href="/weapon"><img class="popular_p float-center" src="/spear.jpg" /></a><img class="popular_p float-center" src="/kinovarka_wbgr.jpg" /></div>
</div>
</div>
<div class="bg-white mt-5 d-flex allign-items-center justify-content-center" id="official_site"><a class="text-decoration-none fw-bold text-primary fs-4" href="https://genshin.hoyoverse.com/ru/home">Официальный сайт</a></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content_header" th:text="'Редкость'"></div>
<div layout:fragment="content">
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/rarity/{id}(id=${id})}" th:object="${rarityDto}" method="post">
<div class="mb-3">
<label for="name" class="form-label">Название</label>
<input type="text" class="form-control" id="name" th:field="${rarityDto.name}"
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="@{/rarity}">
Назад
</a>
</div>
</form>
</div>
</body>
</html>

View File

@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content_header" th:text="'Редкости'"></div>
<div layout:fragment="content">
<div class="d-flex justify-content-end">
<a class="btn btn-success button-fixed"
th:href="@{/rarity/edit}">
Добавить
</a>
</div>
<table class="table text-white" id="tbl-items">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Название</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="rarity, iterator: ${rarities}">
<td th:text="${rarity.id}"/>
<td th:text="${rarity.name}"/>
<td>
<div>
<a type="button" class="m-1 btn btn-primary" th:href="@{/rarity/edit/{id}(id=${rarity.id})}">
Изменить
</a>
<a type="button" class="m-1 btn btn-danger"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${rarity.id}').click()|">
Удалить
</a>
</div>
<form th:action="@{/rarity/delete/{id}(id=${rarity.id})}" method="post">
<button th:id="'remove-' + ${rarity.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content_header" th:text="'Глаз бога'"></div>
<div layout:fragment="content">
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/vision/{id}(id=${id})}" th:object="${visionDto}" method="post">
<div class="mb-3">
<label for="name" class="form-label">Название</label>
<input type="text" class="form-control" id="name" th:field="${visionDto.name}"
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="@{/vision}">
Назад
</a>
</div>
</form>
</div>
</body>
</html>

View File

@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content_header" th:text="'Глаза бога'"></div>
<div layout:fragment="content">
<div class="d-flex justify-content-end">
<a class="btn btn-success button-fixed"
th:href="@{/vision/edit}">
Добавить
</a>
</div>
<table class="table text-white" id="tbl-items">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Название</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="vision, iterator: ${visions}">
<td th:text="${vision.id}"/>
<td th:text="${vision.name}"/>
<td>
<div>
<a type="button" class="m-1 btn btn-primary" th:href="@{/vision/edit/{id}(id=${vision.id})}">
Изменить
</a>
<a type="button" class="m-1 btn btn-danger"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${vision.id}').click()|">
Удалить
</a>
</div>
<form th:action="@{/vision/delete/{id}(id=${vision.id})}" method="post">
<button th:id="'remove-' + ${vision.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content_header" th:text="'Оружие'"></div>
<div layout:fragment="content">
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/weapon/{id}(id=${id})}" th:object="${weaponDto}" method="post">
<div class="mb-3">
<label for="name" class="form-label">Название</label>
<input type="text" class="form-control" id="name" th:field="${weaponDto.name}"
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="@{/weapon}">
Назад
</a>
</div>
</form>
</div>
</body>
</html>

View File

@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content_header" th:text="'Оружие'"></div>
<div layout:fragment="content">
<div class="d-flex justify-content-end">
<a class="btn btn-success button-fixed"
th:href="@{/weapon/edit}">
Добавить
</a>
</div>
<table class="table text-white" id="tbl-items">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Название</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="weapon, iterator: ${weapons}">
<td th:text="${weapon.id}"/>
<td th:text="${weapon.name}"/>
<td>
<div>
<a type="button" class="m-1 btn btn-primary" th:href="@{/weapon/edit/{id}(id=${weapon.id})}">
Изменить
</a>
<a type="button" class="m-1 btn btn-danger"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${weapon.id}').click()|">
Удалить
</a>
</div>
<form th:action="@{/weapon/delete/{id}(id=${weapon.id})}" method="post">
<button th:id="'remove-' + ${weapon.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>