feature/image #26
@ -1,19 +1,30 @@
 | 
			
		||||
package org.hso.ecommerce.controller.intern;
 | 
			
		||||
 | 
			
		||||
import java.awt.image.BufferedImage;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.nio.file.Paths;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import javax.imageio.ImageIO;
 | 
			
		||||
 | 
			
		||||
import org.hso.ecommerce.entities.shop.Article;
 | 
			
		||||
import org.hso.ecommerce.entities.shop.Category;
 | 
			
		||||
import org.hso.ecommerce.entities.shop.Image;
 | 
			
		||||
import org.hso.ecommerce.entities.supplier.ArticleOffer;
 | 
			
		||||
import org.hso.ecommerce.repos.shop.ArticleRepository;
 | 
			
		||||
import org.hso.ecommerce.repos.shop.CategoryRepository;
 | 
			
		||||
import org.hso.ecommerce.repos.shop.ImageRepository;
 | 
			
		||||
import org.hso.ecommerce.repos.shop.OffersRepository;
 | 
			
		||||
import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.stereotype.Controller;
 | 
			
		||||
import org.springframework.ui.Model;
 | 
			
		||||
import org.springframework.util.DigestUtils;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
import org.springframework.web.servlet.view.RedirectView;
 | 
			
		||||
 | 
			
		||||
@Controller
 | 
			
		||||
@ -31,6 +42,9 @@ public class InternArticleController {
 | 
			
		||||
	@Autowired
 | 
			
		||||
	private final OffersRepository offersRepository = null;
 | 
			
		||||
 | 
			
		||||
	@Autowired
 | 
			
		||||
	private final ImageRepository imageRepository = null;
 | 
			
		||||
 | 
			
		||||
	@GetMapping("/")
 | 
			
		||||
	public String internListedArticles(Model model) {
 | 
			
		||||
 | 
			
		||||
@ -69,12 +83,11 @@ public class InternArticleController {
 | 
			
		||||
			@RequestParam(value = "price_netto", required = true) String pricenetto,
 | 
			
		||||
			@RequestParam(value = "reorderMaxPrice", required = true) String reorderMaxPrice,
 | 
			
		||||
			@RequestParam(value = "autobuy", required = true) Boolean shouldReorder,
 | 
			
		||||
			@RequestParam(value = "categories", required = true) String categories) {
 | 
			
		||||
			@RequestParam(value = "categories", required = true) String categories,
 | 
			
		||||
			@RequestParam(value = "img", required = true) MultipartFile imgFile) {
 | 
			
		||||
 | 
			
		||||
		Article tmpArticle = articleRepository.findArticleById(id); // get the old article
 | 
			
		||||
 | 
			
		||||
		// TODO img
 | 
			
		||||
 | 
			
		||||
		String[] separatedCategories = categories.split("\n");
 | 
			
		||||
 | 
			
		||||
		tmpArticle.categories.clear();
 | 
			
		||||
@ -91,6 +104,7 @@ public class InternArticleController {
 | 
			
		||||
		tmpArticle.shopPricePerUnitNetCent = (int) (Float.parseFloat(pricenetto) * 100);
 | 
			
		||||
		tmpArticle.warehouseUnitsPerSlot = Integer.parseInt(warehouseUnitsPerSlot);
 | 
			
		||||
		tmpArticle.title = title;
 | 
			
		||||
		updateImage(tmpArticle, imgFile);
 | 
			
		||||
		tmpArticle.description = description;
 | 
			
		||||
 | 
			
		||||
		articleRepository.save(tmpArticle); // save updated article
 | 
			
		||||
@ -114,15 +128,67 @@ public class InternArticleController {
 | 
			
		||||
		tmpArticle.shouldReorder = false;
 | 
			
		||||
		tmpArticle.title = offeredArticle.title;
 | 
			
		||||
		tmpArticle.warehouseUnitsPerSlot = 1;
 | 
			
		||||
		tmpArticle.image = articleRepository.findAll().get(0).image; // TODO set any static default image
 | 
			
		||||
		setDefaultImage(tmpArticle);
 | 
			
		||||
		tmpArticle.related = offeredArticle;
 | 
			
		||||
 | 
			
		||||
		articleRepository.save(tmpArticle); // save new article
 | 
			
		||||
 | 
			
		||||
		// return to edit article page
 | 
			
		||||
		return new RedirectView("../" + articleRepository.findArticleIDByRelatedID(offeredArticleID).get());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void setDefaultImage(Article article) {
 | 
			
		||||
		String defaultImagePath = "./data/img/no_product_img.jpg"; // path + name of default img
 | 
			
		||||
		Optional<Integer> imageID = imageRepository.findImageIDByPath(defaultImagePath); // get default img
 | 
			
		||||
 | 
			
		||||
		if (imageID.isPresent()) {
 | 
			
		||||
			// default img is in DB
 | 
			
		||||
			article.image = imageRepository.findImageById(imageID.get()); // set default img to new article
 | 
			
		||||
		} else {
 | 
			
		||||
			// default img is not in DB
 | 
			
		||||
			File tmpFile = new File(defaultImagePath);
 | 
			
		||||
			// test if default img file exits
 | 
			
		||||
			if (!tmpFile.exists()) {
 | 
			
		||||
				// fallback if the file not exists 
 | 
			
		||||
				// create new file
 | 
			
		||||
				BufferedImage bufferedImage = new BufferedImage(422, 428, BufferedImage.TYPE_INT_RGB); 
 | 
			
		||||
				try {
 | 
			
		||||
					ImageIO.write(bufferedImage, "jpg", new File(defaultImagePath)); // save new file on disk
 | 
			
		||||
				} catch (IOException e) {
 | 
			
		||||
					e.printStackTrace();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			Image defaultImage = new Image();
 | 
			
		||||
			defaultImage.path = defaultImagePath; // set new file to default img
 | 
			
		||||
			imageRepository.save(defaultImage); // save default img
 | 
			
		||||
			article.image = defaultImage; // set default img to new article
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void updateImage(Article article, MultipartFile imgFile) {
 | 
			
		||||
		// check if a file is present
 | 
			
		||||
		if (imgFile.getSize() > 0) {
 | 
			
		||||
			try {
 | 
			
		||||
				// get file name based on MD5 hash
 | 
			
		||||
				String fileName = DigestUtils.md5DigestAsHex(imgFile.getBytes()) + ".jpg";
 | 
			
		||||
				// check if img is already in system
 | 
			
		||||
				Optional<Integer> imageID = imageRepository.findImageIDByPath("./data/img/" + fileName);
 | 
			
		||||
				if (imageID.isPresent()) {
 | 
			
		||||
					article.image = imageRepository.findImageById(imageID.get()); // add existing img to article
 | 
			
		||||
				} else {
 | 
			
		||||
					// write new img file to disk
 | 
			
		||||
					Files.newOutputStream(Paths.get("./data/img/", fileName)).write(imgFile.getBytes());
 | 
			
		||||
					// create new img
 | 
			
		||||
					Image newImage = new Image();
 | 
			
		||||
					newImage.path = "./data/img/" + fileName; // set new file to new img
 | 
			
		||||
					imageRepository.save(newImage); // save new img
 | 
			
		||||
					article.image = newImage; // set new img to article
 | 
			
		||||
				}
 | 
			
		||||
			} catch (Exception e) {
 | 
			
		||||
				setDefaultImage(article); // if upload failed, reset to default img
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static class UImodelArticles {
 | 
			
		||||
 | 
			
		||||
		public String imgPath;
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,20 @@
 | 
			
		||||
package org.hso.ecommerce.repos.shop;
 | 
			
		||||
 | 
			
		||||
import org.hso.ecommerce.entities.shop.Image;
 | 
			
		||||
import org.springframework.data.jpa.repository.JpaRepository;
 | 
			
		||||
import org.springframework.data.jpa.repository.Query;
 | 
			
		||||
import org.springframework.data.repository.query.Param;
 | 
			
		||||
import org.springframework.stereotype.Repository;
 | 
			
		||||
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
 | 
			
		||||
@Repository
 | 
			
		||||
public interface ImageRepository extends JpaRepository<Image, Long> {
 | 
			
		||||
 | 
			
		||||
	@Query("SELECT i.id FROM Image i WHERE i.path = :path")
 | 
			
		||||
	Optional<Integer> findImageIDByPath(@Param("path") String path);
 | 
			
		||||
 | 
			
		||||
	@Query("SELECT i FROM Image i WHERE i.id = :imageId")
 | 
			
		||||
	Image findImageById(@Param("imageId") long imageId);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -16,6 +16,8 @@ spring.jpa.show-sql=true
 | 
			
		||||
#server.servlet.session.persistent=true
 | 
			
		||||
# ----------------------------------------
 | 
			
		||||
# WEB PROPERTIES
 | 
			
		||||
spring.servlet.multipart.max-file-size=10MB
 | 
			
		||||
spring.servlet.multipart.max-request-size=10MB
 | 
			
		||||
# ----------------------------------------
 | 
			
		||||
# EMBEDDED SERVER CONFIGURATION (ServerProperties)
 | 
			
		||||
server.address=::1
 | 
			
		||||
 | 
			
		||||
@ -278,7 +278,7 @@ img.s {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
img.m {
 | 
			
		||||
   width: var(--u8);
 | 
			
		||||
   width: 20rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 13 KiB  | 
| 
		 Before Width: | Height: | Size: 18 KiB  | 
| 
		 Before Width: | Height: | Size: 15 KiB  | 
| 
		 Before Width: | Height: | Size: 5.5 KiB  | 
| 
		 Before Width: | Height: | Size: 9.1 KiB  | 
| 
		 Before Width: | Height: | Size: 14 KiB  | 
| 
		 Before Width: | Height: | Size: 12 KiB  | 
| 
		 Before Width: | Height: | Size: 8.7 KiB  | 
@ -24,7 +24,7 @@
 | 
			
		||||
            <form class="detailgrid" action="#" th:action="@{/intern/articles/{id}/saveChanges(id = ${ArticleID.id})}" th:object="${ArticleID}" method="POST" enctype="multipart/form-data">
 | 
			
		||||
               <p class="m">
 | 
			
		||||
                  <label for="title">Titel</label>
 | 
			
		||||
                  <input class=" full-width" type="text" id="title" name="title" th:value="${ArticleID.title}"/>
 | 
			
		||||
                  <input class=" full-width" type="text" id="title" name="title" required="required" pattern="[A-Za-z0-9]{1,20}" th:value="${ArticleID.title}"/>
 | 
			
		||||
               </p>
 | 
			
		||||
               <p class="s">
 | 
			
		||||
                  <label for="ref-article">Refernzierter Artikel</label>
 | 
			
		||||
 | 
			
		||||
@ -53,7 +53,7 @@
 | 
			
		||||
                     <td><span th:text="${article.price_netto}"></span> €</td>
 | 
			
		||||
                     <td><span th:text="${article.categorie}"></span></td>
 | 
			
		||||
                     <td><span th:text="${article.stock}"></span></td>
 | 
			
		||||
                     <td><a th:href="${'/intern/supplierOffers/#q=' + {article.id}}" th:text="${article.offer_id}"></a></td>
 | 
			
		||||
                     <td><a th:href="${'/intern/supplierOffers/#q=' + {article.title}}" th:text="${article.offer_id}"></a></td>
 | 
			
		||||
                     <td><a th:href="@{/intern/articles/{id}(id = ${article.id})}" th:text="${article.id}"></a></td>
 | 
			
		||||
                     <td>
 | 
			
		||||
                        <form th:action="@{/intern/articles/{id}(id = ${article.id})}"><input type="submit" value="Bearbeiten" /></form>
 | 
			
		||||
 | 
			
		||||