LabWork05 35
This commit is contained in:
parent
6699eda085
commit
743f35ffef
@ -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'
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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; }
|
||||||
}
|
}
|
||||||
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
|
||||||
|
@ -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; }
|
||||||
}
|
}
|
||||||
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
@ -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}")
|
||||||
|
@ -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; }
|
||||||
}
|
}
|
||||||
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
@ -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; }
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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("*");
|
||||||
|
49
src/main/resources/templates/categories.html
Normal file
49
src/main/resources/templates/categories.html
Normal 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>
|
31
src/main/resources/templates/category-update.html
Normal file
31
src/main/resources/templates/category-update.html
Normal 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>
|
48
src/main/resources/templates/default.html
Normal file
48
src/main/resources/templates/default.html
Normal 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>
|
10
src/main/resources/templates/error.html
Normal file
10
src/main/resources/templates/error.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
31
src/main/resources/templates/manufacturer-update.html
Normal file
31
src/main/resources/templates/manufacturer-update.html
Normal 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>
|
51
src/main/resources/templates/manufacturers.html
Normal file
51
src/main/resources/templates/manufacturers.html
Normal 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>
|
50
src/main/resources/templates/product-mtm.html
Normal file
50
src/main/resources/templates/product-mtm.html
Normal 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>
|
44
src/main/resources/templates/product-update.html
Normal file
44
src/main/resources/templates/product-update.html
Normal 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>
|
59
src/main/resources/templates/products.html
Normal file
59
src/main/resources/templates/products.html
Normal 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>
|
Loading…
Reference in New Issue
Block a user