v1.2.0_beta
This commit is contained in:
parent
6fb6a4829c
commit
4f7336e982
|
@ -25,17 +25,18 @@ public class InitialDataLoader implements ApplicationListener<ApplicationReadyEv
|
|||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
|
||||
if (!materialTypeService.getByName(MaterialType.DEFAULT_MATERIAL_TYPE_NAME).isPresent()) {
|
||||
createDefaultMaterialType();
|
||||
}
|
||||
if (!materialTypeService.getByName(MaterialType.DEFAULT_MATERIAL_TYPE_NAME).isPresent())
|
||||
createInitialMaterialType(MaterialType.DEFAULT_MATERIAL_TYPE_NAME);
|
||||
if (!materialTypeService.getByName(MaterialType.BASE_MATERIAL_TYPE_NAME).isPresent())
|
||||
createInitialMaterialType(MaterialType.BASE_MATERIAL_TYPE_NAME);
|
||||
}
|
||||
|
||||
private void createDefaultMaterialType() {
|
||||
MaterialType defaultMaterialType = new MaterialType(MaterialType.DEFAULT_MATERIAL_TYPE_NAME, "", false);
|
||||
private void createInitialMaterialType(String name) {
|
||||
MaterialType defaultMaterialType = new MaterialType(name, "", false);
|
||||
|
||||
Optional<MaterialType> optionalSavedMaterialType = materialTypeService.save(defaultMaterialType);
|
||||
if (!optionalSavedMaterialType.isPresent()) {
|
||||
ColorRecipesExplorerApplication.LOGGER.warn("Échec de la création du type de produit par défaut.");
|
||||
ColorRecipesExplorerApplication.LOGGER.warn(String.format("Échec de la création du type de produit par défaut '%s'.", name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ public enum ResponseCode {
|
|||
FILE_NOT_IMAGE(24, ResponseCodeType.ERROR, 0),
|
||||
RECIPE_NOT_FOUND_NO_PARAMS(25, ResponseCodeType.ERROR, 0),
|
||||
MATERIAL_NOT_FOUND_BY_NAME(26, ResponseCodeType.ERROR, 1),
|
||||
SUCCESS_DELETING_COMPANY(27, ResponseCodeType.SUCCESS, 1),
|
||||
|
||||
// HTTP Errors
|
||||
_500(100, ResponseCodeType.ERROR, 0),
|
||||
|
|
|
@ -1,73 +1,32 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.model;
|
||||
|
||||
import lombok.*;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "companies")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@RequiredArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Company extends BeanModel implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
private int companyID;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
@Length(min = 2, max = 50)
|
||||
@Column(unique = true)
|
||||
@NotNull
|
||||
private String companyName;
|
||||
|
||||
public Company() {
|
||||
|
||||
}
|
||||
|
||||
public Company(@Length(min = 2, max = 50) @NotNull String companyName) {
|
||||
this.companyName = companyName;
|
||||
}
|
||||
|
||||
public int getCompanyID() {
|
||||
return companyID;
|
||||
}
|
||||
|
||||
public void setCompanyID(int companyID) {
|
||||
this.companyID = companyID;
|
||||
}
|
||||
|
||||
public String getCompanyName() {
|
||||
return companyName;
|
||||
}
|
||||
|
||||
public void setCompanyName(String companyName) {
|
||||
this.companyName = companyName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getID() {
|
||||
return companyID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Company{" +
|
||||
"companyID=" + companyID +
|
||||
", companyName='" + companyName + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Company company = (Company) o;
|
||||
return companyID == company.companyID &&
|
||||
Objects.equals(companyName, company.companyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(companyID, companyName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,115 +1,53 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.model;
|
||||
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "materials")
|
||||
@Data
|
||||
@RequiredArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class Material extends BeanModel implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
private Integer materialID = 0;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
@NotEmpty
|
||||
@Column(unique = true)
|
||||
private String materialCode;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
private float inventoryQuantity = 0;
|
||||
@ColumnDefault("0")
|
||||
private float inventoryQuantity;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
@ColumnDefault("false")
|
||||
private boolean isMixType = false;
|
||||
private boolean isMixType;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
@ManyToOne
|
||||
private MaterialType materialType;
|
||||
|
||||
public Material() {
|
||||
|
||||
}
|
||||
|
||||
public Material(@NotNull String materialCode, @NotNull float inventoryQuantity, @NotNull boolean isMixType, MaterialType materialType) {
|
||||
this.materialCode = materialCode;
|
||||
this.inventoryQuantity = inventoryQuantity;
|
||||
this.isMixType = isMixType;
|
||||
this.materialType = materialType;
|
||||
}
|
||||
|
||||
public Integer getMaterialID() {
|
||||
return materialID;
|
||||
}
|
||||
|
||||
public void setMaterialID(Integer materialID) {
|
||||
this.materialID = materialID;
|
||||
}
|
||||
|
||||
public String getMaterialCode() {
|
||||
return materialCode;
|
||||
}
|
||||
|
||||
public void setMaterialCode(String materialCode) {
|
||||
this.materialCode = materialCode;
|
||||
}
|
||||
|
||||
public float getInventoryQuantity() {
|
||||
return inventoryQuantity;
|
||||
}
|
||||
|
||||
public void setInventoryQuantity(float inventoryQuantity) {
|
||||
this.inventoryQuantity = inventoryQuantity;
|
||||
}
|
||||
|
||||
public boolean isMixType() {
|
||||
return isMixType;
|
||||
}
|
||||
|
||||
public void setMixType(boolean mixType) {
|
||||
isMixType = mixType;
|
||||
}
|
||||
|
||||
public MaterialType getMaterialType() {
|
||||
return materialType;
|
||||
}
|
||||
|
||||
public void setMaterialType(MaterialType materialType) {
|
||||
this.materialType = materialType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getID() {
|
||||
return materialID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Material{" +
|
||||
"materialID=" + materialID +
|
||||
", materialCode='" + materialCode + '\'' +
|
||||
", inventoryQuantity=" + inventoryQuantity +
|
||||
", isMixType=" + isMixType +
|
||||
", materialType=" + materialType +
|
||||
'}';
|
||||
public boolean isMixType() {
|
||||
return isMixType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Material material = (Material) o;
|
||||
return Objects.equals(materialID, material.materialID) &&
|
||||
Objects.equals(materialCode, material.materialCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(materialID, materialCode, inventoryQuantity, isMixType, materialType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,111 +1,48 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.model;
|
||||
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@RequiredArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MaterialType extends BeanModel implements Serializable {
|
||||
|
||||
public static final String DEFAULT_MATERIAL_TYPE_NAME = "Aucun";
|
||||
public static final String BASE_MATERIAL_TYPE_NAME = "Base";
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
private Integer materialTypeID;
|
||||
|
||||
@Column(unique = true)
|
||||
@NonNull
|
||||
@NotNull
|
||||
@Column(unique = true)
|
||||
private String materialTypeName;
|
||||
|
||||
@Column(unique = true)
|
||||
@NonNull
|
||||
@NotNull
|
||||
@Column(unique = true)
|
||||
private String prefix;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
@ColumnDefault("false")
|
||||
private Boolean usePercentages = false;
|
||||
private Boolean usePercentages;
|
||||
|
||||
@OneToMany
|
||||
@JoinColumn(name = "material_type")
|
||||
private List<Material> materials;
|
||||
|
||||
public MaterialType() {
|
||||
|
||||
}
|
||||
|
||||
public MaterialType(@NotNull String materialTypeName, @NotNull String prefix, @NotNull Boolean usePercentages) {
|
||||
this.materialTypeName = materialTypeName;
|
||||
this.prefix = prefix.toUpperCase();
|
||||
this.usePercentages = usePercentages;
|
||||
}
|
||||
|
||||
public Integer getMaterialTypeID() {
|
||||
return materialTypeID;
|
||||
}
|
||||
|
||||
public void setMaterialTypeID(Integer materialTypeID) {
|
||||
this.materialTypeID = materialTypeID;
|
||||
}
|
||||
|
||||
public String getMaterialTypeName() {
|
||||
return materialTypeName;
|
||||
}
|
||||
|
||||
public void setMaterialTypeName(String materialTypeName) {
|
||||
this.materialTypeName = materialTypeName;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix.toUpperCase();
|
||||
}
|
||||
|
||||
public Boolean getUsePercentages() {
|
||||
return usePercentages;
|
||||
}
|
||||
|
||||
public void setUsePercentages(Boolean usePercentages) {
|
||||
this.usePercentages = usePercentages;
|
||||
}
|
||||
|
||||
public List<Material> getMaterials() {
|
||||
return materials;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getID() {
|
||||
return materialTypeID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MaterialType{" +
|
||||
"materialTypeID=" + materialTypeID +
|
||||
", materialTypeName='" + materialTypeName + '\'' +
|
||||
", prefix='" + prefix + '\'' +
|
||||
", usePercentages=" + usePercentages +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MaterialType that = (MaterialType) o;
|
||||
return Objects.equals(materialTypeID, that.materialTypeID) &&
|
||||
Objects.equals(materialTypeName, that.materialTypeName) &&
|
||||
Objects.equals(prefix, that.prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(materialTypeID, materialTypeName, prefix, usePercentages, materials);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.model;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "mixes")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@RequiredArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Mix extends BeanModel implements Serializable {
|
||||
|
||||
@Id
|
||||
|
@ -15,10 +20,13 @@ public class Mix extends BeanModel implements Serializable {
|
|||
@Basic
|
||||
private Integer mixID = 0;
|
||||
|
||||
@NonNull
|
||||
@ToString.Exclude
|
||||
@NotNull
|
||||
@ManyToOne
|
||||
private Recipe recipe;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
@ManyToOne
|
||||
private MixType mixType;
|
||||
|
@ -29,84 +37,9 @@ public class Mix extends BeanModel implements Serializable {
|
|||
// Casier
|
||||
private String location;
|
||||
|
||||
public Mix() {
|
||||
|
||||
}
|
||||
|
||||
public Mix(@NotNull Recipe recipe, @NotNull MixType mixType, List<MixQuantity> mixQuantities) {
|
||||
this.recipe = recipe;
|
||||
this.mixType = mixType;
|
||||
this.mixQuantities = mixQuantities;
|
||||
}
|
||||
|
||||
public Recipe getRecipe() {
|
||||
return recipe;
|
||||
}
|
||||
|
||||
public void setRecipe(Recipe recipe) {
|
||||
this.recipe = recipe;
|
||||
}
|
||||
|
||||
public Integer getMixID() {
|
||||
return mixID;
|
||||
}
|
||||
|
||||
public void setMixID(Integer mixID) {
|
||||
this.mixID = mixID;
|
||||
}
|
||||
|
||||
public MixType getMixType() {
|
||||
return mixType;
|
||||
}
|
||||
|
||||
public void setMixType(MixType mixType) {
|
||||
this.mixType = mixType;
|
||||
}
|
||||
|
||||
public List<MixQuantity> getMixQuantities() {
|
||||
return mixQuantities;
|
||||
}
|
||||
|
||||
public void setMixQuantities(List<MixQuantity> mixQuantities) {
|
||||
this.mixQuantities = mixQuantities;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getID() {
|
||||
return mixID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Mix{" +
|
||||
"mixID=" + mixID +
|
||||
// ", recipe=" + recipe +
|
||||
", mixType=" + mixType +
|
||||
// ", mixQuantities=" + mixQuantities +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Mix mix = (Mix) o;
|
||||
return mixID.equals(mix.mixID) &&
|
||||
Objects.equals(recipe, mix.recipe) &&
|
||||
Objects.equals(mixType, mix.mixType) &&
|
||||
Objects.equals(mixQuantities, mix.mixQuantities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mixID, recipe, mixType, mixQuantities, location);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "mixQuantities")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@RequiredArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MixQuantity extends BeanModel implements Serializable {
|
||||
|
||||
@Id
|
||||
|
@ -16,86 +20,24 @@ public class MixQuantity extends BeanModel implements Serializable {
|
|||
@Basic
|
||||
private Integer mixQuantityID = 0;
|
||||
|
||||
@NonNull
|
||||
@ToString.Exclude
|
||||
@NotNull
|
||||
@JsonIgnore
|
||||
@ManyToOne
|
||||
private Mix mix;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
@ManyToOne
|
||||
private Material material;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
private Float quantity;
|
||||
|
||||
public MixQuantity() {
|
||||
|
||||
}
|
||||
|
||||
public MixQuantity(Mix mix, Material material, @NotNull Float quantity) {
|
||||
this.mix = mix;
|
||||
this.material = material;
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
public Integer getMixQuantityID() {
|
||||
return mixQuantityID;
|
||||
}
|
||||
|
||||
public void setMixQuantityID(Integer mixQuantityID) {
|
||||
this.mixQuantityID = mixQuantityID;
|
||||
}
|
||||
|
||||
public Mix getMix() {
|
||||
return mix;
|
||||
}
|
||||
|
||||
public void setMix(Mix mix) {
|
||||
this.mix = mix;
|
||||
}
|
||||
|
||||
public Material getMaterial() {
|
||||
return material;
|
||||
}
|
||||
|
||||
public void setMaterial(Material material) {
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
public Float getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public void setQuantity(Float quantity) {
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getID() {
|
||||
return mixQuantityID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MixQuantity{" +
|
||||
"mixQuantityID=" + mixQuantityID +
|
||||
", mix=" + mix +
|
||||
", material=" + material +
|
||||
", quantity=" + quantity +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MixQuantity that = (MixQuantity) o;
|
||||
return Objects.equals(mixQuantityID, that.mixQuantityID) &&
|
||||
Objects.equals(mix, that.mix) &&
|
||||
Objects.equals(material, that.material) &&
|
||||
Objects.equals(quantity, that.quantity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mixQuantityID, mix, material, quantity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,84 +1,35 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.model;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "mixTypes") // TODO retirer @Table
|
||||
@Table(name = "mixTypes")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@RequiredArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MixType extends BeanModel implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
private int typeID;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
@Column(unique = true)
|
||||
private String typeName;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
@OneToOne(cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "materialid")
|
||||
private Material material;
|
||||
|
||||
public MixType() {
|
||||
|
||||
}
|
||||
|
||||
public MixType(@NotNull String typeName, @NotNull Material material) {
|
||||
this.typeName = typeName;
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
public int getTypeID() {
|
||||
return typeID;
|
||||
}
|
||||
|
||||
public void setTypeID(int typeID) {
|
||||
this.typeID = typeID;
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
public void setTypeName(String typeName) {
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
public Material getMaterial() {
|
||||
return material;
|
||||
}
|
||||
|
||||
public void setMaterial(Material material) {
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getID() {
|
||||
return typeID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MixType{" +
|
||||
"typeID=" + typeID +
|
||||
", typeName='" + typeName + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MixType mixType = (MixType) o;
|
||||
return typeID == mixType.typeID &&
|
||||
Objects.equals(typeName, mixType.typeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(typeID, typeName, material);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,41 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.*;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "recipes")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@RequiredArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Recipe extends BeanModel implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
private Integer recipeID = 0;
|
||||
|
||||
@Length(min = 2)
|
||||
@NonNull
|
||||
@NotNull
|
||||
@Length(min = 2)
|
||||
private String recipeCode;
|
||||
|
||||
@ManyToOne
|
||||
@NonNull
|
||||
@NotNull
|
||||
@ManyToOne
|
||||
private Company company;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
private String recipeDescription;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
private int sample;
|
||||
|
||||
|
@ -45,138 +52,32 @@ public class Recipe extends BeanModel implements Serializable {
|
|||
@OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
private List<RecipeStep> recipeSteps;
|
||||
|
||||
public Recipe() {
|
||||
|
||||
}
|
||||
|
||||
public Recipe(@Length(min = 2) String recipeCode, @NotNull Company company, String recipeDescription, @NotNull int sample, @NotNull String approbationDate, String remark, String note) {
|
||||
this.recipeCode = recipeCode;
|
||||
this.company = company;
|
||||
this.recipeDescription = recipeDescription;
|
||||
this.sample = sample;
|
||||
this.approbationDate = approbationDate;
|
||||
this.remark = remark;
|
||||
this.note = note;
|
||||
}
|
||||
|
||||
public Integer getRecipeID() {
|
||||
return recipeID;
|
||||
}
|
||||
|
||||
public void setRecipeID(Integer recipeID) {
|
||||
this.recipeID = recipeID;
|
||||
}
|
||||
|
||||
public String getRecipeCode() {
|
||||
return recipeCode;
|
||||
}
|
||||
|
||||
public void setRecipeCode(String recipeCode) {
|
||||
this.recipeCode = recipeCode;
|
||||
}
|
||||
|
||||
public Company getCompany() {
|
||||
return company;
|
||||
}
|
||||
|
||||
public void setCompany(Company company) {
|
||||
this.company = company;
|
||||
}
|
||||
|
||||
public String getRecipeDescription() {
|
||||
return recipeDescription;
|
||||
}
|
||||
|
||||
public void setRecipeDescription(String recipeDescription) {
|
||||
this.recipeDescription = recipeDescription;
|
||||
}
|
||||
|
||||
public int getSample() {
|
||||
return sample;
|
||||
}
|
||||
|
||||
public void setSample(int sample) {
|
||||
this.sample = sample;
|
||||
}
|
||||
|
||||
public String getApprobationDate() {
|
||||
return approbationDate;
|
||||
}
|
||||
|
||||
public void setApprobationDate(String approbationDate) {
|
||||
this.approbationDate = approbationDate;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public String getNote() {
|
||||
return note;
|
||||
}
|
||||
|
||||
public void setNote(String note) {
|
||||
this.note = note;
|
||||
}
|
||||
|
||||
public List<Mix> getRecipeMixes() {
|
||||
return recipeMixes;
|
||||
}
|
||||
|
||||
public void setRecipeMixes(List<Mix> recipeMixes) {
|
||||
this.recipeMixes = recipeMixes;
|
||||
}
|
||||
|
||||
public List<RecipeStep> getRecipeSteps() {
|
||||
return recipeSteps == null ? new ArrayList<>() : recipeSteps;
|
||||
}
|
||||
|
||||
public void setRecipeSteps(List<RecipeStep> recipeSteps) {
|
||||
this.recipeSteps = recipeSteps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getID() {
|
||||
return recipeID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Recipe{" +
|
||||
"recipeID=" + recipeID +
|
||||
", recipeCode=" + recipeCode +
|
||||
", company=" + company +
|
||||
", recipeDescription='" + recipeDescription +
|
||||
", sample=" + sample +
|
||||
", approbationDate=" + approbationDate +
|
||||
", remark='" + remark +
|
||||
", note='" + note +
|
||||
'}';
|
||||
}
|
||||
public Material getBase() {
|
||||
if (recipeMixes.isEmpty() || recipeMixes.stream().allMatch(m -> m.getMixQuantities().isEmpty())) return null;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Recipe recipe = (Recipe) o;
|
||||
return recipeID.equals(recipe.recipeID) &&
|
||||
recipeCode.equals(recipe.recipeCode) &&
|
||||
sample == recipe.sample &&
|
||||
Objects.equals(company, recipe.company) &&
|
||||
Objects.equals(recipeDescription, recipe.recipeDescription) &&
|
||||
Objects.equals(approbationDate, recipe.approbationDate) &&
|
||||
Objects.equals(remark, recipe.remark) &&
|
||||
Objects.equals(note, recipe.note) &&
|
||||
Objects.equals(recipeMixes, recipe.recipeMixes) &&
|
||||
Objects.equals(recipeSteps, recipe.recipeSteps);
|
||||
}
|
||||
Material base = recipeMixes
|
||||
.stream()
|
||||
.map(mix -> mix
|
||||
.getMixQuantities()
|
||||
.stream()
|
||||
.filter(mq -> mq.getMaterial().getMaterialType().getMaterialTypeName().equals(MaterialType.BASE_MATERIAL_TYPE_NAME))
|
||||
.findFirst().get()
|
||||
)
|
||||
.findFirst().orElse(recipeMixes
|
||||
.stream()
|
||||
.filter(m -> !m.getMixQuantities().isEmpty())
|
||||
.findFirst()
|
||||
.get()
|
||||
.getMixQuantities()
|
||||
.stream()
|
||||
.findFirst()
|
||||
.get()).getMaterial();
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(recipeID, recipeCode, company, recipeDescription, sample, approbationDate, remark, note, recipeMixes, recipeSteps);
|
||||
return base;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,85 +1,36 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "steps")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@RequiredArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class RecipeStep extends BeanModel implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
private int stepID;
|
||||
|
||||
@NonNull
|
||||
@ToString.Exclude
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JsonIgnore
|
||||
private Recipe recipe;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
private String stepMessage;
|
||||
|
||||
public RecipeStep() {
|
||||
|
||||
}
|
||||
|
||||
public RecipeStep(Recipe recipe, @NotNull String stepMessage) {
|
||||
this.recipe = recipe;
|
||||
this.stepMessage = stepMessage;
|
||||
}
|
||||
|
||||
public int getStepID() {
|
||||
return stepID;
|
||||
}
|
||||
|
||||
public void setStepID(int stepID) {
|
||||
this.stepID = stepID;
|
||||
}
|
||||
|
||||
public String getStepMessage() {
|
||||
return stepMessage;
|
||||
}
|
||||
|
||||
public void setStepMessage(String stepMessage) {
|
||||
this.stepMessage = stepMessage;
|
||||
}
|
||||
|
||||
public Recipe getRecipe() {
|
||||
return recipe;
|
||||
}
|
||||
|
||||
public void setRecipe(Recipe recipe) {
|
||||
this.recipe = recipe;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getID() {
|
||||
return stepID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RecipeStep{" +
|
||||
"stepID=" + stepID +
|
||||
", stepMessage='" + stepMessage + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
RecipeStep recipeStep = (RecipeStep) o;
|
||||
return stepID == recipeStep.stepID &&
|
||||
Objects.equals(stepMessage, recipeStep.stepMessage) &&
|
||||
Objects.equals(recipe, recipeStep.recipe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(stepID, recipe, stepMessage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.model.dto;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.MaterialType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Recipe;
|
||||
import lombok.Data;
|
||||
|
||||
|
@ -12,6 +13,8 @@ public class MixCreationFormDto {
|
|||
|
||||
private String mixTypeName;
|
||||
|
||||
private MaterialType materialType;
|
||||
|
||||
private List<String> materials;
|
||||
|
||||
private List<Float> quantities;
|
||||
|
|
|
@ -46,7 +46,7 @@ public class MixService extends GenericService<Mix, MixDao> {
|
|||
materials.add(found.get());
|
||||
}
|
||||
|
||||
Optional<MixType> optionalMixType = mixTypeService.createByName(formDto.getMixTypeName());
|
||||
Optional<MixType> optionalMixType = mixTypeService.createByName(formDto.getMixTypeName(), formDto.getMaterialType());
|
||||
if (!optionalMixType.isPresent()) return modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING);
|
||||
|
||||
MixType mixType = optionalMixType.get();
|
||||
|
@ -54,7 +54,7 @@ public class MixService extends GenericService<Mix, MixDao> {
|
|||
return modelResponseBuilder.addResponseCode(ResponseCode.MIX_TYPE_ALREADY_USED, mixType.getTypeName());
|
||||
|
||||
// Crée le mélange en premier pour avoir accès à son ID pour les autres éléments
|
||||
Mix mix = new Mix(recipe, mixType, null);
|
||||
Mix mix = new Mix(recipe, mixType);
|
||||
|
||||
Optional<Mix> savedMix = save(mix);
|
||||
if (savedMix.isPresent()) {
|
||||
|
@ -75,6 +75,7 @@ public class MixService extends GenericService<Mix, MixDao> {
|
|||
@Transactional
|
||||
public ModelResponseBuilder edit(Mix mix, MixCreationFormDto formDto) {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
|
||||
Material material = mix.getMixType().getMaterial();
|
||||
|
||||
List<Material> materials = new ArrayList<>();
|
||||
for (String materialCode : formDto.getMaterials()) {
|
||||
|
@ -86,7 +87,9 @@ public class MixService extends GenericService<Mix, MixDao> {
|
|||
materials.add(found.get());
|
||||
}
|
||||
|
||||
mix.getMixType().getMaterial().setMaterialType(formDto.getMaterialType());
|
||||
mix.getMixType().setTypeName(formDto.getMixTypeName());
|
||||
material.setMaterialCode(formDto.getMixTypeName());
|
||||
|
||||
List<MixQuantity> mixQuantities = createMixQuantities(mix, materials, formDto.getQuantities());
|
||||
|
||||
|
@ -96,7 +99,7 @@ public class MixService extends GenericService<Mix, MixDao> {
|
|||
}
|
||||
|
||||
mix.setMixQuantities(mixQuantities);
|
||||
if (update(mix).isPresent()) return null;
|
||||
if (materialService.update(material).isPresent() && update(mix).isPresent()) return null;
|
||||
else return modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,16 +29,8 @@ public class MixTypeService extends GenericService<MixType, MixTypeDao> {
|
|||
return dao.findByMaterial(material);
|
||||
}
|
||||
|
||||
public Optional<MixType> createByName(String name) {
|
||||
Optional<MaterialType> defaultType = materialTypeService.getDefaultMaterialType();
|
||||
if (!defaultType.isPresent()) return Optional.empty();
|
||||
|
||||
Optional<MixType> mixTypeByName = getByName(name);
|
||||
if (mixTypeByName.isPresent()) {
|
||||
return mixTypeByName;
|
||||
}
|
||||
|
||||
Material mixTypeMaterial = new Material(name, 0, true, defaultType.get());
|
||||
public Optional<MixType> createByName(String name, MaterialType type) {
|
||||
Material mixTypeMaterial = new Material(name, 0f, true, type);
|
||||
MixType mixType = new MixType(name, mixTypeMaterial);
|
||||
|
||||
return save(mixType);
|
||||
|
|
|
@ -17,7 +17,7 @@ import javax.validation.Valid;
|
|||
import java.util.Optional;
|
||||
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.PagesPaths.CREATOR_COMPANY;
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.PagesPaths.CREATOR_COMPANY_SUCCESS;
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.PagesPaths.INDEX;
|
||||
|
||||
@Controller
|
||||
public class CompanyCreatorController {
|
||||
|
@ -56,7 +56,7 @@ public class CompanyCreatorController {
|
|||
*/
|
||||
@PostMapping(value = CREATOR_COMPANY, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
public ModelAndView createCompany(@ModelAttribute @Valid Company company) {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(CREATOR_COMPANY_SUCCESS);
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder().withRedirect(INDEX);
|
||||
|
||||
if (companyService.isValidForCreation(company)) {
|
||||
Optional<Company> savedCompany = companyService.save(company);
|
||||
|
|
|
@ -7,10 +7,7 @@ import dev.fyloz.trial.colorrecipesexplorer.core.model.Material;
|
|||
import dev.fyloz.trial.colorrecipesexplorer.core.model.MixType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Recipe;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.dto.MixCreationFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MaterialService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MixService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MixTypeService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.RecipeService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.*;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.utils.ControllerUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
|
@ -36,13 +33,15 @@ public class MixCreatorController {
|
|||
private RecipeService recipeService;
|
||||
private MaterialService materialService;
|
||||
private MixTypeService mixTypeService;
|
||||
private MaterialTypeService materialTypeService;
|
||||
|
||||
@Autowired
|
||||
public MixCreatorController(MixService mixService, RecipeService recipeService, MaterialService materialService, MixTypeService mixTypeService) {
|
||||
public MixCreatorController(MixService mixService, RecipeService recipeService, MaterialService materialService, MixTypeService mixTypeService, MaterialTypeService materialTypeService) {
|
||||
this.mixService = mixService;
|
||||
this.recipeService = recipeService;
|
||||
this.materialService = materialService;
|
||||
this.mixTypeService = mixTypeService;
|
||||
this.materialTypeService = materialTypeService;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,6 +78,7 @@ public class MixCreatorController {
|
|||
|
||||
ModelResponseBuilder responseBuilder = modelResponseBuilder
|
||||
.addResponseData(ResponseDataType.RECIPE, recipe)
|
||||
.addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAll())
|
||||
.addAttribute("materialsJson", materialService.asJson(materials));
|
||||
|
||||
if (materialService.getAll().isEmpty()) {
|
||||
|
|
|
@ -7,10 +7,7 @@ import dev.fyloz.trial.colorrecipesexplorer.core.model.Material;
|
|||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Mix;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.MixType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.dto.MixCreationFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MaterialService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MixService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MixTypeService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.RecipeService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.*;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.utils.ControllerUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
|
@ -28,7 +25,7 @@ import java.util.Optional;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.PagesPaths.*;
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.StringBank.MIX_ID;
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.StringBank.*;
|
||||
|
||||
@Controller
|
||||
public class MixEditorController {
|
||||
|
@ -37,13 +34,15 @@ public class MixEditorController {
|
|||
private MaterialService materialService;
|
||||
private RecipeService recipeService;
|
||||
private MixTypeService mixTypeService;
|
||||
private MaterialTypeService materialTypeService;
|
||||
|
||||
@Autowired
|
||||
public MixEditorController(MixService mixService, MaterialService materialService, RecipeService recipeService, MixTypeService mixTypeService) {
|
||||
public MixEditorController(MixService mixService, MaterialService materialService, RecipeService recipeService, MixTypeService mixTypeService, MaterialTypeService materialTypeService) {
|
||||
this.mixService = mixService;
|
||||
this.materialService = materialService;
|
||||
this.recipeService = recipeService;
|
||||
this.mixTypeService = mixTypeService;
|
||||
this.materialTypeService = materialTypeService;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,7 +78,9 @@ public class MixEditorController {
|
|||
|
||||
return modelResponseBuilder
|
||||
.addResponseData(ResponseDataType.MIX, mix)
|
||||
.addResponseData(ResponseDataType.RECIPE_CODE, mix.getRecipe().getRecipeCode())
|
||||
.addResponseData(ResponseDataType.RECIPE, mix.getRecipe())
|
||||
.addAttribute(MATERIAL_TYPE, mix.getMixType().getMaterial().getMaterialType())
|
||||
.addAttribute(MATERIAL_TYPES, materialTypeService.getAll())
|
||||
.addAttribute("mixJson", materialService.asJson(mix))
|
||||
.addAttribute("materialsJson", materialService.asJson(materials))
|
||||
.build();
|
||||
|
|
|
@ -71,11 +71,9 @@ public class CompanyRemoverController {
|
|||
if (optionalCompany.isPresent()) {
|
||||
Company company = optionalCompany.get();
|
||||
|
||||
if (companyService.deleteIfNotLinked(company)) {
|
||||
modelResponseBuilder.addResponseData(ResponseDataType.COMPANY_NAME, company.getCompanyName());
|
||||
} else {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.COMPANY_LINKED, company.getCompanyName());
|
||||
}
|
||||
if (companyService.deleteIfNotLinked(company))
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_DELETING_COMPANY, company.getCompanyName());
|
||||
else modelResponseBuilder.addResponseCode(ResponseCode.COMPANY_LINKED, company.getCompanyName());
|
||||
} else {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.COMPANY_NOT_FOUND, companyID);
|
||||
}
|
||||
|
|
|
@ -18,10 +18,14 @@ spring:
|
|||
h2:
|
||||
console:
|
||||
enabled: true
|
||||
path: /dbconsole
|
||||
settings:
|
||||
trace: true
|
||||
web-allow-others: true
|
||||
server:
|
||||
port: 9090
|
||||
error:
|
||||
whitelabel:
|
||||
enabled: false
|
||||
response:
|
||||
useport: true
|
||||
useport: true
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
company.form.companyName=Banner name
|
||||
menu.list=List
|
||||
menu.explore=Explore
|
||||
menu.add=Add
|
||||
menu.edit=Edit
|
||||
menu.delete=Delete
|
||||
|
@ -100,3 +100,6 @@ recipe.warning.exportAll=Do you really want to export all the colors? This can t
|
|||
warning.noResult=Nothing corresponding the the research was found
|
||||
inventory.askUseMix=Do you really want to deduct this mix from the inventory?
|
||||
inventory.askUseRecipe=Do you really want to deduct this recipe from the inventory?
|
||||
keyword.images=Images
|
||||
warning.askChangePage=Are you sure you want to continue? Unsaved changes will be lost.
|
||||
keyword.print=Print
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
menu.list=Listes
|
||||
menu.explore=Explorer
|
||||
menu.add=Ajouter
|
||||
menu.edit=Modifier
|
||||
menu.delete=Supprimer
|
||||
|
@ -100,4 +100,7 @@ recipe.warning.exportAll=Voulez-vous vraiment exporter toutes les couleurs? Cela
|
|||
warning.noResult=Rien correspondant à la recherche n'a été trouvé
|
||||
inventory.askUseMix=Êtes-vous certain de vouloir déduire ce mélange de l'inventaire?
|
||||
inventory.askUseRecipe=Êtes-vous certain de vouloir déduire cette recette de l'inventaire?
|
||||
keyword.images=Images
|
||||
warning.askChangePage=Êtes-vous sûr de vouloir continuer? Les modifications non enregistrées seront perdues.
|
||||
keyword.print=Imprimer
|
||||
|
||||
|
|
|
@ -26,4 +26,5 @@ response.22=No companies were found
|
|||
response.23=No materials were found.
|
||||
response.24=This file need to be an image
|
||||
response.25=The recipe was not found
|
||||
response.26=The material with the code {0} was not found
|
||||
response.26=The material with the code {0} was not found
|
||||
response.27=The banner {0} has been delete
|
||||
|
|
|
@ -26,4 +26,5 @@ response.22=Aucune compagnie n'a été trouvée
|
|||
response.23=Aucun produit n'a été trouvée.
|
||||
response.24=Ce fichier doit être une image
|
||||
response.25=La recette n'a pas été trouvée
|
||||
response.26=Le produit ayant le code {0} n''a pas été trouvé
|
||||
response.26=Le produit ayant le code {0} n''a pas été trouvé
|
||||
response.27=La bannière {0} a bien été supprimée
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
.mix {
|
||||
width: 600px;
|
||||
}
|
||||
|
||||
p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.mixContainer {
|
||||
display: flex;
|
||||
padding: 20px 0;
|
||||
border-style: solid;
|
||||
border-width: 1px 0;
|
||||
border-color: #555555;
|
||||
}
|
||||
|
||||
.mixContainer:first-child {
|
||||
border-top-color: white;
|
||||
}
|
||||
|
||||
.mixContainer:last-child {
|
||||
border-bottom-color: white;
|
||||
}
|
||||
|
||||
.mixContainer .mixInfo {
|
||||
width: 130px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.mixContainer .mix {
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.mixContainer .mixActionsContainer {
|
||||
margin-left: 15px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mix td, .mix th {
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.notEnough td {
|
||||
background-color: #ffb3b3;
|
||||
}
|
||||
|
||||
.quantityColumn, .mix input {
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.totalQuantityLabel {
|
||||
padding-right: 10px;
|
||||
text-align: right;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.inventoryQuantity {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.inventoryQuantityColumn {
|
||||
min-width: auto !important;
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
.unitsColumn {
|
||||
width: 25px !important;
|
||||
min-width: 0 !important;
|
||||
max-width: 25px !important;
|
||||
}
|
||||
|
||||
.calculationColumn {
|
||||
max-width: 125px !important;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.calculation {
|
||||
color: dimgrey;
|
||||
}
|
||||
|
||||
.calculation span {
|
||||
color: darkgreen;
|
||||
}
|
||||
|
||||
.materialCodeColumn {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.recipeLocation {
|
||||
width: 55px;
|
||||
}
|
||||
|
||||
.recipeDescription {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.recipeDescription div {
|
||||
border-color: #555555;
|
||||
border-width: 1px 0;
|
||||
border-style: solid;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.recipeDescription div:first-child {
|
||||
border-top-color: white;
|
||||
}
|
||||
|
||||
.recipeDescription div:nth-last-child(2) {
|
||||
border-bottom-color: white;
|
||||
}
|
||||
|
||||
.recipeDescription div b {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.recipeDescription div :not(b) {
|
||||
float: right;
|
||||
margin: 0 0 0 20px;
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
.steps {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.steps li {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.steps li:nth-child(even) {
|
||||
background-color: #f5f5f5;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.steps li:nth-child(odd) {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.imagesContainer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.imagesContainer img {
|
||||
margin: 10px;
|
||||
border: 1px solid #7a7a7a;
|
||||
transition: all 0.5s;
|
||||
}
|
||||
|
||||
.imagesContainer .recipeImage:hover {
|
||||
width: 420px;
|
||||
}
|
||||
|
||||
.imagesContainer.hovering .recipeImage:not(:hover) {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1900px) {
|
||||
.imagesContainer {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
.content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
margin-left: 50px;
|
||||
margin-right: 50px;
|
||||
}
|
||||
|
||||
.content .flexContent {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.formWrap, .formEndButtons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.formEndButtons button[type="button"] {
|
||||
margin-right: 75px;
|
||||
}
|
||||
|
||||
.formEndButtons button[type="submit"] {
|
||||
margin-left: 75px;
|
||||
}
|
||||
|
||||
.formColumn {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.formColumn div {
|
||||
min-height: 25px;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.formColumn select, .formColumn input, .formColumn button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.formColumn input[type="text"], .formColumn input[type="number"], .formColumn input[type="date"], .formColumn select {
|
||||
width: 145px;
|
||||
}
|
||||
|
||||
.formColumn:first-child {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.formColumn:last-child {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.rawInput:not(textarea):not(.noStyle) {
|
||||
border-bottom-color: #7a7a7a;
|
||||
color: #454545;
|
||||
}
|
||||
|
||||
.rawInput:hover:not(textarea):not(.noStyle) {
|
||||
border-bottom-color: #7a7a7a;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
.form {
|
||||
display: inline-block;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
td:not(.centerTd) {
|
||||
text-align: right;
|
||||
}
|
|
@ -1,61 +1,18 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: black;
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
font-size: large;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
header, footer {
|
||||
background-color: black;
|
||||
height: 70px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
color: white;
|
||||
}
|
||||
|
||||
footer {
|
||||
position: fixed;
|
||||
height: 5%;
|
||||
bottom: 0;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
header img {
|
||||
float: right;
|
||||
}
|
||||
|
||||
section {
|
||||
text-align: center;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
nav {
|
||||
overflow: hidden;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
nav a {
|
||||
float: left;
|
||||
font-size: 18px;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 14px 16px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
|
@ -109,85 +66,44 @@ input[type=number] {
|
|||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
textarea {
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
background-color: #fafafa;
|
||||
border-style: solid;
|
||||
border-color: #7a7a7a;
|
||||
border-width: 1px;
|
||||
font-family: inherit;
|
||||
border: 1px solid #7a7a7a;
|
||||
margin-left: 20px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
margin-top: 22px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
/*.error {*/
|
||||
/* color: red;*/
|
||||
/*}*/
|
||||
|
||||
/*.success {*/
|
||||
/* color: green;*/
|
||||
/*}*/
|
||||
|
||||
/*.error, .success {*/
|
||||
/* font-weight: bold;*/
|
||||
/*}*/
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.dropdown .dropbtn {
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
color: white;
|
||||
outline: none;
|
||||
padding: 14px 16px;
|
||||
background-color: inherit;
|
||||
font-family: inherit;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
nav a:hover, .dropdown:hover .dropbtn {
|
||||
background-color: #0d0d0d;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #0d0d0d;
|
||||
min-width: 160px;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.dropdown-content a {
|
||||
float: none;
|
||||
color: white;
|
||||
padding: 12px 16px;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
table:not(.noStyle) {
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #7a7a7a;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.dropdown-content a:hover {
|
||||
background-color: #1a1a1a;
|
||||
table:not(.noStyle) th {
|
||||
background-color: black;
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.dropdown:hover .dropdown-content {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.success {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.error, .success {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.mainTable {
|
||||
border-spacing: 30px;
|
||||
}
|
||||
|
||||
.mainTableEndButtons {
|
||||
text-align: center;
|
||||
table:not(.noStyle) tr:nth-child(odd) {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.nosimdut td {
|
||||
|
@ -199,7 +115,7 @@ nav a:hover, .dropdown:hover .dropbtn {
|
|||
}
|
||||
|
||||
.unapproved {
|
||||
background-color: #fff0b3;
|
||||
background-color: #fff0b3 !important;
|
||||
}
|
||||
|
||||
#researchBoxContainer {
|
||||
|
@ -254,28 +170,38 @@ nav a:hover, .dropdown:hover .dropbtn {
|
|||
|
||||
.messageBox p {
|
||||
display: inline-block;
|
||||
/*padding: 3px 0;*/
|
||||
margin: 0 0 0 16px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
/*.errorBox div {*/
|
||||
/* height: 24px;*/
|
||||
/* !*padding: 20px;*!*/
|
||||
/* margin: auto;*/
|
||||
/* vertical-align: middle;*/
|
||||
/*}*/
|
||||
.subtitle {
|
||||
padding: 0 !important;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*.errorBox img {*/
|
||||
/* display: inline-block;*/
|
||||
/* float: left;*/
|
||||
/* height: 25px;*/
|
||||
/*}*/
|
||||
.rawInput:not(.noStyle) {
|
||||
border-color: white;
|
||||
color: #7a7a7a;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/*.errorBox p {*/
|
||||
/* !*float: left;*!*/
|
||||
/* display: inline-block;*/
|
||||
/* font-size: 18px;*/
|
||||
/* margin: auto;*/
|
||||
/* padding: 2px 0;*/
|
||||
/*}*/
|
||||
.rawInput:hover:not(.noStyle) {
|
||||
border-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.rawInput:focus:not(.noStyle) {
|
||||
border-color: #7a7a7a;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.formEndButtons {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.returnButton {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.submitButton {
|
||||
float: right;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
header, footer {
|
||||
background-color: black;
|
||||
height: 70px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
color: white;
|
||||
}
|
||||
|
||||
footer {
|
||||
position: fixed;
|
||||
height: 5%;
|
||||
bottom: 0;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
nav img {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow: visible;
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
nav a {
|
||||
float: left;
|
||||
font-size: 18px;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 14px 16px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
margin-top: 22px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.dropdown .dropbtn {
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
color: white;
|
||||
outline: none;
|
||||
padding: 14px 16px;
|
||||
background-color: inherit;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
nav a:hover, .dropdown:hover .dropbtn {
|
||||
background-color: #0d0d0d;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #0d0d0d;
|
||||
min-width: 160px;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.dropdown-content a {
|
||||
float: none;
|
||||
color: white;
|
||||
padding: 12px 16px;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.dropdown-content a:hover {
|
||||
background-color: #1a1a1a;
|
||||
}
|
||||
|
||||
.dropdown:hover .dropdown-content {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 702px) {
|
||||
nav img {
|
||||
display: none;
|
||||
}
|
||||
}
|
|
@ -4,6 +4,10 @@
|
|||
width: 150px;
|
||||
}
|
||||
|
||||
.materialSelector {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.materialSelector .materialList {
|
||||
border-color: #7a7a7a;
|
||||
border-width: 1px;
|
||||
|
@ -12,9 +16,10 @@
|
|||
max-height: 300px;
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
position: fixed;
|
||||
width: 150px;
|
||||
z-index: 99;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
width: 200px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.materialSelector .materialList.show {
|
||||
|
@ -36,6 +41,70 @@
|
|||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.unitsColumn {
|
||||
vertical-align: middle;
|
||||
.materialListWrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mixMaterialListTitle {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.mixMaterialListTitle div {
|
||||
display: block !important;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.materialListWrap div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.mixMaterialList {
|
||||
flex-direction: column !important;
|
||||
background-color: #f5f5f5;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: #7a7a7a;
|
||||
}
|
||||
|
||||
.materialListRow:nth-child(odd) {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.material, .material *, .quantity, .quantity * {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.material input {
|
||||
text-align: left;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.quantity input {
|
||||
text-align: right;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.units, .units * {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.removeButton, .removeButton * {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.positionButtons {
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
width: 50px;
|
||||
padding: 1px 3px 1px 1px;
|
||||
/*border-bottom: solid 1px #7a7a7a;*/
|
||||
}
|
||||
|
||||
.positionButtons button {
|
||||
margin: 1px;
|
||||
width: inherit;
|
||||
height: 50%;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
h1 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.content .recipesList {
|
||||
border-collapse: collapse;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.recipesList th {
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.recipesList td {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.recipeDescription {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.descriptionCell {
|
||||
border-right-color: #e6e6e6;
|
||||
border-right-style: solid;
|
||||
border-right-width: 2px;
|
||||
}
|
||||
|
||||
.researchEnabled .companyTab:not(.researchResult), .researchEnabled .recipeRow:not(.researchResult) {
|
||||
display: none;
|
||||
}
|
|
@ -6,30 +6,24 @@ const warningMsgBoxText = warningMsgBox.querySelector("p");
|
|||
const successMsgBox = document.querySelector(".successBox");
|
||||
const successMsgBoxText = successMsgBox.querySelector("p");
|
||||
|
||||
// Ne fonctionne pas dans window#load
|
||||
(() => {
|
||||
// Ajoute Axios
|
||||
const axiosElement = document.createElement("script");
|
||||
axiosElement.src = "/js/libs/axios.min.js";
|
||||
body.appendChild(axiosElement);
|
||||
$(() => {
|
||||
$('.materialCode').each(function () {
|
||||
const row = $(this);
|
||||
const materialID = row.data("materialid");
|
||||
|
||||
axiosElement.onload = () => {
|
||||
// Vérifie si les SIMDUTs sont présents
|
||||
document.querySelectorAll(".materialCode").forEach(e => {
|
||||
const materialID = e.getAttribute("data-materialID");
|
||||
axios.post(`/simdut/${materialID}`)
|
||||
.catch(err => {
|
||||
if (err.response.status === 404) {
|
||||
e.parentElement.classList.add("nosimdut");
|
||||
e.parentElement.title = simdutNotFoundText;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
axios.post(`/simdut/${materialID}`)
|
||||
.catch(function (err) {
|
||||
if (err.response.status === 404) {
|
||||
row.parent().addClass("nosimdut");
|
||||
row.parent().title = simdutNotFoundText;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Placé ici pour un chargement plus rapide
|
||||
document.querySelectorAll(".messageBox").forEach(e => checkMessageBoxesDisplay(e));
|
||||
})();
|
||||
$(".messageBox").each(function () {
|
||||
checkMessageBoxesDisplay($(this)[0])
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
|
||||
|
@ -64,9 +58,7 @@ window.addEventListener("load", () => {
|
|||
e.querySelectorAll(".remover").forEach(elem => {
|
||||
elem.addEventListener("click", () => {
|
||||
e.action += elem.getAttribute("data-entityID");
|
||||
e.onsubmit = () => {
|
||||
return checkPassword(e);
|
||||
}
|
||||
checkPassword(e);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -84,6 +76,10 @@ window.addEventListener("load", () => {
|
|||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('input[type="text"], input[type="number"], input[type="date"], textarea').forEach(e => e.classList.add("rawInput"))
|
||||
|
||||
document.querySelectorAll(".rawInput").forEach(e => e.placeholder = "N/A");
|
||||
|
||||
window.addEventListener("keyup", e => {
|
||||
if (e.target) {
|
||||
if (e.target.classList.contains("toSave")) {
|
||||
|
@ -108,32 +104,33 @@ function checkPassword(form, callback) {
|
|||
hideElement(errorMsgBox);
|
||||
|
||||
const password = prompt(askPasswordText);
|
||||
if (!password) return false;
|
||||
|
||||
let data = {};
|
||||
data.password = password;
|
||||
|
||||
axios.post("/password/valid", data)
|
||||
.then(r => {
|
||||
if (r.data) {
|
||||
if (r.data === true) {
|
||||
if (form != null) form.submit();
|
||||
if (callback != null) callback();
|
||||
return true;
|
||||
} else {
|
||||
errorMsgBoxText.innerText = invalidPasswordText;
|
||||
showElement(errorMsgBox);
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
errorMsgBoxText.innerText = generalErrorText;
|
||||
showElement(errorMsgBox);
|
||||
console.log(e);
|
||||
return false;
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkMessageBoxesDisplay(element) {
|
||||
if (!element.querySelector("p").innerText) hideElement(element);
|
||||
if (!element.querySelector("p").textContent) hideElement(element);
|
||||
else showElement(element);
|
||||
}
|
||||
|
||||
|
@ -142,7 +139,7 @@ function hideElement(element) {
|
|||
}
|
||||
|
||||
function showElement(element) {
|
||||
element.style.display = "inline-block";
|
||||
element.style.display = "";
|
||||
}
|
||||
|
||||
const lTomL = 1000;
|
||||
|
@ -151,17 +148,19 @@ const galTomL = 3785.41;
|
|||
let currentUnit = "mL";
|
||||
|
||||
// Change les unités selon la sélection de l'utilisateur
|
||||
function changeUnits(unitSelect, quantitiesSelector, unitsSelector) {
|
||||
function changeUnits(unitSelect, quantitiesSelector, unitsDisplay) {
|
||||
currentUnit = unitSelect.value;
|
||||
|
||||
document.querySelectorAll(unitsSelector).forEach(e => {
|
||||
document.querySelectorAll(unitsDisplay).forEach(e => {
|
||||
e.innerText = currentUnit;
|
||||
|
||||
// Modifie la quantitée
|
||||
const quantityElem = e.parentElement.parentElement.querySelector(quantitiesSelector);
|
||||
const originalQuantity = parseInt(quantityElem.dataset.quantityml);
|
||||
if (quantityElem) {
|
||||
const originalQuantity = parseInt(quantityElem.dataset.quantityml);
|
||||
|
||||
quantityElem.innerText = convertMlToUnit(originalQuantity);
|
||||
quantityElem.innerText = convertMlToUnit(originalQuantity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ let removeText;
|
|||
let materialSelectorHtml;
|
||||
let recipeID;
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
$(() => {
|
||||
recipeID = document.querySelector("#recipeID").value;
|
||||
|
||||
axios.get(`/mix/selector/${recipeID}/-1`)
|
||||
|
@ -16,65 +16,115 @@ window.addEventListener("load", () => {
|
|||
init();
|
||||
})
|
||||
.catch(e => {
|
||||
console.log(e.status);
|
||||
errorMsgBoxText.innerText = generalErrorText;
|
||||
showElement(errorMsgBox);
|
||||
console.log(e);
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener("click", e => {
|
||||
if (e.target) {
|
||||
if (e.target.classList.contains("rowRemover")) {
|
||||
document.querySelector(`#row_${e.target.dataset.remove}`).remove();
|
||||
return;
|
||||
}
|
||||
|
||||
const materialSelector = e.target.parentElement;
|
||||
if (materialSelector == null || materialSelector.parentElement == null) {
|
||||
hideMaterialList();
|
||||
return;
|
||||
}
|
||||
if (!materialSelector.classList.contains("materialSelector") && !materialSelector.parentElement.classList.contains("materialSelector")) hideMaterialList();
|
||||
}
|
||||
$(document).on("click", function () {
|
||||
hideMaterialList();
|
||||
});
|
||||
|
||||
document.querySelector("#materials button").addEventListener("click", () => {
|
||||
$(document).on("click", ".materialSelector", function (event) {
|
||||
event.stopPropagation();
|
||||
showMaterialList($(this)[0]);
|
||||
});
|
||||
|
||||
$(document).on("click", ".removeMaterial", function () {
|
||||
const id = $(this).data("removerow");
|
||||
if ($(".materialListRow").length > 1) $(`#${id}`).remove();
|
||||
});
|
||||
|
||||
$(document).on("click", ".upRow", function () {
|
||||
const row = $(this).parent().parent();
|
||||
row.insertBefore(row.prev());
|
||||
});
|
||||
|
||||
$(document).on("click", ".downRow", function () {
|
||||
const row = $(this).parent().parent();
|
||||
row.insertBefore(row.next());
|
||||
});
|
||||
|
||||
document.querySelector(".mixMaterialListTitle button").addEventListener("click", () => {
|
||||
addMaterial(null, null);
|
||||
});
|
||||
|
||||
function addMaterial(materialCode, quantity) {
|
||||
let row = addRow();
|
||||
const row = addRow(materialNbr);
|
||||
const positionColumn = addColumn("positionButtons", row);
|
||||
const materialColumn = addColumn("material", row);
|
||||
const quantityColumn = addColumn("quantity", row);
|
||||
const unitsColumn = addColumn("units", row);
|
||||
const removeButtonColumn = addColumn("removeButton", row);
|
||||
|
||||
let materialSelectionColumn = addColumn(row, null);
|
||||
let quantityInputColumn = addColumn(row, null);
|
||||
let unitsColumn = addColumn(row, "unitsColumn");
|
||||
let removeButtonColumn = addColumn(row, null);
|
||||
addPositionButtons(positionColumn);
|
||||
addQuantityInput(quantity, quantityColumn);
|
||||
addUnits(unitsColumn);
|
||||
addRemoveButton(materialNbr, removeButtonColumn);
|
||||
|
||||
addInput(quantityInputColumn, quantity);
|
||||
addSpan(unitsColumn);
|
||||
addButton(removeButtonColumn);
|
||||
|
||||
materialSelectionColumn.innerHTML = materialSelectorHtml;
|
||||
const input = materialSelectionColumn.querySelector("input");
|
||||
materialColumn.innerHTML = materialSelectorHtml;
|
||||
const materialSelector = materialColumn.querySelector("input");
|
||||
if (materialCode) {
|
||||
const material = materialSelectionColumn.querySelector(`.materialList p[data-materialcode="${materialCode}"]`);
|
||||
const material = materialColumn.querySelector(`.materialList p[data-materialcode="${materialCode}"]`);
|
||||
|
||||
if (material) {
|
||||
input.value = material.dataset.materialcode;
|
||||
input.dataset.usepercentages = material.dataset.usepercentages;
|
||||
materialSelector.value = material.dataset.materialcode;
|
||||
materialSelector.dataset.usepercentages = material.dataset.usepercentages;
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelector("#materials tbody").appendChild(row);
|
||||
materialNbr++;
|
||||
row.appendChild(materialColumn);
|
||||
row.appendChild(quantityColumn);
|
||||
row.appendChild(unitsColumn);
|
||||
row.appendChild(removeButtonColumn);
|
||||
|
||||
checkUnits(input, row);
|
||||
document.querySelector(".mixMaterialList").appendChild(row);
|
||||
|
||||
checkUnits(materialSelector, row);
|
||||
materialNbr++;
|
||||
}
|
||||
|
||||
function addInput(parent, quantity) {
|
||||
function addRow(index) {
|
||||
const row = document.createElement("div");
|
||||
row.classList.add("materialListRow");
|
||||
row.id = `material_${index}`;
|
||||
return row;
|
||||
}
|
||||
|
||||
function addColumn(type, parent) {
|
||||
const column = document.createElement("div");
|
||||
column.classList.add(type);
|
||||
|
||||
parent.appendChild(column);
|
||||
return column;
|
||||
}
|
||||
|
||||
function addUnits(parent) {
|
||||
const units = document.createElement("p");
|
||||
units.classList.add("quantityUnits");
|
||||
units.textContent = "mL";
|
||||
|
||||
parent.appendChild(units);
|
||||
return units;
|
||||
}
|
||||
|
||||
function addRemoveButton(index, parent) {
|
||||
const button = document.createElement("button");
|
||||
button.type = "button";
|
||||
button.textContent = removeText;
|
||||
button.dataset.removerow = `material_${index}`;
|
||||
button.classList.add("removeMaterial");
|
||||
|
||||
parent.appendChild(button);
|
||||
return button;
|
||||
}
|
||||
|
||||
function addQuantityInput(quantity, parent) {
|
||||
let input = document.createElement("input");
|
||||
|
||||
if (quantity === null) quantity = 1;
|
||||
if (quantity === undefined || quantity === null) quantity = 1;
|
||||
|
||||
input.type = "number";
|
||||
input.name = "quantities";
|
||||
|
@ -87,41 +137,18 @@ function addInput(parent, quantity) {
|
|||
return input;
|
||||
}
|
||||
|
||||
function addSpan(parent) {
|
||||
let span = document.createElement("span");
|
||||
function addPositionButtons(parent) {
|
||||
const up = document.createElement("button");
|
||||
up.classList.add("upRow");
|
||||
up.type = "button";
|
||||
up.textContent = "↑";
|
||||
parent.appendChild(up);
|
||||
|
||||
span.className = "quantityUnit";
|
||||
span.innerText = "mL";
|
||||
|
||||
parent.appendChild(span);
|
||||
return span;
|
||||
}
|
||||
|
||||
function addButton(parent) {
|
||||
let button = document.createElement("button");
|
||||
|
||||
button.type = "button";
|
||||
button.dataset.remove = materialNbr;
|
||||
button.className = "rowRemover";
|
||||
button.innerText = removeText;
|
||||
|
||||
parent.appendChild(button);
|
||||
return button;
|
||||
}
|
||||
|
||||
function addRow() {
|
||||
let row = document.createElement("tr");
|
||||
row.id = `row_${materialNbr}`;
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
function addColumn(parent, className) {
|
||||
let column = document.createElement("td");
|
||||
if (className != null) column.className = className;
|
||||
|
||||
parent.appendChild(column);
|
||||
return column;
|
||||
const down = document.createElement("button");
|
||||
down.classList.add("downRow");
|
||||
down.type = "button";
|
||||
down.textContent = "↓";
|
||||
parent.appendChild(down);
|
||||
}
|
||||
|
||||
function showMaterialList(input) {
|
||||
|
@ -152,7 +179,7 @@ function searchMaterial(input) {
|
|||
materials = input.parentElement.querySelectorAll(".materialList p");
|
||||
|
||||
materials.forEach(e => {
|
||||
if (searchIn(filter, e.textContent) || searchIn(filter, e.dataset.materialType)) e.style.display = "";
|
||||
if (searchIn(filter, e.textContent) || searchIn(filter, e.dataset.materialtype)) e.style.display = "";
|
||||
else e.style.display = "none";
|
||||
});
|
||||
|
||||
|
@ -163,7 +190,7 @@ function searchMaterial(input) {
|
|||
}
|
||||
|
||||
function checkUnits(materialSelector, row) {
|
||||
const quantityUnits = row.querySelector(".quantityUnit");
|
||||
const quantityUnits = row.querySelector(".quantityUnits");
|
||||
if (materialSelector.dataset.usepercentages === "true") quantityUnits.innerText = "%";
|
||||
else quantityUnits.innerText = "mL";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
(() => {
|
||||
document.querySelectorAll(".recipeRow").forEach(e => {
|
||||
if (e.dataset.approbationdate === undefined) {
|
||||
e.classList.add("unapproved");
|
||||
e.title = recipeNotApproved;
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
function closeTabs() {
|
||||
document.querySelectorAll(".recipesList").forEach(l => l.style.display = "none");
|
||||
}
|
||||
|
||||
function openTabs() {
|
||||
document.querySelectorAll(".recipesList").forEach(l => l.style.display = "");
|
||||
}
|
||||
|
||||
const companyRows = document.querySelectorAll(".companyTab");
|
||||
|
||||
function performSearch(searchString) {
|
||||
let found = false;
|
||||
let emptySearch = false;
|
||||
|
||||
const recipesContainer = document.querySelector(".recipesContainer:not(.researchEnabled)");
|
||||
if (recipesContainer !== undefined && recipesContainer !== null) {
|
||||
recipesContainer.classList.add("researchEnabled");
|
||||
}
|
||||
|
||||
document.querySelectorAll(".researchResult").forEach(t => {
|
||||
t.classList.remove("researchResult");
|
||||
});
|
||||
|
||||
companyRows.forEach(c => {
|
||||
const recipeRows = c.querySelectorAll(".recipeRow");
|
||||
|
||||
hideElement(warningMsgBox);
|
||||
|
||||
if (!searchString || !searchString.replace(/\s/g, '').length) {
|
||||
c.classList.add("researchResult");
|
||||
|
||||
recipeRows.forEach(r => {
|
||||
r.classList.add("researchResult");
|
||||
});
|
||||
|
||||
found = true;
|
||||
emptySearch = true;
|
||||
} else if (searchIn(searchString, c.querySelector("h2").dataset.companyname)) {
|
||||
c.classList.add("researchResult");
|
||||
recipeRows.forEach(r => r.classList.add("researchResult"));
|
||||
found = true;
|
||||
} else {
|
||||
recipeRows.forEach(r => {
|
||||
r.querySelectorAll(".descriptionCell").forEach(d => {
|
||||
if (searchIn(searchString, d.textContent)) {
|
||||
r.classList.add("researchResult");
|
||||
c.classList.add("researchResult");
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
warningMsgBoxText.innerText = researchNotFound;
|
||||
showElement(warningMsgBox);
|
||||
}
|
||||
|
||||
if (emptySearch) closeTabs();
|
||||
else openTabs();
|
||||
}
|
||||
);
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{company.add.title})"></th:block>
|
||||
|
||||
<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 th:text="#{company.add.title}"></h1>
|
||||
<p th:text="#{company.success.created(${companyName})}"></p>
|
||||
<button class="returnButton" th:text="#{keyword.back}"></button>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,10 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{company.add.title})"></th:block>
|
||||
|
||||
<link href="/css/main.css" rel="stylesheet"/>
|
||||
<link href="/css/forms.css" rel="stylesheet"/>
|
||||
<th:block th:include="fragments.html :: head(#{company.add.title}, 'form')"></th:block>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -15,22 +12,29 @@
|
|||
<div th:include="fragments.html :: messages"></div>
|
||||
<h1 th:text="#{company.add.title}"></h1>
|
||||
|
||||
<div class="form">
|
||||
<form th:action="@{/company/creator}" th:object="${company}" class="requireAuth" method="POST">
|
||||
<table>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('companyName')}"
|
||||
th:text="#{company.form.companyName} + ':'"></label></b></td>
|
||||
<td><input type="text" th:field="*{companyName}" required /></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: mainTableButtons"></tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<form th:action="@{/company/creator}"
|
||||
th:object="${company}"
|
||||
class="requireAuth"
|
||||
method="POST">
|
||||
<div class="content">
|
||||
<div class="formWrap">
|
||||
<div class="formColumn">
|
||||
<label th:for="${#ids.next('companyName')}"
|
||||
th:text="#{company.form.companyName} + ':'"></label>
|
||||
</div>
|
||||
<div class="formColumn">
|
||||
<input class="rawInput"
|
||||
required
|
||||
th:field="*{companyName}"
|
||||
type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="fragments.html :: formEndButtons"></div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{company.delete.title})"></th:block>
|
||||
|
||||
<!-- <link href="/css/forms.css" rel="stylesheet"/>-->
|
||||
<th:block th:include="fragments.html :: head(#{company.delete.title}, null)"></th:block>
|
||||
|
||||
<style>
|
||||
table {
|
||||
|
@ -58,6 +56,5 @@
|
|||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer('/company/remover', true)"></footer>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,29 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{app.title}, null)"></th:block>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Fragment de l'entête -->
|
||||
<header th:include="fragments.html :: header"></header>
|
||||
|
||||
<section>
|
||||
<h2 class="error" style="margin-top: 100px" th:text="#{${error}}"></h2>
|
||||
<button id="backButton" type="button">Retour</button>
|
||||
<div th:include="fragments.html :: messages"></div>
|
||||
<br/>
|
||||
|
||||
<div class="content">
|
||||
<button class="returnButton" type="button" th:text="#{keyword.back}"></button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, false)"></footer>
|
||||
|
||||
|
||||
<script>
|
||||
/*<![CDATA[*/
|
||||
(() => {
|
||||
document.querySelector("#backButton").addEventListener("click", () => {
|
||||
document.location.href = '[[${referer}]]';
|
||||
});
|
||||
})();
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||
<head th:fragment="head(title)">
|
||||
<head th:fragment="head(title, styleName)">
|
||||
<title th:text="${title}"></title>
|
||||
<meta charset="UTF-8"/>
|
||||
<link rel="stylesheet" th:href="@{|${baseUrl}/css/main.css|}"/>
|
||||
<link rel="stylesheet" th:href="@{|${baseUrl}/css/menu.css|}"/>
|
||||
<link rel="stylesheet" th:href="@{|${baseUrl}/css/flex.css|}"/>
|
||||
|
||||
<link rel="stylesheet" th:if="${styleName != null}" th:href="@{|${baseUrl}/css/${styleName}.css|}">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div th:fragment="header">
|
||||
<nav>
|
||||
<img alt="logo" id="logo" th:src="@{|${baseUrl}/logo.png|}" onclick="location.href = '/'"/>
|
||||
<div class="dropdown">
|
||||
<button class="dropbtn" onclick="document.location.href='/'" th:text="#{menu.list}">
|
||||
<button class="dropbtn" onclick="document.location.href='/'" th:text="#{menu.explore}">
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown">
|
||||
|
@ -52,6 +55,7 @@
|
|||
<a th:href="@{|${baseUrl}/updates|}" th:text="#{keyword.updates}"></a>
|
||||
</div>
|
||||
</div>
|
||||
<img alt="logo" id="logo" th:src="@{|${baseUrl}/logo.png|}" onclick="location.href = '/'"/>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
@ -75,7 +79,8 @@
|
|||
<div class="messageBox successBox">
|
||||
<div class="messageBoxContainer">
|
||||
<img th:src="@{|${baseUrl}/icons/success.svg|}" alt="success icon"/>
|
||||
<p th:if="${success != null && !success.isEmpty()}" th:text="#{${success}}"></p>
|
||||
<p th:if="${success != null && !success.isEmpty()}"
|
||||
th:text="#{${success}(${responseArg1}, ${responseArg2})}"></p>
|
||||
<p th:if="${success == null || success.isEmpty()}"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -85,7 +90,8 @@
|
|||
<div class="messageBox warningBox">
|
||||
<div class="messageBoxContainer">
|
||||
<img th:src="@{|${baseUrl}/icons/warning.svg|}" alt="warning icon"/>
|
||||
<p th:if="${warning != null && !warning.isEmpty()}" th:text="#{${warning}}"></p>
|
||||
<p th:if="${warning != null && !warning.isEmpty()}"
|
||||
th:text="#{${warning}(${responseArg1}, ${responseArg2})}"></p>
|
||||
<p th:if="${warning == null || warning.isEmpty()}"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -105,7 +111,9 @@
|
|||
th:text="#{footer.lang}"></a>
|
||||
</th:block>
|
||||
|
||||
<script src="/js/main.js"></script>
|
||||
<script th:src="@{|${baseUrl}/js/libs/jquery-3.4.1.min.js|}"></script>
|
||||
<script th:src="@{|${baseUrl}/js/libs/axios.min.js|}"></script>
|
||||
<script th:src="@{|${baseUrl}/js/main.js|}"></script>
|
||||
<script>
|
||||
/*<![CDATA[*/
|
||||
const simdutNotFoundText = "[[#{material.simdutFile.notFound}]]".replace("'", "'");
|
||||
|
@ -115,6 +123,8 @@
|
|||
const invalidPasswordText = "[[#{password.notValid}]]".replace("'", "'");
|
||||
const generalErrorText = "[[#{error.serverError}]]".replace("'", "'");
|
||||
const researchNotFound = "[[#{warning.noResult}]]".replace("'", "'");
|
||||
const recipeNotApproved = "[[#{recipe.warning.notApproved}]]".replace("'", "'");
|
||||
const askChangePage = "[[#{warning.askChangePage}]]".replace("'", "'");
|
||||
|
||||
const referer = "[[${referer}]]";
|
||||
/*]]>*/
|
||||
|
@ -130,5 +140,12 @@
|
|||
</td>
|
||||
</div>
|
||||
|
||||
<div th:fragment="formEndButtons">
|
||||
<div class="formEndButtons">
|
||||
<button class="returnButton" type="button" th:text="#{keyword.back}"></button>
|
||||
<button class="submitButton" type="submit" th:text="#{keyword.save}"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{image.add.title})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{image.add.title}, null)"></th:block>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
|
|
@ -1,46 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{app.title})"></th:block>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
th {
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.descriptionCell {
|
||||
border-right-color: #e6e6e6;
|
||||
border-right-style: solid;
|
||||
border-right-width: 2px;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 10px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
section {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.recipeDescription {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.researchEnabled .companyTab:not(.researchResult), .researchEnabled .recipeRow:not(.researchResult) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<th:block th:include="fragments.html :: head(#{app.title}, 'recipesList')"></th:block>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Fragment de l'entête -->
|
||||
|
@ -48,45 +9,49 @@
|
|||
<!-- Corps de la page -->
|
||||
<section>
|
||||
<div id="researchBoxContainer">
|
||||
<input id="researchBox" type="text" th:placeholder="#{keyword.search}" onkeyup="performSearch(this.value)"/>
|
||||
<input id="researchBox" class="noStyle" type="text" th:placeholder="#{keyword.search}"
|
||||
onkeyup="performSearch(this.value)"/>
|
||||
</div>
|
||||
|
||||
<div th:include="fragments.html :: messages"></div>
|
||||
|
||||
<div class="recipesContainer">
|
||||
<h1 th:text="#{menu.explore}"></h1>
|
||||
|
||||
<div class="content recipesContainer">
|
||||
<div class="companyTab" th:if="${!recipeMap.empty}" th:each="company : ${recipeMap.keySet()}"
|
||||
th:data-companyID="${company.companyID}">
|
||||
<h1 class="companyTabTitle" th:data-companyName="${company.companyName}"
|
||||
th:text="${company.companyName}"></h1>
|
||||
<h2 class="companyTabTitle" th:data-companyName="${company.companyName}"
|
||||
th:text="${company.companyName}"></h2>
|
||||
|
||||
<table class="recipesList" th:if="${!recipeMap.get(company).empty}" style="display:none"
|
||||
th:id="'recipes_' + ${company.companyName}">
|
||||
<table style="display:none" th:id="'recipes_' + ${company.companyName}" class="recipesList"
|
||||
th:if="${!recipeMap.get(company).empty}">
|
||||
<tr>
|
||||
<th th:text="#{recipe.color}"></th>
|
||||
<th th:text="#{recipe.description}"></th>
|
||||
<th th:text="#{recipe.sample}"></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr th:each="recipe : ${recipeMap.get(company)}" class="recipeRow"
|
||||
<tr class="recipeRow" th:each="recipe : ${recipeMap.get(company)}"
|
||||
th:data-approbationDate="${recipe.approbationDate}" th:data-recipeID="${recipe.recipeID}">
|
||||
<td class="descriptionCell" th:text="${recipe.recipeCode}"></td>
|
||||
<td class="descriptionCell recipeDescription" th:text="${recipe.recipeDescription}"></td>
|
||||
<td class="descriptionCell" th:text="'#' + ${recipe.sample}"></td>
|
||||
<td>
|
||||
<button class="gotoRecipe" th:data-recipeID="${recipe.recipeID}" type="button"
|
||||
<button class="gotoRecipe" th:data-recipeid="${recipe.recipeID}" type="button"
|
||||
th:text="#{keyword.see}"></button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<b class="error" th:if="${recipeMap.empty}" th:text="#{company.error.anyFound}"></b>
|
||||
|
||||
<b th:if="${recipeMap.empty}" class="error" th:text="#{recipe.error.anyFound}"></b>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
||||
<script th:inline="javascript">
|
||||
/*<![CDATA[*/
|
||||
<script th:src="@{|${baseUrl}/js/recipeResearch.js|}"></script>
|
||||
<script>
|
||||
(() => {
|
||||
document.querySelectorAll(".gotoRecipe").forEach(e => {
|
||||
e.addEventListener("click", () => {
|
||||
|
@ -95,82 +60,7 @@
|
|||
document.location.href = "/recipe/explore/" + recipeID;
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll(".recipeRow").forEach(e => {
|
||||
const approbationDate = e.getAttribute("data-approbationDate");
|
||||
|
||||
if (approbationDate === null) {
|
||||
e.classList.add("unapproved");
|
||||
e.title = [[#{recipe.warning.notApproved}]];
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
const companyRows = document.querySelectorAll(".companyTab");
|
||||
|
||||
function performSearch(searchString) {
|
||||
let found = false;
|
||||
let emptySearch = false;
|
||||
|
||||
const recipesContainer = document.querySelector(".recipesContainer:not(.researchEnabled)");
|
||||
if (recipesContainer !== undefined && recipesContainer !== null) {
|
||||
recipesContainer.classList.add("researchEnabled");
|
||||
}
|
||||
|
||||
document.querySelectorAll(".researchResult").forEach(t => {
|
||||
t.classList.remove("researchResult");
|
||||
});
|
||||
|
||||
companyRows.forEach(c => {
|
||||
const recipeRows = c.querySelectorAll(".recipeRow");
|
||||
|
||||
hideElement(warningMsgBox);
|
||||
|
||||
if (!searchString || !searchString.replace(/\s/g, '').length) {
|
||||
c.classList.add("researchResult");
|
||||
|
||||
recipeRows.forEach(r => {
|
||||
r.classList.add("researchResult");
|
||||
});
|
||||
|
||||
found = true;
|
||||
emptySearch = true;
|
||||
} else if (searchIn(searchString, c.querySelector("h1").dataset.companyname)) {
|
||||
c.classList.add("researchResult");
|
||||
recipeRows.forEach(r => r.classList.add("researchResult"));
|
||||
found = true;
|
||||
} else {
|
||||
recipeRows.forEach(r => {
|
||||
r.querySelectorAll(".descriptionCell").forEach(d => {
|
||||
if (searchIn(searchString, d.textContent)) {
|
||||
r.classList.add("researchResult");
|
||||
c.classList.add("researchResult");
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
warningMsgBoxText.innerText = researchNotFound;
|
||||
showElement(warningMsgBox);
|
||||
}
|
||||
|
||||
if (emptySearch) closeTabs();
|
||||
else openTabs();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function closeTabs() {
|
||||
document.querySelectorAll(".recipesList").forEach(l => l.style.display = "none");
|
||||
}
|
||||
|
||||
function openTabs() {
|
||||
document.querySelectorAll(".recipesList").forEach(l => l.style.display = "");
|
||||
}
|
||||
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<!-- Fragment du head -->
|
||||
<th:block th:include="fragments.html :: head(#{menu.inventory})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{menu.inventory}, null)"></th:block>
|
||||
|
||||
<!-- Style de la page -->
|
||||
<style>
|
||||
|
@ -43,6 +43,15 @@
|
|||
.researchEnabled .materialRow:not(.researchResult) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.options {
|
||||
padding-top: 80px !important;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.options div {
|
||||
padding: 20px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -59,36 +68,58 @@
|
|||
<h1 th:text="#{menu.inventory}"></h1>
|
||||
|
||||
<div id="researchBoxContainer">
|
||||
<input type="text" id="researchBox" th:placeholder="#{keyword.search}" onkeyup="performSearch(this.value)"/>
|
||||
<input type="text" id="researchBox" class="noStyle" th:placeholder="#{keyword.search}"
|
||||
onkeyup="performSearch(this.value)"/>
|
||||
</div>
|
||||
|
||||
<div th:include="fragments.html :: messages"></div>
|
||||
|
||||
<table class="materialsContainer" th:if="${!materials.empty}">
|
||||
<div class="content">
|
||||
<div class="flexContent">
|
||||
<table class="materialsContainer" th:if="${!materials.empty}">
|
||||
<!--Titres des colonnes et options de recherche-->
|
||||
<tr>
|
||||
<th th:text="#{keyword.material}"></th>
|
||||
<th th:text="#{keyword.quantity}"></th>
|
||||
|
||||
<!--Titres des colonnes et options de recherche-->
|
||||
<tr>
|
||||
<th th:text="#{keyword.material}"></th>
|
||||
<th th:text="#{keyword.quantity}"></th>
|
||||
<!--Unités de la quantité-->
|
||||
<th th:text="#{keyword.units}"></th>
|
||||
|
||||
<!--Unités de la quantité-->
|
||||
<th th:text="#{keyword.units}"></th>
|
||||
<th th:text="#{keyword.type}"></th>
|
||||
<th></th>
|
||||
|
||||
<th th:text="#{keyword.type}"></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
|
||||
<!--Options-->
|
||||
<td rowspan="5" style="padding-left : 20px">
|
||||
<!--Produits-->
|
||||
<tr class="materialRow" th:each="material : ${materials}"
|
||||
th:data-materialType="${material.materialType.materialTypeID}"
|
||||
th:data-materialID="${material.materialID}">
|
||||
<td class="materialCode" th:data-materialID="${material.materialID}"
|
||||
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 class="materialType" th:text="${material.materialType.materialTypeName}"></td>
|
||||
<td>
|
||||
<button class="modifyMaterial" th:data-materialID="${material.materialID}" type="button"
|
||||
th:text="#{keyword.edit}"></button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<b th:if="${materials.empty}" class="error" th:text="#{material.error.anyFound}"></b>
|
||||
</div>
|
||||
<div class="flexContent options" style="display: flex; flex-direction: column">
|
||||
<div>
|
||||
<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"/>
|
||||
<input id="lowQuantity" min="0" onkeyup="checkLowQuantity(this.value)" step="0.01"
|
||||
style="width: 65px" type="number"/>
|
||||
<br/>
|
||||
<input id="hideOthers" onchange="hide(this.checked)" type="checkbox"/><label for="hideOthers"
|
||||
th:text="#{inventory.hideOthers}"></label>
|
||||
<br/>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="materialTypeSelect" th:text="#{inventory.showOnly} + ':'"> </label>
|
||||
<select id="materialTypeSelect" name="materialTypeSelect" onchange="hideMaterialTypes(this)">
|
||||
<th:block th:each="materialType : ${materialTypes}">
|
||||
|
@ -96,9 +127,9 @@
|
|||
th:value="${materialType.materialTypeID}"></option>
|
||||
</th:block>
|
||||
</select>
|
||||
<br/>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="units" th:text="#{keyword.units} + ':'"></label>
|
||||
<select id="units" name="units"
|
||||
onchange="changeUnits(this, '.inventoryQuantity', '.inventoryQuantityUnits')">
|
||||
|
@ -106,28 +137,11 @@
|
|||
<option value="L" th:text="#{units.liters}"></option>
|
||||
<option value="gal" th:text="#{units.gallons}"></option>
|
||||
</select>
|
||||
</td>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</tr>
|
||||
|
||||
<!--Produits-->
|
||||
<tr class="materialRow" th:each="material : ${materials}"
|
||||
th:data-materialType="${material.materialType.materialTypeID}"
|
||||
th:data-materialID="${material.materialID}">
|
||||
<td class="materialCode" th:data-materialID="${material.materialID}"
|
||||
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 class="materialType" th:text="${material.materialType.materialTypeName}"></td>
|
||||
<td>
|
||||
<button class="modifyMaterial" th:data-materialID="${material.materialID}" type="button"
|
||||
th:text="#{keyword.edit}"></button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<b th:if="${materials.empty}" class="error" th:text="#{material.error.anyFound}"></b>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
@ -135,6 +149,8 @@
|
|||
<script>
|
||||
/*<![CDATA[*/
|
||||
|
||||
const defaultLowQuantity = 100;
|
||||
|
||||
(() => {
|
||||
|
||||
// Rajoute un événement sur les boutons pour modifier les produits pour rediriger l'utilisateur vers la page de modification
|
||||
|
@ -144,6 +160,9 @@
|
|||
});
|
||||
});
|
||||
|
||||
document.querySelector("#lowQuantity").value = defaultLowQuantity;
|
||||
checkLowQuantity(defaultLowQuantity)
|
||||
|
||||
})();
|
||||
|
||||
// Ajoute la classe "lowQuantity" au produits qui ont une quantité en inventaire inférieur à la quantité limite définie
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{material.add.title})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{material.add.title}, null)"></th:block>
|
||||
|
||||
<link href="/css/main.css" rel="stylesheet"/>
|
||||
</head>
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{material.add.title})"></th:block>
|
||||
|
||||
<link href="/css/main.css" rel="stylesheet"/>
|
||||
<link href="/css/forms.css" rel="stylesheet"/>
|
||||
<th:block th:include="fragments.html :: head(#{material.add.title}, 'form')"></th:block>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -16,62 +13,78 @@
|
|||
<div th:include="fragments.html :: messages"></div>
|
||||
|
||||
<h1 th:text="#{material.add.title}"></h1>
|
||||
<div class="form">
|
||||
<form th:action="@{/material/creator}" th:object="${material}" class="requireAuth" enctype="multipart/form-data"
|
||||
method="POST">
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('materialCode')}" th:text="#{material.code} + ':'"></label></b>
|
||||
</td>
|
||||
<td><input type="text" th:field="*{materialCode}" required /></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><b><label for="quantity" th:text="#{material.inventoryQuantity} + ':'"></label></b></td>
|
||||
<td><input data-unit="mL" id="quantity" min="0" name="quantity"
|
||||
onchange="calculateMilliliters(this.value, this.dataset.unit)" step="0.01" type="number"
|
||||
th:value="${material.inventoryQuantity}" required>
|
||||
<form th:action="@{/material/creator}" th:object="${material}" class="requireAuth" enctype="multipart/form-data"
|
||||
method="POST">
|
||||
<div class="content">
|
||||
<div class="formWrap">
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<label th:for="${#ids.next('materialCode')}" th:text="#{material.code} + ':'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label for="quantity" th:text="#{material.inventoryQuantity} + ':'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('materialType')}" th:text="#{material.type} + ':'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label for="simdut" th:text="#{material.simdutFile} + ':'"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<input type="text"
|
||||
class="rawInput"
|
||||
th:field="*{materialCode}"
|
||||
style="width: 145px"
|
||||
required/>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<input class="rawInput"
|
||||
data-unit="mL"
|
||||
id="quantity"
|
||||
min="0"
|
||||
name="quantity"
|
||||
onchange="calculateMilliliters(this.value, this.dataset.unit)"
|
||||
required
|
||||
step="0.001"
|
||||
th:value="${material.inventoryQuantity}"
|
||||
type="number"
|
||||
style="margin-right: 10px; width: 50px">
|
||||
<!--Contient la quantité en millilitres-->
|
||||
<input type="hidden" th:field="*{inventoryQuantity}"/>
|
||||
</td>
|
||||
<input type="hidden"
|
||||
th:field="*{inventoryQuantity}"/>
|
||||
|
||||
<td>
|
||||
<select id="units" name="units"
|
||||
<select id="units"
|
||||
name="units"
|
||||
onchange="switchUnits(this)">
|
||||
<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>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('materialType')}" th:text="#{material.type} + ':'"></label></b>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
<div>
|
||||
<select th:field="*{materialType}" required>
|
||||
<option th:each="materialType : ${materialTypes}" th:value="${materialType.materialTypeID}"
|
||||
th:text="${materialType.materialTypeName}"></option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><b><label for="simdut" th:text="#{material.simdutFile} + ':'"></label></b></td>
|
||||
<td><input id="simdut" name="simdut" type="file"/></td>
|
||||
</tr>
|
||||
|
||||
<tr th:include="fragments.html :: mainTableButtons"></tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<input id="simdut"
|
||||
class="rawInput"
|
||||
name="simdut"
|
||||
type="file"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="fragments.html :: formEndButtons"></div>
|
||||
</form>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
||||
|
||||
<script>
|
||||
function switchUnits(unitSelect) {
|
||||
const quantityElem = document.querySelector("#quantity");
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{material.editing.title(${material.materialCode})})"></th:block>
|
||||
<th:block
|
||||
th:include="fragments.html :: head(#{material.editing.title(${material.materialCode})}, 'form')"></th:block>
|
||||
|
||||
<link th:href="@{|${baseUrl}/css/forms.css|}" rel="stylesheet"/>
|
||||
</head>
|
||||
|
@ -14,58 +15,67 @@
|
|||
<div th:include="fragments.html :: messages"></div>
|
||||
|
||||
<h1 class="materialCode" th:text="#{material.editing.title(${material.materialCode})}"></h1>
|
||||
<div class="form">
|
||||
<form th:action="@{/material/editor}" th:object="${material}" class="requireAuth" method="POST">
|
||||
<input type="hidden" th:field="*{materialID}"/>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><b th:text="#{keyword.id} + ':'"></b></td>
|
||||
<td th:text="${material.materialID}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('materialCode')}" th:text="#{material.code} + ':'"></label></b>
|
||||
</td>
|
||||
<td><input type="text" th:field="*{materialCode}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><label for="quantity" th:text="#{material.inventoryQuantity}"></label></b></td>
|
||||
<td><input data-unit="mL" id="quantity" min="0" name="quantity"
|
||||
onchange="calculateMilliliters(this.value, this.dataset.unit)" step="0.01"
|
||||
th:value="${material.inventoryQuantity}" type="number"></td>
|
||||
<form th:action="@{/material/editor}" th:object="${material}" class="requireAuth" method="POST">
|
||||
<input type="hidden" th:field="*{materialID}"/>
|
||||
|
||||
<!--Contient la quantité en millilitres-->
|
||||
<input type="hidden" th:field="*{inventoryQuantity}"/>
|
||||
<td>
|
||||
<select id="units" name="units"
|
||||
<div class="content">
|
||||
<div class="formWrap">
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<label th:for="${#ids.next('materialID')}" th:text="#{keyword.id} + ':'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('materialCode')}" th:text="#{material.code} + ':'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label for="quantity" th:text="#{material.inventoryQuantity}"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('materialType')}">Type de produit: </label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<input type="number" th:field="*{materialID}" required disabled/>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" th:field="*{materialCode}"/>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<input data-unit="mL"
|
||||
id="quantity"
|
||||
min="0"
|
||||
name="quantity"
|
||||
onchange="calculateMilliliters(this.value, this.dataset.unit)"
|
||||
step="0.01"
|
||||
th:value="${material.inventoryQuantity}"
|
||||
type="number"
|
||||
style="margin-right: 10px; width: 50px">
|
||||
<!--Contient la quantité en millilitres-->
|
||||
<input type="hidden" th:field="*{inventoryQuantity}"/>
|
||||
|
||||
<select id="units"
|
||||
name="units"
|
||||
onchange="switchUnits(this)">
|
||||
<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>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('materialType')}">Type de produit: </label></b></td>
|
||||
<td><select th:field="*{materialType}">
|
||||
<option th:each="mType : ${materialTypes}"
|
||||
th:attrappend="selected=${mType.materialTypeID == material.materialType.materialTypeID}"
|
||||
th:text="${mType.materialTypeName}"
|
||||
th:value="${mType.materialTypeID}"></option>
|
||||
</select></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<button id="showSIMDUT" type="button" th:text="#{material.simdutFile}">Fichier SIMDUT</button>
|
||||
</td>
|
||||
<td>
|
||||
<button id="editSIMDUT" type="button" th:text="#{keyword.edit}"></button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: mainTableButtons"></tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<select th:field="*{materialType}">
|
||||
<option th:each="mType : ${materialTypes}"
|
||||
th:attrappend="selected=${mType.materialTypeID == material.materialType.materialTypeID}"
|
||||
th:text="${mType.materialTypeName}"
|
||||
th:value="${mType.materialTypeID}"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="fragments.html :: formEndButtons"></div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{material.edit.title})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{material.edit.title}, null)"></th:block>
|
||||
|
||||
<style>
|
||||
table {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{material.delete.title})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{material.delete.title}, null)"></th:block>
|
||||
|
||||
<style>
|
||||
table {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{material.add.title})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{material.add.title}, null)"></th:block>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{materialType.add.title})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{materialType.add.title}, 'form')"></th:block>
|
||||
|
||||
<link rel="stylesheet" th:href="@{|${baseUrl}/css/forms.css|}"/>
|
||||
</head>
|
||||
|
@ -14,30 +14,46 @@
|
|||
<div th:include="fragments.html :: messages"></div>
|
||||
<h1 th:text="#{materialType.add.title}"></h1>
|
||||
|
||||
<div class="form">
|
||||
<form th:action="@{/materialType/creator}" th:object="${materialType}" class="requireAuth" method="POST">
|
||||
<table>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('materialTypeName')}"
|
||||
th:text="#{materialType.name} + ':'"></label></b>
|
||||
</td>
|
||||
<td><input type="text" th:field="*{materialTypeName}" required></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('prefix')}"
|
||||
th:text="#{materialType.prefix} + ' (3 ' + #{keyword.characters} + '):'"></label></b>
|
||||
</td>
|
||||
<td><input maxlength="3" minlength="3" type="text" th:field="*{prefix}" required></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('usePercentages')}"
|
||||
th:text="#{materialType.usePercents} + ':'"></label></b></td>
|
||||
<td><input type="checkbox" th:field="*{usePercentages}"></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: mainTableButtons"></tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<form th:action="@{/materialType/creator}" th:object="${materialType}" class="requireAuth" method="POST">
|
||||
<div class="content">
|
||||
<div class="formWrap">
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<label th:for="${#ids.next('materialTypeName')}"
|
||||
th:text="#{materialType.name} + ':'"></label>
|
||||
</div>
|
||||
<div><label th:for="${#ids.next('prefix')}"
|
||||
th:text="#{materialType.prefix} + ' (3 ' + #{keyword.characters} + '):'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('usePercentages')}"
|
||||
th:text="#{materialType.usePercents} + ':'"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<input required
|
||||
class="rawInput"
|
||||
th:field="*{materialTypeName}"
|
||||
type="text"/>
|
||||
</div>
|
||||
<div>
|
||||
<input maxlength="3"
|
||||
minlength="3"
|
||||
class="rawInput"
|
||||
required
|
||||
th:field="*{prefix}"
|
||||
type="text"/>
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox"
|
||||
th:field="*{usePercentages}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="fragments.html :: formEndButtons"></div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block
|
||||
th:include="fragments.html :: head(#{materialType.editing.title(${materialType.materialTypeName})})"></th:block>
|
||||
|
||||
<link th:href="@{|${baseUrl}/css/forms.css|}" rel="stylesheet"/>
|
||||
th:include="fragments.html :: head(#{materialType.editing.title(${materialType.materialTypeName})}, 'form')"></th:block>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -15,35 +13,44 @@
|
|||
<div th:include="fragments.html :: messages"></div>
|
||||
|
||||
<h1 class="materialCode" th:text="#{materialType.editing.title(${materialType.materialTypeName})}"></h1>
|
||||
<div class="form">
|
||||
<form th:action="@{/materialType/editor}" th:object="${materialType}" class="requireAuth" method="POST">
|
||||
<input type="hidden" th:field="*{materialTypeID}">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><b th:text="#{keyword.id} + ':'"></b></td>
|
||||
<td th:text="${materialType.materialTypeID}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('materialTypeName')}"
|
||||
th:text="#{materialType.name} + ':'"></label></b></td>
|
||||
<td><input type="text" th:field="*{materialTypeName}" required></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('prefix')}"
|
||||
th:text="#{materialType.prefix} + ' (3 ' + #{keyword.characters} + '):'"></label></b>
|
||||
</td>
|
||||
<td><input type="text" minlength="3" maxlength="3" th:field="*{prefix}" required></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('usePercentages')}"
|
||||
th:text="#{materialType.usePercents} + ':'"></label></b></td>
|
||||
<td><input type="checkbox" th:field="*{usePercentages}"></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: mainTableButtons"></tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<form th:action="@{/materialType/editor}" th:object="${materialType}" class="requireAuth" method="POST">
|
||||
<div class="content">
|
||||
<div class="formWrap">
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<label th:for="${#ids.next('materialTypeID')}" th:text="#{material.type}"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('materialTypeName')}" th:text="#{materialType.name} + ':'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('prefix')}"
|
||||
th:text="#{materialType.prefix} + ' (3 ' + #{keyword.characters} + '):'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('usePercentages')}"
|
||||
th:text="#{materialType.usePercents} + ':'"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<input type="number" th:field="*{materialTypeID}" required disabled/>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" th:field="*{materialTypeName}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" minlength="3" maxlength="3" th:field="*{prefix}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" th:field="*{usePercentages}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="fragments.html :: formEndButtons"></div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{materialType.editor.title})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{materialType.editor.title}, null)"></th:block>
|
||||
|
||||
<style>
|
||||
table {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{materialType.delete.title})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{materialType.delete.title}, null)"></th:block>
|
||||
|
||||
<style>
|
||||
table {
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{mix.add.title})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{mix.add.title}, 'mix')"></th:block>
|
||||
|
||||
<link href="/css/forms.css" rel="stylesheet"/>
|
||||
<link href="/css/mix.css" rel="stylesheet"/>
|
||||
|
||||
<style>
|
||||
table {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/css/form.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -23,39 +16,58 @@
|
|||
<br/>
|
||||
<br/>
|
||||
|
||||
<div class="form">
|
||||
<form th:action="@{/mix/creator}" class="requireAuth" method="POST">
|
||||
<label for="mixType" th:text="#{mix.mixType} + ':'"></label><input type="text" id="mixType"
|
||||
name="mixTypeName"
|
||||
placeholder="ex: Teinture" required/>
|
||||
<form th:action="@{/mix/creator}" class="requireAuth" method="POST">
|
||||
<!-- Information nécessaire à la création des mélanges -->
|
||||
<input id="recipeID" name="recipe" th:value="${recipe.recipeID}" type="hidden"/>
|
||||
|
||||
<!-- Information nécessaire à la création des mélanges -->
|
||||
<input id="recipeID" name="recipe" th:value="${recipe.recipeID}" type="hidden"/>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<!-- Produits -->
|
||||
<table id="materials">
|
||||
<tr>
|
||||
<th th:text="#{keyword.material}"></th>
|
||||
<th>
|
||||
<span th:text="#{keyword.quantity}"></span>
|
||||
<button type="button">+</button>
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: mainTableButtons"></tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="flexContent formWrap">
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<label for="mixType" th:text="#{mix.mixType} + ':'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label for="materialType" th:text="#{material.type} + ':'"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<input type="text" id="mixType"
|
||||
name="mixTypeName"
|
||||
placeholder="ex: Teinture"
|
||||
required/>
|
||||
</div>
|
||||
<div>
|
||||
<select name="materialType" id="materialType">
|
||||
<option th:each="materialType : ${materialTypes}" th:value="${materialType.materialTypeID}"
|
||||
th:text="${materialType.materialTypeName}"></option>
|
||||
</select></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flexContent materialListWrap" style="margin: auto">
|
||||
<div class="mixMaterialListTitle">
|
||||
<div class="positionButtons">
|
||||
</div>
|
||||
<div class="material">
|
||||
<h3 th:text="#{keyword.material}"></h3>
|
||||
</div>
|
||||
<div class="quantity">
|
||||
<h3 th:text="#{keyword.quantity}"></h3>
|
||||
</div>
|
||||
<div class="units">
|
||||
<button type="button">+</button>
|
||||
</div>
|
||||
<div class="removeButton"></div>
|
||||
</div>
|
||||
<div class="mixMaterialList"></div>
|
||||
</div>
|
||||
<div th:include="fragments.html :: formEndButtons"></div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
||||
|
||||
<script src="/js/mix.js"></script>
|
||||
<script>
|
||||
/*<![CDATA[*/
|
||||
|
@ -67,7 +79,7 @@
|
|||
});
|
||||
|
||||
function init() {
|
||||
addMaterial(null, null);
|
||||
addMaterial();
|
||||
}
|
||||
|
||||
/*]]*/
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{mix.edit.title})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{mix.edit.title}, 'mix')"></th:block>
|
||||
|
||||
<link href="/css/forms.css" rel="stylesheet"/>
|
||||
<link href="/css/mix.css" rel="stylesheet"/>
|
||||
|
||||
<style>
|
||||
table {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
<link href="/css/form.css" rel="stylesheet"/>
|
||||
</head>
|
||||
<body th:with="nbrMaterials = 0">
|
||||
<!-- Fragment de l'entête -->
|
||||
|
@ -18,47 +11,69 @@
|
|||
<!-- Corps de la page -->
|
||||
<section>
|
||||
<div th:include="fragments.html :: messages"></div>
|
||||
<h1 th:text="#{mix.edit.subtitle(${recipeCode}, ${mix.mixType.typeName})}"></h1>
|
||||
<button id="removeMix" type="button" th:text="#{keyword.delete}"></button>
|
||||
<h1 th:text="#{mix.edit.subtitle(${recipe.recipeCode}, ${mix.mixType.typeName})}"></h1>
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<div class="form">
|
||||
<form th:action="@{/mix/editor}" class="requireAuth" method="POST">
|
||||
<!-- Information nécessaire à la création des mélanges -->
|
||||
<input name="mixID" th:value="${mix.mixID}" type="hidden"/>
|
||||
<input name="recipeID" id="recipeID" th:value="${mix.recipe.recipeID}" type="hidden"/>
|
||||
<form th:action="@{/mix/editor/}" class="requireAuth" method="POST">
|
||||
<!-- Information nécessaire à la création des mélanges -->
|
||||
<input id="recipeID" name="recipe" th:value="${recipe.recipeID}" type="hidden"/>
|
||||
<input id="mixID" name="mixID" th:value="${mix.mixID}" type="hidden"/>
|
||||
|
||||
<label for="mixType" th:text="#{mix.mixType} + ':'"></label>
|
||||
<input type="text"
|
||||
id="mixType"
|
||||
name="mixTypeName"
|
||||
th:value="${mix.mixType.typeName}"
|
||||
required/>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<table id="materials">
|
||||
<tr>
|
||||
<th th:text="#{keyword.material}"></th>
|
||||
<th>
|
||||
<span th:text="#{keyword.quantity}"></span>
|
||||
<button type="button">+</button>
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: mainTableButtons"></tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="flexContent formWrap">
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<label for="mixType" th:text="#{mix.mixType} + ':'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label for="materialType" th:text="#{material.type} + ':'"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<input type="text" id="mixType"
|
||||
name="mixTypeName"
|
||||
placeholder="ex: Teinture"
|
||||
th:value="${mix.mixType.typeName}"
|
||||
required/>
|
||||
</div>
|
||||
<div>
|
||||
<select name="materialType" id="materialType">
|
||||
<option th:each="currentMaterialType : ${materialTypes}"
|
||||
th:value="${currentMaterialType.materialTypeID}"
|
||||
th:text="${currentMaterialType.materialTypeName}"
|
||||
th:selected="${currentMaterialType.materialTypeID == materialType.materialTypeID}"></option>
|
||||
</select></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flexContent materialListWrap" style="margin: auto">
|
||||
<div class="mixMaterialListTitle">
|
||||
<div class="positionButtons">
|
||||
</div>
|
||||
<div class="material">
|
||||
<h3 th:text="#{keyword.material}"></h3>
|
||||
</div>
|
||||
<div class="quantity">
|
||||
<h3 th:text="#{keyword.quantity}"></h3>
|
||||
</div>
|
||||
<div class="units">
|
||||
<button type="button">+</button>
|
||||
</div>
|
||||
<div class="removeButton"></div>
|
||||
</div>
|
||||
<div class="mixMaterialList"></div>
|
||||
</div>
|
||||
<div th:include="fragments.html :: formEndButtons"></div>
|
||||
<div>
|
||||
<button type="button" id="removeMix" th:text="#{keyword.delete}"></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
||||
|
||||
<script src="/js/mix.js"></script>
|
||||
<script>
|
||||
/*<![CDATA[*/
|
||||
|
@ -72,7 +87,7 @@
|
|||
document.querySelector("#removeMix").addEventListener("click", () => {
|
||||
showElement(errorMsgBox);
|
||||
|
||||
checkPassword(null, () => document.location.href = `/mix/remover/${mix.mixID}`);
|
||||
checkPassword(null, () => document.location.href = `/mix/remover/[[${mix.mixID}]]`);
|
||||
});
|
||||
})();
|
||||
|
||||
|
|
|
@ -13,17 +13,15 @@
|
|||
autocomplete="off"
|
||||
data-usepercentages="false"
|
||||
required/>
|
||||
|
||||
<div class="materialList">
|
||||
<p
|
||||
th:each="material : ${materials}"
|
||||
th:text="${material.materialType.materialTypeName == 'Aucun' ? '' : '[' + material.materialType.prefix + ']'} + ' ' + ${material.materialCode}"
|
||||
th:data-materialcode="${material.materialCode}"
|
||||
th:data-materialtype="${material.materialType.materialTypeName}"
|
||||
th:data-usepercentages="${material.materialType.usePercentages}"
|
||||
onclick="selectMaterial(this)"></p>
|
||||
th:data-usepercentages="${material.materialType.usePercentages}"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
<div class="form">
|
||||
<form th:action="@{/recipe/editor}" th:object="${recipe}" class="requireAuth" method="POST">
|
||||
<input type="hidden" th:field="*{recipeID}"/>
|
||||
|
||||
<table class="mainTable">
|
||||
<tr>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td><b th:text="#{keyword.id} + ':'"></b></td>
|
||||
<td th:text="${recipe.recipeID}"></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('recipeCode')}"
|
||||
th:text="#{recipe.color} + ':'"></label></b></td>
|
||||
<td><input type="text" th:field="*{recipeCode}"></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('company')}"
|
||||
th:text="#{keyword.company} + ':'"></label></b>
|
||||
</td>
|
||||
<td>
|
||||
<select th:field="*{company}">
|
||||
<option th:each="company : ${companies}"
|
||||
th:selected="${recipe.company.equals(company)}"
|
||||
th:text="${company.companyName}"
|
||||
th:value="${company.companyID}"></option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('recipeDescription')}"
|
||||
th:text="#{recipe.description} + ':'"></label></b></td>
|
||||
<td><input type="text" th:field="*{recipeDescription}"/></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('sample')}" th:text="#{recipe.sample} + ':'"></label></b>
|
||||
</td>
|
||||
<td><input type="number" th:field="*{sample}"/></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('approbationDate')}"
|
||||
th:text="#{recipe.approbationDate} + ':'"></label></b></td>
|
||||
<td><input type="date" th:field="*{approbationDate}"/></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('remark')}" th:text="#{recipe.remark} + ':'"></label></b>
|
||||
</td>
|
||||
<td><textarea cols="20" rows="2" th:field="*{remark}"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="2" style="height: 40px; text-align: right">
|
||||
<button id="newMix" type="button" th:text="#{recipe.edit.addMix}"></button>
|
||||
</td>
|
||||
</tr>
|
||||
<th:block th:each="mix : ${mixes}">
|
||||
<tr>
|
||||
<td class="mixNameColumn">
|
||||
<b th:text="${mix.mixType.typeName} + ':'"></b>
|
||||
<br/>
|
||||
<th:block th:if="${mix != null}">
|
||||
<button class="mixEditor" th:data-mixID="${mix.mixID}" type="button"
|
||||
th:text="#{keyword.edit}"></button>
|
||||
</th:block>
|
||||
</td>
|
||||
<td>
|
||||
<div class="recipe">
|
||||
<table style="margin-left: 50px">
|
||||
<!-- Produits -->
|
||||
<tr>
|
||||
<th th:text="#{keyword.material}"></th>
|
||||
<th th:text="#{keyword.type}"></th>
|
||||
<th th:text="#{keyword.quantity}"></th>
|
||||
</tr>
|
||||
<tr th:each="mixQuantity : ${mix.mixQuantities}"
|
||||
th:with="material = ${mixQuantity.material}">
|
||||
<td th:classappend="${material.isMixType()} ? '' : materialCode"
|
||||
th:data-materialID="${material.materialID}"
|
||||
th:text="${material.materialCode}"></td>
|
||||
<td>
|
||||
<p th:text="${material.materialType.materialTypeName}"></p>
|
||||
</td>
|
||||
<td th:text="${mixQuantity.quantity} + ' ' + ${material.materialType.usePercentages ? '%' : 'mL'}"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
</th:block>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<!-- Images -->
|
||||
<table>
|
||||
<tr th:each="image : ${images}">
|
||||
<td class="centerTD">
|
||||
<img alt="Image supprimée ou corrompue" th:src="'/images/' + ${image}"
|
||||
height="250px"/>
|
||||
</td>
|
||||
<td style="text-align: left; padding-left: 50px">
|
||||
<button class="deleteImg" th:data-image="${image}" type="button"
|
||||
style="height: 250px">
|
||||
<span th:text="#{keyword.delete}"
|
||||
style="display: inline-block; transform: rotate(90deg); font-weight: bolder"></span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<!-- Étapes -->
|
||||
<table>
|
||||
<tr>
|
||||
<td style="text-align: center">
|
||||
<h3 th:text="#{recipe.steps}"></h3>
|
||||
</td>
|
||||
<td style="text-align: left; vertical-align: middle; padding-left: 20px">
|
||||
<button id="addStep" type="button">+</button>
|
||||
</td>
|
||||
<td style="width: 100%"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<table id="steps" style="width:100%">
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<button id="addImg" th:data-recipeID="${recipe.recipeID}" type="button"
|
||||
th:text="#{recipe.edit.addImage}"></button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: mainTableButtons"></tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{recipe.add.title})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{recipe.add.title}, null)"></th:block>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{recipe.add.title})"></th:block>
|
||||
|
||||
<link href="/css/main.css" rel="stylesheet"/>
|
||||
<link href="/css/forms.css" rel="stylesheet"/>
|
||||
<th:block th:include="fragments.html :: head(#{recipe.add.title}, 'form')"></th:block>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Fragment de l'entête -->
|
||||
|
@ -14,42 +11,58 @@
|
|||
<div th:include="fragments.html :: messages"></div>
|
||||
|
||||
<h1 th:text="#{recipe.add.title}"></h1>
|
||||
<div class="form">
|
||||
<form th:action="@{/recipe/creator}" th:object="${recipe}" class="requireAuth" id="recipe-form" method="POST">
|
||||
<table>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('recipeCode')}" th:text="#{recipe.color} + ':'"></label></b></td>
|
||||
<td><input type="text" th:field="*{recipeCode}" required/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('company')}" th:text="#{keyword.company} + ':'"></label></b></td>
|
||||
<td><select th:field="*{company}">
|
||||
<option th:each="company : ${companies}" th:text="${company.companyName}"
|
||||
th:value="${company.companyID}"></option>
|
||||
</select></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('recipeDescription')}"
|
||||
th:text="#{recipe.description} + ':'"></label></b></td>
|
||||
<td><input type="text" th:field="*{recipeDescription}" required/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('sample')}" th:text="#{recipe.sample} + ':'"></label></b></td>
|
||||
<td><input type="number" th:field="*{sample}" required/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('approbationDate')}"
|
||||
th:text="#{recipe.approbationDate} + ':'"></label></b></td>
|
||||
<td><input type="date" th:field="*{approbationDate}"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('remark')}" th:text="#{recipe.remark}"></label></b></td>
|
||||
<td><textarea cols="20" form="recipe-form" rows="2" th:field="*{remark}"></textarea></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: mainTableButtons"></tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form th:action="@{/recipe/creator}" th:object="${recipe}" class="requireAuth" id="recipe-form" method="POST">
|
||||
<div class="content">
|
||||
<div class="formWrap">
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<label th:for="${#ids.next('recipeCode')}" th:text="#{recipe.color} + ':'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('company')}" th:text="#{keyword.company} + ':'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('recipeDescription')}" th:text="#{recipe.description} + ':'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('sample')}" th:text="#{recipe.sample} + ':'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('approbationDate')}"
|
||||
th:text="#{recipe.approbationDate} + ':'"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('remark')}" th:text="#{recipe.remark} + ':'"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<input type="text" th:field="*{recipeCode}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<select th:field="*{company}">
|
||||
<option th:each="company : ${companies}" th:text="${company.companyName}"
|
||||
th:value="${company.companyID}"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" th:field="*{recipeDescription}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<input type="number" th:field="*{sample}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<input type="date" th:field="*{approbationDate}"/>
|
||||
</div>
|
||||
<div>
|
||||
<textarea cols="20" form="recipe-form" rows="2" th:field="*{remark}"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="fragments.html :: formEndButtons"></div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
|
|
@ -1,42 +1,69 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{recipe.editing.title(${recipe.recipeCode})})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{recipe.editing.title(${recipe.recipeCode})}, 'form')"></th:block>
|
||||
|
||||
<link href="/css/forms.css" rel="stylesheet"/>
|
||||
<link href="/css/explore.css" rel="stylesheet"/>
|
||||
|
||||
<style>
|
||||
p {
|
||||
display: inline;
|
||||
/*p {*/
|
||||
/* display: inline;*/
|
||||
/*}*/
|
||||
|
||||
/*.recipe table {*/
|
||||
/* background-color: #fafafa;*/
|
||||
/* border: 1px solid #7a7a7a;*/
|
||||
/* border-collapse: collapse !important;*/
|
||||
/*}*/
|
||||
|
||||
/*.recipe td, .recipe th {*/
|
||||
/* min-width: 100px;*/
|
||||
/* text-align: center;*/
|
||||
/*}*/
|
||||
|
||||
/*.recipe tr:nth-child(odd) {*/
|
||||
/* background-color: #f5f5f5;*/
|
||||
/*}*/
|
||||
|
||||
/*.mixNameColumn {*/
|
||||
/* display: inline-block;*/
|
||||
/*}*/
|
||||
|
||||
.content {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: separate !important;
|
||||
.mix {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 368px;
|
||||
}
|
||||
|
||||
.recipe table {
|
||||
background-color: #fafafa;
|
||||
border: 1px solid #7a7a7a;
|
||||
border-collapse: collapse !important;
|
||||
}
|
||||
|
||||
.recipe td, .recipe th {
|
||||
min-width: 100px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.recipe tr:nth-child(odd) {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.mixNameColumn {
|
||||
.mixInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 150px;
|
||||
max-width: 200px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.mixNameColumn {
|
||||
display: inline-block;
|
||||
min-width: 150px;
|
||||
.materialCodeColumn, .materialTypeColumn, .materialQuantityColumn {
|
||||
min-width: 112px;
|
||||
}
|
||||
|
||||
.imageContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#steps input {
|
||||
min-width: 300px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#steps label {
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
@ -50,164 +77,135 @@
|
|||
|
||||
<h1 th:text="#{recipe.editing.title(${recipe.recipeCode})}"></h1>
|
||||
<button id="gotoRecipe" type="button" th:text="#{keyword.see}"></button>
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<div class="form">
|
||||
<form th:action="@{/recipe/editor}" th:object="${recipe}" class="requireAuth" method="POST">
|
||||
<input type="hidden" th:field="*{recipeID}"/>
|
||||
<form th:action="@{/recipe/editor}" th:object="${recipe}" class="requireAuth" method="POST">
|
||||
<div class="content">
|
||||
<!-- Informations -->
|
||||
<div class="flexContent" style="padding-top: 40px">
|
||||
<input type="hidden" th:field="*{recipeID}"/>
|
||||
<div class="formWrap">
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<label th:for="${#ids.next('recipeID')}" th:text="#{keyword.id}"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('recipeCode')}" th:text="#{recipe.color}"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('banner')}" th:text="#{keyword.company}"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('recipeDescription')}" th:text="#{recipe.description}"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('sample')}" th:text="#{recipe.sample}"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('approbationDate')}" th:text="#{recipe.approbationDate}"></label>
|
||||
</div>
|
||||
<div>
|
||||
<label th:for="${#ids.next('remark')}" th:text="#{recipe.remark}"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formColumn">
|
||||
<div>
|
||||
<input type="number" th:field="*{recipeID}" required disabled/>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" th:field="*{recipeCode}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<select th:field="*{company}">
|
||||
<option th:each="company : ${companies}"
|
||||
th:selected="${recipe.company.equals(company)}"
|
||||
th:text="${company.companyName}"
|
||||
th:value="${company.companyID}"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" th:field="*{recipeDescription}"/>
|
||||
</div>
|
||||
<div>
|
||||
<input type="number" th:field="*{sample}"/>
|
||||
</div>
|
||||
<div>
|
||||
<input type="date" th:field="*{approbationDate}"/>
|
||||
</div>
|
||||
<div>
|
||||
<textarea cols="20" rows="2" th:field="*{remark}"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Mélanges -->
|
||||
<div class="flexContent mixes">
|
||||
<div style="text-align: right">
|
||||
<button id="newMix" type="button" th:text="#{recipe.edit.addMix}"></button>
|
||||
</div>
|
||||
<div th:each="mix : ${mixes}" class="mixContainer">
|
||||
<div class="mixInfo">
|
||||
<b th:text="${mix.mixType.typeName} + ':'"></b>
|
||||
<button class="mixEditor" th:data-mixID="${mix.mixID}" type="button"
|
||||
th:text="#{keyword.edit}" style="width: 75%"></button>
|
||||
</div>
|
||||
<div>
|
||||
<table class="mix"
|
||||
th:id="'mix-' + ${mix.mixID}">
|
||||
<tr>
|
||||
<th th:text="#{keyword.material}"></th>
|
||||
<th th:text="#{keyword.type}"></th>
|
||||
<th th:text="#{keyword.quantity}"></th>
|
||||
</tr>
|
||||
<!-- Produits -->
|
||||
<tr th:each="mixQuantity : ${mix.mixQuantities}"
|
||||
th:with="material = ${mixQuantity.material}"
|
||||
th:id="'material-' + ${material.materialID}">
|
||||
<td class="materialCodeColumn"
|
||||
th:classappend="${material.isMixType()} ? '' : materialCode"
|
||||
th:data-materialID="${material.materialID}"
|
||||
th:text="${material.materialCode}"></td>
|
||||
<td class="materialTypeColumn"
|
||||
th:text="${material.materialType.materialTypeName}"></td>
|
||||
<td class="materialQuantityColumn"
|
||||
th:text="${mixQuantity.quantity} + ' ' + ${material.materialType.usePercentages ? '%' : 'mL'}"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="mixActionsContainer">
|
||||
<button class="useMixSubmit" type="button" th:text="#{keyword.use}"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Étapes -->
|
||||
<div class="flexContent" id="steps" style="display: flex; flex-direction: column">
|
||||
<div style="display: flex; flex-direction: row; justify-content: center">
|
||||
<h3 th:text="#{recipe.steps}"></h3>
|
||||
<button id="addStep" type="button" style="width: 20px; height: 20px; margin:20px">+</button>
|
||||
</div>
|
||||
|
||||
<table class="mainTable">
|
||||
<tr>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td><b th:text="#{keyword.id} + ':'"></b></td>
|
||||
<td th:text="${recipe.recipeID}"></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('recipeCode')}"
|
||||
th:text="#{recipe.color} + ':'"></label></b></td>
|
||||
<td><input type="text" th:field="*{recipeCode}"></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('company')}"
|
||||
th:text="#{keyword.company} + ':'"></label></b>
|
||||
</td>
|
||||
<td>
|
||||
<select th:field="*{company}">
|
||||
<option th:each="company : ${companies}"
|
||||
th:selected="${recipe.company.equals(company)}"
|
||||
th:text="${company.companyName}"
|
||||
th:value="${company.companyID}"></option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('recipeDescription')}"
|
||||
th:text="#{recipe.description} + ':'"></label></b></td>
|
||||
<td><input type="text" th:field="*{recipeDescription}"/></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('sample')}" th:text="#{recipe.sample} + ':'"></label></b>
|
||||
</td>
|
||||
<td><input type="number" th:field="*{sample}"/></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('approbationDate')}"
|
||||
th:text="#{recipe.approbationDate} + ':'"></label></b></td>
|
||||
<td><input type="date" th:field="*{approbationDate}"/></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b><label th:for="${#ids.next('remark')}" th:text="#{recipe.remark} + ':'"></label></b>
|
||||
</td>
|
||||
<td><textarea cols="20" rows="2" th:field="*{remark}"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="2" style="height: 40px; text-align: right">
|
||||
<button id="newMix" type="button" th:text="#{recipe.edit.addMix}"></button>
|
||||
</td>
|
||||
</tr>
|
||||
<th:block th:each="mix : ${mixes}">
|
||||
<tr>
|
||||
<td class="mixNameColumn">
|
||||
<b th:text="${mix.mixType.typeName} + ':'"></b>
|
||||
<br/>
|
||||
<th:block th:if="${mix != null}">
|
||||
<button class="mixEditor" th:data-mixID="${mix.mixID}" type="button"
|
||||
th:text="#{keyword.edit}"></button>
|
||||
</th:block>
|
||||
</td>
|
||||
<td>
|
||||
<div class="recipe">
|
||||
<table style="margin-left: 50px">
|
||||
<!-- Produits -->
|
||||
<tr>
|
||||
<th th:text="#{keyword.material}"></th>
|
||||
<th th:text="#{keyword.type}"></th>
|
||||
<th th:text="#{keyword.quantity}"></th>
|
||||
</tr>
|
||||
<tr th:each="mixQuantity : ${mix.mixQuantities}"
|
||||
th:with="material = ${mixQuantity.material}">
|
||||
<td th:classappend="${material.isMixType()} ? '' : materialCode"
|
||||
th:data-materialID="${material.materialID}"
|
||||
th:text="${material.materialCode}"></td>
|
||||
<td>
|
||||
<p th:text="${material.materialType.materialTypeName}"></p>
|
||||
</td>
|
||||
<td th:text="${mixQuantity.quantity} + ' ' + ${material.materialType.usePercentages ? '%' : 'mL'}"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
</th:block>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<!-- Images -->
|
||||
<table>
|
||||
<tr th:each="image : ${images}">
|
||||
<td class="centerTD">
|
||||
<img alt="Image supprimée ou corrompue" th:src="'/images/' + ${image}"
|
||||
height="250px"/>
|
||||
</td>
|
||||
<td style="text-align: left; padding-left: 50px">
|
||||
<button class="deleteImg" th:data-image="${image}" type="button"
|
||||
style="height: 250px">
|
||||
<span th:text="#{keyword.delete}"
|
||||
style="display: inline-block; transform: rotate(90deg); font-weight: bolder"></span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<!-- Étapes -->
|
||||
<table>
|
||||
<tr>
|
||||
<td style="text-align: center">
|
||||
<h3 th:text="#{recipe.steps}"></h3>
|
||||
</td>
|
||||
<td style="text-align: left; vertical-align: middle; padding-left: 20px">
|
||||
<button id="addStep" type="button">+</button>
|
||||
</td>
|
||||
<td style="width: 100%"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<table id="steps" style="width:100%">
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<button id="addImg" th:data-recipeID="${recipe.recipeID}" type="button"
|
||||
th:text="#{recipe.edit.addImage}"></button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: mainTableButtons"></tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Images -->
|
||||
<div class="flexContent" style="display: flex; flex-direction: column">
|
||||
<div style="display: flex; flex-direction: row; justify-content: center;">
|
||||
<h3 th:text="#{keyword.images}" style="margin: 0"></h3>
|
||||
<button id="addImage" type="button" style="width: 20px; height: 20px; margin: 0 20px;">+</button>
|
||||
</div>
|
||||
<div class="imagesContainer">
|
||||
<div th:each="image : ${images}" class="imageContainer">
|
||||
<img th:alt="#{recipe.image.corrupted}"
|
||||
th:src="@{|${baseUrl}/images/${image}|}"
|
||||
width="400px"/>
|
||||
<div>
|
||||
<button class="deleteImg" th:data-image="${image}" type="button" style="width: 100%">
|
||||
<span th:text="#{keyword.delete}"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="fragments.html :: formEndButtons" style="width: 100%; margin-bottom:50px"></div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
@ -215,7 +213,6 @@
|
|||
|
||||
<script>
|
||||
/*<![CDATA[*/
|
||||
|
||||
let stepNbr = 0;
|
||||
|
||||
(() => {
|
||||
|
@ -239,34 +236,38 @@
|
|||
|
||||
document.querySelectorAll(".deleteImg").forEach(e => {
|
||||
e.addEventListener("click", async () => {
|
||||
checkPassword(null, () => {
|
||||
let data = {};
|
||||
if (confirm(askChangePage)) {
|
||||
checkPassword(null, () => {
|
||||
let data = {};
|
||||
|
||||
data['image'] = e.getAttribute("data-image");
|
||||
hideElement(errorMsgBox);
|
||||
data['image'] = e.getAttribute("data-image");
|
||||
hideElement(errorMsgBox);
|
||||
|
||||
axios.post("/images/delete", data)
|
||||
.then(r => {
|
||||
const data = r.data;
|
||||
axios.post("/images/delete", data)
|
||||
.then(r => {
|
||||
const data = r.data;
|
||||
|
||||
if (data['error'] !== undefined) {
|
||||
errorMsgBoxText.innerText = data['error'];
|
||||
if (data['error'] !== undefined) {
|
||||
errorMsgBoxText.innerText = data['error'];
|
||||
showElement(errorMsgBox);
|
||||
} else {
|
||||
document.location.reload();
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
console.log(e);
|
||||
errorMsgBoxText.innerText = "[[#{error.serverError}]]";
|
||||
showElement(errorMsgBox);
|
||||
} else {
|
||||
document.location.reload();
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
console.log(e);
|
||||
errorMsgBoxText.innerText = "[[#{error.serverError}]]";
|
||||
showElement(errorMsgBox);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector("#addImg").addEventListener("click", () => {
|
||||
document.location.href = "/images/add/[[${recipe.recipeID}]]";
|
||||
document.querySelector("#addImage").addEventListener("click", () => {
|
||||
if (confirm(askChangePage)) {
|
||||
document.location.href = "/images/add/[[${recipe.recipeID}]]";
|
||||
}
|
||||
});
|
||||
|
||||
const recipeText = "[[${recipeJSON}]]";
|
||||
|
@ -283,37 +284,37 @@
|
|||
})();
|
||||
|
||||
function addStep(value) {
|
||||
|
||||
let input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.id = `step_${stepNbr}`;
|
||||
input.classList.add("step", "rawInput");
|
||||
input.name = "step";
|
||||
input.style.width = "100%";
|
||||
input.autocomplete = "off";
|
||||
if (value != null) input.value = value;
|
||||
|
||||
let column = document.createElement("td");
|
||||
column.appendChild(input);
|
||||
let number = document.createElement("label");
|
||||
number.textContent = `${stepNbr + 1}. `;
|
||||
number.for = input.id;
|
||||
|
||||
let deleteButton = document.createElement("button");
|
||||
deleteButton.type = "button";
|
||||
deleteButton.innerText = "[[#{keyword.remove}]]";
|
||||
deleteButton.addEventListener("click", () => deleteStep(input.id));
|
||||
|
||||
let deleteButtonColumn = document.createElement("td");
|
||||
deleteButtonColumn.appendChild(deleteButton);
|
||||
let div = document.createElement("div");
|
||||
div.appendChild(number);
|
||||
div.appendChild(input);
|
||||
div.appendChild(deleteButton);
|
||||
|
||||
let row = document.createElement("tr");
|
||||
row.appendChild(column);
|
||||
row.appendChild(deleteButtonColumn)
|
||||
|
||||
document.querySelector("#steps tbody").appendChild(row);
|
||||
document.querySelector("#steps").appendChild(div);
|
||||
|
||||
stepNbr++;
|
||||
}
|
||||
|
||||
function deleteStep(stepID) {
|
||||
// Supprime la rangée de l'étape
|
||||
document.querySelector(`#${stepID}`).parentElement.parentElement.remove();
|
||||
document.querySelector(`#${stepID}`).parentElement.remove();
|
||||
}
|
||||
|
||||
/*]]*/
|
||||
|
|
|
@ -1,43 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{recipe.edit.title})"></th:block>
|
||||
<title th:text="#{recipe.edit.title}"></title>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
th {
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.descriptionCell {
|
||||
border-right-color: #e6e6e6;
|
||||
border-right-style: solid;
|
||||
border-right-width: 2px;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 10px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
section {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.recipeDescription {
|
||||
max-width: 400px;
|
||||
}
|
||||
</style>
|
||||
<th:block th:include="fragments.html :: head(#{recipe.edit.title}, 'recipesList')"></th:block>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -45,41 +9,49 @@
|
|||
<header th:include="fragments.html :: header"></header>
|
||||
<!-- Corps de la page -->
|
||||
<section>
|
||||
<div id="researchBoxContainer">
|
||||
<input id="researchBox" class="noStyle" type="text" th:placeholder="#{keyword.search}"
|
||||
onkeyup="performSearch(this.value)"/>
|
||||
</div>
|
||||
|
||||
<div th:include="fragments.html :: messages"></div>
|
||||
<p class="success" th:if="${recipeCode != null}"
|
||||
th:text="#{recipe.success.edit(${recipeCode})}"></p>
|
||||
|
||||
<h1 th:text="#{recipe.edit.title}"></h1>
|
||||
<th:block th:if="${!recipeMap.empty}" th:each="company : ${recipeMap.keySet()}">
|
||||
<h2 class="companyTabTitle" th:data-companyName="${company.companyName}"
|
||||
th:text="${company.companyName}"></h2>
|
||||
|
||||
<table style="display:none" th:id="'recipes_' + ${company.companyName}"
|
||||
th:if="${!recipeMap.get(company).empty}">
|
||||
<tr>
|
||||
<th th:text="#{recipe.color}"></th>
|
||||
<th th:text="#{recipe.description}"></th>
|
||||
<th th:text="#{recipe.sample}"></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr class="recipeRow" th:each="recipe : ${recipeMap.get(company)}"
|
||||
th:data-approbationDate="${recipe.approbationDate}">
|
||||
<td class="descriptionCell" th:text="${recipe.recipeCode}"></td>
|
||||
<td class="descriptionCell recipeDescription" th:text="${recipe.recipeDescription}"></td>
|
||||
<td class="descriptionCell" th:text="'#' + ${recipe.sample}"></td>
|
||||
<td>
|
||||
<button class="editRecipe" th:data-code="${recipe.recipeCode}"
|
||||
th:data-recipeID="${recipe.recipeID}" type="button" th:text="#{menu.edit}"></button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</th:block>
|
||||
<b th:if="${recipeMap.empty}" class="error" th:text="#{recipe.error.anyFound}"></b>
|
||||
<div class="content recipesContainer">
|
||||
<div class="companyTab" th:if="${!recipeMap.empty}" th:each="company : ${recipeMap.keySet()}"
|
||||
th:data-companyID="${company.companyID}">
|
||||
<h2 class="companyTabTitle" th:data-companyName="${company.companyName}"
|
||||
th:text="${company.companyName}"></h2>
|
||||
|
||||
<table style="display:none" th:id="'recipes_' + ${company.companyName}" class="recipesList"
|
||||
th:if="${!recipeMap.get(company).empty}">
|
||||
<tr>
|
||||
<th th:text="#{recipe.color}"></th>
|
||||
<th th:text="#{recipe.description}"></th>
|
||||
<th th:text="#{recipe.sample}"></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr class="recipeRow" th:each="recipe : ${recipeMap.get(company)}"
|
||||
th:data-approbationDate="${recipe.approbationDate}" th:data-recipeID="${recipe.recipeID}">
|
||||
<td class="descriptionCell" th:text="${recipe.recipeCode}"></td>
|
||||
<td class="descriptionCell recipeDescription" th:text="${recipe.recipeDescription}"></td>
|
||||
<td class="descriptionCell" th:text="'#' + ${recipe.sample}"></td>
|
||||
<td>
|
||||
<button class="editRecipe" th:data-code="${recipe.recipeCode}"
|
||||
th:data-recipeID="${recipe.recipeID}" type="button" th:text="#{menu.edit}"></button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<b th:if="${recipeMap.empty}" class="error" th:text="#{recipe.error.anyFound}"></b>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
||||
|
||||
<script th:src="@{|${baseUrl}/js/recipeResearch.js|}"></script>
|
||||
<script>
|
||||
(() => {
|
||||
document.querySelectorAll(".editRecipe").forEach((e) => {
|
||||
|
|
|
@ -1,111 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{recipe.explore.title(${recipe.recipeCode})})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{recipe.explore.title(${recipe.recipeCode})}, null)"></th:block>
|
||||
|
||||
<style>
|
||||
td, th {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
table {
|
||||
margin: auto;
|
||||
text-align: left;
|
||||
border-collapse: separate;
|
||||
}
|
||||
|
||||
section {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.mixes {
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #7a7a7a;
|
||||
border-collapse: collapse;
|
||||
margin: 0;
|
||||
min-width: 600px;
|
||||
}
|
||||
|
||||
.mixes tr:nth-child(odd) {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
#steps li {
|
||||
padding: 5px;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
#steps li:nth-child(even) {
|
||||
background-color: #f5f5f5;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#steps li:nth-child(odd) {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.mixes td, .mixes th {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.recipeLocation {
|
||||
width: 55px;
|
||||
border-color: white;
|
||||
color: #7a7a7a;
|
||||
}
|
||||
|
||||
.recipeLocation:hover {
|
||||
border-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.recipeLocation:focus {
|
||||
border-color: #7a7a7a;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.notEnough td {
|
||||
background-color: #ffb3b3;
|
||||
}
|
||||
|
||||
.quantityColumn {
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
.totalQuantityLabel {
|
||||
padding-right: 10px;
|
||||
text-align: right;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.inventoryQuantity {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.inventoryQuantityColumn {
|
||||
min-width: auto !important;
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
.unitsColumn {
|
||||
max-width: 25px;
|
||||
}
|
||||
|
||||
.calculationColumn {
|
||||
min-width: 125px !important;
|
||||
}
|
||||
|
||||
.calculation {
|
||||
color: dimgrey;
|
||||
}
|
||||
|
||||
.calculation span {
|
||||
color: darkgreen;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/css/explore.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -114,7 +12,6 @@
|
|||
<!-- Corps de la page -->
|
||||
<section>
|
||||
<div th:include="fragments.html :: messages"></div>
|
||||
<p class="success" th:text="${success}"></p>
|
||||
|
||||
<h1 th:text="#{recipe.explore.title(${recipe.recipeCode})}"></h1>
|
||||
<button id="modifyRecipe" type="button" th:text="#{menu.edit}"></button>
|
||||
|
@ -131,189 +28,183 @@
|
|||
th:text="#{recipe.xlsVersion}">
|
||||
</button>
|
||||
|
||||
<input id="recipeID" name="recipeID" th:value="${recipe.recipeID}" type="hidden"/>
|
||||
<input id="recipeID"
|
||||
name="recipeID"
|
||||
type="hidden"
|
||||
th:value="${recipe.recipeID}"/>
|
||||
|
||||
<table class="mainTable">
|
||||
<tr>
|
||||
<td style="vertical-align: top;">
|
||||
<table>
|
||||
<tr>
|
||||
<td><b th:text="#{recipe.color} + ':'"></b></td>
|
||||
<td th:text="${recipe.recipeCode}"></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b th:text="#{keyword.company} + ':'"></b></td>
|
||||
<td th:text="${recipe.company.companyName}"></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b th:text="#{recipe.description} + ':'"></b></td>
|
||||
<td th:text="${recipe.recipeDescription}"></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b th:text="#{recipe.sample} + ':'"></b></td>
|
||||
<td th:text="${recipe.sample}"></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b th:text="#{recipe.approbationDate} + ':'"></b></td>
|
||||
<td th:if="${recipe.approbationDate != ''}" th:text="${recipe.approbationDate}"></td>
|
||||
<td th:if="${recipe.approbationDate == ''}" th:text="#{recipe.warning.notApproved.short}"></td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b th:text="#{recipe.remark} + ':'"></b></td>
|
||||
<td th:text="${recipe.remark}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
<tr>
|
||||
<td><b th:text="#{recipe.notice} + ':'"></b></td>
|
||||
<td>
|
||||
<textarea class="toSave" cols="20" id="note" name="note" rows="2"
|
||||
th:text="${recipe.note}" style="margin: 0"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<button id="formSubmit" type="button" th:text="#{keyword.save}"
|
||||
style="margin-top: 20px"></button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<!-- Formulaires sans autocomplétion pour éviter que le navigateur cache les valeurs lors d'un rafraichissement et invalide les données dans data-quantityML -->
|
||||
<form action="#" autocomplete="off">
|
||||
<table style="border-spacing: 20px;">
|
||||
<th:block th:each="mix : ${mixes}">
|
||||
<tr>
|
||||
<td><b th:text="${mix.mixType.typeName} + ':'"></b><br/><br/>
|
||||
<label
|
||||
th:for="'location' + ${mix.mixID}"
|
||||
th:text="' ' + #{mix.location} + ': '">
|
||||
<!-- Formulaires sans autocomplétion pour éviter que le navigateur cache des valeurs lors d'un rafraichissement-->
|
||||
<form action="#" autocomplete="off">
|
||||
<div class="content">
|
||||
<div class="flexContent recipeDescription">
|
||||
<div>
|
||||
<b th:text="#{recipe.color} + ':'"></b>
|
||||
<p th:text="${recipe.recipeCode}">
|
||||
</div>
|
||||
<div>
|
||||
<b th:text="#{keyword.company} + ':'"></b>
|
||||
<p th:text="${recipe.company.companyName}">
|
||||
</div>
|
||||
<div>
|
||||
<b th:text="#{recipe.description} + ':'"></b>
|
||||
<p th:text="${recipe.recipeDescription}">
|
||||
</div>
|
||||
<div>
|
||||
<b th:text="#{recipe.sample} + ':'"></b>
|
||||
<p th:text="${recipe.sample}">
|
||||
</div>
|
||||
<div>
|
||||
<b th:text="#{recipe.approbationDate} + ':'"></b>
|
||||
<p th:if="${recipe.approbationDate != ''}" th:text="${recipe.approbationDate}">
|
||||
<p th:if="${recipe.approbationDate == ''}" th:text="#{recipe.warning.notApproved.short}">
|
||||
</div>
|
||||
<div th:if="${!recipe.remark.empty}">
|
||||
<b th:text="#{recipe.remark} + ':'"></b>
|
||||
<p th:text="${recipe.remark}">
|
||||
</div>
|
||||
<div>
|
||||
<b th:text="#{recipe.notice} + ':'"></b>
|
||||
<textarea class="rawInput toSave"
|
||||
id="note"
|
||||
cols="20"
|
||||
rows="2"
|
||||
name="note"
|
||||
placeholder="N/A"
|
||||
th:text="${recipe.note}" style="margin: 0"></textarea>
|
||||
</div>
|
||||
<button id="formSubmit"
|
||||
type="button"
|
||||
th:text="#{keyword.save}"
|
||||
style="margin-top: 20px"></button>
|
||||
</div>
|
||||
<div th:if="${mixes.size() > 0}"
|
||||
class="flexContent">
|
||||
<th:block th:each="mix : ${mixes}">
|
||||
<div class="mixContainer">
|
||||
<div class="mixInfo">
|
||||
<b th:text="${mix.mixType.typeName} + ':'"></b><br/><br/>
|
||||
<label th:for="'location' + ${mix.mixID}"
|
||||
th:text="' ' + #{mix.location} + ': '">
|
||||
|
||||
</label>
|
||||
<input
|
||||
class="recipeLocation toSave"
|
||||
th:id="'location' + ${mix.mixID}"
|
||||
name="location"
|
||||
th:data-mixID="${mix.mixID}"
|
||||
th:value="${mix.location}"
|
||||
placeholder="N/A"
|
||||
type="text"/>
|
||||
</td>
|
||||
<td>
|
||||
<table class="mixes" th:id="'mix-' + ${mix.mixID}">
|
||||
<tr>
|
||||
<th th:text="#{keyword.material}"></th>
|
||||
<th th:text="#{keyword.type}"></th>
|
||||
<th style="min-width: auto !important;">
|
||||
<button
|
||||
type="button"
|
||||
data-hidden="true"
|
||||
onclick="hideQuantities(this)">
|
||||
->
|
||||
</button>
|
||||
</th>
|
||||
<!-- Changement des quantités -->
|
||||
<th></th>
|
||||
<th th:text="#{keyword.units}"></th>
|
||||
<th th:text="#{keyword.calculation}"></th>
|
||||
</tr>
|
||||
<!-- Produits -->
|
||||
<tr th:each="mixQuantity : ${mix.mixQuantities}"
|
||||
th:with="material = ${mixQuantity.material}"
|
||||
th:id="'material-' + ${material.materialID}">
|
||||
<td th:classappend="${material.isMixType()} ? '' : materialCode"
|
||||
th:data-materialID="${material.materialID}"
|
||||
th:text="${material.materialCode}"></td>
|
||||
<td>
|
||||
<p th:text="${material.materialType.materialTypeName}"></p>
|
||||
</td>
|
||||
<td class="inventoryQuantityColumn">
|
||||
<p class="inventoryQuantity"
|
||||
th:data-quantityML="${mixQuantity.quantity}"
|
||||
th:text="${mixQuantity.quantity}"></p>
|
||||
</td>
|
||||
<td class="quantityColumn">
|
||||
<input th:if="${!material.isMixType()}" class="quantityCustomizer"
|
||||
min="0.001" step="0.001"
|
||||
th:data-materialID="${material.materialID}"
|
||||
th:data-mixID="${mix.mixID}"
|
||||
th:data-quantityML="${mixQuantity.quantity}"
|
||||
th:data-usePercentages="${material.materialType.usePercentages}"
|
||||
th:value="${mixQuantity.quantity}"
|
||||
th:disabled="${material.materialType.usePercentages}"
|
||||
type="number"/></td>
|
||||
<td class="unitsColumn">
|
||||
<p class="inventoryQuantityUnits"
|
||||
th:unless="${material.materialType.usePercentages}">mL</p>
|
||||
<p th:if="${material.materialType.usePercentages}">%</p>
|
||||
</td>
|
||||
<td class="calculationColumn">
|
||||
<p class="calculation" th:data-mixID="${mix.mixID}"
|
||||
th:data-materialID="${material.materialID}"></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="totalQuantityLabel" colspan="3">
|
||||
Total:
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
class="totalQuantityCustomizer"
|
||||
type="number"
|
||||
min="0.001"
|
||||
step="0.001"
|
||||
th:data-mixID="${mix.mixID}"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<p class="inventoryQuantityUnits">mL</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<button class="useMixSubmit" type="button" th:text="#{keyword.use}"></button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:include="fragments.html :: separator"></tr>
|
||||
</th:block>
|
||||
</table>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<!-- Images -->
|
||||
<th:block th:each="image : ${images}">
|
||||
<img th:alt="#{recipe.image.corrupted}" th:src="@{|${baseUrl}/images/${image}|}" width="400px"/>
|
||||
</label>
|
||||
<input class="recipeLocation rawInput toSave"
|
||||
th:id="'location' + ${mix.mixID}"
|
||||
name="location"
|
||||
th:data-mixID="${mix.mixID}"
|
||||
th:value="${mix.location}"
|
||||
placeholder="N/A"
|
||||
type="text"/>
|
||||
</div>
|
||||
<div>
|
||||
<table class="mix"
|
||||
th:id="'mix-' + ${mix.mixID}">
|
||||
<tr>
|
||||
<th th:text="#{keyword.material}"></th>
|
||||
<th th:text="#{keyword.type}"></th>
|
||||
<th style="min-width: auto !important;">
|
||||
<button
|
||||
type="button"
|
||||
data-hidden="true"
|
||||
onclick="hideQuantities(this)">
|
||||
->
|
||||
</button>
|
||||
</th>
|
||||
<!-- Changement des quantités -->
|
||||
<th></th>
|
||||
<th th:text="#{keyword.units}"></th>
|
||||
<th th:text="#{keyword.calculation}"></th>
|
||||
</tr>
|
||||
<!-- Produits -->
|
||||
<tr th:each="mixQuantity : ${mix.mixQuantities}"
|
||||
th:with="material = ${mixQuantity.material}"
|
||||
th:id="'material-' + ${material.materialID}">
|
||||
<td class="materialCodeColumn"
|
||||
th:classappend="${material.isMixType()} ? '' : materialCode"
|
||||
th:data-materialID="${material.materialID}"
|
||||
th:text="${material.materialCode}"></td>
|
||||
<td th:text="${material.materialType.materialTypeName}"></td>
|
||||
<td class="inventoryQuantityColumn">
|
||||
<p class="inventoryQuantity"
|
||||
th:data-quantityML="${mixQuantity.quantity}"
|
||||
th:text="${mixQuantity.quantity}"></p>
|
||||
</td>
|
||||
<td class="quantityColumn">
|
||||
<input th:if="${!material.isMixType()}"
|
||||
class="quantityCustomizer noStyle"
|
||||
min="0.001" step="0.001"
|
||||
th:data-materialID="${material.materialID}"
|
||||
th:data-mixID="${mix.mixID}"
|
||||
th:data-quantityML="${mixQuantity.quantity}"
|
||||
th:data-usePercentages="${material.materialType.usePercentages}"
|
||||
th:value="${mixQuantity.quantity}"
|
||||
th:disabled="${material.materialType.usePercentages}"
|
||||
type="number"/></td>
|
||||
<td class="unitsColumn">
|
||||
<p class="inventoryQuantityUnits"
|
||||
th:unless="${material.materialType.usePercentages}">mL</p>
|
||||
<p th:if="${material.materialType.usePercentages}">%</p>
|
||||
</td>
|
||||
<td class="calculationColumn">
|
||||
<p class="calculation" th:data-mixID="${mix.mixID}"
|
||||
th:data-materialID="${material.materialID}"></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="totalQuantityLabel" colspan="3">
|
||||
Total:
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
class="totalQuantityCustomizer noStyle"
|
||||
type="number"
|
||||
min="0.001"
|
||||
step="0.001"
|
||||
th:data-mixID="${mix.mixID}"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<p class="inventoryQuantityUnits">mL</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="mixActionsContainer">
|
||||
<button class="useMixSubmit" type="button" th:text="#{keyword.use}"></button>
|
||||
<button type="button" th:text="#{keyword.print}"></button>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</td>
|
||||
<td id="steps">
|
||||
</div>
|
||||
<div th:with="steps = ${recipe.recipeSteps}"
|
||||
th:if="${recipe.recipeSteps.size() > 0}"
|
||||
class="flexContent steps">
|
||||
<!-- Étapes -->
|
||||
<div style="padding-left:100px">
|
||||
<h3 th:text="#{recipe.steps}"></h3>
|
||||
<div style="min-width: 300px">
|
||||
<div class="subtitle">
|
||||
<h3 th:text="#{recipe.steps}"></h3>
|
||||
</div>
|
||||
<ol>
|
||||
<th:block th:each="step : ${recipe.recipeSteps}">
|
||||
<li th:text="${step.stepMessage}"></li>
|
||||
</th:block>
|
||||
<li th:each="step : ${steps}"
|
||||
th:text="${step.stepMessage}"></li>
|
||||
</ol>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
<div th:if="${images.size() > 0}"
|
||||
class="flexContent imagesContainer">
|
||||
<!-- Images -->
|
||||
<img th:each="image : ${images}"
|
||||
th:alt="#{recipe.image.corrupted}"
|
||||
th:src="@{|${baseUrl}/images/${image}|}"
|
||||
class="recipeImage"
|
||||
width="400px"
|
||||
onmouseenter="startHovering()" onmouseleave="endHovering()"/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
||||
|
||||
<script>
|
||||
/*<![CDATA[*/
|
||||
const quantityKeyword = "[[#{keyword.quantity}]]";
|
||||
|
@ -450,7 +341,7 @@
|
|||
});
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
document.querySelectorAll(".mixes").forEach(e => doCalculations(e));
|
||||
document.querySelectorAll(".mix").forEach(e => doCalculations(e));
|
||||
});
|
||||
})();
|
||||
|
||||
|
@ -495,8 +386,8 @@
|
|||
} else {
|
||||
e.style.display = "inline";
|
||||
|
||||
e.parentElement.setAttribute("style", "min-width: 100px !important");
|
||||
button.parentElement.setAttribute("style", "min-width: 100px !important");
|
||||
e.parentElement.setAttribute("style", "min-width: 75px !important");
|
||||
button.parentElement.setAttribute("style", "min-width: 75px !important");
|
||||
|
||||
button.innerText = quantityKeyword;
|
||||
}
|
||||
|
@ -566,10 +457,60 @@
|
|||
e.dataset.totalQuantity = convertMlToUnit(e.dataset.quantity);
|
||||
});
|
||||
|
||||
document.querySelectorAll(".mixes").forEach(e => doCalculations(e));
|
||||
document.querySelectorAll(".mix").forEach(e => doCalculations(e));
|
||||
}
|
||||
|
||||
startHovering = () => document.querySelector(".imagesContainer").classList.add("hovering");
|
||||
endHovering = () => document.querySelector(".imagesContainer").classList.remove("hovering");
|
||||
|
||||
/*]]>*/
|
||||
</script>
|
||||
<script type="module">
|
||||
import * as bpac from "/js/bpac.js";
|
||||
|
||||
const dataFolder = "/lbx";
|
||||
const labelPath = dataFolder + "/Couleur.lbx";
|
||||
console.log(labelPath);
|
||||
|
||||
const recipeCode = "[[${recipe.recipeCode}]]";
|
||||
const banner = "[[${recipe.company.companyName}]]";
|
||||
const baseMaterial = "[[${recipe.getBase().materialCode}]]";
|
||||
|
||||
async function print(mix) {
|
||||
if (!document.querySelector(".bpac-extension-installed")) {
|
||||
console.log("No extension");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const objDoc = bpac.IDocument;
|
||||
await objDoc.Open("http://localhost:9090/lbx/Couleur.lbx");
|
||||
|
||||
const objColor = await objDoc.GetObject("color");
|
||||
objColor.Text = recipeCode;
|
||||
|
||||
const objBanner = await objDoc.GetObject("banner");
|
||||
objBanner.Text = banner;
|
||||
|
||||
const objBarcode = await objDoc.GetObject("color_barcode");
|
||||
objBarcode.Text = recipeCode;
|
||||
|
||||
objDoc.StartPrint("", 0);
|
||||
objDoc.PrintOut(1, 0);
|
||||
objDoc.EndPrint();
|
||||
|
||||
objDoc.Close();
|
||||
// } else {
|
||||
// console.log("Can't open document");
|
||||
// }
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
//print();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,42 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{recipe.delete.title})"></th:block>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
th {
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.descriptionCell {
|
||||
border-right-color: #e6e6e6;
|
||||
border-right-style: solid;
|
||||
border-right-width: 2px;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 10px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
section {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.recipeDescription {
|
||||
max-width: 400px;
|
||||
}
|
||||
</style>
|
||||
<th:block th:include="fragments.html :: head(#{recipe.delete.title}, 'recipesList')"></th:block>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -44,43 +9,51 @@
|
|||
<header th:include="fragments.html :: header"></header>
|
||||
<!-- Corps de la page -->
|
||||
<section>
|
||||
<div id="researchBoxContainer">
|
||||
<input id="researchBox" class="noStyle" type="text" th:placeholder="#{keyword.search}"
|
||||
onkeyup="performSearch(this.value)"/>
|
||||
</div>
|
||||
|
||||
<div th:include="fragments.html :: messages"></div>
|
||||
<p class="success" th:if="${recipeCode != null}"
|
||||
th:text="#{recipe.success.deleted(${recipeCode})}"></p>
|
||||
|
||||
<h1 th:text="#{recipe.delete.title}"></h1>
|
||||
<form th:action="@{/recipe/remover/}" class="requireAuth-remover" method="POST">
|
||||
<th:block th:if="${!recipeMap.empty}" th:each="company : ${recipeMap.keySet()}">
|
||||
<h2 class="companyTabTitle" th:data-companyName="${company.companyName}"
|
||||
th:text="${company.companyName}"></h2>
|
||||
|
||||
<table style="display:none" th:if="${!recipeMap.get(company).empty}"
|
||||
th:id="'recipes_' + ${company.companyName}">
|
||||
<tr>
|
||||
<th th:text="#{recipe.color}"></th>
|
||||
<th th:text="#{recipe.description}"></th>
|
||||
<th th:text="#{recipe.sample}"></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr th:each="recipe : ${recipeMap.get(company)}" class="recipeRow"
|
||||
th:data-approbationDate="${recipe.approbationDate}">
|
||||
<td class="descriptionCell" th:text="${recipe.recipeCode}"></td>
|
||||
<td class="descriptionCell recipeDescription" th:text="${recipe.recipeDescription}"></td>
|
||||
<td class="descriptionCell" th:text="'#' + ${recipe.sample}"></td>
|
||||
<td>
|
||||
<button class="remover" th:data-code="${recipe.recipeCode}"
|
||||
th:data-entityID="${recipe.recipeID}" type="button"
|
||||
th:text="#{keyword.delete}"></button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</th:block>
|
||||
<b class="error" th:if="${recipeMap.empty}" th:text="#{recipe.error.anyFound}"></b>
|
||||
</form>
|
||||
<div class="content recipesContainer">
|
||||
<form th:action="@{/recipe/remover/}" class="requireAuth-remover" method="POST">
|
||||
<div class="companyTab" th:if="${!recipeMap.empty}" th:each="company : ${recipeMap.keySet()}"
|
||||
th:data-companyID="${company.companyID}">
|
||||
<h2 class="companyTabTitle" th:data-companyName="${company.companyName}"
|
||||
th:text="${company.companyName}"></h2>
|
||||
|
||||
<table style="display:none" th:id="'recipes_' + ${company.companyName}" class="recipesList"
|
||||
th:if="${!recipeMap.get(company).empty}">
|
||||
<tr>
|
||||
<th th:text="#{recipe.color}"></th>
|
||||
<th th:text="#{recipe.description}"></th>
|
||||
<th th:text="#{recipe.sample}"></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr class="recipeRow" th:each="recipe : ${recipeMap.get(company)}"
|
||||
th:data-approbationDate="${recipe.approbationDate}" th:data-recipeID="${recipe.recipeID}">
|
||||
<td class="descriptionCell" th:text="${recipe.recipeCode}"></td>
|
||||
<td class="descriptionCell recipeDescription" th:text="${recipe.recipeDescription}"></td>
|
||||
<td class="descriptionCell" th:text="'#' + ${recipe.sample}"></td>
|
||||
<td>
|
||||
<button class="remover" th:data-code="${recipe.recipeCode}"
|
||||
th:data-entityid="${recipe.recipeID}" type="button"
|
||||
th:text="#{keyword.delete}"></button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<b th:if="${recipeMap.empty}" class="error" th:text="#{recipe.error.anyFound}"></b>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
|
||||
|
||||
<script th:src="@{|${baseUrl}/js/recipeResearch.js|}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:include="fragments.html :: head(#{keyword.updates})"></th:block>
|
||||
<th:block th:include="fragments.html :: head(#{keyword.updates}, null)"></th:block>
|
||||
|
||||
<style>
|
||||
#markdown {
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
# v1.2.0 (Imprimante P-touch)
|
||||
### Corrections
|
||||
* +++ Correction d'un bug qui empêchait la suppression des mélanges.
|
||||
* Correction d'un bug qui empêchait la suppression des mélanges.
|
||||
* Correction d'un bug qui empêche les boutons supprimer de fonctionner.
|
||||
* Correction d'un bug qui permettait d'envoyer les formulaires demandant des mots de passe sans donner un mot de passe valide.
|
||||
* Correction d'une désynchronisation entre le nom des mélanges et leurs produits internes.
|
||||
* Amélioration du style du site.
|
||||
* Transition des modèles vers Lombok.
|
||||
|
||||
### Ajouts
|
||||
* +++ Ajout du support pour l'imprimante P-touch
|
||||
* +++ Ajout du support pour l'imprimante P-touch.
|
||||
* Les produits dans l'inventaire sont maintenant ordonnés alphabétiquement.
|
||||
* Changement de l'ordre d'un mélange.
|
||||
* Ajout d'un type de produit aux mélanges.
|
||||
* Ajout de jQuery, début de la transition.
|
||||
|
||||
# v1.1.3
|
||||
### Corrections
|
||||
|
|
Loading…
Reference in New Issue