done (not)

This commit is contained in:
Калышев Ян 2023-06-19 09:14:36 +04:00
parent 42800e0fbe
commit 361337b5d0
66 changed files with 2156 additions and 1308 deletions

View File

@ -51,7 +51,7 @@ public class SecurityConfiguration {
.logout().permitAll()
.and()
.exceptionHandling().accessDeniedPage("/login");
http.formLogin().defaultSuccessUrl("/index", true);
http.formLogin().defaultSuccessUrl("/categories", true);
return http.userDetailsService(userService).build();
}

View File

@ -1,65 +0,0 @@
package com.kalyshev.yan.cabinet.controller;
import com.kalyshev.yan.WebConfiguration;
import com.kalyshev.yan.cabinet.service.CabinetService;
import com.kalyshev.yan.computer.controller.ComputerDto;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(WebConfiguration.REST_API + "/cabinet")
public class CabinetController {
private final CabinetService cabinetService;
public CabinetController(CabinetService cabinetService) {
this.cabinetService = cabinetService;
}
@GetMapping("/{id}")
public CabinetDto getCabinet(@PathVariable Long id) {
return new CabinetDto(cabinetService.findCabinet(id));
}
@GetMapping("/")
public List<CabinetDto> getCabinets() {
return cabinetService.findAllCabinets().stream()
.map(CabinetDto::new)
.toList();
}
@GetMapping("/{id}/computers")
public List<ComputerDto> getCabinetComputers(@PathVariable Long id) {
return cabinetService.listComputersFromCabinet(id).stream()
.map(ComputerDto::new)
.toList();
}
@GetMapping("/filter")
public List<CabinetDto> getFilteredCabinets(@RequestParam(value = "id", required = false) Long id,
@RequestParam(value = "number", required = false) String number) {
return cabinetService.findFilteredCabinets(id, number).stream()
.map(CabinetDto::new)
.toList();
}
@PostMapping("/")
public CabinetDto createCabinet(@RequestBody @Valid CabinetDto cabinetDto) {
return new CabinetDto(cabinetService.addCabinet(cabinetDto.getNumber()));
}
@PostMapping("/{id}/computer")
public void createCabinetComputer(@PathVariable Long id,
@RequestParam("computerId") Long computerId) {
cabinetService.addComputerToCabinet(computerId, id);
}
@PutMapping("/{id}")
public CabinetDto updateCabinet(@PathVariable Long id,
@RequestBody @Valid CabinetDto cabinetDto) {
return new CabinetDto(cabinetService.updateCabinet(id, cabinetDto.getNumber()));
}
@DeleteMapping("/{id}")
public CabinetDto deleteCabinet(@PathVariable Long id) {
return new CabinetDto(cabinetService.deleteCabinet(id));
}
@DeleteMapping("/{cabinetId}/computer")
public void deleteCabinetComputer(@PathVariable Long cabinetId,
@RequestParam("computerId") Long computerId) {
cabinetService.deleteComputerFromCabinet(computerId, cabinetId);
}
}

View File

@ -1,33 +0,0 @@
package com.kalyshev.yan.cabinet.controller;
import com.kalyshev.yan.cabinet.model.Cabinet;
import com.kalyshev.yan.computer.model.Computer;
import java.util.ArrayList;
import java.util.List;
public class CabinetDto {
private Long id;
private String number;
private List<Long> computerIds;
public CabinetDto() {}
public CabinetDto(Cabinet cabinet) {
this.id = cabinet.getId();
this.number = cabinet.getNumber();
if (cabinet.getComputers() == null) {
this.computerIds = new ArrayList<>();
} else {
this.computerIds = new ArrayList<>();
List<Computer> computers = cabinet.getComputers();
for (Computer computer : computers) {
computerIds.add(computer.getId());
}
}
}
public Long getId() { return this.id; }
public void setId(Long id) { this.id = id; }
public String getNumber() { return this.number; }
public void setNumber(String number) { this.number = number; }
public List<Long> getComputerIds() { return this.computerIds; }
public void setComputerIds(List<Long> computerIds) { this.computerIds = computerIds; }
}

View File

@ -1,83 +0,0 @@
package com.kalyshev.yan.cabinet.controller;
import com.kalyshev.yan.cabinet.service.CabinetService;
import jakarta.validation.Valid;
import com.kalyshev.yan.computer.controller.ComputerDto;
import com.kalyshev.yan.computer.service.ComputerService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/index")
public class CabinetMvcController {
private final CabinetService cabinetService;
private final ComputerService computerService;
public CabinetMvcController(CabinetService cabinetService,
ComputerService computerService) {
this.cabinetService = cabinetService;
this.computerService = computerService;
}
@GetMapping
public String getCabinets(Model model) {
model.addAttribute("cabinets",
cabinetService.findAllCabinets().stream()
.map(CabinetDto::new)
.toList());
return "index";
}
@GetMapping(value = {"/edit", "/edit/{id}"})
public String editCabinet(@PathVariable(required = false) Long id,
Model model) {
if (id == null || id <= 0) {
model.addAttribute("cabinetDto", new CabinetDto());
} else {
model.addAttribute("cabinetId", id);
model.addAttribute("cabinetDto", new CabinetDto(cabinetService.findCabinet(id)));
}
model.addAttribute("computers",
computerService.findFilteredComputers(null, null, null, null, id).stream()
.map(ComputerDto::new)
.toList());
model.addAttribute("allComputers",
computerService.findAllComputers().stream()
.map(ComputerDto::new)
.toList());
return "cabinet-edit";
}
@PostMapping(value = {"", "/{id}"})
public String saveCabinet(@PathVariable(required = false) Long id,
@ModelAttribute @Valid CabinetDto cabinetDto,
BindingResult bindingResult,
Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "cabinet-edit";
}
if (id == null || id <= 0) {
cabinetService.addCabinet(cabinetDto.getNumber());
} else {
cabinetService.updateCabinet(id, cabinetDto.getNumber());
}
return "redirect:/index";
}
@PostMapping(value = "/{id}/computer/{computerId}")
public String addCabinetComputer(@PathVariable(value = "id") Long id,
@PathVariable(value = "computerId") Long computerId) {
cabinetService.addComputerToCabinet(computerId, id);
return "redirect:/index";
}
@PostMapping(value = "/{id}/computerDelete/{computerId}")
public String deleteCabinetComputer(@PathVariable(value = "id") Long id,
@PathVariable(value = "computerId") Long computerId) {
cabinetService.deleteComputerFromCabinet(computerId, id);
return "redirect:/index";
}
@PostMapping("/delete/{id}")
public String deleteCabinet(@PathVariable Long id) {
cabinetService.deleteCabinet(id);
return "redirect:/index";
}
}

View File

@ -1,70 +0,0 @@
package com.kalyshev.yan.cabinet.model;
import com.kalyshev.yan.computer.model.Computer;
import jakarta.persistence.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Entity
@Table(name = "cabinet")
public class Cabinet {
@Id
@GeneratedValue
private Long id;
private String number;
@OneToMany(cascade = {CascadeType.MERGE})
private List<Computer> computers;
public Cabinet() {
}
public Cabinet(String number) {
this.number = number;
}
public Long getId() {
return id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public List<Computer> getComputers() {
return computers;
}
public void addComputer(Computer computer){
if (computers == null){
this.computers = new ArrayList<>();
}
if (!computers.contains(computer)) {
this.computers.add(computer);
computer.setCabinet(this);
}
}
public void removeComputer(Computer computer){
if (computers.contains(computer))
this.computers.remove(computer);
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Cabinet cabinet))
return false;
return Objects.equals(id, cabinet.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return "Cabinet{" +
"id=" + id +
", number='" + number + '\'' +
'}';
}
}

View File

@ -1,7 +0,0 @@
package com.kalyshev.yan.cabinet.repository;
public class CabinetNotFoundException extends RuntimeException {
public CabinetNotFoundException(Long id) {
super(String.format("Cabinet with id [%s] is not found", id));
}
}

View File

@ -1,15 +0,0 @@
package com.kalyshev.yan.cabinet.repository;
import com.kalyshev.yan.cabinet.model.Cabinet;
import com.kalyshev.yan.monitor.model.Monitor;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface CabinetRepository extends JpaRepository<Cabinet, Long> {
@Query(value = "select s from Cabinet s where (s.id = :id or :id is Null) and (s.number = :number or :number is Null)")
public List<Cabinet> findFilteredCabinets(@Param("id") Long id,
@Param("number") String number);
}

View File

@ -1,105 +0,0 @@
package com.kalyshev.yan.cabinet.service;
import com.kalyshev.yan.cabinet.model.Cabinet;
import com.kalyshev.yan.cabinet.repository.CabinetNotFoundException;
import com.kalyshev.yan.cabinet.repository.CabinetRepository;
import com.kalyshev.yan.computer.model.Computer;
import com.kalyshev.yan.computer.service.ComputerService;
import com.kalyshev.yan.util.validation.ValidatorUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@Service
public class CabinetService {
private final CabinetRepository cabinetRepository;
private final ComputerService computerService;
private final ValidatorUtil validatorUtil;
public CabinetService(CabinetRepository cabinetRepository,
ComputerService computerService,
ValidatorUtil validatorUtil) {
this.cabinetRepository = cabinetRepository;
this.computerService = computerService;
this.validatorUtil = validatorUtil;
}
@Transactional
public Cabinet addCabinet(String number) {
if (!StringUtils.hasText(number)) {
throw new IllegalArgumentException("Cabinet number is null or empty");
}
final Cabinet cabinet = new Cabinet(number);
validatorUtil.validate(cabinet);
return cabinetRepository.save(cabinet);
}
@Transactional(readOnly = true)
public Cabinet findCabinet(Long id) {
final Optional<Cabinet> cabinet = cabinetRepository.findById(id);
return cabinet.orElseThrow(() -> new CabinetNotFoundException(id));
}
@Transactional(readOnly = true)
public List<Cabinet> findFilteredCabinets(Long id, String number) {
return cabinetRepository.findFilteredCabinets(id, number);
}
@Transactional(readOnly = true)
public List<Cabinet> findAllCabinets() {
return cabinetRepository.findAll();
}
@Transactional
public Cabinet updateCabinet(Long id, String number) {
if (!StringUtils.hasText(number)) {
throw new IllegalArgumentException("Cabinet number is null or empty");
}
final Cabinet currentCabinet = findCabinet(id);
currentCabinet.setNumber(number);
validatorUtil.validate(currentCabinet);
return cabinetRepository.save(currentCabinet);
}
@Transactional
public Cabinet deleteCabinet(Long id) {
final Cabinet currentCabinet = findCabinet(id);
computerService.deleteRelationsWithCabinets(currentCabinet.getComputers());
cabinetRepository.delete(currentCabinet);
return currentCabinet;
}
@Transactional
public void deleteAllCabinets() {
cabinetRepository.deleteAll();
}
@Transactional
public List<Computer> listComputersFromCabinet(Long id) {
if ((Object)id == null) {
throw new IllegalArgumentException("Cabinet id is null or empty");
}
return findCabinet(id).getComputers();
}
@Transactional
public void addComputerToCabinet(Long computerId, Long cabinetId) {
if ((Object)computerId == null) {
throw new IllegalArgumentException("Computer id is null or empty");
}
if ((Object)cabinetId == null) {
throw new IllegalArgumentException("Cabinet id is null or empty");
}
final Computer computer = computerService.findComputer(computerId);
final Cabinet cabinet = findCabinet(cabinetId);
cabinet.addComputer(computer);
}
@Transactional
public void deleteComputerFromCabinet(Long computerId, Long cabinetId) {
if ((Object) computerId == null) {
throw new IllegalArgumentException("Computer id is null or empty");
}
if ((Object) cabinetId == null) {
throw new IllegalArgumentException("Cabinet id is null or empty");
}
final Computer computer = computerService.findComputer(computerId);
final Cabinet cabinet = findCabinet(cabinetId);
cabinet.removeComputer(computer);
computer.setCabinet(null);
}
}

View File

@ -0,0 +1,51 @@
package com.kalyshev.yan.category.controller;
import com.kalyshev.yan.WebConfiguration;
import com.kalyshev.yan.category.service.CategoryService;
import com.kalyshev.yan.video.service.VideoService;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(WebConfiguration.REST_API + "/category")
public class CategoryController {
private final CategoryService categoryService;
private final VideoService videoService;
public CategoryController(CategoryService categoryService,
VideoService videoService) {
this.categoryService = categoryService;
this.videoService = videoService;
}
@GetMapping("/{id}")
public CategoryDto getCategory(@PathVariable Long id) {
return new CategoryDto(categoryService.findCategory(id));
}
@GetMapping("/")
public List<CategoryDto> getCategories() {
return categoryService.findAllCategories().stream()
.map(CategoryDto::new)
.toList();
}
@GetMapping("/filter")
public List<CategoryDto> getFilteredCategories(@RequestParam(value = "id", required = false) Long id,
@RequestParam(value = "name", required = false) String name) {
return categoryService.findFilteredCategories(id, name).stream()
.map(CategoryDto::new)
.toList();
}
@PostMapping("/")
public CategoryDto createMonitor(@RequestBody @Valid CategoryDto categoryDto) {
return new CategoryDto(categoryService.addCategory(categoryDto.getName()));
}
@PutMapping("/{id}")
public CategoryDto updateMonitor(@PathVariable Long id,
@RequestBody @Valid CategoryDto categoryDto) {
return new CategoryDto(categoryService.updateCategory(id, categoryDto.getName()));
}
@DeleteMapping("/{id}")
public CategoryDto deleteMonitor(@PathVariable Long id) {
return new CategoryDto(categoryService.deleteCategory(id));
}
}

View File

@ -0,0 +1,35 @@
package com.kalyshev.yan.category.controller;
import com.kalyshev.yan.cabinet.model.Cabinet;
import com.kalyshev.yan.category.model.Category;
import com.kalyshev.yan.computer.model.Computer;
import com.kalyshev.yan.video.model.Video;
import java.util.ArrayList;
import java.util.List;
public class CategoryDto {
private Long id;
private String name;
private List<Long> videoIds;
public CategoryDto() {}
public CategoryDto(Category category) {
this.id = category.getId();
this.name = category.getName();
if (category.getVideos() == null) {
this.videoIds = new ArrayList<>();
} else {
this.videoIds = new ArrayList<>();
List<Video> videos = category.getVideos();
for (Video video : videos) {
videoIds.add(video.getId());
}
}
}
public Long getId() { return this.id; }
public void setId(Long id) { this.id = id; }
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
public List<Long> getVideoIds() { return this.videoIds; }
public void setVideoIds(List<Long> videoIds) { this.videoIds = videoIds; }
}

View File

@ -0,0 +1,98 @@
package com.kalyshev.yan.category.controller;
import com.kalyshev.yan.category.model.Category;
import com.kalyshev.yan.category.service.CategoryService;
import com.kalyshev.yan.video.controller.VideoDto;
import com.kalyshev.yan.video.service.VideoService;
import jakarta.servlet.http.HttpServletRequest;
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.*;
@Controller
@RequestMapping("/categories")
public class CategoryMvcController {
private final CategoryService categoryService;
private final VideoService videoService;
public CategoryMvcController(CategoryService categoryService,
VideoService videoService) {
this.categoryService = categoryService;
this.videoService = videoService;
}
@GetMapping(value = {"", "/"})
public String getCategories(Model model) {
model.addAttribute("categories",
categoryService.findAllCategories().stream()
.map(CategoryDto::new)
.toList());
return "categories";
}
@GetMapping(value = {"/filter/", "/filter"})
public String getFilteredCategories(@RequestParam(value = "id", required = false) Long id,
Model model) {
model.addAttribute("categories",
categoryService.findFilteredCategories().stream()
.map(CategoryDto::new)
.toList());
return "categories";
}
@GetMapping(value = {"/edit/", "/edit/{id}"})
public String editCategory(@PathVariable(required = false) Long id,
Model model) {
if (id == null || id <= 0) {
model.addAttribute("categoryDto", new CategoryDto());
} else {
model.addAttribute("categoryId", id);
model.addAttribute("categoryDto", new CategoryDto(categoryService.findCategory(id)));
model.addAttribute("videos",
categoryService.listVideosFromCategory(id).stream()
.map(VideoDto::new)
.toList());
}
model.addAttribute("allVideos",
videoService.findAllVideos().stream()
.map(VideoDto::new)
.toList());
return "category-edit";
}
@PostMapping(value = {"", "/", "/{id}"})
public String saveCategory(@PathVariable(required = false) Long id,
@ModelAttribute @Valid CategoryDto categoryDto,
BindingResult bindingResult,
Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "category-edit";
}
if (id == null || id <= 0) {
categoryService.addCategory(categoryDto.getName());
} else {
categoryService.updateCategory(id, categoryDto.getName());
}
return "redirect:/categories";
}
@PostMapping("/delete/{id}")
public String deleteCategory(@PathVariable Long id) {
categoryService.deleteCategory(id);
return "redirect:/categories";
}
@PostMapping(value = "/{id}/video/{videoId}")
public String addCategoryVideo(@PathVariable(value = "id") Long id,
@PathVariable(value = "videoId") Long videoId,
HttpServletRequest request) {
categoryService.addVideoToCategory(id, videoId);
String referer = request.getHeader("Referer");
return "redirect:"+ referer;
}
@GetMapping(value = "/{id}/videoDelete/{videoId}")
public String deleteCategoryVideo(@PathVariable(value = "id") Long id,
@PathVariable(value = "videoId") Long videoId,
HttpServletRequest request) {
categoryService.deleteVideoFromCategory(id, videoId);
String referer = request.getHeader("Referer");
return "redirect:"+ referer;
}
}

View File

@ -0,0 +1,71 @@
package com.kalyshev.yan.category.model;
import com.kalyshev.yan.video.model.Video;
import jakarta.persistence.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Entity
@Table(name = "category")
public class Category {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToMany(cascade = {CascadeType.MERGE})
private List<Video> videos;
public Category() {
}
public Category(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Video> getVideos() {
return videos;
}
public void addVideo(Video video){
if (videos == null){
this.videos = new ArrayList<>();
}
if (!videos.contains(video)) {
this.videos.add(video);
video.addCategory(this);
}
}
public void removeVideo(Video video){
if (videos.contains(video))
this.videos.remove(video);
video.removeCategory(this);
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Category category))
return false;
return Objects.equals(id, category.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return "Video{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}

View File

@ -0,0 +1,7 @@
package com.kalyshev.yan.category.repository;
public class CategoryNotFoundException extends RuntimeException {
public CategoryNotFoundException(Long id) {
super(String.format("Category with id [%s] is not found", id));
}
}

View File

@ -0,0 +1,17 @@
package com.kalyshev.yan.category.repository;
import com.kalyshev.yan.category.model.Category;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import javax.management.monitor.Monitor;
import java.util.List;
public interface CategoryRepository extends JpaRepository<Category, Long> {
@Query(value = "select * from Category where (\"ID\" = :id or :id is Null) and " +
"(\"NAME\" = :name or :name is Null)", nativeQuery = true)
public List<Category> findFilteredCategories(@Param("id") Long id,
@Param("name") String name);
}

View File

@ -0,0 +1,136 @@
package com.kalyshev.yan.category.service;
import com.kalyshev.yan.category.repository.CategoryRepository;
import com.kalyshev.yan.category.model.Category;
import com.kalyshev.yan.category.repository.CategoryNotFoundException;
import com.kalyshev.yan.playlist.model.Playlist;
import com.kalyshev.yan.util.validation.ValidatorUtil;
import com.kalyshev.yan.video.model.Video;
import com.kalyshev.yan.video.service.VideoService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Optional;
@Service
public class CategoryService {
private final CategoryRepository categoryRepository;
private final VideoService videoService;
private final ValidatorUtil validatorUtil;
public CategoryService(CategoryRepository categoryRepository,
VideoService videoService,
ValidatorUtil validatorUtil) {
this.categoryRepository = categoryRepository;
this.videoService = videoService;
this.validatorUtil = validatorUtil;
}
@Transactional
public Category addCategory(String name) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Category model name is null or empty");
}
final Category category = new Category(name);
validatorUtil.validate(category);
return categoryRepository.save(category);
}
@Transactional(readOnly = true)
public Category findCategory(Long id) {
final Optional<Category> category = categoryRepository.findById(id);
return category.orElseThrow(() -> new CategoryNotFoundException(id));
}
@Transactional(readOnly = true)
public List<Category> findAllCategories() {
return categoryRepository.findAll();
}
@Transactional(readOnly = true)
public List<Category> findFilteredCategories(Long id, String name) {
return categoryRepository.findFilteredCategories(id, name);
}
@Transactional
public Category updateCategory(Long id, String name) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Category name is null or empty");
}
final Category currentCategory = findCategory(id);
currentCategory.setName(name);
validatorUtil.validate(currentCategory);
return categoryRepository.save(currentCategory);
}
@Transactional
public Category deleteCategory(Long id) {
Category category = categoryRepository.findById(id).orElseThrow(() -> new CategoryNotFoundException(id));
categoryRepository.delete(category);
return category;
}
@Transactional
public void deleteAllCategories() { categoryRepository.deleteAll(); }
@Transactional
public List<Video> listVideosFromCategory(Long id) {
if (id == null) {
throw new IllegalArgumentException("Category id is null or empty");
}
return findCategory(id).getVideos();
}
@Transactional
public Category addVideoToCategory(Long categoryId, Long videoId) {
if (videoId == null) {
throw new IllegalArgumentException("Video id is null or empty");
}
if (categoryId == null) {
throw new IllegalArgumentException("Category id is null or empty");
}
final Video video = videoService.findVideo(videoId);
final Category category = findCategory(categoryId);
category.addVideo(video);
return category;
}
@Transactional
public Category deleteVideoFromCategory(Long categoryId, Long videoId) {
if (videoId == null) {
throw new IllegalArgumentException("Video id is null or empty");
}
if (categoryId == null) {
throw new IllegalArgumentException("Category id is null or empty");
}
final Video video = videoService.findVideo(videoId);
final Category category = findCategory(categoryId);;
category.removeVideo(video);
return category;
}
@Transactional
public List<Category> listCategoriesFromVideo(Long id) {
if (id == null) {
throw new IllegalArgumentException("Video id is null or empty");
}
return videoService.findVideo(id).getCategories();
}
@Transactional
public Video addCategoryToVideo(Long videoId, Long categoryId) {
if ((Object)videoId == null) {
throw new IllegalArgumentException("Video id is null or empty");
}
if ((Object)categoryId == null) {
throw new IllegalArgumentException("Category id is null or empty");
}
final Video video = videoService.findVideo(videoId);
final Category category = findCategory(categoryId);
video.addCategory(category);
return video;
}
@Transactional
public Video deleteCategoryFromVideo(Long videoId, Long categoryId) {
if (videoId == null) {
throw new IllegalArgumentException("Video id is null or empty");
}
if (categoryId == null) {
throw new IllegalArgumentException("Category id is null or empty");
}
final Video video = videoService.findVideo(videoId);
final Category category = findCategory(categoryId);
video.removeCategory(category);
return video;
}
}

View File

@ -0,0 +1,67 @@
package com.kalyshev.yan.comment.controller;
import com.kalyshev.yan.WebConfiguration;
import com.kalyshev.yan.category.controller.CategoryDto;
import com.kalyshev.yan.category.model.Category;
import com.kalyshev.yan.category.service.CategoryService;
import com.kalyshev.yan.comment.service.CommentService;
import com.kalyshev.yan.playlist.controller.PlaylistDto;
import com.kalyshev.yan.playlist.model.Playlist;
import com.kalyshev.yan.playlist.service.PlaylistService;
import com.kalyshev.yan.user.model.User;
import com.kalyshev.yan.user.service.UserService;
import com.kalyshev.yan.util.validation.ValidatorUtil;
import com.kalyshev.yan.video.controller.VideoDto;
import com.kalyshev.yan.video.model.Video;
import com.kalyshev.yan.video.repository.VideoNotFoundException;
import com.kalyshev.yan.video.repository.VideoRepository;
import com.kalyshev.yan.video.service.VideoService;
import jakarta.validation.Valid;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping(WebConfiguration.REST_API + "/comment")
public class CommentController {
private final CommentService commentService;
public CommentController(CommentService commentService) {
this.commentService = commentService;
}
@GetMapping("/{id}")
public CommentDto getComment(@PathVariable Long id) {
return new CommentDto(commentService.findComment(id));
}
@GetMapping("/")
public List<CommentDto> getComments() {
return commentService.findAllComments().stream()
.map(CommentDto::new)
.toList();
}
// @GetMapping("/filter")
// public List<VideoDto> getFilteredVideos(@RequestParam(value = "id", required = false) Long id,
// @RequestParam(value = "name", required = false) String name,
// @RequestParam(value = "date", required = false) LocalDate date,
// @RequestParam(value = "userId", required = false) Long monitorId) {
// return videoService.findFilteredVideos(id, name, date, monitorId).stream()
// .map(VideoDto::new)
// .toList();
// }
@PostMapping("/")
public CommentDto createPlaylist(@RequestBody @Valid CommentDto commentDto) {
return new CommentDto(commentService.addComment(commentDto.getComment(), commentDto.getUserId(), commentDto.getVideoId()));
}
@PutMapping("/{id}")
public CommentDto updateComment(@PathVariable Long id,
@RequestBody @Valid CommentDto commentDto) {
return new CommentDto(commentService.updateComment(id, commentDto.getComment()));
}
@DeleteMapping("/{id}")
public CommentDto deleteComment(@PathVariable Long id) {
return new CommentDto(commentService.deleteComment(id));
}
}

View File

@ -0,0 +1,31 @@
package com.kalyshev.yan.comment.controller;
import com.kalyshev.yan.category.model.Category;
import com.kalyshev.yan.comment.model.Comment;
import com.kalyshev.yan.comment.service.CommentService;
import com.kalyshev.yan.video.model.Video;
import java.util.ArrayList;
import java.util.List;
public class CommentDto {
private Long id;
private String comment;
private Long videoId;
private Long userId;
public CommentDto() {}
public CommentDto(Comment comment) {
this.id = comment.getId();
this.comment = comment.getComment();
this.videoId = comment.getVideo().getId();
this.userId = comment.getUser().getId();
}
public Long getId() { return this.id; }
public void setId(Long id) { this.id = id; }
public String getComment() { return this.comment; }
public void setComment(String comment) { this.comment = comment; }
public Long getVideoId() { return this.videoId; }
public void setVideoId(Long videoId) { this.videoId = videoId; }
public Long getUserId() { return this.userId; }
public void setUserId(Long userId) { this.userId = userId; }
}

View File

@ -0,0 +1,72 @@
package com.kalyshev.yan.comment.controller;
import com.kalyshev.yan.category.controller.CategoryDto;
import com.kalyshev.yan.category.service.CategoryService;
import com.kalyshev.yan.comment.service.CommentService;
import com.kalyshev.yan.user.model.User;
import com.kalyshev.yan.user.service.UserService;
import com.kalyshev.yan.video.controller.VideoDto;
import com.kalyshev.yan.video.service.VideoService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/comments")
public class CommentMvcService {
private final CommentService commentService;
private final UserService userService;
private final VideoService videoService;
public CommentMvcService(CommentService commentService,
VideoService videoService,
UserService userService) {
this.commentService = commentService;
this.userService = userService;
this.videoService = videoService;
}
@GetMapping(value = {"", "/"})
public String getComments(Model model) {
model.addAttribute("comments",
commentService.findAllComments().stream()
.map(CommentDto::new)
.toList());
return "comments";
}
@GetMapping(value = {"/edit/", "/edit/{id}"})
public String editComment(@PathVariable(required = false) Long id,
Model model) {
if (id == null || id <= 0) {
model.addAttribute("commentDto", new CommentDto());
} else {
model.addAttribute("commentId", id);
model.addAttribute("commentDto", new CommentDto(commentService.findComment(id)));
}
return "comment-edit";
}
@PostMapping(value = {"", "/", "/{id}"})
public String saveComment(@PathVariable(required = false) Long id,
@ModelAttribute @Valid CommentDto commentDto,
BindingResult bindingResult,
Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "comment-edit";
}
User user = userService.findByLogin(SecurityContextHolder.getContext().getAuthentication().getName());
if (id == null || id <= 0) {
commentService.addComment(commentDto.getComment(), user.getId(), commentDto.getVideoId());
} else {
commentService.updateComment(id, commentDto.getComment());
}
return "redirect:/comments";
}
@PostMapping("/delete/{id}")
public String deleteComment(@PathVariable Long id) {
commentService.deleteComment(id);
return "redirect:/comments";
}
}

View File

@ -0,0 +1,75 @@
package com.kalyshev.yan.comment.model;
import com.kalyshev.yan.user.model.User;
import com.kalyshev.yan.video.model.Video;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import java.util.Objects;
@Entity
@Table(name = "comment")
public class Comment {
@Id
@GeneratedValue
private Long id;
@NotNull
private String comment;
@NotNull
@ManyToOne(cascade = {CascadeType.MERGE})
private User user;
@NotNull
@ManyToOne(cascade = {CascadeType.REMOVE})
private Video video;
public Comment() {
}
public Comment(String comment, User user, Video video) {
this.comment = comment;
this.user = user;
this.video = video;
}
public Long getId() {
return id;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Video getVideo() {
return video;
}
public void setVideo(Video video) {
this.video = video;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Comment comment))
return false;
return Objects.equals(id, comment.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return "Comment{" +
"id=" + id +
", comment='" + comment + '\'' +
", user='" + user + '\'' +
", video='" + video + '\'' +
'}';
}
}

View File

@ -0,0 +1,7 @@
package com.kalyshev.yan.comment.repository;
public class CommentNotFoundException extends RuntimeException {
public CommentNotFoundException(Long id) {
super(String.format("Comment with id [%s] is not found", id));
}
}

View File

@ -0,0 +1,7 @@
package com.kalyshev.yan.comment.repository;
import com.kalyshev.yan.comment.model.Comment;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CommentRepository extends JpaRepository<Comment, Long> {
}

View File

@ -0,0 +1,84 @@
package com.kalyshev.yan.comment.service;
import com.kalyshev.yan.playlist.model.Playlist;
import com.kalyshev.yan.user.model.User;
import com.kalyshev.yan.user.service.UserService;
import com.kalyshev.yan.util.validation.ValidatorUtil;
import com.kalyshev.yan.comment.model.Comment;
import com.kalyshev.yan.comment.repository.CommentNotFoundException;
import com.kalyshev.yan.comment.repository.CommentRepository;
import com.kalyshev.yan.video.model.Video;
import com.kalyshev.yan.video.service.VideoService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Optional;
@Service
public class CommentService {
private final CommentRepository commentRepository;
private final UserService userService;
private final VideoService videoService;
private final ValidatorUtil validatorUtil;
public CommentService(CommentRepository commentRepository,
VideoService videoService,
UserService userService,
ValidatorUtil validatorUtil) {
this.commentRepository = commentRepository;
this.userService = userService;
this.videoService = videoService;
this.validatorUtil = validatorUtil;
}
@Transactional
public Comment addComment(String comment, Long userId, Long videoId) {
if (!StringUtils.hasText(comment)) {
throw new IllegalArgumentException("Comment comment is null or empty");
}
if (userId == null) {
throw new IllegalArgumentException("Comment userId is null or empty");
}
if (videoId == null) {
throw new IllegalArgumentException("Comment videoId is null or empty");
}
User user = userService.findUser(userId);
Video video = videoService.findVideo(videoId);
final Comment curcomment = new Comment(comment, user, video);
validatorUtil.validate(curcomment);
return commentRepository.save(curcomment);
}
@Transactional(readOnly = true)
public Comment findComment(Long id) {
final Optional<Comment> comment = commentRepository.findById(id);
return comment.orElseThrow(() -> new CommentNotFoundException(id));
}
@Transactional(readOnly = true)
public List<Comment> findAllComments() {
return commentRepository.findAll();
}
// @Transactional(readOnly = true)
// public List<Comment> findFilteredComments(Long id, String modelName, String serialNum, Long monitorId, Long cabinetId) {
// return commentRepository.findFilteredComments(id, modelName, serialNum, monitorId, cabinetId);
// }
@Transactional
public Comment updateComment(Long id, String comment) {
if (!StringUtils.hasText(comment)) {
throw new IllegalArgumentException("Comment value is null or empty");
}
final Comment currentComment = findComment(id);
currentComment.setComment(comment);
validatorUtil.validate(currentComment);
return commentRepository.save(currentComment);
}
@Transactional
public Comment deleteComment(Long id) {
final Comment currentComment = findComment(id);
commentRepository.delete(currentComment);
return currentComment;
}
@Transactional
public void deleteAllComments() {
commentRepository.deleteAll();
}
}

View File

@ -1,56 +0,0 @@
package com.kalyshev.yan.computer.controller;
import com.kalyshev.yan.WebConfiguration;
import com.kalyshev.yan.computer.service.ComputerService;
import com.kalyshev.yan.monitor.controller.MonitorDto;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(WebConfiguration.REST_API + "/computer")
public class ComputerController {
private final ComputerService computerService;
public ComputerController(ComputerService computerService) {
this.computerService = computerService;
}
@GetMapping("/{id}")
public ComputerDto getStudent(@PathVariable Long id) {
return new ComputerDto(computerService.findComputer(id));
}
@GetMapping("/")
public List<ComputerDto> getComputers() {
return computerService.findAllComputers().stream()
.map(ComputerDto::new)
.toList();
}
@GetMapping("/filter")
public List<ComputerDto> getFilteredComputers(@RequestParam(value = "id", required = false) Long id,
@RequestParam(value = "modelName", required = false) String modelName,
@RequestParam(value = "serialNum", required = false) String serialNum,
@RequestParam(value = "monitorId", required = false) Long monitorId,
@RequestParam(value = "cabinetId", required = false) Long cabinetId) {
return computerService.findFilteredComputers(id, modelName, serialNum, monitorId, cabinetId).stream()
.map(ComputerDto::new)
.toList();
}
@PostMapping("/")
public ComputerDto createComputer(@RequestBody @Valid ComputerDto computerDto) {
return new ComputerDto(computerService.addComputer(computerDto.getModelName(), computerDto.getSerialNum(), computerDto.getMonitorId()));
}
@PostMapping("/{id}/monitor")
public MonitorDto setMonitorComputer(@PathVariable Long id,
@RequestParam("monitorId") Long monitorId) {
return new MonitorDto(computerService.setMonitor(monitorId, id));
}
@PutMapping("/{id}")
public ComputerDto updateComputer(@PathVariable Long id,
@RequestBody @Valid ComputerDto computerDto) {
return new ComputerDto(computerService.updateComputer(id, computerDto.getModelName(), computerDto.getSerialNum(), computerDto.getMonitorId(), computerDto.getCabinetId()));
}
@DeleteMapping("/{id}")
public ComputerDto deleteComputer(@PathVariable Long id) {
return new ComputerDto(computerService.deleteComputer(id));
}
}

View File

@ -1,44 +0,0 @@
package com.kalyshev.yan.computer.controller;
import com.kalyshev.yan.computer.model.Computer;
public class ComputerDto {
private Long id;
private String modelName;
private String serialNum;
private Long monitorId;
private String monitorModelName;
private Long cabinetId;
private String cabinetNumber;
public ComputerDto() {}
public ComputerDto(Computer computer) {
this.id = computer.getId();
this.modelName = computer.getModelName();
this.serialNum = computer.getSerialNum();
if (computer.getMonitor() == null) {
this.monitorId = null;
this.monitorModelName = "";
} else {
this.monitorId = computer.getMonitor().getId();
this.monitorModelName = computer.getMonitor().getModelName();
}
if (computer.getCabinet() == null) {
this.cabinetId = null;
this.cabinetNumber = "";
} else {
this.cabinetId = computer.getCabinet().getId();
this.cabinetNumber = computer.getCabinet().getNumber();
}
}
public Long getId() { return this.id; }
public String getModelName() { return this.modelName; }
public void setModelName(String modelName) { this.modelName = modelName; }
public String getSerialNum() { return this.serialNum; }
public void setSerialNum(String serialNum) { this.serialNum = serialNum; }
public Long getMonitorId() { return this.monitorId; }
public void setMonitorId(Long monitorId) { this.monitorId = monitorId; }
public Long getCabinetId() { return this.cabinetId; }
public void setCabinetId(Long cabinetId) { this.cabinetId = cabinetId; }
public String getMonitorModelName() { return this.monitorModelName; }
public String getCabinetNumber() { return this.cabinetNumber; }
}

View File

@ -1,66 +0,0 @@
package com.kalyshev.yan.computer.controller;
import com.kalyshev.yan.cabinet.controller.CabinetDto;
import com.kalyshev.yan.cabinet.service.CabinetService;
import com.kalyshev.yan.computer.service.ComputerService;
import com.kalyshev.yan.monitor.service.MonitorService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
@Controller
@RequestMapping("/computers")
public class ComputerMvcController {
private final ComputerService computerService;
private final MonitorService monitorService;
public ComputerMvcController(ComputerService computerService,
MonitorService monitorService) {
this.computerService = computerService;
this.monitorService = monitorService;
}
@GetMapping
public String getComputers(Model model) {
model.addAttribute("computers",
computerService.findAllComputers().stream()
.map(ComputerDto::new)
.toList());
return "computers";
}
@GetMapping(value = {"/edit", "/edit/{id}"})
public String editComputer(@PathVariable(required = false) Long id,
Model model) {
if (id == null || id <= 0) {
model.addAttribute("computerDto", new ComputerDto());
} else {
model.addAttribute("computerId", id);
model.addAttribute("computerDto", new ComputerDto(computerService.findComputer(id)));
}
model.addAttribute("monitors",
monitorService.findAllMonitors());
return "computer-edit";
}
@PostMapping(value = {"", "/{id}"})
public String saveComputer(@PathVariable(required = false) Long id,
@ModelAttribute @Valid ComputerDto computerDto,
BindingResult bindingResult,
Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "computer-edit";
}
if (id == null || id <= 0) {
computerService.addComputer(computerDto.getModelName(), computerDto.getSerialNum(), computerDto.getMonitorId());
} else {
computerService.updateComputer(id, computerDto.getModelName(), computerDto.getSerialNum(), computerDto.getMonitorId(), computerDto.getCabinetId());
}
return "redirect:/computers";
}
@PostMapping("/delete/{id}")
public String deleteComputer(@PathVariable Long id) {
computerService.deleteComputer(id);
return "redirect:/computers";
}
}

View File

@ -1,80 +0,0 @@
package com.kalyshev.yan.computer.model;
import com.kalyshev.yan.cabinet.model.Cabinet;
import com.kalyshev.yan.monitor.model.Monitor;
import jakarta.persistence.*;
import java.util.Objects;
@Entity
@Table(name = "computer")
public class Computer {
@Id
@GeneratedValue
private Long id;
private String modelName;
private String serialNum;
@ManyToOne( cascade = {CascadeType.MERGE}, fetch = FetchType.EAGER)
@JoinColumn(name = "cabinet", nullable = true)
private Cabinet cabinet;
@OneToOne(cascade = {CascadeType.MERGE})
@JoinColumn(name = "monitor_id")
private Monitor monitor;
public Computer() {
}
public Computer(String modelName, String serialNum) {
this.modelName = modelName;
this.serialNum = serialNum;
}
public Long getId() {
return id;
}
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public String getSerialNum() {
return serialNum;
}
public void setSerialNum(String serialNum) { this.serialNum = serialNum; }
public Cabinet getCabinet() {
return cabinet;
}
public void setCabinet(Cabinet cabinet) { this.cabinet = cabinet; }
public Monitor getMonitor() {
return monitor;
}
public void setMonitor(Monitor monitor) {
this.monitor = monitor;
}
public Monitor removeMonitor() {
Monitor temp = this.monitor;
this.monitor = null;
return temp;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Computer computer))
return false;
return Objects.equals(id, computer.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return "Computer{" +
"id=" + id +
", modelName='" + modelName + '\'' +
", serialNum='" + serialNum + '\'' +
'}';
}
}

View File

@ -1,7 +0,0 @@
package com.kalyshev.yan.computer.repository;
public class ComputerNotFoundException extends RuntimeException {
public ComputerNotFoundException(Long id) {
super(String.format("Computer with id [%s] is not found", id));
}
}

View File

@ -1,34 +0,0 @@
package com.kalyshev.yan.computer.repository;
import com.kalyshev.yan.computer.model.Computer;
import com.kalyshev.yan.monitor.model.Monitor;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.Collection;
import java.util.List;
public interface ComputerRepository extends JpaRepository<Computer, Long> {
@Query(value = "select * from Computer where (\"ID\" = :id or :id is Null) and " +
"(\"MODEL_NAME\" = :modelName or :modelName is Null) and " +
"(\"SERIAL_NUM\" = :serialNum or :serialNum is Null) and " +
"(\"MONITOR_ID\" = :monitorId or :monitorId is Null) and " +
"(\"CABINET\" = :cabinetId or :cabinetId is Null)", nativeQuery = true)
public List<Computer> findFilteredComputers(@Param("id") Long id,
@Param("modelName") String modelName,
@Param("serialNum") String serialNum,
@Param("monitorId") Long monitorId,
@Param("cabinetId") Long cabinetId);
@Query(value = "select * from Computer where \"MONITOR_ID\" = :monitorId", nativeQuery = true)
public Computer findComputerByMonitor(@Param("monitorId") Long monitorId);
@Modifying
@Query(value = "update Computer set \"MONITOR_ID\" = null", nativeQuery = true)
public void removeAllComputerMonitorRelations();
// @Query(value = "update Computer where id in :computerIds set cabinet_id = null")
// public void deleteRelationsWithCabinets(@Param("computerIds") Collection<Long> computerIds);
}

View File

@ -1,135 +0,0 @@
package com.kalyshev.yan.computer.service;
import com.kalyshev.yan.cabinet.model.Cabinet;
import com.kalyshev.yan.computer.model.Computer;
import com.kalyshev.yan.computer.repository.ComputerNotFoundException;
import com.kalyshev.yan.computer.repository.ComputerRepository;
import com.kalyshev.yan.monitor.model.Monitor;
import com.kalyshev.yan.monitor.service.MonitorService;
import com.kalyshev.yan.util.validation.ValidatorUtil;
import jakarta.validation.constraints.Null;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.*;
@Service
public class ComputerService {
private final ComputerRepository computerRepository;
private final MonitorService monitorService;
private final ValidatorUtil validatorUtil;
public ComputerService(ComputerRepository computerRepository,
MonitorService monitorService,
ValidatorUtil validatorUtil) {
this.computerRepository = computerRepository;
this.monitorService = monitorService;
this.validatorUtil = validatorUtil;
}
@Transactional
public Computer addComputer(String modelName, String serialNum, @Null Long monitorId) {
if (!StringUtils.hasText(modelName)) {
throw new IllegalArgumentException("Computer model name is null or empty");
}
if (!StringUtils.hasText(serialNum)) {
throw new IllegalArgumentException("Computer serial number is null or empty");
}
final Computer computer = new Computer(modelName, serialNum);
if (monitorId != null) {
final Monitor monitor = monitorService.findMonitor(monitorId);
computer.setMonitor(monitor);
}
validatorUtil.validate(computer);
return computerRepository.save(computer);
}
@Transactional(readOnly = true)
public Computer findComputer(Long id) {
final Optional<Computer> computer = computerRepository.findById(id);
return computer.orElseThrow(() -> new ComputerNotFoundException(id));
}
@Transactional(readOnly = true)
public List<Computer> findAllComputers() {
return computerRepository.findAll();
}
@Transactional(readOnly = true)
public List<Computer> findFilteredComputers(Long id, String modelName, String serialNum, Long monitorId, Long cabinetId) {
return computerRepository.findFilteredComputers(id, modelName, serialNum, monitorId, cabinetId);
}
@Transactional
public Computer updateComputer(Long id, String modelName, String serialNum, Long monitorId, Long cabinetId) {
if (!(StringUtils.hasText(modelName) || StringUtils.hasText(serialNum))) {
throw new IllegalArgumentException("Need at least one argument");
}
final Computer currentComputer = findComputer(id);
if (modelName != null) {
currentComputer.setModelName(modelName);
}
if (serialNum != null) {
currentComputer.setSerialNum(serialNum);
}
if (monitorId != null) {
final Monitor monitor = monitorService.findMonitor(monitorId);
currentComputer.setMonitor(monitor);
}
validatorUtil.validate(currentComputer);
return computerRepository.save(currentComputer);
}
@Transactional
public Computer deleteComputer(Long id) {
final Computer currentComputer = findComputer(id);
Cabinet currentComputerCabinet = currentComputer.getCabinet();
if (currentComputerCabinet != null) {
currentComputerCabinet.removeComputer(currentComputer);
}
computerRepository.delete(currentComputer);
return currentComputer;
}
@Transactional
public void deleteAllComputers() {
List<Computer> computers = findAllComputers();
for (Computer computer : computers) {
deleteComputer(computer.getId());
}
}
@Transactional
public Monitor setMonitor(Long monitorId, Long computerId) {
if ((Object)computerId == null) {
throw new IllegalArgumentException("Computer id is null or empty");
}
if ((Object)monitorId == null) {
throw new IllegalArgumentException("Monitor id is null or empty");
}
final Computer computer = findComputer(computerId);
final Monitor monitor = monitorService.findMonitor(monitorId);
computer.setMonitor(monitor);
return monitor;
}
@Transactional
public void deleteRelationsWithCabinets(List<Computer> computers) {
for (Computer computer: computers) {
computer.setCabinet(null);
}
}
@Transactional
public Computer findComputerByMonitor(Monitor monitor) {
if (monitor.getId() == null) {
return null;
}
return computerRepository.findComputerByMonitor(monitor.getId());
}
@Transactional
public Monitor deleteMonitorWithRelation(Long id) {
final Monitor currentMonitor = monitorService.findMonitor(id);
Computer computer = findComputerByMonitor(currentMonitor);
if (computer != null) {
computer.removeMonitor();
}
monitorService.deleteMonitor(currentMonitor);
return currentMonitor;
}
@Transactional
public void deleteAllMonitorsWithRelations() {
computerRepository.removeAllComputerMonitorRelations();
monitorService.deleteAllMonitors();
}
}

View File

@ -1,51 +0,0 @@
package com.kalyshev.yan.monitor.controller;
import com.kalyshev.yan.WebConfiguration;
import com.kalyshev.yan.computer.service.ComputerService;
import com.kalyshev.yan.monitor.service.MonitorService;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(WebConfiguration.REST_API + "/monitor")
public class MonitorController {
private final MonitorService monitorService;
private final ComputerService computerService;
public MonitorController(MonitorService monitorService,
ComputerService computerService) {
this.monitorService = monitorService;
this.computerService = computerService;
}
@GetMapping("/{id}")
public MonitorDto getMonitor(@PathVariable Long id) {
return new MonitorDto(monitorService.findMonitor(id));
}
@GetMapping("/")
public List<MonitorDto> getMonitors() {
return monitorService.findAllMonitors().stream()
.map(MonitorDto::new)
.toList();
}
@GetMapping("/filter")
public List<MonitorDto> getFilteredmonitors(@RequestParam(value = "id", required = false) Long id,
@RequestParam(value = "modelName", required = false) String modelName) {
return monitorService.findFilteredMonitors(id, modelName).stream()
.map(MonitorDto::new)
.toList();
}
@PostMapping("/")
public MonitorDto createMonitor(@RequestBody @Valid MonitorDto monitorDto) {
return new MonitorDto(monitorService.addMonitor(monitorDto.getModelName()));
}
@PutMapping("/{id}")
public MonitorDto updateMonitor(@PathVariable Long id,
@RequestBody @Valid MonitorDto monitorDto) {
return new MonitorDto(monitorService.updateMonitor(id, monitorDto.getModelName()));
}
@DeleteMapping("/{id}")
public MonitorDto deleteMonitor(@PathVariable Long id) {
return new MonitorDto(computerService.deleteMonitorWithRelation(id));
}
}

View File

@ -1,23 +0,0 @@
package com.kalyshev.yan.monitor.controller;
import com.kalyshev.yan.monitor.model.Monitor;
public class MonitorDto {
private Long id;
private String modelName;
public MonitorDto() {
}
public MonitorDto(Monitor monitor) {
this.id = monitor.getId();
this.modelName = monitor.getModelName();
}
public Long getId() {
return id;
}
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
}

View File

@ -1,62 +0,0 @@
package com.kalyshev.yan.monitor.controller;
import com.kalyshev.yan.cabinet.controller.CabinetDto;
import com.kalyshev.yan.cabinet.service.CabinetService;
import com.kalyshev.yan.computer.service.ComputerService;
import com.kalyshev.yan.monitor.model.Monitor;
import com.kalyshev.yan.monitor.service.MonitorService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
@Controller
@RequestMapping("/monitors")
public class MonitorMvcController {
private final MonitorService monitorService;
public MonitorMvcController(MonitorService monitorService) {
this.monitorService = monitorService;
}
@GetMapping
public String getMonitors(Model model) {
model.addAttribute("monitors",
monitorService.findAllMonitors().stream()
.map(MonitorDto::new)
.toList());
return "monitors";
}
@GetMapping(value = {"/edit", "/edit/{id}"})
public String editMonitor(@PathVariable(required = false) Long id,
Model model) {
if (id == null || id <= 0) {
model.addAttribute("monitorDto", new MonitorDto());
} else {
model.addAttribute("monitorId", id);
model.addAttribute("monitorDto", new MonitorDto(monitorService.findMonitor(id)));
}
return "monitor-edit";
}
@PostMapping(value = {"", "/{id}"})
public String saveComputer(@PathVariable(required = false) Long id,
@ModelAttribute @Valid MonitorDto monitorDto,
BindingResult bindingResult,
Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "monitor-edit";
}
if (id == null || id <= 0) {
monitorService.addMonitor(monitorDto.getModelName());
} else {
monitorService.updateMonitor(id, monitorDto.getModelName());
}
return "redirect:/monitors";
}
@PostMapping("/delete/{id}")
public String deleteComputer(@PathVariable Long id) {
monitorService.deleteMonitor(monitorService.findMonitor(id));
return "redirect:/monitors";
}
}

View File

@ -1,47 +0,0 @@
package com.kalyshev.yan.monitor.model;
import jakarta.persistence.*;
import java.util.Objects;
@Entity
@Table(name = "monitor")
public class Monitor {
@Id
@GeneratedValue
private Long id;
private String modelName;
public Monitor() {
}
public Monitor(String modelName) {
this.modelName = modelName;
}
public Long getId() {
return id;
}
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Monitor monitor))
return false;
return Objects.equals(id, monitor.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return "Monitor{" +
"id=" + id +
", modelName='" + modelName + '\'' +
'}';
}
}

View File

@ -1,7 +0,0 @@
package com.kalyshev.yan.monitor.repository;
public class MonitorNotFoundException extends RuntimeException {
public MonitorNotFoundException(Long id) {
super(String.format("Monitor with id [%s] is not found", id));
}
}

View File

@ -1,15 +0,0 @@
package com.kalyshev.yan.monitor.repository;
import com.kalyshev.yan.monitor.model.Monitor;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface MonitorRepository extends JpaRepository<Monitor, Long> {
@Query(value = "select * from Monitor where (\"ID\" = :id or :id is Null) and " +
"(\"MODEL_NAME\" = :modelName or :modelName is Null)", nativeQuery = true)
public List<Monitor> findFilteredMonitors(@Param("id") Long id,
@Param("modelName") String modelName);
}

View File

@ -1,63 +0,0 @@
package com.kalyshev.yan.monitor.service;
import com.kalyshev.yan.monitor.model.Monitor;
import com.kalyshev.yan.monitor.repository.MonitorNotFoundException;
import com.kalyshev.yan.monitor.repository.MonitorRepository;
import com.kalyshev.yan.util.validation.ValidatorUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@Service
public class MonitorService {
private final MonitorRepository monitorRepository;
private final ValidatorUtil validatorUtil;
public MonitorService(MonitorRepository monitorRepository,
ValidatorUtil validatorUtil) {
this.monitorRepository = monitorRepository;
this.validatorUtil = validatorUtil;
}
@Transactional
public Monitor addMonitor(String modelName) {
if (!StringUtils.hasText(modelName)) {
throw new IllegalArgumentException("Monitor model name is null or empty");
}
final Monitor monitor = new Monitor(modelName);
validatorUtil.validate(monitor);
return monitorRepository.save(monitor);
}
@Transactional(readOnly = true)
public Monitor findMonitor(Long id) {
final Optional<Monitor> monitor = monitorRepository.findById(id);
return monitor.orElseThrow(() -> new MonitorNotFoundException(id));
}
@Transactional(readOnly = true)
public List<Monitor> findAllMonitors() {
return monitorRepository.findAll();
}
@Transactional(readOnly = true)
public List<Monitor> findFilteredMonitors(Long id, String modelName) {
return monitorRepository.findFilteredMonitors(id, modelName);
}
@Transactional
public Monitor updateMonitor(Long id, String modelName) {
if (!StringUtils.hasText(modelName)) {
throw new IllegalArgumentException("Monitor model name is null or empty");
}
final Monitor currentMonitor = findMonitor(id);
currentMonitor.setModelName(modelName);
validatorUtil.validate(currentMonitor);
return monitorRepository.save(currentMonitor);
}
@Transactional
public void deleteMonitor(Monitor monitor) {
monitorRepository.delete(monitor);
}
@Transactional
public void deleteAllMonitors() { monitorRepository.deleteAll(); }
}

View File

@ -0,0 +1,80 @@
package com.kalyshev.yan.playlist.controller;
import com.kalyshev.yan.WebConfiguration;
import com.kalyshev.yan.category.controller.CategoryDto;
import com.kalyshev.yan.category.model.Category;
import com.kalyshev.yan.category.service.CategoryService;
import com.kalyshev.yan.playlist.model.Playlist;
import com.kalyshev.yan.playlist.service.PlaylistService;
import com.kalyshev.yan.user.model.User;
import com.kalyshev.yan.user.service.UserService;
import com.kalyshev.yan.util.validation.ValidatorUtil;
import com.kalyshev.yan.video.controller.VideoDto;
import com.kalyshev.yan.video.model.Video;
import com.kalyshev.yan.video.repository.VideoNotFoundException;
import com.kalyshev.yan.video.repository.VideoRepository;
import com.kalyshev.yan.video.service.VideoService;
import jakarta.validation.Valid;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping(WebConfiguration.REST_API + "/playlist")
public class PlaylistController {
private final PlaylistService playlistService;
public PlaylistController(PlaylistService playlistService) {
this.playlistService = playlistService;
}
@GetMapping("/{id}")
public PlaylistDto getPlaylist(@PathVariable Long id) {
return new PlaylistDto(playlistService.findPlaylist(id));
}
@GetMapping("/")
public List<PlaylistDto> getVideos() {
return playlistService.findAllPlaylists().stream()
.map(PlaylistDto::new)
.toList();
}
// @GetMapping("/filter")
// public List<VideoDto> getFilteredVideos(@RequestParam(value = "id", required = false) Long id,
// @RequestParam(value = "name", required = false) String name,
// @RequestParam(value = "date", required = false) LocalDate date,
// @RequestParam(value = "userId", required = false) Long monitorId) {
// return videoService.findFilteredVideos(id, name, date, monitorId).stream()
// .map(VideoDto::new)
// .toList();
// }
@PostMapping("/")
public PlaylistDto createPlaylist(@RequestBody @Valid PlaylistDto playlistDto) {
return new PlaylistDto(playlistService.addPlaylist(playlistDto.getName(), playlistDto.getUserId()));
}
@PutMapping("/{id}")
public PlaylistDto updatePlaylist(@PathVariable Long id,
@RequestBody @Valid PlaylistDto playlistDto) {
return new PlaylistDto(playlistService.updatePlaylist(id, playlistDto.getName()));
}
@DeleteMapping("/{id}")
public PlaylistDto deletePlaylist(@PathVariable Long id) {
return new PlaylistDto(playlistService.deletePlaylist(id));
}
@GetMapping("/{id}/videos")
public List<VideoDto> getPlaylistVideos(@PathVariable Long id) {
return playlistService.listVideosFromPlaylist(id).stream()
.map(VideoDto::new)
.toList();
}
@PostMapping("/{id}/video")
public PlaylistDto addPlaylistVideo(@PathVariable Long id,
@RequestParam("videoId") Long videoId) {
return new PlaylistDto(playlistService.addVideoToPlaylist(id, videoId));
}
@DeleteMapping("/{id}/video/{videoId}")
public PlaylistDto deletePlaylistVideo(@PathVariable Long id, @PathVariable Long videoId) {
return new PlaylistDto(playlistService.deleteVideoFromPlaylist(id, videoId));
}
}

View File

@ -0,0 +1,37 @@
package com.kalyshev.yan.playlist.controller;
import com.kalyshev.yan.comment.model.Comment;
import com.kalyshev.yan.playlist.model.Playlist;
import com.kalyshev.yan.video.model.Video;
import java.util.ArrayList;
import java.util.List;
public class PlaylistDto {
private Long id;
private String name;
private Long userId;
private List<Long> videoIds;
public PlaylistDto() {}
public PlaylistDto(Playlist playlist) {
this.id = playlist.getId();
this.name = playlist.getName();
if (playlist.getVideos() == null) {
this.videoIds = new ArrayList<>();
} else {
this.videoIds = new ArrayList<>();
List<Video> videos = playlist.getVideos();
for (Video video : videos) {
videoIds.add(video.getId());
}
}
}
public Long getId() { return this.id; }
public void setId(Long id) { this.id = id; }
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
public List<Long> getVideoIds() { return this.videoIds; }
public void setVideoIds(List<Long> videoIds) { this.videoIds = videoIds; }
public Long getUserId() { return this.userId; }
public void setUserId(Long userId) { this.userId = userId; }
}

View File

@ -0,0 +1,97 @@
package com.kalyshev.yan.playlist.controller;
import com.kalyshev.yan.category.controller.CategoryDto;
import com.kalyshev.yan.category.service.CategoryService;
import com.kalyshev.yan.playlist.controller.PlaylistDto;
import com.kalyshev.yan.playlist.service.PlaylistService;
import com.kalyshev.yan.user.model.User;
import com.kalyshev.yan.user.service.UserService;
import com.kalyshev.yan.video.controller.VideoDto;
import com.kalyshev.yan.video.service.VideoService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/playlists")
public class PlaylistMvcController {
private final PlaylistService playlistService;
private final UserService userService;
private final VideoService videoService;
public PlaylistMvcController(VideoService videoService,
UserService userService,
PlaylistService playlistService) {
this.playlistService = playlistService;
this.videoService = videoService;
this.userService = userService;
}
@GetMapping(value = {"", "/"})
public String getPlaylists(Model model) {
model.addAttribute("playlists",
playlistService.findAllPlaylists().stream()
.map(PlaylistDto::new)
.toList());
return "playlists";
}
@GetMapping(value = {"/edit/", "/edit/{id}"})
public String editPlaylist(@PathVariable(required = false) Long id,
Model model) {
if (id == null || id <= 0) {
model.addAttribute("playlistDto", new PlaylistDto());
} else {
model.addAttribute("playlistId", id);
model.addAttribute("playlistDto", new PlaylistDto(playlistService.findPlaylist(id)));
model.addAttribute("videos",
playlistService.listVideosFromPlaylist(id).stream()
.map(VideoDto::new)
.toList());
}
model.addAttribute("allVideos",
videoService.findAllVideos().stream()
.map(VideoDto::new)
.toList());
return "playlist-edit";
}
@PostMapping(value = {"", "/", "/{id}"})
public String savePlaylist(@PathVariable(required = false) Long id,
@ModelAttribute @Valid PlaylistDto playlistDto,
BindingResult bindingResult,
Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "playlist-edit";
}
User user = userService.findByLogin(SecurityContextHolder.getContext().getAuthentication().getName());
if (id == null || id <= 0) {
playlistService.addPlaylist(playlistDto.getName(), user.getId());
} else {
playlistService.updatePlaylist(id, playlistDto.getName());
}
return "redirect:/playlists";
}
@PostMapping("/delete/{id}")
public String deleteVideo(@PathVariable Long id) {
videoService.deleteVideo(id);
return "redirect:/videos";
}
@PostMapping(value = "/{id}/video/{videoId}")
public String addPlaylistVideo(@PathVariable(value = "id") Long id,
@PathVariable(value = "videoId") Long videoId,
HttpServletRequest request) {
playlistService.addVideoToPlaylist(id, videoId);
String referer = request.getHeader("Referer");
return "redirect:"+ referer;
}
@GetMapping(value = "/{id}/videoDelete/{videoId}")
public String deletePlaylistVideo(@PathVariable(value = "id") Long id,
@PathVariable(value = "videoId") Long videoId,
HttpServletRequest request) {
playlistService.deleteVideoFromPlaylist(id, videoId);
String referer = request.getHeader("Referer");
return "redirect:"+ referer;
}
}

View File

@ -0,0 +1,81 @@
package com.kalyshev.yan.playlist.model;
import com.kalyshev.yan.user.model.User;
import com.kalyshev.yan.video.model.Video;
import jakarta.persistence.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Entity
@Table(name = "playlist")
public class Playlist {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToOne(cascade = {CascadeType.MERGE})
private User user;
@ManyToMany(cascade = {CascadeType.MERGE})
private List<Video> videos;
public Playlist() {
}
public Playlist(String name, User user) {
this.name = name;
this.user = user;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Video> getVideos() {
return videos;
}
public void addVideo(Video video){
if (videos == null){
this.videos = new ArrayList<>();
}
if (!videos.contains(video)) {
this.videos.add(video);
video.addPlaylist(this);
}
}
public void removeVideo(Video video){
if (videos.contains(video)) {
this.videos.remove(video);
video.removePlaylist(this);
}
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Playlist playlist))
return false;
return Objects.equals(id, playlist.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return "Playlist{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}

View File

@ -0,0 +1,7 @@
package com.kalyshev.yan.playlist.repository;
public class PlaylistNotFoundException extends RuntimeException {
public PlaylistNotFoundException(Long id) {
super(String.format("Playlist with id [%s] is not found", id));
}
}

View File

@ -0,0 +1,8 @@
package com.kalyshev.yan.playlist.repository;
import com.kalyshev.yan.playlist.model.Playlist;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PlaylistRepository extends JpaRepository<Playlist, Long> {
}

View File

@ -0,0 +1,158 @@
package com.kalyshev.yan.playlist.service;
import com.kalyshev.yan.category.model.Category;
import com.kalyshev.yan.playlist.model.Playlist;
import com.kalyshev.yan.playlist.repository.PlaylistNotFoundException;
import com.kalyshev.yan.playlist.repository.PlaylistRepository;
import com.kalyshev.yan.user.model.User;
import com.kalyshev.yan.user.service.UserService;
import com.kalyshev.yan.util.validation.ValidatorUtil;
import com.kalyshev.yan.video.model.Video;
import com.kalyshev.yan.video.repository.VideoNotFoundException;
import com.kalyshev.yan.video.repository.VideoRepository;
import com.kalyshev.yan.video.service.VideoService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Optional;
@Service
public class PlaylistService {
private final PlaylistRepository playlistRepository;
private final VideoService videoService;
private final UserService userService;
private final ValidatorUtil validatorUtil;
public PlaylistService(PlaylistRepository playlistRepository,
VideoService videoService,
UserService userService,
ValidatorUtil validatorUtil) {
this.playlistRepository = playlistRepository;
this.videoService = videoService;
this.userService = userService;
this.validatorUtil = validatorUtil;
}
@Transactional
public Playlist addPlaylist(String name, Long userId) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Playlist name is null or empty");
}
if (userId == null) {
throw new IllegalArgumentException("Playlist userId is null or empty");
}
User user = userService.findUser(userId);
final Playlist playlist = new Playlist(name, user);
validatorUtil.validate(playlist);
return playlistRepository.save(playlist);
}
@Transactional(readOnly = true)
public Playlist findPlaylist(Long id) {
final Optional<Playlist> playlist = playlistRepository.findById(id);
return playlist.orElseThrow(() -> new PlaylistNotFoundException(id));
}
@Transactional(readOnly = true)
public List<Playlist> findAllPlaylists() {
return playlistRepository.findAll();
}
// @Transactional(readOnly = true)
// public List<Video> findFilteredVideos(Long id, String modelName, String serialNum, Long monitorId, Long cabinetId) {
// return videoRepository.findFilteredVideos(id, modelName, serialNum, monitorId, cabinetId);
// }
@Transactional
public Playlist updatePlaylist(Long id, String name) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Video name is null or empty");
}
final Playlist currentPlaylist = findPlaylist(id);
currentPlaylist.setName(name);
validatorUtil.validate(currentPlaylist);
return playlistRepository.save(currentPlaylist);
}
@Transactional
public Playlist deletePlaylist(Long id) {
final Playlist currentPlaylist = findPlaylist(id);
List<Video> currentPlaylistVideos = currentPlaylist.getVideos();
if (currentPlaylistVideos != null && currentPlaylistVideos.size() > 0) {
for (Video currentPlaylistVideo: currentPlaylistVideos) {
currentPlaylistVideo.removePlaylist(currentPlaylist);
}
}
playlistRepository.delete(currentPlaylist);
return currentPlaylist;
}
@Transactional
public void deleteAllVideos() {
List<Playlist> playlists = findAllPlaylists();
for (Playlist playlist : playlists) {
deletePlaylist(playlist.getId());
}
}
@Transactional
public List<Video> listVideosFromPlaylist(Long id) {
if (id == null) {
throw new IllegalArgumentException("Playlist id is null or empty");
}
return findPlaylist(id).getVideos();
}
@Transactional
public Playlist addVideoToPlaylist(Long playlistId, Long videoId) {
if (videoId == null) {
throw new IllegalArgumentException("Video id is null or empty");
}
if (playlistId == null) {
throw new IllegalArgumentException("Playlist id is null or empty");
}
final Video video = videoService.findVideo(videoId);
final Playlist playlist = findPlaylist(playlistId);
playlist.addVideo(video);
return playlist;
}
@Transactional
public Playlist deleteVideoFromPlaylist(Long playlistId, Long videoId) {
if (videoId == null) {
throw new IllegalArgumentException("Video id is null or empty");
}
if (playlistId == null) {
throw new IllegalArgumentException("Playlist id is null or empty");
}
final Video video = videoService.findVideo(videoId);
final Playlist playlist = findPlaylist(playlistId);;
playlist.removeVideo(video);
return playlist;
}
@Transactional
public List<Playlist> listPlaylistsFromVideo(Long id) {
if (id == null) {
throw new IllegalArgumentException("Video id is null or empty");
}
return videoService.findVideo(id).getPlaylists();
}
@Transactional
public Video addPlaylistToVideo(Long videoId, Long playlistId) {
if (videoId == null) {
throw new IllegalArgumentException("Video id is null or empty");
}
if (playlistId == null) {
throw new IllegalArgumentException("Playlist id is null or empty");
}
final Video video = videoService.findVideo(videoId);
final Playlist playlist = findPlaylist(playlistId);
video.addPlaylist(playlist);
return video;
}
@Transactional
public Video deletePlaylistFromVideo(Long videoId, Long playlistId) {
if (videoId == null) {
throw new IllegalArgumentException("Video id is null or empty");
}
if (playlistId == null) {
throw new IllegalArgumentException("Playlist id is null or empty");
}
final Video video = videoService.findVideo(videoId);
final Playlist playlist = findPlaylist(playlistId);
video.removePlaylist(playlist);
return video;
}
}

View File

@ -0,0 +1,7 @@
package com.kalyshev.yan.user.repository;
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(Long id) {
super(String.format("User with id [%s] is not found", id));
}
}

View File

@ -2,10 +2,12 @@ package com.kalyshev.yan.user.service;
import com.kalyshev.yan.user.model.User;
import com.kalyshev.yan.user.model.UserRole;
import com.kalyshev.yan.user.repository.UserNotFoundException;
import com.kalyshev.yan.user.repository.UserRepository;
import com.kalyshev.yan.util.validation.ValidationException;
import com.kalyshev.yan.util.validation.ValidatorUtil;
import jakarta.transaction.Transactional;
import com.kalyshev.yan.video.model.Video;
import com.kalyshev.yan.video.repository.VideoNotFoundException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
@ -14,9 +16,11 @@ import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.Objects;
import java.util.Optional;
@Service
public class UserService implements UserDetailsService {
@ -33,6 +37,11 @@ public class UserService implements UserDetailsService {
public Page<User> findAllPages(int page, int size) {
return userRepository.findAll(PageRequest.of(page - 1, size, Sort.by("id").ascending()));
}
@Transactional(readOnly = true)
public User findUser(Long id) {
final Optional<User> user = userRepository.findById(id);
return user.orElseThrow(() -> new UserNotFoundException(id));
}
public User findByLogin(String login) {
return userRepository.findOneByLoginIgnoreCase(login);
}

View File

@ -1,7 +1,11 @@
package com.kalyshev.yan.util.error;
import com.kalyshev.yan.cabinet.repository.CabinetNotFoundException;
import com.kalyshev.yan.category.repository.CategoryNotFoundException;
import com.kalyshev.yan.comment.repository.CommentNotFoundException;
import com.kalyshev.yan.playlist.repository.PlaylistNotFoundException;
import com.kalyshev.yan.user.repository.UserNotFoundException;
import com.kalyshev.yan.util.validation.ValidationException;
import com.kalyshev.yan.video.repository.VideoNotFoundException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@ -15,7 +19,11 @@ import java.util.stream.Collectors;
@ControllerAdvice(annotations = RestController.class)
public class AdviceController {
@ExceptionHandler({
CabinetNotFoundException.class,
VideoNotFoundException.class,
PlaylistNotFoundException.class,
CategoryNotFoundException.class,
CommentNotFoundException.class,
UserNotFoundException.class,
ValidationException.class
})
public ResponseEntity<Object> handleException(Throwable e) {

View File

@ -0,0 +1,93 @@
package com.kalyshev.yan.video.controller;
import com.kalyshev.yan.WebConfiguration;
import com.kalyshev.yan.category.controller.CategoryDto;
import com.kalyshev.yan.category.service.CategoryService;
import com.kalyshev.yan.computer.controller.ComputerDto;
import com.kalyshev.yan.computer.service.ComputerService;
import com.kalyshev.yan.monitor.controller.MonitorDto;
import com.kalyshev.yan.playlist.controller.PlaylistDto;
import com.kalyshev.yan.playlist.service.PlaylistService;
import com.kalyshev.yan.video.service.VideoService;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
import java.util.List;
@RestController
@RequestMapping(WebConfiguration.REST_API + "/video")
public class VideoController {
private final VideoService videoService;
private final PlaylistService playlistService;
private final CategoryService categoryService;
public VideoController(VideoService videoService,
PlaylistService playlistService,
CategoryService categoryService) {
this.videoService = videoService;
this.playlistService = playlistService;
this.categoryService = categoryService;
}
@GetMapping("/{id}")
public VideoDto getVideo(@PathVariable Long id) {
return new VideoDto(videoService.findVideo(id));
}
@GetMapping("/")
public List<VideoDto> getVideos() {
return videoService.findAllVideos().stream()
.map(VideoDto::new)
.toList();
}
// @GetMapping("/filter")
// public List<VideoDto> getFilteredVideos(@RequestParam(value = "id", required = false) Long id,
// @RequestParam(value = "name", required = false) String name,
// @RequestParam(value = "date", required = false) LocalDate date,
// @RequestParam(value = "userId", required = false) Long monitorId) {
// return videoService.findFilteredVideos(id, name, date, monitorId).stream()
// .map(VideoDto::new)
// .toList();
// }
@PostMapping("/")
public VideoDto createVideo(@RequestBody @Valid VideoDto videoDto) {
return new VideoDto(videoService.addVideo(videoDto.getName(), videoDto.getUserId()));
}
@PutMapping("/{id}")
public VideoDto updateVideo(@PathVariable Long id,
@RequestBody @Valid VideoDto updateVideo) {
return new VideoDto(videoService.updateVideo(id, updateVideo.getName()));
}
@DeleteMapping("/{id}")
public VideoDto deleteVideo(@PathVariable Long id) {
return new VideoDto(videoService.deleteVideo(id));
}
@GetMapping("/{id}/playlists")
public List<PlaylistDto> getVideoPlaylists(@PathVariable Long id) {
return playlistService.listPlaylistsFromVideo(id).stream()
.map(PlaylistDto::new)
.toList();
}
@PostMapping("/{id}/playlist")
public VideoDto addVideoPlaylist(@PathVariable Long id,
@RequestParam("playlistId") Long playlistId) {
return new VideoDto(playlistService.addPlaylistToVideo(id, playlistId));
}
@DeleteMapping("/{id}/playlist/{playlistId}")
public VideoDto deleteVideoPlaylist(@PathVariable Long id, @PathVariable Long playlistId) {
return new VideoDto(playlistService.deletePlaylistFromVideo(id, playlistId));
}
@GetMapping("/{id}/categories")
public List<CategoryDto> getVideoCategories(@PathVariable Long id) {
return categoryService.listCategoriesFromVideo(id).stream()
.map(CategoryDto::new)
.toList();
}
@PostMapping("/{id}/category")
public VideoDto addVideoCategory(@PathVariable Long id,
@RequestParam("categoryId") Long categoryId) {
return new VideoDto(categoryService.addCategoryToVideo(id, categoryId));
}
@DeleteMapping("/{id}/category/{categoryId}")
public VideoDto deleteVideoCategory(@PathVariable Long id, @PathVariable Long categoryId) {
return new VideoDto(categoryService.deleteCategoryFromVideo(id, categoryId));
}
}

View File

@ -0,0 +1,55 @@
package com.kalyshev.yan.video.controller;
import com.kalyshev.yan.category.model.Category;
import com.kalyshev.yan.playlist.model.Playlist;
import com.kalyshev.yan.video.model.Video;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
public class VideoDto {
private Long id;
private String name;
private Long userId;
private LocalDate date;
private List<Long> categoryIds;
private List<Long> playlistIds;
public VideoDto() {}
public VideoDto(Video video) {
this.id = video.getId();
this.name = video.getName();
this.date = video.getDate();
this.userId = video.getUser().getId();
if (video.getCategories() == null) {
this.categoryIds = new ArrayList<>();
} else {
this.categoryIds = new ArrayList<>();
List<Category> categories = video.getCategories();
for (Category category : categories) {
categoryIds.add(category.getId());
}
}
if (video.getPlaylists() == null) {
this.playlistIds = new ArrayList<>();
} else {
this.playlistIds = new ArrayList<>();
List<Playlist> playlists = video.getPlaylists();
for (Playlist playlist : playlists) {
playlistIds.add(playlist.getId());
}
}
}
public Long getId() { return this.id; }
public void setId(Long id) { this.id = id; }
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
public Long getUserId() { return this.userId; }
public void setUserId(Long userId) { this.userId = userId; }
public String getDate() { return this.date.toString(); }
public List<Long> getCategoryIds() { return this.categoryIds; }
public void setCategoryIds(List<Long> categoryIds) { this.categoryIds = categoryIds; }
public List<Long> getPlaylistIds() { return this.playlistIds; }
public void setPlaylistIds(List<Long> playlistIds) { this.playlistIds = playlistIds; }
public void setDate(LocalDate date) { this.date = date; }
}

View File

@ -0,0 +1,124 @@
package com.kalyshev.yan.video.controller;
import com.kalyshev.yan.category.controller.CategoryDto;
import com.kalyshev.yan.category.service.CategoryService;
import com.kalyshev.yan.playlist.controller.PlaylistDto;
import com.kalyshev.yan.playlist.service.PlaylistService;
import com.kalyshev.yan.user.model.User;
import com.kalyshev.yan.user.service.UserService;
import com.kalyshev.yan.video.service.VideoService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/videos")
public class VideoMvcController {
private final CategoryService categoryService;
private final PlaylistService playlistService;
private final UserService userService;
private final VideoService videoService;
public VideoMvcController(CategoryService categoryService,
VideoService videoService,
UserService userService,
PlaylistService playlistService) {
this.categoryService = categoryService;
this.playlistService = playlistService;
this.videoService = videoService;
this.userService = userService;
}
@GetMapping(value = {"", "/"})
public String getVideos(Model model) {
model.addAttribute("videos",
videoService.findAllVideos().stream()
.map(VideoDto::new)
.toList());
return "videos";
}
@GetMapping(value = {"/edit/", "/edit/{id}"})
public String editVideo(@PathVariable(required = false) Long id,
Model model) {
if (id == null || id <= 0) {
model.addAttribute("videoDto", new VideoDto());
} else {
model.addAttribute("videoId", id);
model.addAttribute("videoDto", new VideoDto(videoService.findVideo(id)));
model.addAttribute("categories",
categoryService.listCategoriesFromVideo(id).stream()
.map(CategoryDto::new)
.toList());
model.addAttribute("playlists",
playlistService.listPlaylistsFromVideo(id).stream()
.map(PlaylistDto::new)
.toList());
}
model.addAttribute("allCategories",
categoryService.findAllCategories().stream()
.map(CategoryDto::new)
.toList());
model.addAttribute("allPlaylists",
playlistService.findAllPlaylists().stream()
.map(PlaylistDto::new)
.toList());
return "video-edit";
}
@PostMapping(value = {"", "/", "/{id}"})
public String saveVideo(@PathVariable(required = false) Long id,
@ModelAttribute @Valid VideoDto videoDto,
BindingResult bindingResult,
Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "video-edit";
}
User user = userService.findByLogin(SecurityContextHolder.getContext().getAuthentication().getName());
if (id == null || id <= 0) {
videoService.addVideo(videoDto.getName(), user.getId());
} else {
videoService.updateVideo(id, videoDto.getName());
}
return "redirect:/videos";
}
@PostMapping("/delete/{id}")
public String deleteVideo(@PathVariable Long id) {
videoService.deleteVideo(id);
return "redirect:/videos";
}
@PostMapping(value = "/{id}/category/{categoryId}")
public String addVideoCategory(@PathVariable(value = "id") Long id,
@PathVariable(value = "categoryId") Long categoryId,
HttpServletRequest request) {
categoryService.addCategoryToVideo(id, categoryId);
String referer = request.getHeader("Referer");
return "redirect:"+ referer;
}
@GetMapping(value = "/{id}/categoryDelete/{categoryId}")
public String deleteVideoCategory(@PathVariable(value = "id") Long id,
@PathVariable(value = "categoryId") Long categoryId,
HttpServletRequest request) {
categoryService.deleteCategoryFromVideo(id, categoryId);
String referer = request.getHeader("Referer");
return "redirect:"+ referer;
}
@PostMapping(value = "/{id}/playlist/{playlistId}")
public String addVideoPlaylist(@PathVariable(value = "id") Long id,
@PathVariable(value = "playlistId") Long playlistId,
HttpServletRequest request) {
playlistService.addPlaylistToVideo(id, playlistId);
String referer = request.getHeader("Referer");
return "redirect:"+ referer;
}
@GetMapping(value = "/{id}/playlistDelete/{playlistId}")
public String deleteVideoPlaylist(@PathVariable(value = "id") Long id,
@PathVariable(value = "playlistId") Long playlistId,
HttpServletRequest request) {
playlistService.deletePlaylistFromVideo(id, playlistId);
String referer = request.getHeader("Referer");
return "redirect:"+ referer;
}
}

View File

@ -0,0 +1,112 @@
package com.kalyshev.yan.video.model;
import com.kalyshev.yan.category.model.Category;
import com.kalyshev.yan.playlist.model.Playlist;
import com.kalyshev.yan.user.model.User;
import jakarta.persistence.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Entity
@Table(name = "video")
public class Video {
@Id
@GeneratedValue
private Long id;
private String name;
private LocalDate date;
@ManyToMany(cascade = {CascadeType.MERGE})
private List<Category> categories;
@ManyToMany(cascade = {CascadeType.MERGE})
private List<Playlist> playlists;
@ManyToOne(cascade = {CascadeType.MERGE})
private User user;
public Video() {
}
public Video(String name, User user) {
this.name = name;
this.user = user;
this.date = LocalDate.now();
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDate getDate() {
return date;
}
public void setDate(LocalDate date) {
this.date = date;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Category> getCategories() {
return categories;
}
public void addCategory(Category category){
if (categories == null){
this.categories = new ArrayList<>();
}
if (!categories.contains(category)) {
this.categories.add(category);
category.addVideo(this);
}
}
public void removeCategory(Category category){
if (categories.contains(category)) {
this.categories.remove(category);
category.removeVideo(this);
}
}
public List<Playlist> getPlaylists() {
return playlists;
}
public void addPlaylist(Playlist playlist){
if (playlists == null){
this.playlists = new ArrayList<>();
}
if (!playlists.contains(playlist)) {
this.playlists.add(playlist);
playlist.addVideo(this);
}
}
public void removePlaylist(Playlist playlist){
if (playlists.contains(playlist)) {
this.playlists.remove(playlist);
playlist.removeVideo(this);
}
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Video video))
return false;
return Objects.equals(id, video.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return "Video{" +
"id=" + id +
", name='" + name + '\'' +
", date='" + date + '\'' +
'}';
}
}

View File

@ -0,0 +1,7 @@
package com.kalyshev.yan.video.repository;
public class VideoNotFoundException extends RuntimeException {
public VideoNotFoundException(Long id) {
super(String.format("Video with id [%s] is not found", id));
}
}

View File

@ -0,0 +1,7 @@
package com.kalyshev.yan.video.repository;
import com.kalyshev.yan.video.model.Video;
import org.springframework.data.jpa.repository.JpaRepository;
public interface VideoRepository extends JpaRepository<Video, Long> {
}

View File

@ -0,0 +1,89 @@
package com.kalyshev.yan.video.service;
import com.kalyshev.yan.category.model.Category;
import com.kalyshev.yan.category.service.CategoryService;
import com.kalyshev.yan.playlist.model.Playlist;
import com.kalyshev.yan.playlist.repository.PlaylistRepository;
import com.kalyshev.yan.playlist.service.PlaylistService;
import com.kalyshev.yan.user.model.User;
import com.kalyshev.yan.user.service.UserService;
import com.kalyshev.yan.video.model.Video;
import com.kalyshev.yan.video.repository.VideoNotFoundException;
import com.kalyshev.yan.video.repository.VideoRepository;
import com.kalyshev.yan.util.validation.ValidatorUtil;
import jakarta.validation.constraints.Null;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Optional;
@Service
public class VideoService {
private final VideoRepository videoRepository;
private final UserService userService;
private final ValidatorUtil validatorUtil;
public VideoService(VideoRepository videoRepository,
UserService userService,
ValidatorUtil validatorUtil) {
this.videoRepository = videoRepository;
this.userService = userService;
this.validatorUtil = validatorUtil;
}
@Transactional
public Video addVideo(String name, Long userId) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Video name is null or empty");
}
if (userId == null) {
throw new IllegalArgumentException("Video userId is null or empty");
}
User user = userService.findUser(userId);
final Video video = new Video(name, user);
validatorUtil.validate(video);
return videoRepository.save(video);
}
@Transactional(readOnly = true)
public Video findVideo(Long id) {
final Optional<Video> video = videoRepository.findById(id);
return video.orElseThrow(() -> new VideoNotFoundException(id));
}
@Transactional(readOnly = true)
public List<Video> findAllVideos() {
return videoRepository.findAll();
}
// @Transactional(readOnly = true)
// public List<Video> findFilteredVideos(Long id, String modelName, String serialNum, Long monitorId, Long cabinetId) {
// return videoRepository.findFilteredVideos(id, modelName, serialNum, monitorId, cabinetId);
// }
@Transactional
public Video updateVideo(Long id, String name) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Video name is null or empty");
}
final Video currentVideo = findVideo(id);
currentVideo.setName(name);
validatorUtil.validate(currentVideo);
return videoRepository.save(currentVideo);
}
@Transactional
public Video deleteVideo(Long id) {
final Video currentVideo = findVideo(id);
List<Playlist> currentVideoPlaylists = currentVideo.getPlaylists();
if (currentVideoPlaylists != null && currentVideoPlaylists.size() > 0) {
for (Playlist currentVideoPlaylist: currentVideoPlaylists) {
currentVideoPlaylist.removeVideo(currentVideo);
}
}
videoRepository.delete(currentVideo);
return currentVideo;
}
@Transactional
public void deleteAllVideos() {
List<Video> videos = findAllVideos();
for (Video video : videos) {
deleteVideo(video.getId());
}
}
}

View File

@ -1,72 +0,0 @@
<!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 th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/index/{id}(id=${id})}" th:object="${cabinetDto}" method="post">
<div class="mb-3">
<label for="number" class="form-label">Номер кабинета</label>
<input type="text" class="form-control" id="number" th:field="${cabinetDto.number}" required="true">
</div>
<div th:if="${id != null}" class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Название</th>
<th scope="col">Серийный номер</th>
<th scope="col">Монитор</th>
<th scope="col">Кабинет</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="computer, iterator: ${computers}">
<th scope="row" th:text="${iterator.index} + 1"/>
<td th:text="${computer.modelName}" style="width: 60%"/>
<td th:text="${computer.serialNum}" style="width: 60%"/>
<td th:text="${computer.monitorModelName}" style="width: 60%"/>
<td style="width: 10%">
<div class="btn-group" role="group" aria-label="Basic example">
<button type="button" class="btn btn-danger button-fixed button-sm"
th:attr="onclick=|confirm('Удалить?') && document.getElementById('remove-${computer.id}').click()|">
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
</div>
<form th:action="@{/index/{id}/computerDelete/{computerId}(id=${id}, computerId=${computer.id})}" method="post">
<button th:id="'remove-' + ${computer.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</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="@{/index}">
Назад
</a>
</div>
</form>
<form th:if="${id != null}" th:action="@{/index/{id}/computer(id=${id})}" id="addComputerForm" method="post">
<div class="mb-3">
<label for="computers" class="form-label">Добавить компьютер</label>
<select class="form-select" id="computers" required>
<option disabled value="">Выберите компьютер</option>
<option th:each="computer, iterator: ${allComputers}" th:text="${computer.modelName}" th:value="${computer.id}">
</select>
<button class="btn btn-outline-secondary" id="addComputerButton" th:attr="onclick=|document.getElementById('addComputerForm').action = document.getElementById('addComputerForm').action + '/' + document.getElementById('computers').value ; document.getElementById('addComputerForm}').submit()|">Добавить</button>
</div>
</form>
</div>
</body>
</html>

View File

@ -8,7 +8,7 @@
<div layout:fragment="content">
<div>
<a class="btn btn-success button-fixed"
th:href="@{/monitors/edit/}">
th:href="@{/categories/edit/}">
<i class="fa-solid fa-plus"></i> Добавить
</a>
</div>
@ -22,22 +22,22 @@
</tr>
</thead>
<tbody>
<tr th:each="monitor, iterator: ${monitors}">
<tr th:each="category, iterator: ${categories}">
<th scope="row" th:text="${iterator.index} + 1"/>
<td th:text="${monitor.modelName}" style="width: 60%"/>
<td th:text="${category.name}" style="width: 60%"/>
<td style="width: 10%">
<div class="btn-group" role="group" aria-label="Basic example">
<a class="btn btn-warning button-fixed button-sm"
th:href="@{/monitors/edit/{id}(id=${monitor.id})}">
th:href="@{/categories/edit/{id}(id=${category.id})}">
<i class="fa fa-pencil" aria-hidden="true"></i> Изменить
</a>
<button type="button" class="btn btn-danger button-fixed button-sm"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${monitor.id}').click()|">
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${category.id}').click()|">
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
</div>
<form th:action="@{/monitors/delete/{id}(id=${monitor.id})}" method="post">
<button th:id="'remove-' + ${monitor.id}" type="submit" style="display: none">
<form th:action="@{/categories/delete/{id}(id=${category.id})}" method="post">
<button th:id="'remove-' + ${category.id}" type="submit" style="display: none">
Удалить
</button>
</form>

View File

@ -0,0 +1,66 @@
<!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 th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/categories/{id}(id=${id})}" th:object="${categoryDto}" method="post">
<div class="mb-3">
<label for="number" class="form-label">Название</label>
<input type="text" class="form-control" id="number" th:field="${categoryDto.name}" required="true">
</div>
<div th:if="${id != null}" class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Название</th>
<th scope="col">Дата</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="video, iterator: ${videos}">
<th scope="row" th:text="${iterator.index} + 1"/>
<td th:text="${video.name}" style="width: 60%"/>
<td th:text="${video.date}" style="width: 60%"/>
<td style="width: 10%">
<div class="btn-group" role="group" aria-label="Basic example">
<a th:href="@{/categories/{id}/videoDelete/{videoId}(id=${id}, videoId=${video.id})}" class="btn btn-danger button-fixed button-sm">Удалить</a>
</div>
<!-- <form th:action="@{/categories/{id}/videoDelete/{videoId}(id=${id}, videoId=${video.id})}" method="post">-->
<!-- <button th:id="'remove-' + ${video.id}" type="submit" style="display: none">-->
<!-- Удалить-->
<!-- </button>-->
<!-- </form>-->
</td>
</tr>
</tbody>
</table>
</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="@{/categories}">
Назад
</a>
</div>
</form>
<form th:if="${id != null}" th:action="@{/categories/{id}/video(id=${id})}" id="addVideoForm" method="post">
<div class="mb-3">
<label for="videos" class="form-label">Добавить видео</label>
<select class="form-select" id="videos" required>
<option disabled value="">Выберите видео</option>
<option th:each="video, iterator: ${allVideos}" th:text="${video.name}" th:value="${video.id}">
</select>
<button class="btn btn-outline-secondary" id="addVideoButton" th:attr="onclick=|document.getElementById('addVideoForm').action = document.getElementById('addVideoForm').action + '/' + document.getElementById('videos').value ; document.getElementById('addVideoForm}').submit()|">Добавить</button>
</div>
</form>
</div>
</body>
</html>

View File

@ -7,17 +7,21 @@
<body>
<div layout:fragment="content">
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/monitors/{id}(id=${id})}" th:object="${monitorDto}" method="post">
<form action="#" th:action="@{/comments/{id}(id=${id})}" th:object="${commentDto}" method="post">
<div class="mb-3">
<label for="modelName" class="form-label">Название</label>
<input type="text" class="form-control" id="modelName" th:field="${monitorDto.modelName}" required="true">
<label for="number" class="form-label">Комментарий</label>
<input type="text" class="form-control" id="number" th:field="${commentDto.comment}" required="true">
</div>
<div class="mb-3">
<label for="video" class="form-label">Видео</label>
<input type="text" class="form-control" id="video" th:field="${commentDto.videoId}" 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="@{/monitors}">
<a class="btn btn-secondary button-fixed" th:href="@{/comments}">
Назад
</a>
</div>

View File

@ -0,0 +1,53 @@
<!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>
<a class="btn btn-success button-fixed"
th:href="@{/comments/edit/}">
<i class="fa-solid fa-plus"></i> Добавить
</a>
</div>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Комментарий</th>
<th scope="col">Видео</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="comment, iterator: ${comments}">
<th scope="row" th:text="${iterator.index} + 1"/>
<td th:text="${comment.comment}" style="width: 60%"/>
<td th:text="${comment.videoId}" style="width: 60%"/>
<td style="width: 10%">
<div class="btn-group" role="group" aria-label="Basic example">
<a class="btn btn-warning button-fixed button-sm"
th:href="@{/comments/edit/{id}(id=${comment.id})}">
<i class="fa fa-pencil" aria-hidden="true"></i> Изменить
</a>
<button type="button" class="btn btn-danger button-fixed button-sm"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${comment.id}').click()|">
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
</div>
<form th:action="@{/comments/delete/{id}(id=${comment.id})}" method="post">
<button th:id="'remove-' + ${comment.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>

View File

@ -1,38 +0,0 @@
<!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 th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/computers/{id}(id=${id})}" th:object="${computerDto}" method="post">
<div class="mb-3">
<label for="modelName" class="form-label">Название</label>
<input type="text" class="form-control" id="modelName" th:field="${computerDto.modelName}" required="true">
</div>
<div class="mb-3">
<label for="serialNum" class="form-label">Серийный номер</label>
<input type="text" class="form-control" id="serialNum" th:field="${computerDto.serialNum}" required="true">
</div>
<label for="monitor" class="form-label">Монитор</label>
<select class="form-select" id="monitor" th:field="${computerDto.monitorId}">
<option value="">Выберите монитор</option>
<option th:each="monitor, iterator: ${monitors}" th:text="${monitor.modelName}" th:value="${monitor.id}"
th:selected="${monitor.id==computerDto.monitorId}">
</option>
</select>
<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="@{/computers}">
Назад
</a>
</div>
</form>
</div>
</body>
</html>

View File

@ -1,57 +0,0 @@
<!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>
<a class="btn btn-success button-fixed"
th:href="@{/computers/edit/}">
<i class="fa-solid fa-plus"></i> Добавить
</a>
</div>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Название</th>
<th scope="col">Серийный номер</th>
<th scope="col">Монитор</th>
<th scope="col">Кабинет</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="computer, iterator: ${computers}">
<th scope="row" th:text="${iterator.index} + 1"/>
<td th:text="${computer.modelName}" style="width: 60%"/>
<td th:text="${computer.serialNum}" style="width: 60%"/>
<td th:text="${computer.monitorModelName}" style="width: 60%"/>
<td th:text="${computer.cabinetNumber}" style="width: 60%"/>
<td style="width: 10%">
<div class="btn-group" role="group" aria-label="Basic example">
<a class="btn btn-warning button-fixed button-sm"
th:href="@{/computers/edit/{id}(id=${computer.id})}">
<i class="fa fa-pencil" aria-hidden="true"></i> Изменить
</a>
<button type="button" class="btn btn-danger button-fixed button-sm"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${computer.id}').click()|">
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
</div>
<form th:action="@{/computers/delete/{id}(id=${computer.id})}" method="post">
<button th:id="'remove-' + ${computer.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>

View File

@ -27,12 +27,12 @@
</button>
<div class="collapse navbar-collapse" id="navbarNav" sec:authorize="isAuthenticated()">
<ul class="navbar-nav" th:with="activeLink=${#ctx.springRequestContext.requestUri}">
<a class="nav-link" href="/index"
th:classappend="${#strings.equals(activeLink, '/index')} ? 'active' : ''">Кабинеты</a>
<a class="nav-link" href="/computers"
th:classappend="${#strings.equals(activeLink, '/computers')} ? 'active' : ''">Компьютеры</a>
<a class="nav-link" href="/monitors"
th:classappend="${#strings.equals(activeLink, '/monitors')} ? 'active' : ''">Мониторы</a>
<a class="nav-link" href="/categories"
th:classappend="${#strings.equals(activeLink, '/categories')} ? 'active' : ''">Категории</a>
<a class="nav-link" href="/videos"
th:classappend="${#strings.equals(activeLink, '/videos')} ? 'active' : ''">Видео</a>
<a class="nav-link" href="/playlists"
th:classappend="${#strings.equals(activeLink, '/playlists')} ? 'active' : ''">Плейлисты</a>
<a class="nav-link" href="/users"
th:classappend="${#strings.equals(activeLink, '/users')} ? 'active' : ''">Пользователи</a>
</ul>

View File

@ -1,52 +0,0 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
<title>Сайт</title>
</head>
<body>
<div layout:fragment="content">
<div>
<a class="btn btn-success button-fixed"
th:href="@{/index/edit/}">
<i class="fa-solid fa-plus"></i> Добавить
</a>
</div>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Номер кабинета</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="cabinet, iterator: ${cabinets}">
<th scope="row" th:text="${iterator.index} + 1"/>
<td th:text="${cabinet.number}" style="width: 60%"/>
<td style="width: 10%">
<div class="btn-group" role="group" aria-label="Basic example">
<a class="btn btn-warning button-fixed button-sm"
th:href="@{/index/edit/{id}(id=${cabinet.id})}">
<i class="fa fa-pencil" aria-hidden="true"></i> Изменить
</a>
<button type="button" class="btn btn-danger button-fixed button-sm"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${cabinet.id}').click()|">
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
</div>
<form th:action="@{/index/delete/{id}(id=${cabinet.id})}" method="post">
<button th:id="'remove-' + ${cabinet.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,66 @@
<!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 th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/playlists/{id}(id=${id})}" th:object="${playlistDto}" method="post">
<div class="mb-3">
<label for="name" class="form-label">Название</label>
<input type="text" class="form-control" id="name" th:field="${playlistDto.name}" required="true">
</div>
<div th:if="${id != null}" class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Название</th>
<th scope="col">Дата</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="video, iterator: ${videos}">
<th scope="row" th:text="${iterator.index} + 1"/>
<td th:text="${video.name}" style="width: 60%"/>
<td th:text="${video.date}" style="width: 60%"/>
<td style="width: 10%">
<div class="btn-group" role="group" aria-label="Basic example">
<a th:href="@{/playlists/{id}/videoDelete/{videoId}(id=${id}, videoId=${video.id})}" class="btn btn-danger button-fixed button-sm">Удалить</a>
</div>
<!-- <form th:action="@{/categories/{id}/videoDelete/{videoId}(id=${id}, videoId=${video.id})}" method="post">-->
<!-- <button th:id="'remove-' + ${video.id}" type="submit" style="display: none">-->
<!-- Удалить-->
<!-- </button>-->
<!-- </form>-->
</td>
</tr>
</tbody>
</table>
</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="@{/playlists}">
Назад
</a>
</div>
</form>
<form th:if="${id != null}" th:action="@{/playlists/{id}/video(id=${id})}" id="addVideoForm" method="post">
<div class="mb-3">
<label for="videos" class="form-label">Добавить видео</label>
<select class="form-select" id="videos" required>
<option disabled value="">Выберите видео</option>
<option th:each="video, iterator: ${allVideos}" th:text="${video.name}" th:value="${video.id}">
</select>
<button class="btn btn-outline-secondary" id="addVideoButton" th:attr="onclick=|document.getElementById('addVideoForm').action = document.getElementById('addVideoForm').action + '/' + document.getElementById('videos').value ; document.getElementById('addVideoForm}').submit()|">Добавить</button>
</div>
</form>
</div>
</body>
</html>

View File

@ -0,0 +1,51 @@
<!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>
<a class="btn btn-success button-fixed"
th:href="@{/playlists/edit/}">
<i class="fa-solid fa-plus"></i> Добавить
</a>
</div>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Название</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="playlist, iterator: ${playlists}">
<th scope="row" th:text="${iterator.index} + 1"/>
<td th:text="${playlist.name}" style="width: 60%"/>
<td style="width: 10%">
<div class="btn-group" role="group" aria-label="Basic example">
<a class="btn btn-warning button-fixed button-sm"
th:href="@{/playlists/edit/{id}(id=${playlist.id})}">
<i class="fa fa-pencil" aria-hidden="true"></i> Изменить
</a>
<button type="button" class="btn btn-danger button-fixed button-sm"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${playlist.id}').click()|">
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
</div>
<form th:action="@{/playlists/delete/{id}(id=${playlist.id})}" method="post">
<button th:id="'remove-' + ${playlist.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,105 @@
<!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 th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/videos/{id}(id=${id})}" th:object="${videoDto}" method="post">
<div class="mb-3">
<label for="number" class="form-label">Название</label>
<input type="text" class="form-control" id="number" th:field="${videoDto.name}" required="true">
</div>
<div th:if="${id != null}" class="table-responsive">
<p>Категории</p>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Название</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="category, iterator: ${categories}">
<th scope="row" th:text="${iterator.index} + 1"/>
<td th:text="${category.name}" style="width: 60%"/>
<td style="width: 10%">
<div class="btn-group" role="group" aria-label="Basic example">
<a th:href="@{/videos/{id}/categoryDelete/{categoryId}(id=${id}, categoryId=${category.id})}" class="btn btn-danger button-fixed button-sm">Удалить</a>
</div>
<!-- <form th:action="@{/videos/{id}/categoryDelete/{categoryId}(id=${id}, categoryId=${category.id})}" method="post">-->
<!-- <button th:id="'remove-' + ${category.id}" type="submit" style="display: none">-->
<!-- Удалить-->
<!-- </button>-->
<!-- </form>-->
</td>
</tr>
</tbody>
</table>
</div>
<div th:if="${id != null}" class="table-responsive">
<p>Плейлисты</p>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Название</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="playlist, iterator: ${playlists}">
<th scope="row" th:text="${iterator.index} + 1"/>
<td th:text="${playlist.name}" style="width: 60%"/>
<td style="width: 10%">
<div class="btn-group" role="group" aria-label="Basic example">
<a th:href="@{/videos/{id}/playlistDelete/{playlistId}(id=${id}, playlistId=${playlist.id})}" class="btn btn-danger button-fixed button-sm">Удалить</a>
</div>
<!-- <form th:action="@{/videos/{id}/playlistDelete/{playlistId}(id=${id}, playlistId=${playlist.id})}" method="post">-->
<!-- <button th:id="'remove-' + ${playlist.id}" type="submit" style="display: none">-->
<!-- Удалить-->
<!-- </button>-->
<!-- </form>-->
</td>
</tr>
</tbody>
</table>
</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="@{/videos}">
Назад
</a>
</div>
</form>
<form th:if="${id != null}" th:action="@{/videos/{id}/category(id=${id})}" id="addCategoryForm" method="post">
<div class="mb-3">
<label for="categories" class="form-label">Добавить категорию</label>
<select class="form-select" id="categories" required>
<option disabled value="">Выберите категорию</option>
<option th:each="category, iterator: ${allCategories}" th:text="${category.name}" th:value="${category.id}">
</select>
<button class="btn btn-outline-secondary" id="addCategoryButton" th:attr="onclick=|document.getElementById('addCategoryForm').action = document.getElementById('addCategoryForm').action + '/' + document.getElementById('categories').value ; document.getElementById('addCategoryForm}').submit()|">Добавить</button>
</div>
</form>
<form th:if="${id != null}" th:action="@{/videos/{id}/playlist(id=${id})}" id="addPlaylistForm" method="post">
<div class="mb-3">
<label for="playlists" class="form-label">Добавить плейлист</label>
<select class="form-select" id="playlists" required>
<option disabled value="">Выберите плейлист</option>
<option th:each="playlist, iterator: ${allPlaylists}" th:text="${playlist.name}" th:value="${playlist.id}">
</select>
<button class="btn btn-outline-secondary" id="addPlaylistButton" th:attr="onclick=|document.getElementById('addPlaylistForm').action = document.getElementById('addPlaylistForm').action + '/' + document.getElementById('playlists').value ; document.getElementById('addPlaylistForm}').submit()|">Добавить</button>
</div>
</form>
</div>
</body>
</html>

View File

@ -0,0 +1,53 @@
<!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>
<a class="btn btn-success button-fixed"
th:href="@{/videos/edit/}">
<i class="fa-solid fa-plus"></i> Добавить
</a>
</div>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Название</th>
<th scope="col">Дата</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="video, iterator: ${videos}">
<th scope="row" th:text="${iterator.index} + 1"/>
<td th:text="${video.name}" style="width: 60%"/>
<td th:text="${video.date}" style="width: 60%"/>
<td style="width: 10%">
<div class="btn-group" role="group" aria-label="Basic example">
<a class="btn btn-warning button-fixed button-sm"
th:href="@{/videos/edit/{id}(id=${video.id})}">
<i class="fa fa-pencil" aria-hidden="true"></i> Изменить
</a>
<button type="button" class="btn btn-danger button-fixed button-sm"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${video.id}').click()|">
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
</div>
<form th:action="@{/videos/delete/{id}(id=${video.id})}" method="post">
<button th:id="'remove-' + ${video.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>