LabWork05 35

This commit is contained in:
Артём Алейкин 2023-05-14 23:44:06 +04:00
parent 6699eda085
commit 743f35ffef
25 changed files with 755 additions and 38 deletions

View File

@ -13,11 +13,14 @@ repositories {
} }
dependencies { dependencies {
// https://mvnrepository.com/artifact/commons-io/commons-io
implementation group: 'commons-io', name: 'commons-io', version: '2.6'
implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.h2database:h2:2.1.210' implementation 'com.h2database:h2:2.1.210'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
implementation 'org.webjars:bootstrap:5.1.3'
implementation 'org.webjars:jquery:3.6.0'
implementation 'org.webjars:font-awesome:6.1.0'
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.5' implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.5'

View File

@ -19,9 +19,6 @@
<td> <td>
<button class="btn btn-danger" @click="deleteCategory(categor.id)">Удалить</button> <button class="btn btn-danger" @click="deleteCategory(categor.id)">Удалить</button>
</td> </td>
<td>
<button class="btn btn-primary mr-2" @click="OpenModelForProducts();getProductsFromCategory(categor.id)">Просмотр продуктов</button>
</td>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -98,9 +95,6 @@ export default {
const addModal = document.getElementById('editModal'); const addModal = document.getElementById('editModal');
addModal.addEventListener('shown.bs.modal', function () { addModal.addEventListener('shown.bs.modal', function () {
}) })
const ModelForProducts = document.getElementById('ModelForProducts');
addModal.addEventListener('shown.bs.modal', function () {
})
}, },
data() { data() {
@ -169,22 +163,6 @@ export default {
console.log(error); console.log(error);
}); });
}, },
getProductsFromCategory(category_id){
axios.get(this.URL + `group/${category_id}/products`)
.then(response => {
this.products = response.data;
console.log(response.data);
})
.catch(error => {
console.log(error);
});
},
OpenModelForProducts() {
document.getElementById("ModelForProducts").style.display = "block";
},
closeModelForProducts() {
document.getElementById("ModelForProducts").style.display = "none";
},
} }
} }
</script> </script>

View File

@ -25,6 +25,9 @@
<td> <td>
<button class="btn btn-danger" @click="deleteProduct(prdct.id)">Удалить</button> <button class="btn btn-danger" @click="deleteProduct(prdct.id)">Удалить</button>
</td> </td>
<td>
<button class="btn btn-primary" @click="product = prdct; openManyToManyModal()">Производители</button>
</td>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -69,6 +72,44 @@
</div> </div>
</div> </div>
</div> </div>
<div class="modal" tabindex="-1" id="manyToManyModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add Manufacturers to Product</h5>
</div>
<div class="modal-body">
<form>
<table class="table table-striped">
<thead>
<tr>
<th>Название:</th>
<th>Редактировать запись:</th>
</tr>
</thead>
<tbody>
<tr v-for="prod in productManufacturers" :key="prod.id">
<td>{{ prod.name }}</td>
<td>
<button class="btn btn-primary" type="button" @click="removeManufacturer(prod.id)">Удалить</button>
</td>
</tr>
</tbody>
</table>
<div class="input-group mb-3">
<select class="form-select" v-model="manufacturerId">
<option v-for="mnfctr in manufacturers" :key="mnfctr.id" :value="mnfctr.id">{{ mnfctr.name }}</option>
</select>
<button class="btn btn-outline-secondary" type="button" @click="addManufacturer()">Добавить</button>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="editModal" @click="closeManyToManyModal()">Закрыть</button>
</div>
</div>
</div>
</div>
</template> </template>
<script> <script>
import 'axios'; import 'axios';
@ -89,6 +130,9 @@ export default {
return{ return{
products: [], products: [],
categories: [], categories: [],
manufacturers: [],
productManufacturers: [],
manufacturerId: 0,
URL: "http://localhost:8080/", URL: "http://localhost:8080/",
product: new Product(), product: new Product(),
editedProduct: new Product(), editedProduct: new Product(),
@ -135,7 +179,8 @@ export default {
}) })
}, },
async editProduct(product){ async editProduct(product){
await this.toBase64(); if(product.photo === undefined) await this.toBase64();
console.log(product);
axios.put(this.URL + `product/${product.id}`, product) axios.put(this.URL + `product/${product.id}`, product)
.then(() =>{ .then(() =>{
const index = this.products.findIndex((s) => s.id === product.id); const index = this.products.findIndex((s) => s.id === product.id);
@ -169,7 +214,7 @@ export default {
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
reader.onload = function () { reader.onload = function () {
phototemp.photo = reader.result; phototemp.photo = reader.result;
console.log("phototemp: " + phototemp); console.log(phototemp);
resolve(); resolve();
}; };
reader.onerror = function (error) { reader.onerror = function (error) {
@ -178,6 +223,49 @@ export default {
}; };
}); });
}, },
openManyToManyModal(){
this.getAllManufacturers();
this.getProductManufacturers();
document.getElementById("manyToManyModal").style.display = "block";
},
closeManyToManyModal() {
document.getElementById("manyToManyModal").style.display = "none";
},
getAllManufacturers(){
axios.get(this.URL + "manufacturer")
.then(response => {
this.manufacturers = response.data;
console.log(response.data);
})
.catch(error => {
console.log(error);
});
},
getProductManufacturers(){
axios.get(this.URL + `product/${this.product.id}/manufacturers`)
.then(response => {
this.productManufacturers = response.data;
console.log(response.data);
})
.catch(error => {
console.log(error);
});
},
addManufacturer(){
axios.post(this.URL + `product/${this.product.id}/Manufacturer/${this.manufacturerId}`)
.then(() => {
this.getProductManufacturers();
})
.catch(error => {
console.log(error);
});
},
removeManufacturer(id){
axios.delete(this.URL + `product/${this.product.id}/Manufacturer/${id}`)
.then(() =>{
this.getProductManufacturers();
})
}
} }
} }
</script> </script>

View File

@ -3,6 +3,7 @@ package ru.ulstu.is.sbapp.HardwareShop.controller;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.sbapp.HardwareShop.models.Category; import ru.ulstu.is.sbapp.HardwareShop.models.Category;
import ru.ulstu.is.sbapp.HardwareShop.services.CategoryService; import ru.ulstu.is.sbapp.HardwareShop.services.CategoryService;
import ru.ulstu.is.sbapp.WebConfiguration;
import javax.validation.Valid; import javax.validation.Valid;
import javax.xml.crypto.dsig.CanonicalizationMethod; import javax.xml.crypto.dsig.CanonicalizationMethod;
@ -11,7 +12,7 @@ import java.io.IOException;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/category") @RequestMapping(WebConfiguration.REST_API + "/category")
public class CategoryController { public class CategoryController {
private final CategoryService categoryService; private final CategoryService categoryService;

View File

@ -24,4 +24,8 @@ public class CategoryDTO {
public String getName() { public String getName() {
return name; return name;
} }
public void setId(Long id) { this.id = id; }
public void setName(String name) { this.name = name; }
} }

View File

@ -0,0 +1,65 @@
package ru.ulstu.is.sbapp.HardwareShop.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.sbapp.HardwareShop.models.Category;
import ru.ulstu.is.sbapp.HardwareShop.services.CategoryService;
import java.io.IOException;
@Controller
@RequestMapping("/category")
public class CategoryMvcController {
private final CategoryService categoryService;
public CategoryMvcController(CategoryService categoryService) {
this.categoryService = categoryService;
}
@GetMapping
public String getCategories(Model model) {
model.addAttribute("categories", categoryService.findAllCategories()
.stream()
.map(CategoryDTO::new)
.toList());
return "categories";
}
@GetMapping(value = {"/update", "/update/{id}"})
public String updateCategory(@PathVariable(required = false) Long id,
Model model) {
if (id == null || id <= 0) {
model.addAttribute("categoryDto", new CategoryDTO());
} else {
model.addAttribute("categoryDto", id);
model.addAttribute("categoryDto", new CategoryDTO(categoryService.findCategory(id)));
}
return "category-update";
}
@PostMapping(value = {"/", "/{id}"})
public String saveCategory(@PathVariable(required = false) Long id,
@ModelAttribute("categoryDto") CategoryDTO categoryDTO,
BindingResult bindingResult,
Model model) throws IOException {
if (bindingResult.hasErrors()) {
model.addAttribute("errors",
bindingResult.getAllErrors());
return "category-update";
}
if (id == null || id <= 0) {
categoryService.addCategory(categoryDTO);
} else {
categoryService.updateCategory(id, categoryDTO);
}
return "redirect:/category";
}
@PostMapping("/delete/{id}")
public String deleteCategory(@PathVariable Long id) {
categoryService.deleteCategory(id);
return "redirect:/category";
}
}

View File

@ -4,13 +4,14 @@ package ru.ulstu.is.sbapp.HardwareShop.controller;
import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.sbapp.HardwareShop.services.ManufacturerService; import ru.ulstu.is.sbapp.HardwareShop.services.ManufacturerService;
import ru.ulstu.is.sbapp.WebConfiguration;
import javax.validation.Valid; import javax.validation.Valid;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/manufacturer") @RequestMapping(WebConfiguration.REST_API + "/manufacturer")
public class ManufacturerController { public class ManufacturerController {
private final ManufacturerService manufacturerService; private final ManufacturerService manufacturerService;

View File

@ -30,4 +30,10 @@ public class ManufacturerDTO {
public String getAddress() { public String getAddress() {
return address; return address;
} }
public void setId(Long id) { this.id = id; }
public void setName(String name) { this.name = name; }
public void setAddress(String address) { this.address = address; }
} }

View File

@ -0,0 +1,64 @@
package ru.ulstu.is.sbapp.HardwareShop.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.sbapp.HardwareShop.services.ManufacturerService;
import java.io.IOException;
@Controller
@RequestMapping("/manufacturer")
public class ManufacturerMvcController {
private final ManufacturerService manufacturerService;
public ManufacturerMvcController(ManufacturerService manufacturerService) {
this.manufacturerService = manufacturerService;
}
@GetMapping
public String getManufacturers(Model model) {
model.addAttribute("manufacturers",
manufacturerService.findAllManufacturers().stream()
.map(ManufacturerDTO::new)
.toList());
return "manufacturers";
}
@GetMapping(value = {"/update", "/update/{id}"})
public String editManufacturer(@PathVariable(required = false) Long id,
Model model) {
if (id == null || id <= 0) {
model.addAttribute("manufacturerDto", new ManufacturerDTO());
} else {
model.addAttribute("manufacturerDto", id);
model.addAttribute("manufacturerDto", new ManufacturerDTO(manufacturerService.findManufacturer(id)));
}
return "manufacturer-update";
}
@PostMapping(value = {"/", "/{id}"})
public String saveManufacturer(@PathVariable(required = false) Long id,
@ModelAttribute("manufacturerDto") ManufacturerDTO manufacturerDTO,
BindingResult bindingResult,
Model model) throws IOException {
if (bindingResult.hasErrors()) {
model.addAttribute("errors",
bindingResult.getAllErrors());
return "manufacturer-update";
}
if (id == null || id <= 0) {
manufacturerService.addManufacturer(manufacturerDTO);
} else {
manufacturerService.updateManufacturer(id, manufacturerDTO);
}
return "redirect:/manufacturer";
}
@PostMapping("/delete/{id}")
public String deleteGenre(@PathVariable Long id) {
manufacturerService.deleteManufacturer(id);
return "redirect:/manufacturer";
}
}

View File

@ -6,6 +6,7 @@ import org.springframework.web.multipart.MultipartFile;
import ru.ulstu.is.sbapp.HardwareShop.models.Product; import ru.ulstu.is.sbapp.HardwareShop.models.Product;
import ru.ulstu.is.sbapp.HardwareShop.services.ManufacturerService; import ru.ulstu.is.sbapp.HardwareShop.services.ManufacturerService;
import ru.ulstu.is.sbapp.HardwareShop.services.ProductService; import ru.ulstu.is.sbapp.HardwareShop.services.ProductService;
import ru.ulstu.is.sbapp.WebConfiguration;
import javax.validation.Valid; import javax.validation.Valid;
import java.io.IOException; import java.io.IOException;
@ -13,7 +14,7 @@ import java.util.Base64;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/product") @RequestMapping(WebConfiguration.REST_API + "/product")
public class ProductController { public class ProductController {
private final ProductService productService; private final ProductService productService;
@ -34,6 +35,11 @@ public class ProductController {
.toList(); .toList();
} }
@GetMapping("/{id}/manufacturers")
public List<ManufacturerDTO> getProductManufacturers(@PathVariable Long id){
return productService.getProductManufacturers(id).stream().map(ManufacturerDTO::new).toList();
}
@PostMapping @PostMapping
public ProductDTO createProduct(@RequestBody @Valid ProductDTO productDTO) throws IOException{ public ProductDTO createProduct(@RequestBody @Valid ProductDTO productDTO) throws IOException{
return new ProductDTO(productService.addProduct(productDTO)); return new ProductDTO(productService.addProduct(productDTO));
@ -44,9 +50,14 @@ public class ProductController {
return new ProductDTO(productService.updateProduct(id, productDTO)); return new ProductDTO(productService.updateProduct(id, productDTO));
} }
@PostMapping("/{id}/{manufacturer}") @PostMapping("/{id}/Manufacturer/{manufacturerId}")
public void addManufacturer(@PathVariable Long id, @PathVariable Long manufacturer_id) { public void addManufacturer(@PathVariable Long id, @PathVariable Long manufacturerId) {
productService.addManufacturersToProduct(id, manufacturer_id); productService.addManufacturersToProduct(id, manufacturerId);
}
@DeleteMapping("/{id}/Manufacturer/{manufacturerId}")
public void removeManufacturer(@PathVariable Long id, @PathVariable Long manufacturerId) {
productService.removeManufacturersToProduct(id, manufacturerId);
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")

View File

@ -15,6 +15,8 @@ public class ProductDTO {
@JsonProperty("categoryId") @JsonProperty("categoryId")
private Long category_id; private Long category_id;
private String categoryName;
private String name; private String name;
public ProductDTO() {} public ProductDTO() {}
@ -25,6 +27,7 @@ public class ProductDTO {
this.price = product.getPrice(); this.price = product.getPrice();
this.photo = new String(product.getPhoto(), StandardCharsets.UTF_8); this.photo = new String(product.getPhoto(), StandardCharsets.UTF_8);
this.category_id = product.getCategory().getId(); this.category_id = product.getCategory().getId();
this.categoryName = product.getCategory().getName();
} }
public Long getId() { public Long getId() {
@ -45,9 +48,15 @@ public class ProductDTO {
return category_id; return category_id;
} }
public String getCategoryName() { return categoryName; }
public void setId(Long id) { this.id = id; }
public void setPhoto(String photo) { this.photo = photo; } public void setPhoto(String photo) { this.photo = photo; }
public void setName(String name) { this.name = name; } public void setName(String name) { this.name = name; }
public void setPrice(Integer price) { this.price = price; } public void setPrice(Integer price) { this.price = price; }
public void setCategoryName(String name) { this.categoryName = name; }
} }

View File

@ -0,0 +1,104 @@
package ru.ulstu.is.sbapp.HardwareShop.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import ru.ulstu.is.sbapp.HardwareShop.services.CategoryService;
import ru.ulstu.is.sbapp.HardwareShop.services.ManufacturerService;
import ru.ulstu.is.sbapp.HardwareShop.services.ProductService;
import java.io.IOException;
import java.util.Base64;
@Controller
@RequestMapping("/product")
public class ProductMvcController {
private final ProductService productService;
private final ManufacturerService manufacturerService;
private final CategoryService categoryService;
public ProductMvcController(ProductService productService, ManufacturerService manufacturerService, CategoryService categoryService) {
this.productService = productService;
this.manufacturerService = manufacturerService;
this.categoryService = categoryService;
}
@GetMapping
public String getProducts(Model model) {
model.addAttribute("products",
productService.findAllProducts().stream()
.map(ProductDTO::new)
.toList());
return "products";
}
@GetMapping(value = {"/update", "/update/{id}"})
public String updateProduct(@PathVariable(required = false) Long id,
Model model) {
model.addAttribute("Manufacturers", manufacturerService.findAllManufacturers());
if (id == null || id <= 0) {
model.addAttribute("productDto", new ProductDTO());
} else {
model.addAttribute("productDto", id);
model.addAttribute("productDto", new ProductDTO(productService.findProduct(id)));
}
return "product-update";
}
@PostMapping(value = {"/", "/{id}"})
public String saveProduct(@PathVariable(required = false) Long id,
@RequestParam(value = "multipartFile") MultipartFile multipartFile,
@ModelAttribute("productDto") ProductDTO productDTO,
BindingResult bindingResult,
Model model) throws IOException {
if (bindingResult.hasErrors()) {
model.addAttribute("errors",
bindingResult.getAllErrors());
return "product-update";
}
productDTO.setPhoto("data:" + multipartFile.getContentType() + ";base64," + Base64.getEncoder().encodeToString(multipartFile.getBytes()));
productDTO.setCategoryName(categoryService.findCategory(productDTO.getCategory_id()).getName());
if (id == null || id <= 0) {
productService.addProduct(productDTO);
} else {
productService.updateProduct(id, productDTO);
}
return "redirect:/product";
}
@PostMapping("/delete/{id}")
public String deleteBook(@PathVariable Long id) {
productService.deleteProduct(id);
return "redirect:/product";
}
@GetMapping("/{id}/manufacturers")
public String getProductManufacturers(@PathVariable Long id, Model model){
model.addAttribute("product",
new ProductDTO(productService.findProduct(id)));
model.addAttribute("productmanufacturers",
productService.getProductManufacturers(id).stream()
.map(ManufacturerDTO::new)
.toList());
model.addAttribute("manufacturers",
manufacturerService.findAllManufacturers().stream()
.map(ManufacturerDTO::new)
.toList());
return "product-mtm";
}
@PostMapping("/{id}/manufacturers")
public String addManufacturerToProduct(@PathVariable Long id, @RequestParam(value = "manufacturerid") Long manufacturerid){
productService.addManufacturersToProduct(id, manufacturerid);
return "redirect:/product/" + id.toString() + "/manufacturers";
}
@PostMapping("/{id}/manufacturers/{manufacturerid}")
public String removeManufacturerFromProduct(@PathVariable Long id, @PathVariable Long manufacturerid){
productService.removeManufacturersToProduct(id, manufacturerid);
return "redirect:/product/" + id.toString() + "/manufacturers";
}
}

View File

@ -58,7 +58,7 @@ public class Product {
public String getName() { return name; } public String getName() { return name; }
public void setName() { this.name = name; } public void setName(String name) { this.name = name; }
public void setPrice(Integer price) { this.price = price; } public void setPrice(Integer price) { this.price = price; }

View File

@ -76,8 +76,10 @@ public class ProductService {
@Transactional @Transactional
public Product updateProduct(Long id, ProductDTO productDTO) { public Product updateProduct(Long id, ProductDTO productDTO) {
final Product currentProduct = findProduct(id); final Product currentProduct = findProduct(id);
currentProduct.setName(productDTO.getName());
currentProduct.setPrice(productDTO.getPrice()); currentProduct.setPrice(productDTO.getPrice());
/*currentProduct.setPhoto(productDTO.getPhoto().getBytes(StandardCharsets.UTF_8));*/ currentProduct.setPhoto(productDTO.getPhoto().getBytes(StandardCharsets.UTF_8));
currentProduct.setCategory(categoryService.findCategory(productDTO.getCategory_id()));
validatorUtil.validate(currentProduct); validatorUtil.validate(currentProduct);
return productRepository.save(currentProduct); return productRepository.save(currentProduct);
} }
@ -121,8 +123,7 @@ public class ProductService {
} }
@Transactional @Transactional
public List getProductManufacturers(Long id){ public List<Manufacturer> getProductManufacturers(Long id){
List manufacturers = productRepository.getManufacturers(id); return productRepository.findById(id).get().getManufacturerList();
return manufacturers;
} }
} }

View File

@ -7,10 +7,11 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.RestController;
import ru.ulstu.is.sbapp.Util.Validation.ValidationException; import ru.ulstu.is.sbapp.Util.Validation.ValidationException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ControllerAdvice @ControllerAdvice(annotations = RestController.class)
public class AdviceController { public class AdviceController {
@ExceptionHandler({ @ExceptionHandler({
ValidationException.class ValidationException.class

View File

@ -2,10 +2,18 @@ package ru.ulstu.is.sbapp;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration @Configuration
public class WebConfiguration implements WebMvcConfigurer { public class WebConfiguration implements WebMvcConfigurer {
public static final String REST_API = "/api";
@Override
public void addViewControllers(ViewControllerRegistry registry) {
WebMvcConfigurer.super.addViewControllers(registry);
registry.addViewController("product");
}
@Override @Override
public void addCorsMappings(CorsRegistry registry) { public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*"); registry.addMapping("/**").allowedMethods("*");

View File

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content">
<div>
<a class="btn btn-success button-fixed"
th:href="@{/category/update/}">
<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>
</tr>
</thead>
<tbody>
<tr th:each="category, iterator: ${categories}">
<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="@{/category/update/{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-${category.id}').click()|">
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
</div>
<form th:action="@{/category/delete/{id}(id=${category.id})}" method="post">
<button th:id="'remove-' + ${category.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content">
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/category/{id}(id=${id})}" th:object="${categoryDto}" method="post">
<div class="mb-3">
<label for="name" class="form-label">Название</label>
<input type="text" class="form-control" id="name" th:field="${categoryDto.name}" required="true">
</div>
<div class="mb-3">
<button type="submit" class="btn btn-success button-fixed">
<span th:if="${id == null}">
<i class="fa-solid fa-plus"></i> Добавить
</span>
<span th:if="${id != null}">
<i class="fa fa-pencil" aria-hidden="true"></i> Сохранить
</span>
</button>
<a class="btn btn-secondary button-fixed" th:href="@{/category}">
Назад
</a>
</div>
</form>
</div>
</body>
</html>

View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>Онлайн магазин</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="icon" href="/favicon.svg">
<script type="text/javascript" src="/webjars/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="/webjars/bootstrap/5.1.3/css/bootstrap.min.css"/>
<link rel="stylesheet" href="/webjars/font-awesome/6.1.0/css/all.min.css"/>
</head>
<body>
<header class="fixed-top">
<nav class="navbar navbar-expand-lg bg-success" data-bs-theme="dark">
<div class="container">
<a class="navbar-brand" href="#">
<strong class="text-white"> Online Shop </strong>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="navbar-nav" th:with="activeLink=${#request.requestURI}">
<a class="nav-link active text-white" aria-current="page" href="/product" th:classappend="${#strings.equals(activeLink, '/product')} ? 'active' : ''">Products</a>
<a class="nav-link active text-white" href="/category" th:classappend="${#strings.equals(activeLink, '/category')} ? 'active' : ''">Categories</a>
<a class="nav-link active text-white" href="/manufacturer" th:classappend="${#strings.equals(activeLink, '/manufacturer')} ? 'active' : ''">Manufacturers</a>
</div>
</div>
</div>
</nav>
</header>
<div class="container-fluid" style="margin-top: 50pt;">
<div class="container container-padding" layout:fragment="content">
</div>
</div>
<footer class="container pt-4 my-md-5 pt-md-5 text-center border-top">
<div class="row">
<div class="col-12 col-md">
<h5 class=""><strong>End</strong></h5>
</div>
</div>
</footer>
</body>
<th:block layout:fragment="scripts">
</th:block>
</html>

View File

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

View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content">
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/manufacturer/{id}(id=${id})}" th:object="${manufacturerDto}" method="post">
<div class="mb-3">
<label for="name" class="form-label">Название</label>
<input type="text" class="form-control" id="name" th:field="${manufacturerDto.name}" required="true">
</div>
<div class="mb-3">
<button type="submit" class="btn btn-success button-fixed">
<span th:if="${id == null}">
<i class="fa-solid fa-plus"></i> Добавить
</span>
<span th:if="${id != null}">
<i class="fa fa-pencil" aria-hidden="true"></i> Сохранить
</span>
</button>
<a class="btn btn-secondary button-fixed" th:href="@{/manufacturer}">
Назад
</a>
</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="@{/manufacturer/update/}">
<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="manufacturer, iterator: ${manufacturers}">
<td th:text="${manufacturer.name}" style="width: 35%"/>
<td th:text="${manufacturer.address}" style="width: 35%"/>
<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="@{/manufacturer/update/{id}(id=${manufacturer.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-${manufacturer.id}').click()|">
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
</div>
<form th:action="@{/manufacturer/delete/{id}(id=${manufacturer.id})}" method="post">
<button th:id="'remove-' + ${manufacturer.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,50 @@
<!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 class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col">Название</th>
<th scope="col">Редактировать запись</th>
</tr>
</thead>
<tbody>
<tr th:each="pm, iterator: ${productmanufacturers}">
<td th:text="${pm.name}" style="width: 25%"/>
<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-${pm.id}').click()|">
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
</div>
<form th:action="@{/product/{id}/manufacturers/{manufacturerid}(id=${product.id}, manufacturerid=${bg.id})}" method="post">
<button th:id="'remove-' + ${pm.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
<form th:action="@{/product/{id}/manufacturers(id=${product.id})}" enctype="manufacturerid/form-data" method="post">
<div class="input-group mb-3">
<select class="form-select" th:name="manufacturerid">
<option th:each="manufacturer, iterator: ${manufacturers}" th:value="${manufacturer.id}" th:text="${manufacturer.name}"></option>
</select>
<button class="btn btn-outline-secondary" type="submit">Добавить</button>
</div>
</form>
<div>
<a class="btn btn-secondary" th:href="@{/product}">Закрыть</a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,44 @@
<!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="@{/product/{id}(id=${id})}" th:object="${productDto}" method="post" enctype="multipart/form-data">
<div class="mb-3">
<label for="name" class="form-label">Название</label>
<input type="text" class="form-control" id="name" th:field="${productDto.name}" required="true">
</div>
<div class="mb-3">
<label for="price" class="form-label">Цена</label>
<input type="text" class="form-control" id="price" th:field="${productDto.price}" required="true">
</div>
<div class="mb-3">
<label for="photo" class="form-label">Фото</label>
<input type="file" class="form-control" id="photo" th:name="multipartFile" required="true">
<img th:src="${productDto.photo}" class="img-thumbnail mw-50 mh-50"/>
</div>
<label for="category" class="form-label">Категория</label>
<select id="category" class="form-control" th:field="${productDto.category_id}">
<option th:each="category : ${categories}" th:value="${category.id}" th:text="${category.name}"></option>
</select>
<div class="mb-3">
<button type="submit" class="btn btn-success button-fixed">
<span th:if="${id == null}">
<i class="fa-solid fa-plus"></i> Добавить
</span>
<span th:if="${id != null}">
<i class="fa fa-pencil" aria-hidden="true"></i> Сохранить
</span>
</button>
<a class="btn btn-secondary button-fixed" th:href="@{/product}">
Назад
</a>
</div>
</form>
</div>
</body>
</html>

View File

@ -0,0 +1,59 @@
<!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="@{/product/update/}">
<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>
</tr>
</thead>
<tbody>
<tr th:each="product, iterator: ${products}">
<td th:text="${product.name}" style="width: 25%"/>
<td th:text="${product.price}" style="width: 25%"/>
<td><img th:src="${product.photo}" class="img-thumbnail mw-50 mh-50"/></td>
<td th:text="${product.categoryName}" style="width: 25%"/>
<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="@{/product/update/{id}(id=${product.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-${product.id}').click()|">
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
<a class="btn btn-primary button-fixed button-sm"
th:href="@{/product/{id}/manufacturers(id=${product.id})}">
<i class="fa fa-pencil" aria-hidden="true"></i> Производители
</a>
</div>
<form th:action="@{/product/delete/{id}(id=${product.id})}" method="post">
<button th:id="'remove-' + ${product.id}" type="submit" style="display: none">
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>