Début d'ajout des langues

This commit is contained in:
FyloZ 2019-08-20 22:38:20 -04:00
parent e7be998913
commit c818f9f7b6
42 changed files with 1688 additions and 169 deletions

View File

@ -15,6 +15,7 @@
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>

Binary file not shown.

View File

@ -0,0 +1,51 @@
package fyloz.trial.ColorRecipesExplorer.core.configuration;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import java.util.Locale;
@Configuration
public class LocaleConfiguration implements WebMvcConfigurer {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:lang/messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.FRENCH);
return localeResolver;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
return localeChangeInterceptor;
}
@Bean
public LocalValidatorFactoryBean validator(MessageSource messageSource) {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource);
return bean;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
}

View File

@ -25,8 +25,8 @@ public class Material extends BeanModel implements Serializable {
@ColumnDefault("false")
private boolean isMixType = false;
// Peut être null pour la création des types de mélanges
@ManyToOne
@NotNull
private MaterialType materialType;
public Material() {

View File

@ -17,6 +17,15 @@ public class CompanyService extends GenericService<Company> {
this.recipeDao = recipeDao;
}
@Override
public boolean isValidForCreation(Company entity) {
return super.isValidForCreation(entity) && getByName(entity.getCompanyName()) == null;
}
public Company getByName(String name) {
return ((CompanyDao) dao).findByCompanyName(name);
}
/**
* Vérifie si une bannière est liée à une ou plusieurs recettes en faisant une requête dans la base de données,
* pour retourner s'il y a des résultats ou non.

View File

@ -21,7 +21,22 @@ public class MaterialTypeService extends GenericService<MaterialType> {
return entity != null && !existsByName(entity);
}
public MaterialType getByName(String name) {
return materialTypeDao.findByMaterialTypeName(name);
}
public MaterialType getDefaultMaterialType() {
MaterialType defaultType = getByName("Aucun");
if (defaultType == null) {
defaultType = new MaterialType("Aucun", "", false);
save(defaultType);
}
return defaultType;
}
public boolean existsByName(MaterialType entity) {
return materialTypeDao.findByMaterialTypeName(entity.getMaterialTypeName()) != null;
return getByName(entity.getMaterialTypeName()) != null;
}
}

View File

@ -10,11 +10,13 @@ import org.springframework.stereotype.Service;
public class MixTypeService extends GenericService<MixType> {
private MixTypeDao mixTypeDao;
private MaterialTypeService materialTypeService;
@Autowired
public MixTypeService(MixTypeDao mixTypeDao) {
public MixTypeService(MixTypeDao mixTypeDao, MaterialTypeService materialTypeService) {
super(mixTypeDao);
this.mixTypeDao = mixTypeDao;
this.materialTypeService = materialTypeService;
}
public MixType getByName(String name) {
@ -26,7 +28,7 @@ public class MixTypeService extends GenericService<MixType> {
}
public MixType createByName(String name) {
Material mixTypeMaterial = new Material(name, 0, true, null);
Material mixTypeMaterial = new Material(name, 0, true, materialTypeService.getDefaultMaterialType());
MixType mixType = new MixType(name, mixTypeMaterial);
mixType = save(mixType);

View File

@ -65,4 +65,8 @@ public class IndexController {
public boolean validatePassword(@RequestBody Map<String, Object> data) {
return PasswordValidator.isValid((String) data.get("password"));
}
/**
* Donne acc
*/
}

View File

@ -7,6 +7,7 @@ import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import javax.validation.Valid;
@ -31,7 +32,8 @@ public class CompanyCreatorController {
* @return La page à afficher.
*/
@GetMapping(CREATOR_COMPANY)
public String showCreationPage() {
public String showCreationPage(Model model, Company company) {
model.addAttribute("company", company);
return CREATOR_COMPANY;
}
@ -49,12 +51,11 @@ public class CompanyCreatorController {
* <p>
* REQUIERT UNE AUTORISATION
*
* @param model Le modèle injecté par Thymeleaf
* @param company La bannière à créer
* @return La page à afficher.
*/
@PostMapping(value = CREATOR_COMPANY, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String createCompany(Model model, @Valid Company company) {
public String createCompany(Model model, @ModelAttribute @Valid Company company) {
if (companyService.isValidForCreation(company)) {
if ((company = companyService.save(company)) != null) {
model.addAttribute("companyName", company.getCompanyName());
@ -66,6 +67,6 @@ public class CompanyCreatorController {
model.addAttribute(RESPONSE_ERROR, String.format(COMPANY_ALREADY_EXIST, company.getCompanyName()));
}
return showCreationPage();
return showCreationPage(model, company);
}
}

View File

@ -11,13 +11,14 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.MultiValueMap;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
@ -86,18 +87,21 @@ public class MixCreatorController {
* @return La page à afficher.
*/
@PostMapping(value = CREATOR_MIX, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String createMix(Model model, @RequestBody MultiValueMap<String, String> form) {
String mixTypeName = form.getFirst(MIX_TYPE);
int recipeID = Integer.parseInt(form.getFirst(RECIPE_ID));
public String createMix(Model model, @RequestBody LinkedMultiValueMap<String, String> form) {
String mixTypeName = form.get(MIX_TYPE).get(0);
int recipeID = Integer.parseInt(form.get(RECIPE_ID).get(0));
List<Integer> materials = new ArrayList<>();
List<Float> quantities = new ArrayList<>();
// Trie les valeurs du formulaire de création du mélange
for (String key : form.keySet()) {
String value = form.getFirst(key);
LinkedList<String> value = (LinkedList) form.get(key);
if (key.startsWith("product")) materials.add(Integer.parseInt(value));
else if (key.startsWith("quantity") && !value.isEmpty()) quantities.add(Float.parseFloat(value));
if (key.equals("product")) {
value.forEach(m -> materials.add(Integer.parseInt(m)));
} else if (key.equals("inventoryQuantity")) {
value.forEach(q -> quantities.add(Float.parseFloat(q)));
}
}
Recipe recipe = recipeService.getByID(recipeID);

View File

@ -11,13 +11,14 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.MultiValueMap;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import static fyloz.trial.ColorRecipesExplorer.web.PagesPaths.*;
@ -91,8 +92,8 @@ public class MixEditorController {
* @return La page à afficher.
*/
@PostMapping(value = EDITOR_MIX, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String saveMix(Model model, @RequestBody MultiValueMap<String, String> form) {
int mixID = Integer.parseInt(form.getFirst(MIX_ID));
public String saveMix(Model model, @RequestBody LinkedMultiValueMap<String, Object> form) {
int mixID = Integer.parseInt((String) form.get(MIX_ID).get(0));
Mix mix = mixService.getByID(mixID);
if (mix == null) {
@ -104,10 +105,14 @@ public class MixEditorController {
List<Float> quantities = new ArrayList<>();
for (String key : form.keySet()) {
String value = form.getFirst(key);
LinkedList<String> value = (LinkedList) form.get(key);
assert value != null : "Une valeur du formulaire d'édition d'un mélange est nulle.";
if (key.startsWith("product")) materials.add(Integer.parseInt(value));
else if (key.startsWith("quantity")) quantities.add(Float.parseFloat(value));
if (key.equals("product")) {
value.forEach(m -> materials.add(Integer.parseInt(m)));
} else if (key.equals("inventoryQuantity")) {
value.forEach(q -> quantities.add(Float.parseFloat(q)));
}
}
if (!mixService.edit(mix, materials, quantities)) {

View File

@ -1,5 +1,5 @@
# Tomcat
server.port=8080
server.port=8081
# Favicon
spring.mvc.favicon.enabled=false
# H2
@ -16,11 +16,18 @@ spring.jpa.properties.hibernate.format_sql=false
spring.thymeleaf.template-loader-path=classpath:/templates
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false
# Messages
spring.messages.cache-duration=1
#spring.messages.basename=lang/messages
#spring.messages.encoding=UTF-8
#server.tomcat.uri-encoding=UTF-8
#spring.http.encoding.charset=UTF-8
#spring.thymeleaf.encoding=UTF-8
# Max file size.
spring.servlet.multipart.max-file-size=10MB
# Max request size.
spring.servlet.multipart.max-request-size=15MB
# DEBUG
logging.level.org.springframework.web=DEBUG
logging.level.com.zaxxer.hikari=DEBUG
#logging.level.com.zaxxer.hikari=DEBUG
spring.h2.console.enabled=true

View File

@ -0,0 +1,41 @@
menu.list=Liste
menu.add=Ajouter
menu.edit=Modifier
menu.delete=Supprimer
menu.inventory=Inventaire
menu.others=Autres
recipe.color=Couleur
recipe.description=Courte description
recipe.sample=Échantillon
recipe.approbationDate=Date d'approbation
recipe.remark=Remarque
recipe.notice=Note
recipe.steps=Étapes
keyword.company=Bannière
keyword.material=Produit
keyword.recipe=Recette
keyword.touchUpKitPDF=PDF Kits de retouche
keyword.quantity=Quantité
keyword.type=Type
keyword.units=Unités
keyword.edit=Modifier
keyword.use=Utiliser
keyword.save=Enregistrer
keyword.back=Retour
mix.location=Position
material.code=Code
material.inventoryQuantity=Quantité en inventaire
material.type=Type de produit
material.SIMDUTFile=Fichier SIMDUT
units.milliliters=Millilitres
units.liters=Litres
units.gallons=Gallons
inventory.lowQuantity=Quantité faible
inventory.hideOthers=Cacher les autres produits
inventory.showOnly=Voir seulement
product.error.notFound=Aucun produit n'a été trouvé.
app.title=Explorateur de recettes de couleur
footer.lang=See in english
company.add.title=Ajout d'une bannière
company.success.created=La bannière {0} à été enregistrée.
company.form.companyName=Nom de la bannière

View File

@ -0,0 +1,41 @@
company.form.companyName=Banner name
menu.list=List
menu.add=Add
menu.edit=Edit
menu.delete=Delete
menu.inventory=Inventory
menu.others=Others
recipe.color=Color
recipe.description=Short description
recipe.sample=Sample
recipe.approbationDate=Approbation date
recipe.remark=Remark
recipe.notice=Notice
recipe.steps=Steps
keyword.company=Banner
keyword.material=Material
keyword.recipe=Recipe
keyword.touchUpKitPDF=Touch Up Kit PDF
keyword.quantity=Quantity
keyword.type=Type
keyword.units=Units
keyword.edit=Edit
keyword.use=Use
keyword.save=Save
keyword.back=Back
mix.location=Location
material.code=Code
material.inventoryQuantity=Inventory quantity
material.type=Product type
material.SIMDUTFile=SIMDUT File
units.milliliters=Milliliters
units.liters=Liters
units.gallons=Gallons
inventory.lowQuantity=Low quantity
inventory.hideOthers=Hide other products
inventory.showOnly=Show only
product.error.notFound=No products were found.
app.title=Color recipes explorer
footer.lang=Voir en français
company.add.title=Adding a banner
company.success.created=The banner {0} has been saved.

View File

@ -7,11 +7,18 @@ h1 {
text-decoration: underline;
}
header {
header, footer {
background-color: black;
height: 70px;
text-align: center;
width: 100%;
color: white;
}
footer {
position: fixed;
bottom: 0;
padding-top: 10px;
}
header img {
@ -20,6 +27,7 @@ header img {
section {
text-align: center;
margin-bottom: 50px;
}
nav {
@ -45,8 +53,8 @@ nav a {
.dropdown .dropbtn {
font-size: 16px;
border: none;
outline: none;
color: white;
outline: none;
padding: 14px 16px;
background-color: inherit;
font-family: inherit;
@ -107,3 +115,6 @@ nav a:hover, .dropdown:hover .dropbtn {
background-color: #ffc299;
}
.unapproved {
background-color: #fff0b3;
}

View File

@ -1,51 +0,0 @@
<nav>
<img alt="logo" src="/logo.png"/>
<div class="dropdown">
<button class="dropbtn" onclick="document.location.href='/'">
Liste
</button>
</div>
<div class="dropdown">
<button class="dropbtn">
Ajouter
</button>
<div class="dropdown-content">
<a href="/company/creator">Bannière</a>
<a href="/material/creator">Produit</a>
<a href="/recipe/creator">Recette</a>
<a href="/materialType/creator">Type de produit</a>
</div>
</div>
<div class="dropdown">
<button class="dropbtn">
Modifier
</button>
<div class="dropdown-content">
<a href="/material/editor">Produit</a>
<a href="/recipe/editor">Recette</a>
</div>
</div>
<div class="dropdown">
<button class="dropbtn">
Supprimer
</button>
<div class="dropdown-content">
<a href="/company/remover">Bannière</a>
<a href="/material/remover">Produit</a>
<a href="/recipe/remover">Recette</a>
</div>
</div>
<div class="dropdown">
<button class="dropbtn" onclick="document.location.href='/inventory'">
Inventaire
</button>
</div>
<div class="dropdown">
<button class="dropbtn">
Autres
</button>
<div class="dropdown-content">
<a href="/touchup">PDF Kits de retouche</a>
</div>
</div>
</nav>

View File

@ -8,18 +8,6 @@
body.appendChild(axiosElement);
axiosElement.onload = () => {
// Ajoute le header
axios.get('/header.html')
.then(r => {
const header = document.createElement("header");
header.innerHTML = r.data;
body.insertBefore(header, document.querySelector("section"));
})
.catch(e => {
console.log(e);
errorP.innerHTML = "Une erreur est survenue lors de la récupération de l'entête";
});
// Vérifie si les SIMDUTs sont présents
document.querySelectorAll(".materialCode").forEach(e => {
const materialID = e.getAttribute("data-materialID");

View File

@ -1,18 +1,24 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Ajout d'une bannière</title>
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title th:text="#{company.add.title}"></title>
<link href="/css/main.css" rel="stylesheet"/>
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<h1>Ajout d'une bannière</h1>
<p th:text="'La bannière ' + ${companyName} + ' à été enregistrée.'"></p>
<button class="returnIndex">Retour</button>
<h1 th:text="#{company.add.title}"></h1>
<p th:text="#{company.success.created(${companyName})}"></p>
<button class="returnIndex" th:text="#{keyword.back}"></button>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
</body>

View File

@ -1,37 +1,44 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Ajout d'une bannière</title>
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title th:text="#{company.add.title}"></title>
<link href="/css/main.css" rel="stylesheet"/>
<link href="/css/forms.css" rel="stylesheet"/>
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
<h1>Ajout d'une bannière</h1>
<h1 th:text="#{company.add.title}"></h1>
<div class="form">
<form action="/company/creator" class="requireAuth" method="POST">
<form th:action="@{/company/creator}" th:object="${company}" class="requireAuth" method="POST">
<table>
<tr>
<td><b><label for="companyName">Nom de la bannière: </label></b></td>
<td><input id="companyName" name="companyName" type="text"/></td>
<td><b><label th:for="${#ids.next('companyName')}"
th:text="#{company.form.companyName} + ':'"></label></b></td>
<td><input type="text" th:field="*{companyName}"/></td>
</tr>
<tr>
<td>
<button class="returnIndex" type="button">Retour</button>
<button class="returnIndex" type="button" th:text="#{keyword.back}"></button>
</td>
<td>
<button type="submit">Enregistrer</button>
<button type="submit" th:text="#{keyword.save}"></button>
</td>
</tr>
</table>
</form>
</div>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
</body>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Supprimer des bannières</title>
<link href="/css/main.css" rel="stylesheet"/>
@ -23,6 +23,9 @@
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
<p class="success" th:if="${successCompanyName != null}"
@ -54,6 +57,9 @@
<b class="error">Aucune bannière n'a été trouvée.</b>
</th:block>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
</body>

View File

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
<head th:fragment="head(title)">
<title th:text="${title}"></title>
<meta charset="UTF-8"/>
<link rel="stylesheet" th:href="@{/css/main.css}"/>
</head>
<body>
<div th:fragment="header">
<nav>
<img alt="logo" th:src="@{/logo.png}"/>
<div class="dropdown">
<button class="dropbtn" onclick="document.location.href='/'" th:text="#{menu.list}">
</button>
</div>
<div class="dropdown">
<button class="dropbtn" th:text="#{menu.add}"></button>
<div class="dropdown-content">
<a href="/company/creator" th:text="#{keyword.company}"></a>
<a href="/material/creator" th:text="#{keyword.material}"></a>
<a href="/recipe/creator" th:text="#{keyword.recipe}"></a>
<a href="/materialType/creator" th:text="#{material.type}"></a>
</div>
</div>
<div class="dropdown">
<button class="dropbtn" th:text="#{menu.edit}"></button>
<div class="dropdown-content">
<a href="/material/editor" th:text="#{keyword.material}"></a>
<a href="/recipe/editor" th:text="#{keyword.recipe}"></a>
</div>
</div>
<div class="dropdown">
<button class="dropbtn" th:text="#{menu.delete}"></button>
<div class="dropdown-content">
<a href="/company/remover" th:text="#{keyword.company}"></a>
<a href="/material/remover" th:text="#{keyword.material}"></a>
<a href="/recipe/remover" th:text="#{keyword.recipe}"></a>
</div>
</div>
<div class="dropdown">
<button class="dropbtn" onclick="document.location.href='/inventory'" th:text="#{menu.inventory}"></button>
</div>
<div class="dropdown">
<button class="dropbtn" th:text="#{menu.others}"></button>
<div class="dropdown-content">
<a href="/touchup" th:text="#{keyword.touchUpKitPDF}"></a>
</div>
</div>
</nav>
</div>
<div th:fragment="footer">
<a th:href="@{''(lang=__${#locale.toString() == 'en' ? 'fr' : 'en'}__)}" th:text="#{footer.lang}"></a>
</div>
</body>
</html>

View File

@ -1,13 +1,16 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Ajout une image</title>
<link href="/css/main.css" rel="stylesheet"/>
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
@ -19,6 +22,9 @@
<input type="submit" value="Sauvegarde"/>
</form>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
</body>

View File

@ -1,10 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Explorateur de recettes de couleur</title>
<link href="/css/main.css" rel="stylesheet"/>
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<style>
h1 {
@ -42,13 +39,12 @@
.recipeDescription {
max-width: 400px;
}
.unapproved {
background-color: #fff0b3;
}
</style>
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
@ -86,6 +82,9 @@
</th:block>
</div>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
<script>

View File

@ -1,11 +1,10 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Inventaire</title>
<link href="/css/main.css" rel="stylesheet"/>
<!-- Fragment du head -->
<th:block th:include="fragments.html :: head(#{menu.inventory})"></th:block>
<!-- Style de la page -->
<style>
td, th {
min-width: 100px;
@ -36,40 +35,43 @@
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<th:block th:each="materialType : ${materialTypes}"
th:if="${materialType.materialTypeName.equalsIgnoreCase('aucun')}">
<input id="anyTypeId" th:value="${materialType.materialTypeID}" type="hidden"/>
</th:block>
<h1>Inventaire</h1>
<h1 th:text="#{menu.inventory}"></h1>
<th:block th:if="${!materials.empty}">
<table>
<!--Titres des colonnes et options de recherche-->
<tr>
<th>Produit</th>
<th>Quantité</th>
<th th:text="#{keyword.material}"></th>
<th th:text="#{keyword.quantity}"></th>
<!--Unités de la quantité-->
<td></td>
<th>Type</th>
<th th:text="#{keyword.type}"></th>
<td></td>
<!--Options-->
<td rowspan="5">
<label for="lowQuantity">Quantité faible: </label>
<label for="lowQuantity" th:text="#{inventory.lowQuantity} + ':'"></label>
<input id="lowQuantity" min="0" onchange="checkLowQuantity(this.value)" step="0.01"
style="width: 65px" type="number"
value="100"/>
<br/>
<input id="hideOthers" onchange="hide(this.checked)" type="checkbox"/><label for="hideOthers">Cacher
les autres produits</label>
<input id="hideOthers" onchange="hide(this.checked)" type="checkbox"/><label for="hideOthers"
th:text="#{inventory.hideOthers}"></label>
<br/>
<br/>
<label for="materialTypeSelect">Voir seulement: </label>
<label for="materialTypeSelect" th:text="#{inventory.showOnly} + ':'"> </label>
<select id="materialTypeSelect" name="materialTypeSelect" onchange="hideMaterialTypes(this)">
<th:block th:each="materialType : ${materialTypes}">
<option th:text="${materialType.materialTypeName}"
@ -79,12 +81,12 @@
<br/>
<br/>
<label for="units">Unités: </label>
<label for="units" th:text="#{keyword.units} + ':'"></label>
<select id="units" name="units"
onchange="changeUnits(this, '.inventoryQuantity', '.inventoryQuantityUnits')">
<option selected value="mL">Millilitres</option>
<option value="L">Litres</option>
<option value="gal">Gallons</option>
<option selected value="mL" th:text="#{units.milliliters}"></option>
<option value="L" th:text="#{units.liters}"></option>
<option value="gal" th:text="#{units.gallons}"></option>
</select>
</td>
@ -98,12 +100,12 @@
th:text="${material.materialCode}"></td>
<td class="inventoryQuantity" th:data-quantityML="${material.inventoryQuantity}"
th:text="${material.inventoryQuantity}"></td>
<td><span class="inventoryQuantityUnits">mL</span></td>
<td><span th:classappend="${!material.materialType.getUsePercentages()} ? inventoryQuantityUnits"
th:attrappend="text=${material.materialType.getUsePercentages()}"></span></td>
<td class="materialType" th:text="${material.materialType.materialTypeName}"></td>
<td>
<button class="modifyMaterial" th:data-materialID="${material.materialID}" type="button">
Modifier
</button>
<button class="modifyMaterial" th:data-materialID="${material.materialID}" type="button"
th:text="#{keyword.edit}"></button>
</td>
</tr>
</th:block>
@ -111,9 +113,11 @@
</table>
</th:block>
<th:block th:if="${materials.empty}">
<b class="error">Aucun produit n'a été trouvé.</b>
<b class="error" th:text="#{product.error.notFound}"></b>
</th:block>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script>
(() => {

View File

@ -1,18 +1,24 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Ajout d'un produit</title>
<link href="/css/main.css" rel="stylesheet"/>
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<h1>Ajout d'un produit</h1>
<p th:text="'Le produit ' + ${materialCode} + ' a été enregistré.'"></p>
<button class="returnIndex">Retour</button>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
</body>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Ajout d'un produit</title>
<link href="/css/main.css" rel="stylesheet"/>
@ -9,6 +9,9 @@
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
@ -71,6 +74,9 @@
</form>
</div>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
<script>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title th:text="'Modification de ' + ${material.materialCode}"></title>
<link href="/css/main.css" rel="stylesheet"/>
@ -9,6 +9,9 @@
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
@ -67,6 +70,9 @@
</form>
</div>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
<script>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Modifier un produit</title>
<link href="/css/main.css" rel="stylesheet"/>
@ -19,6 +19,9 @@
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
<p class="success" th:if="${materialCode != null}"
@ -49,6 +52,9 @@
<b class="error">Aucun produit n'a été trouvé</b>
</th:block>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
<script>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Supprimer des produits</title>
<link href="/css/main.css" rel="stylesheet"/>
@ -19,6 +19,9 @@
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
<p class="success" th:if="${materialCode != null}"
@ -53,6 +56,9 @@
<b class="error">Aucun produit n'a été trouvé.</b>
</th:block>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
</body>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Ajout d'un produit</title>
<link href="/css/main.css" rel="stylesheet"/>
@ -9,6 +9,9 @@
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<h1>Ajout d'un produit</h1>
<div class="form">
@ -25,6 +28,9 @@
</form>
</div>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
</body>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Ajout d'un type de produit</title>
<link href="/css/main.css" rel="stylesheet"/>
@ -9,6 +9,9 @@
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
<h1>Ajout d'un type de produit</h1>
@ -40,6 +43,9 @@
</form>
</div>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
</body>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Ajout d'un mélange</title>
<link href="/css/main.css" rel="stylesheet"/>
@ -15,6 +15,9 @@
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
<h1>Ajout d'un mélange pour<br>la recette <span th:text="${recipe.recipeCode}"></span></h1>
@ -39,7 +42,7 @@
</th>
</tr>
<tr id="row_0">
<td><select class="materialList" name="product_0">
<td><select class="materialList" name="product">
<th:block th:each="material : ${materials}">
<option th:class="'material_' + ${material.materialID}"
th:classappend="${material.materialType.getUsePercentages()} ? usePercents"
@ -48,7 +51,7 @@
</option>
</th:block>
</select></td>
<td><input class="quantity" min="0" name="userQuantity" step="0.01" type="number"/>
<td><input class="quantity" min="0" name="inventoryQuantity" step="0.01" type="number"/>
<span class="quantityUnit">mL</span></td>
<td>
<button data-remove="0" onclick="removeRow(this)" type="button">Retirer</button>
@ -69,6 +72,9 @@
</form>
</div>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
<script>
@ -83,7 +89,7 @@
document.querySelector("#products button").addEventListener("click", () => {
let select = document.createElement("select");
select.name = `product_${productNbr}`;
select.name = "product";
products.forEach(p => {
let option = document.createElement("option");
@ -98,7 +104,7 @@
let input = document.createElement("input");
input.type = "number";
input.name = `quantity_${productNbr}`;
input.name = "inventoryQuantity";
input.step = "0.01";
let quantity = document.createElement("td");
@ -123,12 +129,6 @@
productNbr++;
});
document.querySelectorAll(".materialList").forEach(e => {
e.addEventListener("change", () => {
});
});
})();
function removeRow(e) {
@ -137,10 +137,6 @@
});
}
function switchUnits(unitSelect) {
document.querySelectorAll(".")
}
/*]]*/
</script>
</body>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Modifier un mélange</title>
<link href="/css/main.css" rel="stylesheet"/>
@ -16,6 +16,9 @@
<body th:with="nbrProducts = 0">
<th:block th:with="nbrSteps = 0">
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
<h1>Modifier un mélange pour<br>la recette <span
@ -54,6 +57,9 @@
</form>
</div>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
<script>
@ -71,7 +77,7 @@
// Ajoute les produits déjà présents dans la recette
mix.mixQuantities.forEach((q) => {
let select = document.createElement("select");
select.name = `product_${productNbr}`;
select.name = "product";
materials.forEach(p => {
const materialID = p.materialID;
@ -86,7 +92,7 @@
let input = document.createElement("input");
input.type = "number";
input.name = `quantity_${productNbr}`;
input.name = "inventoryQuantity";
input.value = q.quantity;
input.step = 0.01;
@ -118,7 +124,7 @@
document.querySelector("#products button").addEventListener("click", () => {
let select = document.createElement("select");
select.name = `product_${productNbr}`;
select.name = "product";
materials.forEach(p => {
let option = document.createElement("option");
@ -130,7 +136,7 @@
let input = document.createElement("input");
input.type = "number";
input.name = `quantity_${productNbr}`;
input.name = "inventoryQuantity";
input.step = 0.01;
let product = document.createElement("td");
@ -149,6 +155,7 @@
removeColumn.appendChild(removeButton);
let row = document.createElement("tr");
row.id = `row_${productNbr}`;
row.appendChild(product);
row.appendChild(quantity);
row.appendChild(removeButton);

View File

@ -1,13 +1,16 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Ajout d'une recette</title>
<link href="/css/main.css" rel="stylesheet"/>
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
@ -15,6 +18,9 @@
<p th:text="'La recette ' + ${recipeCode} + ' à été enregistrée. Vous pouvez maintenant ajouter les ingrédients.'"></p>
<button th:onclick="'document.location.href=\'/recipe/editor/' + ${recipeID} + '\''">Continuer</button>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
</body>

View File

@ -1,13 +1,16 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Ajout d'une recette</title>
<link href="/css/main.css" rel="stylesheet"/>
<link href="/css/forms.css" rel="stylesheet"/>
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
@ -55,6 +58,9 @@
</form>
</div>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
</body>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title th:text="'Modification de ' + ${recipe.recipeCode}"></title>
<link href="/css/main.css" rel="stylesheet"/>
@ -26,6 +26,9 @@
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
@ -199,6 +202,9 @@
</form>
</div>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
<script>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Modifier une recette</title>
<link href="/css/main.css" rel="stylesheet"/>
@ -27,6 +27,9 @@
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
<p class="success" th:if="${recipeCode != null}"
@ -66,6 +69,9 @@
<b class="error">Aucune bannière n'a été trouvée.</b>
</th:block>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
<script>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title th:text="'Couleur ' + ${recipe.recipeCode}"></title>
<link href="/css/main.css" rel="stylesheet"/>
@ -47,6 +47,9 @@
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
<p class="success" th:text="${success}"></p>
@ -228,6 +231,9 @@
</th:block>
</table>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
<script>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Supprimer des recettes</title>
<link href="/css/main.css" rel="stylesheet"/>
@ -23,6 +23,9 @@
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<p class="error" th:text="${error}"></p>
<p class="success" th:if="${recipeCode != null}"
@ -64,6 +67,9 @@
</th:block>
</form>
</section>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
</body>

View File

@ -1,13 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
<title>Génération du PDF d'un kit de retouche</title>
<link href="/css/main.css" rel="stylesheet"/>
<link href="/css/index.css" rel="stylesheet"/>
</head>
<body>
<!-- Fragment de l'entête -->
<header th:include="fragments.html :: header"></header>
<!-- Corps de la page -->
<section>
<h1>Génération du PDF d'un kit de retouche</h1>
@ -18,7 +21,9 @@
<input type="submit" value="Générer"/>
</form>
</section>
<script src="/js/main.js"></script>
<!-- Fragment du pied de page -->
<footer th:include="fragments.html :: footer"></footer>
<script src="/js/main.js"></script>
</body>
</html>

Binary file not shown.

File diff suppressed because it is too large Load Diff