| @ -0,0 +1,25 @@ | |||
| package com.ims.rallyModels.controlador; | |||
| import com.ims.rallyModels.servicio.img.StorageService; | |||
| import jakarta.annotation.Resource; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.http.ResponseEntity; | |||
| import org.springframework.stereotype.Controller; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PathVariable; | |||
| import org.springframework.web.bind.annotation.ResponseBody; | |||
| @Controller | |||
| public class FilesController { | |||
| @Autowired | |||
| StorageService storageService; | |||
| @GetMapping("/files/{filename:.+}") | |||
| @ResponseBody | |||
| public ResponseEntity<Resource> serveFile(@PathVariable String filename) { | |||
| Resource file = (Resource) storageService.loadAsResource(filename); | |||
| return ResponseEntity.ok().body(file); | |||
| } | |||
| } | |||
| @ -0,0 +1,52 @@ | |||
| package com.ims.rallyModels.controlador; | |||
| import com.ims.rallyModels.modelo.UsuarioEntity; | |||
| import com.ims.rallyModels.repositorio.IUserRepository; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Controller; | |||
| import org.springframework.ui.Model; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| @Controller | |||
| public class LoginControlador { | |||
| @Autowired | |||
| private IUserRepository iUserRepository; | |||
| @GetMapping({"/login"}) | |||
| public String goToLogin(Model model){ | |||
| return "login"; | |||
| } | |||
| /* | |||
| @Autowired | |||
| private IUsuarioRepositorio iUserRepository; | |||
| @GetMapping({"/login"}) | |||
| public String goToLogin(Model model){ | |||
| return "login"; | |||
| } | |||
| */ | |||
| /* | |||
| @Autowired | |||
| private IUsuarioRepositorio iUsuarioRepositorio; | |||
| @GetMapping({"/login"}) | |||
| public String goToLogin(Model model) { | |||
| return "login"; | |||
| } | |||
| @GetMapping({"/"}) | |||
| public String verPaginaInicio(Model model) { | |||
| return "index"; | |||
| } | |||
| @GetMapping("/login/valid") | |||
| public String loginValidation(String username) { | |||
| UsuarioEntity user = iUsuarioRepositorio.findByName(username); | |||
| return "login"; | |||
| } | |||
| */ | |||
| } | |||
| @ -0,0 +1,72 @@ | |||
| package com.ims.rallyModels.controlador; | |||
| import com.ims.rallyModels.modelo.UserModel; | |||
| import com.ims.rallyModels.repositorio.IUserRepository; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | |||
| import org.springframework.stereotype.Controller; | |||
| import org.springframework.ui.Model; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| @Controller | |||
| public class RegistroControlador { | |||
| @Autowired | |||
| private IUserRepository iUserRepository; | |||
| @GetMapping({"/register"}) | |||
| public String goToregister(Model model){ | |||
| model.addAttribute("user", new UserModel()); | |||
| return "register"; | |||
| } | |||
| @PostMapping("/process_register") | |||
| public String processRegister(UserModel user) { | |||
| BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); | |||
| String encodedPassword = passwordEncoder.encode(user.getPassword()); | |||
| user.setPassword(encodedPassword); | |||
| iUserRepository.save(user); | |||
| return "login"; | |||
| } | |||
| /*@Autowired | |||
| private IUsuarioRepositorio iUsuarioRepositorio; | |||
| //@GetMapping | |||
| //public String mostrarFormularioRegistro() { | |||
| //return "login"; | |||
| //} | |||
| /* | |||
| @PostMapping | |||
| public String registrarCuentaDeUsuario(@ModelAttribute("usuario") UsuarioRegistroDTU usuario) { | |||
| usuarioServicio.guardar(usuario); | |||
| //si logramos registrar correctamente se mandará el | |||
| //mensaje de éxito al html del registro (l.35) | |||
| return "redirect:/register?exito"; | |||
| } | |||
| @GetMapping("security/user") | |||
| public String getUser( Model model) { | |||
| CustomUserDetails currentUser = (CustomUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); | |||
| UsuarioEntity user = iUsuarioRepositorio.findByNombre(currentUser.getUsername()); | |||
| model.addAttribute("user", user); | |||
| return "security/user"; | |||
| } | |||
| @GetMapping({"/register"}) | |||
| public String goToregister(Model model){ | |||
| model.addAttribute("user", new UsuarioEntity()); | |||
| return "register"; | |||
| } | |||
| @PostMapping("/process_register") | |||
| public String processRegister(UsuarioEntity user) { | |||
| BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); | |||
| String encodedPassword = passwordEncoder.encode(user.getContrasena()); | |||
| user.setContrasena(encodedPassword); | |||
| iUsuarioRepositorio.save(user); | |||
| return "index"; | |||
| }*/ | |||
| } | |||
| @ -0,0 +1,32 @@ | |||
| package com.ims.rallyModels.controlador; | |||
| import org.springframework.stereotype.Controller; | |||
| import org.springframework.ui.Model; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| import org.springframework.web.bind.annotation.RequestParam; | |||
| import org.springframework.web.multipart.MultipartFile; | |||
| import java.io.IOException; | |||
| import java.nio.file.Files; | |||
| import java.nio.file.Path; | |||
| import java.nio.file.Paths; | |||
| @Controller | |||
| public class UploadController { | |||
| public static String UPLOAD_DIRECTORY = System.getProperty("user.dir") + "/uploads"; | |||
| @GetMapping("/uploadimage") public String displayUploadForm() { | |||
| return "redirect:/public/maquetas"; | |||
| } | |||
| @PostMapping("/upload") public String uploadImage(Model model, @RequestParam("image") MultipartFile file) throws IOException { | |||
| StringBuilder fileNames = new StringBuilder(); | |||
| Path fileNameAndPath = Paths.get(UPLOAD_DIRECTORY, file.getOriginalFilename()); | |||
| fileNames.append(file.getName()); | |||
| Files.write(fileNameAndPath, file.getBytes()); | |||
| model.addAttribute("msg", "Uploaded images: " + fileNames.toString()); | |||
| return "redirect:/public/maquetas"; | |||
| } | |||
| } | |||
| @ -1,20 +0,0 @@ | |||
| package com.ims.rallyModels.controlador; | |||
| import com.ims.rallyModels.servicio.IMaquetasServicio; | |||
| import com.ims.rallyModels.servicio.IUsuarioServicio; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.ui.Model; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| public class UsuarioControlador { | |||
| @Autowired | |||
| private IUsuarioServicio servicio; | |||
| @GetMapping({"/usuarios",""}) | |||
| public String listarMaquetas(Model model) { | |||
| model.addAttribute("usuarios",servicio.listAll()); | |||
| return "usuarios"; | |||
| } | |||
| } | |||
| @ -0,0 +1,61 @@ | |||
| package com.ims.rallyModels.dtu; | |||
| public class UsuarioRegistroDTU { | |||
| private int idUsuario; | |||
| private String nombre; | |||
| private String password; | |||
| private String sudo; | |||
| public UsuarioRegistroDTU(int idUsuario, String nombre, String password, String sudo) { | |||
| this.idUsuario = idUsuario; | |||
| this.nombre = nombre; | |||
| this.password = password; | |||
| this.sudo = sudo; | |||
| } | |||
| public UsuarioRegistroDTU(String nombre, String password, String sudo) { | |||
| this.nombre = nombre; | |||
| this.password = password; | |||
| this.sudo = sudo; | |||
| } | |||
| public UsuarioRegistroDTU(String nombre) { | |||
| this.nombre = nombre; | |||
| } | |||
| public UsuarioRegistroDTU() { | |||
| } | |||
| public int getIdUsuario() { | |||
| return idUsuario; | |||
| } | |||
| public void setIdUsuario(int idUsuario) { | |||
| this.idUsuario = idUsuario; | |||
| } | |||
| public String getNombre() { | |||
| return nombre; | |||
| } | |||
| public void setNombre(String nombre) { | |||
| this.nombre = nombre; | |||
| } | |||
| public String getContrasena() { | |||
| return password; | |||
| } | |||
| public void setContrasena(String contrasena) { | |||
| this.password = contrasena; | |||
| } | |||
| public String getSudo() { | |||
| return sudo; | |||
| } | |||
| public void setSudo(String sudo) { | |||
| this.sudo = sudo; | |||
| } | |||
| } | |||
| @ -0,0 +1,97 @@ | |||
| package com.ims.rallyModels.modelo; | |||
| import jakarta.persistence.*; | |||
| import org.springframework.data.annotation.CreatedDate; | |||
| import org.springframework.data.jpa.domain.support.AuditingEntityListener; | |||
| import java.util.Date; | |||
| import java.util.Objects; | |||
| @Entity | |||
| @EntityListeners(AuditingEntityListener.class) | |||
| public class UserModel { | |||
| @Id | |||
| @GeneratedValue | |||
| private long id; | |||
| private String email; | |||
| private String password; | |||
| private String name; | |||
| private String surname; | |||
| @CreatedDate | |||
| @Temporal(TemporalType.TIMESTAMP) | |||
| private Date createdDate; | |||
| public UserModel() { } | |||
| public UserModel(String name, String surname, String email, String password) { | |||
| this.name = name; | |||
| this.surname = surname; | |||
| this.email = email; | |||
| this.password = password; | |||
| } | |||
| public long getId() { | |||
| return id; | |||
| } | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| public String getSurname() { | |||
| return surname; | |||
| } | |||
| public Date getCreatedDate() { | |||
| return createdDate; | |||
| } | |||
| public String getEmail() { | |||
| return email; | |||
| } | |||
| public String getPassword() { | |||
| return password; | |||
| } | |||
| @Override | |||
| public boolean equals(Object o) { | |||
| if (this == o) return true; | |||
| if (o == null || getClass() != o.getClass()) return false; | |||
| UserModel user = (UserModel) o; | |||
| return id == user.id && email.equals(user.email); | |||
| } | |||
| @Override | |||
| public int hashCode() { | |||
| return Objects.hash(id, email); | |||
| } | |||
| public void setPassword(String password) { | |||
| this.password = password; | |||
| } | |||
| public void setId(long id) { | |||
| this.id = id; | |||
| } | |||
| public void setEmail(String email) { | |||
| this.email = email; | |||
| } | |||
| public void setName(String name) { | |||
| this.name = name; | |||
| } | |||
| public void setSurname(String surname) { | |||
| this.surname = surname; | |||
| } | |||
| public void setCreatedDate(Date createdDate) { | |||
| this.createdDate = createdDate; | |||
| } | |||
| } | |||
| @ -0,0 +1,104 @@ | |||
| package com.ims.rallyModels.reportes; | |||
| import com.ims.rallyModels.modelo.MaquetaEntity; | |||
| import jakarta.servlet.ServletOutputStream; | |||
| import jakarta.servlet.http.HttpServletResponse; | |||
| import org.apache.poi.ss.usermodel.Cell; | |||
| import org.apache.poi.ss.usermodel.CellStyle; | |||
| import org.apache.poi.ss.usermodel.Row; | |||
| import org.apache.poi.xssf.usermodel.XSSFFont; | |||
| import org.apache.poi.xssf.usermodel.XSSFSheet; | |||
| import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
| import java.io.IOException; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| public class FacturaExporterExcel { | |||
| private XSSFWorkbook libro; | |||
| private XSSFSheet hoja; | |||
| private List<MaquetaEntity> maquetas; | |||
| public FacturaExporterExcel(List<MaquetaEntity> maquetas) { | |||
| this.maquetas = maquetas; | |||
| libro = new XSSFWorkbook(); | |||
| hoja = libro.createSheet("Maquetas"); | |||
| } | |||
| private void escribirCabeceraTabla() { | |||
| Row fila = hoja.createRow(0); | |||
| CellStyle estilo = libro.createCellStyle(); | |||
| XSSFFont fuente = libro.createFont(); | |||
| fuente.setBold(true); | |||
| fuente.setFontHeight(16); | |||
| estilo.setFont(fuente); | |||
| Cell celda = fila.createCell(0); | |||
| celda.setCellValue("Id"); | |||
| celda.setCellStyle(estilo); | |||
| celda = fila.createCell(1); | |||
| celda.setCellValue("Coche"); | |||
| celda.setCellStyle(estilo); | |||
| celda = fila.createCell(2); | |||
| celda.setCellValue("Piloto"); | |||
| celda.setCellStyle(estilo); | |||
| celda = fila.createCell(3); | |||
| celda.setCellValue("Precio"); | |||
| celda.setCellStyle(estilo); | |||
| } | |||
| public void escribirDatosDeTabla() { | |||
| int numeroFilas = 1; | |||
| CellStyle estilo = libro.createCellStyle(); | |||
| XSSFFont fuente = libro.createFont(); | |||
| fuente.setFontHeight(14); | |||
| estilo.setFont(fuente); | |||
| for (MaquetaEntity m : maquetas) { | |||
| Row fila = hoja.createRow(numeroFilas++); | |||
| Cell celda = fila.createCell(0); | |||
| celda.setCellValue(m.getIdMaqueta()); | |||
| hoja.autoSizeColumn(0); | |||
| celda.setCellStyle(estilo); | |||
| celda = fila.createCell(1); | |||
| celda.setCellValue(m.getMarca()+" "+m.getModelo()); | |||
| hoja.autoSizeColumn(1); | |||
| celda.setCellStyle(estilo); | |||
| celda = fila.createCell(2); | |||
| celda.setCellValue(m.getPiloto()); | |||
| hoja.autoSizeColumn(2); | |||
| celda.setCellStyle(estilo); | |||
| celda = fila.createCell(3); | |||
| celda.setCellValue(m.getPrecio()); | |||
| hoja.autoSizeColumn(3); | |||
| celda.setCellStyle(estilo); | |||
| } | |||
| } | |||
| public void exportar(HttpServletResponse response) throws IOException { | |||
| escribirCabeceraTabla(); | |||
| escribirDatosDeTabla(); | |||
| ServletOutputStream outputStream = response.getOutputStream(); | |||
| libro.write(outputStream); | |||
| libro.close(); | |||
| outputStream.close(); | |||
| } | |||
| } | |||
| @ -0,0 +1,87 @@ | |||
| package com.ims.rallyModels.reportes; | |||
| import com.ims.rallyModels.modelo.CompraEntity; | |||
| import com.ims.rallyModels.modelo.MaquetaEntity; | |||
| import com.lowagie.text.*; | |||
| import com.lowagie.text.Font; | |||
| import com.lowagie.text.pdf.PdfPCell; | |||
| import com.lowagie.text.pdf.PdfPTable; | |||
| import com.lowagie.text.pdf.PdfWriter; | |||
| import jakarta.servlet.http.HttpServletResponse; | |||
| import java.awt.*; | |||
| import java.io.IOException; | |||
| import java.util.List; | |||
| public class FacturaExporterPDF { | |||
| private List<MaquetaEntity> compra; | |||
| public FacturaExporterPDF(List<MaquetaEntity> compra) { | |||
| super(); | |||
| this.compra = compra; | |||
| } | |||
| private void escribirCabeceraDeLaTabla(PdfPTable tabla) { | |||
| PdfPCell cell = new PdfPCell(); | |||
| cell.setBackgroundColor(Color.LIGHT_GRAY); | |||
| cell.setPadding(5); | |||
| Font fuente = FontFactory.getFont(FontFactory.HELVETICA); | |||
| fuente.setColor(Color.WHITE); | |||
| cell.setPhrase(new Phrase("Id",fuente)); | |||
| tabla.addCell(cell); | |||
| cell.setPhrase(new Phrase("Coche",fuente)); | |||
| tabla.addCell(cell); | |||
| cell.setPhrase(new Phrase("Piloto",fuente)); | |||
| tabla.addCell(cell); | |||
| cell.setPhrase(new Phrase("Precio",fuente)); | |||
| tabla.addCell(cell); | |||
| } | |||
| private void escribirDatosDeLaTable(PdfPTable table) { | |||
| for (MaquetaEntity m : compra) { | |||
| table.addCell(String.valueOf(m.getIdMaqueta())); | |||
| table.addCell(m.getMarca()+" "+m.getModelo()); | |||
| table.addCell(m.getPiloto()); | |||
| table.addCell(m.getPrecio().toString()); | |||
| } | |||
| } | |||
| public void exportar(HttpServletResponse response) throws IOException { | |||
| Document documento = new Document(PageSize.A4); | |||
| PdfWriter.getInstance(documento,response.getOutputStream()); | |||
| documento.open(); | |||
| Font fuente = FontFactory.getFont(FontFactory.HELVETICA); | |||
| fuente.setColor(Color.RED); | |||
| fuente.setSize(18); | |||
| Paragraph titulo = new Paragraph("Factura de maquetas", fuente); | |||
| titulo.setAlignment(Paragraph.ALIGN_CENTER); | |||
| documento.add(titulo); | |||
| PdfPTable tabla = new PdfPTable(4); | |||
| tabla.setWidthPercentage(100); | |||
| tabla.setSpacingBefore(15); | |||
| tabla.setWidths(new float[] {1f,2.3f,2.3f,2.3f}); | |||
| tabla.setWidthPercentage(110); | |||
| escribirCabeceraDeLaTabla(tabla); | |||
| escribirDatosDeLaTable(tabla); | |||
| documento.add(tabla); | |||
| documento.close(); | |||
| } | |||
| } | |||
| @ -0,0 +1,9 @@ | |||
| package com.ims.rallyModels.repositorio; | |||
| import com.ims.rallyModels.modelo.CocheEntity; | |||
| import jdk.jfr.Registered; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| import org.springframework.stereotype.Repository; | |||
| @Repository | |||
| public interface ICocheRepositorio extends JpaRepository<CocheEntity,Integer> {} | |||
| @ -0,0 +1,9 @@ | |||
| package com.ims.rallyModels.repositorio; | |||
| import com.ims.rallyModels.modelo.CompeticionEntity; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| import org.springframework.stereotype.Repository; | |||
| @Repository | |||
| public interface ICompeticionRepositorio extends JpaRepository<CompeticionEntity, Integer> { | |||
| } | |||
| @ -1,10 +1,11 @@ | |||
| package com.ims.rallyModels.repositorio; | |||
| import com.ims.rallyModels.modelo.CompraEntity; | |||
| import com.ims.rallyModels.modelo.MaquetaEntity; | |||
| import com.ims.rallyModels.modelo.UsuarioEntity; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| import org.springframework.stereotype.Repository; | |||
| @Repository | |||
| public interface IUsuarioRepositorio extends JpaRepository<UsuarioEntity, Integer> { | |||
| import java.util.List; | |||
| public interface ICompraRepositorio extends JpaRepository<CompraEntity,Integer> { | |||
| } | |||
| @ -1,8 +1,16 @@ | |||
| package com.ims.rallyModels.repositorio; | |||
| import com.ims.rallyModels.modelo.CompraEntity; | |||
| import com.ims.rallyModels.modelo.MaquetaEntity; | |||
| import com.ims.rallyModels.modelo.UserModel; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| import org.springframework.stereotype.Repository; | |||
| import java.util.List; | |||
| @Repository | |||
| public interface IMaquetasRepositorio extends JpaRepository<MaquetaEntity, Integer> { } | |||
| public interface IMaquetasRepositorio extends JpaRepository<MaquetaEntity, Integer> { | |||
| List<MaquetaEntity> findByCompra(CompraEntity c); | |||
| } | |||
| @ -0,0 +1,12 @@ | |||
| package com.ims.rallyModels.repositorio; | |||
| import com.ims.rallyModels.modelo.MaquetaEntity; | |||
| import com.ims.rallyModels.modelo.UserModel; | |||
| import com.ims.rallyModels.modelo.UsuarioEntity; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| import org.springframework.data.jpa.repository.Query; | |||
| import org.springframework.stereotype.Repository; | |||
| public interface IUserRepository extends JpaRepository<UserModel, Integer> { | |||
| UserModel findByEmail(String email); | |||
| } | |||
| @ -0,0 +1,55 @@ | |||
| package com.ims.rallyModels.security; | |||
| import com.ims.rallyModels.servicio.UsuarioServicioImpl; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.security.authentication.dao.DaoAuthenticationProvider; | |||
| import org.springframework.security.config.annotation.web.builders.HttpSecurity; | |||
| import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | |||
| import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | |||
| import org.springframework.security.crypto.password.PasswordEncoder; | |||
| import org.springframework.security.web.SecurityFilterChain; | |||
| @Configuration | |||
| @EnableWebSecurity | |||
| public class SecurityConfig { | |||
| @Bean | |||
| public UsuarioServicioImpl userDetailsService(){ | |||
| return new UsuarioServicioImpl(); | |||
| } | |||
| @Bean | |||
| public PasswordEncoder passwordEncoder() { | |||
| return new BCryptPasswordEncoder(); | |||
| } | |||
| @Bean | |||
| public DaoAuthenticationProvider authenticationProvider() { | |||
| DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); | |||
| authProvider.setUserDetailsService(userDetailsService()); | |||
| authProvider.setPasswordEncoder(passwordEncoder()); | |||
| return authProvider; | |||
| } | |||
| @Bean | |||
| public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { | |||
| http | |||
| .authorizeHttpRequests() | |||
| .requestMatchers("/user").authenticated() | |||
| .anyRequest().permitAll() | |||
| .and() | |||
| .formLogin() | |||
| .usernameParameter("email") | |||
| .loginPage("/login") | |||
| .defaultSuccessUrl("/public/maquetas") | |||
| .permitAll() | |||
| .and() | |||
| .logout().logoutSuccessUrl("/login").permitAll(); | |||
| return http.build(); | |||
| } | |||
| } | |||
| @ -1,11 +0,0 @@ | |||
| package com.ims.rallyModels.servicio; | |||
| import com.ims.rallyModels.modelo.UsuarioEntity; | |||
| import java.util.List; | |||
| public interface IUsuarioServicio { | |||
| public List<UsuarioEntity> listAll(); | |||
| } | |||
| @ -0,0 +1,58 @@ | |||
| package com.ims.rallyModels.servicio; | |||
| import com.ims.rallyModels.modelo.CompraEntity; | |||
| import com.ims.rallyModels.modelo.UserModel; | |||
| import com.ims.rallyModels.modelo.UsuarioEntity; | |||
| import org.springframework.security.core.GrantedAuthority; | |||
| import org.springframework.security.core.userdetails.UserDetails; | |||
| import java.util.Collection; | |||
| import java.util.List; | |||
| public class UserDetailsImpl implements UserDetails { | |||
| private UserModel user; | |||
| public UserDetailsImpl(UserModel user) { | |||
| this.user = user; | |||
| } | |||
| @Override | |||
| public Collection<? extends GrantedAuthority> getAuthorities() { | |||
| return null; | |||
| } | |||
| @Override | |||
| public String getPassword() { | |||
| return user.getPassword(); | |||
| } | |||
| public UserModel getUser() { | |||
| return user; | |||
| } | |||
| @Override | |||
| public String getUsername() { | |||
| return user.getEmail(); | |||
| } | |||
| @Override | |||
| public boolean isAccountNonExpired() { | |||
| return true; | |||
| } | |||
| @Override | |||
| public boolean isAccountNonLocked() { | |||
| return true; | |||
| } | |||
| @Override | |||
| public boolean isCredentialsNonExpired() { | |||
| return true; | |||
| } | |||
| @Override | |||
| public boolean isEnabled() { | |||
| return true; | |||
| } | |||
| } | |||
| @ -1,20 +1,51 @@ | |||
| package com.ims.rallyModels.servicio; | |||
| import com.ims.rallyModels.modelo.UsuarioEntity; | |||
| import com.ims.rallyModels.repositorio.IMaquetasRepositorio; | |||
| import com.ims.rallyModels.repositorio.IUsuarioRepositorio; | |||
| import com.ims.rallyModels.modelo.UserModel; | |||
| import com.ims.rallyModels.repositorio.IUserRepository; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.security.core.userdetails.UserDetails; | |||
| import org.springframework.security.core.userdetails.UserDetailsService; | |||
| import org.springframework.security.core.userdetails.UsernameNotFoundException; | |||
| import org.springframework.stereotype.Service; | |||
| import java.util.List; | |||
| public class UsuarioServicioImpl implements IUsuarioServicio{ | |||
| import java.util.Collection; | |||
| import java.util.stream.Collectors; | |||
| @Service | |||
| public class UsuarioServicioImpl implements UserDetailsService { | |||
| //may cons | |||
| @Autowired | |||
| private IUsuarioRepositorio repositorio; | |||
| private IUserRepository userRepo; | |||
| @Override | |||
| public List<UsuarioEntity> listAll() { | |||
| return repositorio.findAll(); | |||
| public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { | |||
| UserModel user = userRepo.findByEmail(username); | |||
| if (user == null) { | |||
| throw new UsernameNotFoundException("User not found"); | |||
| } | |||
| return new UserDetailsImpl(user); | |||
| } | |||
| /*@Override | |||
| public UsuarioEntity buscarPorNombre(String nombre) { | |||
| return repositorio.findByName(nombre); | |||
| }*/ | |||
| /* | |||
| @Override | |||
| public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { | |||
| UsuarioEntity usuario = repositorio.findByNombre(username); | |||
| if (usuario == null) { | |||
| throw new UsernameNotFoundException("Usuario o password inválidos");; | |||
| } | |||
| return new UsuarioEntity(usuario.getNombre(), usuario.getContrasena(), mapearAutoridadesRoles(usuario.getSudo())); | |||
| }*/ | |||
| /*@Override | |||
| public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { | |||
| UsuarioEntity user = repositorio.findByNombre(username); | |||
| if (user == null) { | |||
| throw new UsernameNotFoundException("User not found"); | |||
| } | |||
| return new UserDetailsImpl(user); | |||
| }*/ | |||
| } | |||
| @ -0,0 +1,42 @@ | |||
| package com.ims.rallyModels.servicio.coche; | |||
| import com.ims.rallyModels.modelo.CocheEntity; | |||
| import com.ims.rallyModels.repositorio.ICocheRepositorio; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import java.util.List; | |||
| @Service | |||
| public class CocheServicioImpl implements ICocheServicio { | |||
| @Autowired | |||
| private ICocheRepositorio repositorio; | |||
| @Override | |||
| public List<CocheEntity> listAll() { | |||
| return repositorio.findAll(); | |||
| } | |||
| @Override | |||
| public CocheEntity guardarCoche(CocheEntity maqueta) { | |||
| return repositorio.save(maqueta); | |||
| } | |||
| @Override | |||
| public CocheEntity obtenerCochePorId(Integer id) { | |||
| return repositorio.findById(id).get(); | |||
| } | |||
| @Override | |||
| public CocheEntity actualizarCoche(CocheEntity maqueta) { | |||
| //primero se busca y luego se edita y guarda | |||
| return repositorio.save(maqueta); | |||
| } | |||
| @Override | |||
| public void eliminarCoches(Integer id) { | |||
| repositorio.deleteById(id); | |||
| } | |||
| } | |||
| @ -0,0 +1,20 @@ | |||
| package com.ims.rallyModels.servicio.coche; | |||
| import com.ims.rallyModels.modelo.CocheEntity; | |||
| import com.ims.rallyModels.modelo.MaquetaEntity; | |||
| import java.util.List; | |||
| public interface ICocheServicio { | |||
| public List<CocheEntity> listAll(); | |||
| public CocheEntity guardarCoche(CocheEntity maqueta); | |||
| public CocheEntity obtenerCochePorId(Integer id); | |||
| public CocheEntity actualizarCoche(CocheEntity maqueta); | |||
| public void eliminarCoches(Integer id); | |||
| } | |||
| @ -0,0 +1,40 @@ | |||
| package com.ims.rallyModels.servicio.competicion; | |||
| import com.ims.rallyModels.modelo.CompeticionEntity; | |||
| import com.ims.rallyModels.repositorio.ICompeticionRepositorio; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import java.util.List; | |||
| @Service | |||
| public class CompeticionServicioImpl implements ICompeticionService { | |||
| @Autowired | |||
| private ICompeticionRepositorio repositorio; | |||
| @Override | |||
| public List<CompeticionEntity> listAll() { | |||
| return repositorio.findAll(); | |||
| } | |||
| @Override | |||
| public CompeticionEntity guardarCompeticion(CompeticionEntity competicion) { | |||
| return repositorio.save(competicion); | |||
| } | |||
| @Override | |||
| public CompeticionEntity obtenerCompeticionPorId(Integer id) { | |||
| return repositorio.findById(id).get(); | |||
| } | |||
| @Override | |||
| public CompeticionEntity actualizarCompeticion(CompeticionEntity competicion) { | |||
| return repositorio.save(competicion); | |||
| } | |||
| @Override | |||
| public void eliminarCompeticion(Integer id) { | |||
| repositorio.deleteById(id); | |||
| } | |||
| } | |||
| @ -0,0 +1,19 @@ | |||
| package com.ims.rallyModels.servicio.competicion; | |||
| import com.ims.rallyModels.modelo.CompeticionEntity; | |||
| import java.util.List; | |||
| public interface ICompeticionService { | |||
| public List<CompeticionEntity> listAll(); | |||
| public CompeticionEntity guardarCompeticion(CompeticionEntity competicion); | |||
| public CompeticionEntity obtenerCompeticionPorId(Integer id); | |||
| public CompeticionEntity actualizarCompeticion(CompeticionEntity competicion); | |||
| public void eliminarCompeticion(Integer id); | |||
| } | |||
| @ -0,0 +1,71 @@ | |||
| package com.ims.rallyModels.servicio.compra; | |||
| import com.ims.rallyModels.modelo.CompraEntity; | |||
| import com.ims.rallyModels.modelo.MaquetaEntity; | |||
| import com.ims.rallyModels.modelo.UserModel; | |||
| import com.ims.rallyModels.modelo.UsuarioEntity; | |||
| import com.ims.rallyModels.repositorio.ICompraRepositorio; | |||
| import com.ims.rallyModels.servicio.maqueta.IMaquetasServicio; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import java.util.List; | |||
| @Service | |||
| public class CompraServicioImpl implements ICompraServicio { | |||
| @Autowired | |||
| private ICompraRepositorio repositorio; | |||
| @Autowired | |||
| IMaquetasServicio maquetasServicio; | |||
| @Override | |||
| public List<CompraEntity> listAll() { | |||
| return repositorio.findAll(); | |||
| } | |||
| @Override | |||
| public CompraEntity guardarCompra(CompraEntity compra) { | |||
| return repositorio.save(compra); | |||
| } | |||
| @Override | |||
| public CompraEntity insertar(CompraEntity c, UserModel u) { | |||
| c.setUsuario(u); | |||
| return repositorio.save(c); | |||
| } | |||
| @Override | |||
| public CompraEntity obtenerCompraPorId(Integer id) { | |||
| return repositorio.findById(id).get(); | |||
| } | |||
| @Override | |||
| public CompraEntity actualizarCompra(CompraEntity compra) { | |||
| return repositorio.save(compra); | |||
| } | |||
| @Override | |||
| public void eliminarCompra(Integer id) { | |||
| repositorio.deleteById(id); | |||
| } | |||
| @Override | |||
| public List<CompraEntity> findByPropietario(UsuarioEntity propietario) { | |||
| return null; | |||
| } | |||
| @Override | |||
| public MaquetaEntity addMaquetaCompra(MaquetaEntity p, CompraEntity c) { | |||
| p.setCompra(c); | |||
| return maquetasServicio.actualizarMaqueta(p); | |||
| } | |||
| @Override | |||
| public void addMaquetaCompraTest(MaquetaEntity p, CompraEntity c) { | |||
| c.getProductos().add(p); | |||
| } | |||
| } | |||
| @ -0,0 +1,30 @@ | |||
| package com.ims.rallyModels.servicio.compra; | |||
| import com.ims.rallyModels.modelo.CompraEntity; | |||
| import com.ims.rallyModels.modelo.MaquetaEntity; | |||
| import com.ims.rallyModels.modelo.UserModel; | |||
| import com.ims.rallyModels.modelo.UsuarioEntity; | |||
| import java.util.List; | |||
| public interface ICompraServicio { | |||
| public List<CompraEntity> listAll(); | |||
| public CompraEntity guardarCompra(CompraEntity compra); | |||
| public CompraEntity insertar(CompraEntity c, UserModel u); | |||
| public CompraEntity obtenerCompraPorId(Integer id); | |||
| public CompraEntity actualizarCompra(CompraEntity compra); | |||
| public void eliminarCompra(Integer id); | |||
| public List<CompraEntity> findByPropietario(UsuarioEntity propietario); | |||
| public MaquetaEntity addMaquetaCompra(MaquetaEntity p, CompraEntity c); | |||
| public void addMaquetaCompraTest(MaquetaEntity p, CompraEntity c); | |||
| } | |||
| @ -0,0 +1,168 @@ | |||
| package com.ims.rallyModels.servicio.img; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.net.MalformedURLException; | |||
| import java.nio.file.Files; | |||
| import java.nio.file.Path; | |||
| import java.nio.file.Paths; | |||
| import java.nio.file.StandardCopyOption; | |||
| import java.util.stream.Stream; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.core.io.Resource; | |||
| import org.springframework.core.io.UrlResource; | |||
| import org.springframework.stereotype.Service; | |||
| import org.springframework.util.FileSystemUtils; | |||
| import org.springframework.util.StringUtils; | |||
| import org.springframework.web.multipart.MultipartFile; | |||
| /** | |||
| * Implementación de un {@link StorageService} que almacena | |||
| * los ficheros subidos dentro del servidor donde se ha desplegado | |||
| * la apliacación. | |||
| * | |||
| * ESTO SE REALIZA ASÍ PARA NO HACER MÁS COMPLEJO EL EJEMPLO. | |||
| * EN UNA APLICACIÓN EN PRODUCCIÓN POSIBLEMENTE SE UTILICE | |||
| * UN ALMACÉN REMOTO. | |||
| * | |||
| * | |||
| * @author Equipo de desarrollo de Spring | |||
| * | |||
| */ | |||
| @Service | |||
| public class FileSystemStorageService implements StorageService{ | |||
| // Directorio raiz de nuestro almacén de ficheros | |||
| private final Path rootLocation; | |||
| @Autowired | |||
| public FileSystemStorageService(StorageProperties properties) { | |||
| this.rootLocation = Paths.get(properties.getLocation()); | |||
| } | |||
| /** | |||
| * Método que almacena un fichero en el almacenamiento secundario | |||
| * desde un objeto de tipo {@link org.springframework.web.multipart#} MultipartFile | |||
| * | |||
| * Modificamos el original del ejemplo de Spring para cambiar el nombre | |||
| * del fichero a almacenar. Como lo asociamos al Empleado que se ha | |||
| * dado de alta, usaremos el ID de empleado como nombre de fichero. | |||
| * | |||
| */ | |||
| @Override | |||
| public String store(MultipartFile file) { | |||
| String filename = null; | |||
| try { | |||
| filename = StringUtils.cleanPath(file.getResource().getURL().toString()); | |||
| } catch (IOException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| String extension = StringUtils.getFilenameExtension(filename); | |||
| String justFilename = filename.replace("."+extension, ""); | |||
| String storedFilename = System.currentTimeMillis() + "_" + justFilename + "." + extension; | |||
| try { | |||
| try (InputStream inputStream = file.getInputStream()) { | |||
| Files.copy(inputStream, this.rootLocation.resolve(storedFilename), | |||
| StandardCopyOption.REPLACE_EXISTING); | |||
| return storedFilename; | |||
| } catch (IOException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } finally { | |||
| } | |||
| } | |||
| /** | |||
| * Método que devuelve la ruta de todos los ficheros que hay | |||
| * en el almacenamiento secundario del proyecto. | |||
| */ | |||
| @Override | |||
| public Stream<Path> loadAll() { | |||
| try { | |||
| return Files.walk(this.rootLocation, 1) | |||
| .filter(path -> !path.equals(this.rootLocation)) | |||
| .map(this.rootLocation::relativize); | |||
| } | |||
| catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return null; | |||
| } | |||
| /** | |||
| * Método que es capaz de cargar un fichero a partir de su nombre | |||
| * Devuelve un objeto de tipo Path | |||
| */ | |||
| @Override | |||
| public Path load(String filename) { | |||
| return rootLocation.resolve(filename); | |||
| } | |||
| /** | |||
| * Método que es capaz de cargar un fichero a partir de su nombre | |||
| * Devuelve un objeto de tipo Resource | |||
| */ | |||
| @Override | |||
| public Resource loadAsResource(String filename) { | |||
| try { | |||
| Path file = load(filename); | |||
| Resource resource = new UrlResource(file.toUri()); | |||
| if (resource.exists() || resource.isReadable()) { | |||
| return resource; | |||
| } | |||
| } | |||
| catch (MalformedURLException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return null; | |||
| } | |||
| /** | |||
| * Método que elimina todos los ficheros del almacenamiento | |||
| * secundario del proyecto. | |||
| */ | |||
| @Override | |||
| public void deleteAll() { | |||
| FileSystemUtils.deleteRecursively(rootLocation.toFile()); | |||
| } | |||
| /** | |||
| * Método que inicializa el almacenamiento secundario del proyecto | |||
| */ | |||
| @Override | |||
| public void init() { | |||
| try { | |||
| Files.createDirectories(rootLocation); | |||
| } | |||
| catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| @Override | |||
| public void delete(String filename) { | |||
| String justFilename = StringUtils.getFilename(filename); | |||
| try { | |||
| Path file = load(justFilename); | |||
| Files.deleteIfExists(file); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,20 @@ | |||
| package com.ims.rallyModels.servicio.img; | |||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||
| import org.springframework.stereotype.Service; | |||
| @Service | |||
| public class StorageProperties { | |||
| private String location = "upload-dir"; | |||
| public String getLocation() { | |||
| return location; | |||
| } | |||
| public void setLocation(String location) { | |||
| this.location = location; | |||
| } | |||
| } | |||
| @ -0,0 +1,27 @@ | |||
| package com.ims.rallyModels.servicio.img; | |||
| import org.springframework.core.io.Resource; | |||
| import org.springframework.stereotype.Service; | |||
| import org.springframework.web.multipart.MultipartFile; | |||
| import java.nio.file.Path; | |||
| import java.util.stream.Stream; | |||
| @Service | |||
| public interface StorageService { | |||
| void init(); | |||
| String store(MultipartFile file); | |||
| Stream<Path> loadAll(); | |||
| Path load(String filename); | |||
| Resource loadAsResource(String filename); | |||
| void delete(String filename); | |||
| void deleteAll(); | |||
| } | |||
| @ -0,0 +1,11 @@ | |||
| package com.ims.rallyModels.servicio.userMng; | |||
| import com.ims.rallyModels.modelo.CompraEntity; | |||
| import com.ims.rallyModels.modelo.UserModel; | |||
| import com.ims.rallyModels.modelo.UsuarioEntity; | |||
| import java.util.List; | |||
| public interface IUsuarioServicio { | |||
| public UserModel findByNombre(String nombre); | |||
| } | |||
| @ -0,0 +1,24 @@ | |||
| package com.ims.rallyModels.servicio.userMng; | |||
| import com.ims.rallyModels.modelo.UserModel; | |||
| import com.ims.rallyModels.repositorio.IUserRepository; | |||
| import com.ims.rallyModels.servicio.userMng.IUsuarioServicio; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| @Service | |||
| public class UserServImpl implements IUsuarioServicio { | |||
| @Autowired | |||
| IUserRepository repositorio; | |||
| @Override | |||
| public UserModel findByNombre(String nombre) { | |||
| return null; | |||
| } | |||
| public UserModel findById(int id) { | |||
| return repositorio.findById(id).get(); | |||
| } | |||
| } | |||
| @ -0,0 +1,43 @@ | |||
| @import url('https://fonts.googleapis.com/css2?family=Manrope:wght@200&display=swap'); | |||
| body { | |||
| font-family: 'Manrope', sans-serif; | |||
| background:#eee; | |||
| } | |||
| .size span { | |||
| font-size: 11px; | |||
| } | |||
| .color span { | |||
| font-size: 11px; | |||
| } | |||
| .product-deta { | |||
| margin-right: 70px; | |||
| } | |||
| .gift-card:focus { | |||
| box-shadow: none; | |||
| } | |||
| .pay-button { | |||
| color: #fff; | |||
| } | |||
| .pay-button:hover { | |||
| color: #fff; | |||
| } | |||
| .pay-button:focus { | |||
| color: #fff; | |||
| box-shadow: none; | |||
| } | |||
| .text-grey { | |||
| color: #a39f9f; | |||
| } | |||
| .qty i { | |||
| font-size: 11px; | |||
| } | |||
| @ -1,56 +0,0 @@ | |||
| <!DOCTYPE html> | |||
| <html xmlns:th="https://www.thymeleaf.org"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>RallyModels</title> | |||
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" | |||
| integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> | |||
| </head> | |||
| <body> | |||
| <nav class="navbar navbar-expand-md bg-dark navbar-dark"> | |||
| <a class="navbar-brand" href="#">Control de Maquetas</a> | |||
| <div class="collapse navbar-collapse" id="collapsibleNavbar"> | |||
| <ul class="navbar-nav"> | |||
| <li class="nav-item"><a class="nav-link" | |||
| th:href="@{/maquetas}">Control de maquetas</a> </li> | |||
| </ul> | |||
| </div> | |||
| </nav> | |||
| <br/> | |||
| <div class="container"> | |||
| <div class="row"> | |||
| <div class="col-lg-6 col-md-6 col-sm-6 container justify-content-center card"> | |||
| <h1 class="text-center">Nueva Maqueta</h1> | |||
| <div class="card-body"> | |||
| <form th:action="@{/maquetas}" th:object="${maqueta}" method="post"> | |||
| <!-- la maqueta de th:object es la que le pasamos al controlador OJO LAS "s" --> | |||
| <div class="form-group"> | |||
| <label>Descripcion: </label> | |||
| <input type="text" name="descripcion" th:field="*{descripcion}" | |||
| class="form-control" placeholder="Descripción de la maqueta: " required> | |||
| </div> | |||
| <br/> | |||
| <div class="form-group"> | |||
| <label>Precio: </label> | |||
| <input type="number" name="precio" th:field="*{precio}" | |||
| class="form-control" placeholder="Precio de la maqueta: " required> | |||
| </div> | |||
| <br/> | |||
| <div class="box-footer"> | |||
| <button class="btn btn-success">Guardar</button> | |||
| </div> | |||
| </form> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @ -1,13 +1,37 @@ | |||
| <!DOCTYPE html> | |||
| <html> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>RallyModels</title> | |||
| <html lang="en" | |||
| xmlns="http://www.w3.org/1999/xhtml" | |||
| xmlns:th="http://www.thymeleaf.org" > | |||
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous"> | |||
| <head> <!--th:replace="~{/fragments/head/head}">--> | |||
| </head> | |||
| <body> | |||
| <header th:replace="~{utils/nav}"> <!--th:replace="~{/fragments/header/headerOne}"--></header> | |||
| <body class="topspace"> | |||
| <div class="imgBoxs"> | |||
| <a href="/login">login</a> | |||
| <br> | |||
| <a href="/register">register</a> | |||
| <div class="container"> | |||
| <div class="btn-group" role="group" aria-label="Basic mixed styles example"> | |||
| <a type="button" class="btn btn-success" href="/login">Inicio de sesión</a> | |||
| <a type="button" class="btn btn-danger" href="/register">Registro</a> | |||
| </div> | |||
| </div> | |||
| <p>INDEX HTML!</p> | |||
| <h1>Lista de maquetas</h1> | |||
| <a href="maqueta.html">Añadir Maqueta</a> | |||
| </div> | |||
| <br> | |||
| <br> | |||
| <br> | |||
| <br> | |||
| <br> | |||
| <br> | |||
| </body> | |||
| <!--<footer th:replace="~{/fragments/footer/footerOne}" ></footer>--> | |||
| </html> | |||
| @ -0,0 +1,95 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en" style="background: aqua"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <title>Login</title> | |||
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" | |||
| rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous"> | |||
| </head> | |||
| <body style="height: 50%; width: 100%; background: aqua"> | |||
| <div class="container"> | |||
| <img src="../static/raw/circLogo.png" style="display: block; | |||
| margin-top: 5%; | |||
| margin-left: auto; | |||
| margin-right: auto; | |||
| width: 25%;" alt="logo"> | |||
| </div> | |||
| <main style="height: 100%; width: 100%"> | |||
| <!-- | |||
| <article> | |||
| <section class="vh-100 gradient-custom"> | |||
| <div class="container py-5 h-100"> | |||
| <div class="row d-flex justify-content-center align-items-center h-100"> | |||
| <div class="col-12 col-md-8 col-lg-6 col-xl-5"> | |||
| <div class="card bg-dark text-white" style="border-radius: 1rem;"> | |||
| <div class="card-body p-5 text-center"> | |||
| <div class="mb-md-5 mt-md-4 pb-5"> | |||
| <h2 class="fw-bold mb-2 text-uppercase">Inicio de sesión</h2> | |||
| <p class="text-white-50 mb-5">Introduce tu nombre y contraseña</p> | |||
| <div class="form-outline form-white mb-4"> | |||
| <input type="email" id="typeEmailX" class="form-control form-control-lg" /> | |||
| <label class="form-label" for="loginform">Nombre</label> | |||
| </div> | |||
| <div class="form-outline form-white mb-4"> | |||
| <input type="password" id="typePasswordX" class="form-control form-control-lg" /> | |||
| <label class="form-label" for="typePasswordX">Contraseña</label> | |||
| </div> | |||
| <button class="btn btn-outline-light btn-lg px-5" type="submit">Iniciar Sesión</button> | |||
| <div class="d-flex justify-content-center text-center mt-4 pt-1"> | |||
| <a href="#" class="text-white"><i class="fab fa-facebook-f fa-lg"></i></a> | |||
| <a href="#" class="text-white"><i class="fab fa-twitter fa-lg mx-4 px-2"></i></a> | |||
| <a href="#" class="text-white"><i class="fab fa-google fa-lg"></i></a> | |||
| </div> | |||
| </div> | |||
| <div> | |||
| <p class="mb-0">Don't have an account? <a href="#!" class="text-white-50 fw-bold">Sign Up</a> | |||
| </p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| </article> | |||
| --> | |||
| <div class="container" style="margin-top: 5%; border-radius: 3%; height: 20%; | |||
| background: linear-gradient(90deg, rgba(131,58,180,1) 0%, rgba(253,29,29,1) 50%, rgba(252,176,69,1) 100%);"> | |||
| <form id="loginform" th:action="@{/login}" method="post" role="form"> | |||
| <div class="form-group"> | |||
| <h2 for="email" style="color: #f2f2f2">Nombre Usuario</h2> | |||
| <input type="text" name="email" id="email" | |||
| class="form-control" aria-describedby="emailHelp" placeholder="Enter email"> | |||
| <small id="emailHelp" class="form-text text-muted"></small> | |||
| </div> | |||
| <div class="form-group"> | |||
| <h2 for="password" style="color: #f2f2f2">Contraseña</h2> | |||
| <input style="margin-bottom: 1%" type="password" name="password" class="form-control" id="password" placeholder="Password"> | |||
| </div> | |||
| <small class="text-muted"><a href="/register">No estas registrado?</a></small> | |||
| <button type="submit" class="btn btn-primary" style="color: #f2f2f2">Submit</button> | |||
| </form> | |||
| </div> | |||
| <!-- | |||
| <form id="loginform" th:action="@{/login}" method="POST" role="form" > | |||
| <h1>Login</h1> | |||
| <input type="text" name="email" id="email" placeholder="Email"> | |||
| <br> | |||
| <input type="password" name="password" id="password" placeholder="Password"> | |||
| <hr> | |||
| <button type="submit">Continue</button> | |||
| <small class="text-muted"><a href="/auth/register">Register here!</a></small> | |||
| </form>--> | |||
| </main> | |||
| </body> | |||
| </html> | |||
| @ -1,76 +0,0 @@ | |||
| <!DOCTYPE html> | |||
| <html xmlns:th="https://www.thymeleaf.org"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>RallyModels</title> | |||
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" | |||
| integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> | |||
| </head> | |||
| <body> | |||
| <nav class="navbar navbar-expand-md bg-dark navbar-dark"> | |||
| <a class="navbar-brand" href="#">Control de Maquetas</a> | |||
| <div class="collapse navbar-collapse" id="collapsibleNavbar"> | |||
| <ul class="navbar-nav"> | |||
| <li class="nav-item"><a class="nav-link" | |||
| th:href="@{/maquetas}">Control de maquetas</a> </li> | |||
| </ul> | |||
| </div> | |||
| </nav> | |||
| <div class="container"> | |||
| <div class="row"> | |||
| <h1>Lista Maquetas</h1> | |||
| </div> | |||
| <table class="table table-striped table-bordered"> | |||
| <thead class="table-dark"> | |||
| <tr> | |||
| <th>Descripcion</th> | |||
| <th>Coche</th> | |||
| <th>Competicion</th> | |||
| <th>Precio</th> | |||
| <th>Acciones</th> | |||
| </tr> | |||
| </thead> | |||
| <tbody> | |||
| <tr th:each="maqueta : ${maquetas}">. | |||
| <td th:text="${maqueta.descripcion}">Descripcion</td> | |||
| <td th:text="${maqueta.fkIdCoche}">Coche</td> | |||
| <td th:text="${maqueta.fkIdCompeticion}">Competicion</td> | |||
| <td th:text="${maqueta.precio}">Precio</td> | |||
| <td> | |||
| <a th:href="@{/maquetas/editar/{id}(id=${maqueta.idMaqueta})}" | |||
| class="btn btn-info">Editar</a> | |||
| <a th:href="@{/maquetas/{id}(id=${maqueta.idMaqueta})}" | |||
| class="btn btn-danger">Eliminar</a> | |||
| </td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| </div> | |||
| <div class="container"> | |||
| <div class="card" style="width: 18rem;"> | |||
| <img src="raw/images.jfif" class="card-img-top" alt="..."> | |||
| <div class="card-body"> | |||
| <h5 class="card-title">Card title</h5> | |||
| <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p> | |||
| <a href="#" class="btn btn-primary">Go somewhere</a> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,57 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en" | |||
| xmlns:th="http://www.thymeleaf.org"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Title</title> | |||
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" | |||
| integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> | |||
| <link href="/static/css/shoppingCart.css" rel="stylesheet" /> | |||
| </head> | |||
| <header th:replace="~{utils/nav}"></header> | |||
| <body> | |||
| <div class="container mt-5 mb-5"> | |||
| <div class="d-flex justify-content-center row"> | |||
| <div class="col-md-8"> | |||
| <div class="p-2"> | |||
| <h4>Carrito de la Compra</h4> | |||
| </div> | |||
| <div th:if="${carrito == null}"> | |||
| <div class="col-md-offset-1 col-md-10"> | |||
| <div class="jumbotron"> | |||
| <div class="container"> | |||
| <h2 class="text-center">Aún no ha seleccionado ningún producto para comprar</h2> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <th:block th:each="producto : ${carrito}"> | |||
| <div class="d-flex flex-row justify-content-between align-items-center p-2 bg-white mt-4 px-3 rounded"> | |||
| <div class="mr-1"><img class="rounded" th:src="@{${producto.image}}" width="70" alt="Imagen de la maqueta" /></div> | |||
| <div class="d-flex flex-column align-items-center product-details"><span class="font-weight-bold" th:text="${producto.piloto}">Maqueta</span> | |||
| <div class="d-flex flex-row product-desc"> | |||
| <div class="size mr-1"><span class="text-grey" th:text="${producto.marca+' '}">Marca del Coche:</span> | |||
| <span class="font-weight-bold"></span> | |||
| </div> | |||
| <div class="color"><span class="text-grey" th:text="${producto.modelo}">Modelo del Coche:</span> | |||
| <span class="font-weight-bold"></span> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div> | |||
| <h5 class="text-grey" th:text="${producto.precio}">$20.00</h5> | |||
| </div> | |||
| <a type="button" class="btn btn-danger" th:href="@{/public/carrito/eliminar/{id}(id=${producto.idMaqueta})}">Eliminar</a> | |||
| <div class="d-flex align-items-center"><i class="fa fa-trash mb-1 text-danger"></i></div> | |||
| </div> | |||
| </th:block> | |||
| <h5>Precio Total: <a th:text="${#numbers.formatCurrency(total_carrito)}"></a></h5> | |||
| <div class="d-flex flex-row align-items-center mt-3 p-2 bg-white rounded"> | |||
| <a th:href="@{/public/carrito/finalizar}" class="btn btn-warning btn-block btn-lg ml-2 pay-button" type="button">Procesar Compra</a> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,89 @@ | |||
| <!DOCTYPE html> | |||
| <html xmlns:th="https://www.thymeleaf.org"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>RallyModels</title> | |||
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" | |||
| integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> | |||
| </head> | |||
| <body> | |||
| <nav class="navbar navbar-expand-md bg-dark navbar-dark"> | |||
| <a class="navbar-brand" href="#">Control de Maquetas</a> | |||
| <div class="collapse navbar-collapse" id="collapsibleNavbar"> | |||
| <ul class="navbar-nav"> | |||
| <li class="nav-item"><a class="nav-link" | |||
| th:href="@{/public/maquetas}">Control de maquetas</a> </li> | |||
| </ul> | |||
| </div> | |||
| </nav> | |||
| <br/> | |||
| <div class="container"> | |||
| <div class="row"> | |||
| <div class="col-lg-6 col-md-6 col-sm-6 container justify-content-center card"> | |||
| <h1 class="text-center">Nueva Maqueta</h1> | |||
| <div class="card-body"> | |||
| <form th:action="@{/public/maquetas}" th:object="${maqueta}" method="post"> | |||
| <!-- la maqueta de th:object es la que le pasamos al controlador OJO LAS "s" --> | |||
| <div class="form-group"> | |||
| <label>Piloto: </label> | |||
| <input type="text" name="piloto" th:field="*{piloto}" | |||
| class="form-control" placeholder="Piloto: " required> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label>Marca: </label> | |||
| <input type="text" name="marca" th:field="*{marca}" | |||
| class="form-control" placeholder="Marca: " required> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label>Modelo del coche: </label> | |||
| <input type="text" name="modelo" th:field="*{modelo}" | |||
| class="form-control" placeholder="Modelo: " required> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label>Competicion: </label> | |||
| <input type="number" name="modelo" th:field="*{competicion}" | |||
| class="form-control" placeholder="Competicion: " required> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label>Precio: </label> | |||
| <input type="text" name="precio" th:field="*{precio}" | |||
| class="form-control" placeholder="Precio de la maqueta: " required> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label>Descripcion: </label> | |||
| <input type="text" name="descripcion" th:field="*{descripcion}" | |||
| class="form-control" placeholder="Descripción de la maqueta: " required> | |||
| </div> | |||
| <!--<div class="form-group"> | |||
| <label>Imagen</label> <input id="filebutton" name="file" class="form-control input-file" type="file"> | |||
| </div> | |||
| <div class="col-md-8 mx-auto"> | |||
| <h2>Upload Image Example</h2> | |||
| <p th:text="${message}" th:if="${message ne null}" class="alert alert-primary"></p> | |||
| <form method="post" th:action="@{/upload}" enctype="multipart/form-data"> | |||
| <div class="form-group"> | |||
| <input type="file" name="image" accept="image/*" class="form-control-file"> | |||
| </div> | |||
| <button type="submit" class="btn btn-primary">Upload image</button> | |||
| </form> | |||
| <span th:if="${msg != null}" th:text="${msg}"></span> | |||
| </div> | |||
| <br/>--> | |||
| <div class="box-footer"> | |||
| <button class="btn btn-success">Guardar</button> | |||
| </div> | |||
| </form> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,79 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Title</title> | |||
| </head> | |||
| <body> | |||
| <div class="container"> | |||
| <div class="row"> | |||
| <div class="col-xs-offset-3 col-xs-6"> | |||
| <div class="invoice-title"> | |||
| <h2>Factura</h2> | |||
| <h3 class="pull-right"> | |||
| Compra #<span th:text="${compra.idCompra}">1234</span> | |||
| </h3> | |||
| </div> | |||
| <hr> | |||
| <div class="row"> | |||
| <!--<div class="col-xs-6"> | |||
| <address> | |||
| <strong>Comprado por:</strong><br> <span | |||
| th:text="${compra.getUsuario().name + ' ' + compra.getUsuario().surname}"></span><br> | |||
| <span th:text="${compra.getUsuario().email}"></span><br> | |||
| </address> | |||
| </div> | |||
| <div class="col-xs-6 text-right"> | |||
| <address> | |||
| <strong>Fecha de compra:</strong><br> <span | |||
| th:text="${#dates.format(compra.fecha,'dd/MMM/yyyy HH:mm')}"></span><br> | |||
| <br> | |||
| </address> | |||
| </div>--> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-md-offset-3 col-md-6"> | |||
| <div class="panel panel-default"> | |||
| <div class="panel-heading"> | |||
| <h3 class="panel-title"> | |||
| <strong>Listado de productos</strong> | |||
| </h3> | |||
| </div> | |||
| <div class="panel-body invoice-body"> | |||
| <div class="table-responsive"> | |||
| <table class="table table-condensed"> | |||
| <thead> | |||
| <tr> | |||
| <td><strong>Producto</strong></td> | |||
| <td class="text-right"><strong>Precio</strong></td> | |||
| </tr> | |||
| </thead> | |||
| <tbody> | |||
| <tr th:each="producto : ${productos}"> | |||
| <td><span th:text="${producto.marca+' '+producto.modelo}">Producto</span></td> | |||
| <td class="text-right"><span th:text="${#numbers.formatCurrency(producto.precio)}">123€</span></td> | |||
| </tr> | |||
| <tr> | |||
| <td class="thick-line text-right"><strong>Total</strong></td> | |||
| <td class="thick-line text-right"><span | |||
| th:text="${#numbers.formatCurrency(total_compra)}"></span></td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| <div class="d-flex flex-row align-items-center mt-3 p-2 bg-white rounded"> | |||
| <a th:href="@{/public/exportarExcel/{id}(id=${compra.getIdCompra()})}" class="btn btn-warning btn-block btn-lg ml-2 pay-button" type="button">Obtener Factura Excel</a> | |||
| </div> | |||
| <div class="d-flex flex-row align-items-center mt-3 p-2 bg-white rounded"> | |||
| <a th:href="@{/public/exportarPDF/{id}(id=${compra.getIdCompra()})}" class="btn btn-warning btn-block btn-lg ml-2 pay-button" type="button">Obtener Factura PDF</a> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,7 @@ | |||
| /*! | |||
| * Start Bootstrap - Shop Item v5.0.5 (https://startbootstrap.com/template/shop-item) | |||
| * Copyright 2013-2022 Start Bootstrap | |||
| * Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-shop-item/blob/master/LICENSE) | |||
| */ | |||
| // This file is intentionally blank | |||
| // Use this file to add JavaScript to your project | |||
| @ -0,0 +1,125 @@ | |||
| <!DOCTYPE html> | |||
| <html xmlns:th="https://www.thymeleaf.org"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>RallyModels</title> | |||
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" | |||
| integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> | |||
| </head> | |||
| <body> | |||
| <nav class="navbar navbar-expand-lg bg-dark navbar-dark"> | |||
| <div class="container-fluid"> | |||
| <a class="navbar-brand" href="#">Rally Models</a> | |||
| <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" | |||
| aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> | |||
| <span class="navbar-toggler-icon"></span> | |||
| </button> | |||
| <div class="collapse navbar-collapse" id="navbarSupportedContent"> | |||
| <ul class="navbar-nav me-auto mb-2 mb-lg-0"> | |||
| <li class="nav-item"> | |||
| <a class="nav-link active" aria-current="page" th:href="@{/public/maquetas}">Home</a> | |||
| </li> | |||
| <li class="nav-item"> | |||
| <a class="nav-link" href="#">Control de maquetas</a> | |||
| </li> | |||
| <li class="nav-item"> | |||
| <a th:href="@{/logout}" method="POST" id="logoutForm">Cerrar Sesion</a> | |||
| </li> | |||
| </ul> | |||
| <a th:href="@{/public/maquetas/nuevo}" | |||
| class="btn btn-primary btn-sm mb3">Agregar Maqueta</a> | |||
| <a th:href="@{/public/carrito}" | |||
| class="btn btn-primary btn-sm mb3">Ver Carrito</a> | |||
| </div> | |||
| </div> | |||
| </nav> | |||
| <!-- | |||
| <nav class="navbar navbar-expand-md bg-dark navbar-dark"> | |||
| <a class="navbar-brand" href="#">Control de Maquetas</a> | |||
| <div class="collapse navbar-collapse" id="collapsibleNavbar"> | |||
| <ul class="navbar-nav"> | |||
| <li class="nav-item"><a class="nav-link" | |||
| th:href="@{/maquetas}">Control de maquetas</a> </li> | |||
| </ul> | |||
| </div> | |||
| </nav> | |||
| --> | |||
| <div class="container"> | |||
| <div class="row"> | |||
| <h1>Lista Maquetas</h1> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-lg-3"> | |||
| <a th:href="@{/public/maquetas/nuevo}" | |||
| class="btn btn-primary btn-sm mb3">Agregar Maqueta</a> | |||
| </div> | |||
| </div> | |||
| <br /> | |||
| <table class="table table-striped table-bordered"> | |||
| <thead class="table-dark"> | |||
| <tr> | |||
| <th>Descripcion</th> | |||
| <th>Coche</th> | |||
| <th>Competicion</th> | |||
| <th>Precio</th> | |||
| <th>Acciones</th> | |||
| </tr> | |||
| </thead> | |||
| <tbody> | |||
| <tr th:each="maqueta : ${maquetas}"> | |||
| <td th:text="${maqueta.getPiloto()}">Descripcion</td> | |||
| <td th:text="${maqueta.getMarca()+maqueta.getModelo()}">Coche</td> | |||
| <td th:text="${maqueta.getCompeticion().getNombre()}">Competicion</td> | |||
| <td th:text="${maqueta.getPrecio()}">Precio</td> | |||
| <td> | |||
| <a th:href="@{/public/maquetas/editar/{id}(id=${maqueta.idMaqueta})}" | |||
| class="btn btn-info">Editar</a> | |||
| <a th:href="@{/public/maquetas/eliminar/{id}(id=${maqueta.idMaqueta})}" | |||
| class="btn btn-danger">Eliminar</a> | |||
| </td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| </div> | |||
| <th:block th:each="maqueta : ${maquetas}"> | |||
| <div class="container"> | |||
| <div class="row"> | |||
| <div class="card" style="width: 18rem; margin: auto"> | |||
| <img th:src="@{${maqueta.getImage()}}" class="card-img-top" alt="fordPuma"> | |||
| <div class="card-body" style=""> | |||
| <h5 class="card-title" th:text="${maqueta.getMarca()+maqueta.getModelo()}" /> | |||
| <input type="hidden" name="selectedElementName" th:value="${maqueta.getCompeticion().getNombre()}" /> | |||
| <p class="card-text" th:text="${maqueta.getPiloto()}" /> | |||
| <p class="card-text" th:text="${maqueta.getPrecio()}" style="text-align: right"/> | |||
| <!--<button class="btn btn-primary form-control" type="submit">Enter</button>--> | |||
| </div> | |||
| <!--<ul th:each="maqueta : ${maquetas}"> | |||
| <li th:text="${maqueta.getCoche().getPiloto()}">Piloto</li> | |||
| <li th:text="${maqueta.getCoche().getMarca()}">Marca</li> | |||
| <li th:text="${maqueta.getCoche().getModelo()}">Modelo</li> | |||
| </ul> | |||
| <h5 class="card-title" ></h5> | |||
| <h5 class="card-title" ></h5> | |||
| <h5 class="card-title"></h5>--> | |||
| <a th:href="@{/public/maquetas/mostrar/{id}(id=${maqueta.idMaqueta})}" | |||
| class="btn btn-primary">Detalles</a> | |||
| <a th:href="@{/public/carrito/add/{id}(id=${maqueta.idMaqueta})}" class="btn btn-primary">Añadir al carrito</a> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </th:block> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,47 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en" xmlns:th="https://www.thymeleaf.org"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> | |||
| <title>Detalles de la maqueta</title> | |||
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" | |||
| integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> | |||
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css" rel="stylesheet" /> | |||
| <link href="/static/css/styles.css" rel="stylesheet" /> | |||
| </head> | |||
| <header th:replace="~{utils/nav}"></header> | |||
| <body> | |||
| <section class="py-5"> | |||
| <div class="container px-4 px-lg-5 my-5"> | |||
| <div class="row gx-4 gx-lg-5 align-items-center"> | |||
| <div class="col-md-6"><img class="card-img-top mb-5 mb-md-0" th:src="@{${maqueta.image}}" alt="Foto de la Maqueta" /></div> | |||
| <div class="col-md-6"> | |||
| <div> | |||
| <div class="small mb-1" th:text="${maqueta.piloto}">Piloto</div> | |||
| <h1 class="display-5 fw-bolder" th:text="${maqueta.marca+' '+maqueta.modelo}">Maqueta</h1> | |||
| <div class="fs-5 mb-5"> | |||
| <span th:text="${maqueta.precio}+'€'">$40.00</span> | |||
| </div> | |||
| <p class="lead" th:text="${maqueta.descripcion}">Descripcion</p> | |||
| <div class="d-flex"> | |||
| <input class="form-control text-center me-3" id="inputQuantity" type="num" value="1" style="max-width: 3rem" /> | |||
| <button th:href="@{/public/carrito/add/{id}(id=${maqueta.idMaqueta})}" class="btn btn-outline-dark flex-shrink-0" type="button"><!-- OJO --> | |||
| <i class="bi-cart-fill me-1"></i> | |||
| Añadir al carrito | |||
| </button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <!-- Footer--> | |||
| <footer class="py-5 bg-dark"> | |||
| <div class="container"><p class="m-0 text-center text-white">Copyright © Rally Models Corp. 2023</p></div> | |||
| </footer> | |||
| <!-- Bootstrap core JS--> | |||
| <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script> | |||
| <!-- Core theme JS--> | |||
| <script src="js/scripts.js"></script> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,25 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en" | |||
| xmlns:th="http://www.w3.org/1999/xhtml" | |||
| xmlns:th="https://www.thymeleaf.org"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Register</title> | |||
| </head> | |||
| <body> | |||
| <main> | |||
| <!--<form id="registerform" th:action="@{/process_register}" th:object="${user}" method="POST" role="form" > | |||
| <h1>Register</h1> | |||
| <input type="text" th:field="*{email}" placeholder="Email"> | |||
| <br> | |||
| <input type="text" th:field="*{name}" placeholder="Username"> | |||
| <br> | |||
| <input type="text" th:field="*{surname}" placeholder="Surname"> | |||
| <br> | |||
| <input type="password" th:field="*{password}" placeholder="Password"> | |||
| <hr> | |||
| <button type="submit">Continue</button> | |||
| </form>--> | |||
| </main> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,72 @@ | |||
| <!DOCTYPE html> | |||
| <html xmlns:th="https://www.thymeleaf.org"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>RallyModels</title> | |||
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" | |||
| integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> | |||
| </head> | |||
| <body> | |||
| <nav class="navbar navbar-expand-md bg-dark navbar-dark"> | |||
| <a class="navbar-brand" href="#">Control de Maquetas</a> | |||
| <div class="collapse navbar-collapse" id="collapsibleNavbar"> | |||
| <ul class="navbar-nav"> | |||
| <li class="nav-item"><a class="nav-link" | |||
| th:href="@{/maquetas}">Control de maquetas</a> </li> | |||
| </ul> | |||
| </div> | |||
| </nav> | |||
| <div class="container"> | |||
| <div class="row"> | |||
| <h1>Lista Maquetas</h1> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-lg-3"> | |||
| <a th:href="@{/maquetas/nuevo}" | |||
| class="btn btn-primary btn-sm mb3">Agregar Maqueta</a> | |||
| </div> | |||
| </div> | |||
| <br /> | |||
| <table class="table table-striped table-bordered"> | |||
| <thead class="table-dark"> | |||
| <tr> | |||
| <th>Descripcion</th> | |||
| <th>Coche</th> | |||
| <th>Competicion</th> | |||
| <th>Precio</th> | |||
| <th>Acciones</th> | |||
| </tr> | |||
| </thead> | |||
| <tbody> | |||
| <tr th:each="maqueta : ${maquetas}">. | |||
| <td th:text="${maqueta.descripcion}">Descripcion</td> | |||
| <td th:text="${maqueta.fkIdCoche}">Coche</td> | |||
| <td th:text="${maqueta.fkIdCompeticion}">Competicion</td> | |||
| <td th:text="${maqueta.precio}">Precio</td> | |||
| <td> | |||
| <a th:href="@{/maquetas/editar/{id}(id=${maqueta.idMaqueta})}" | |||
| class="btn btn-info">Editar</a> | |||
| <a th:href="@{/maquetas/{id}(id=${maqueta.idMaqueta})}" | |||
| class="btn btn-danger">Eliminar</a> | |||
| </td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,111 @@ | |||
| <!DOCTYPE html> | |||
| <html xmlns:th="http://www.thymeleaf.org"> | |||
| <head> | |||
| <meta charset="utf-8"> | |||
| <title>Registro de usuarios</title> | |||
| <!-- Latest compiled and minified CSS --> | |||
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous"> | |||
| </head> | |||
| <header th:replace="~{/utils/nav}"></header> | |||
| <body> | |||
| <div class="container" style="margin-top: 5%; height: 20%; | |||
| background: linear-gradient(90deg, rgba(131,58,180,1) 0%, rgba(253,29,29,1) 50%, rgba(252,176,69,1) 100%);"> | |||
| <form id="loginform" th:action="@{/process_register}" th:object="${user}" method="post" role="form"> | |||
| <h1>Registro</h1> | |||
| <div class="form-group"> | |||
| <h2 for="email" style="color: #f2f2f2">Email</h2> | |||
| <input type="email" th:field="*{email}" placeholder="Email"> | |||
| <small id="emailHelp" class="form-text text-muted"></small> | |||
| </div> | |||
| <div class="form-group"> | |||
| <h2 for="name" style="color: #f2f2f2">Nombre</h2> | |||
| <input type="text" th:field="*{name}" placeholder="Name"> | |||
| <small id="name" class="form-text text-muted"></small> | |||
| </div> | |||
| <div class="form-group"> | |||
| <h2 for="surname" style="color: #f2f2f2">Apellido</h2> | |||
| <input type="text" th:field="*{surname}" placeholder="Surname"> | |||
| <small id="surname" class="form-text text-muted"></small> | |||
| </div> | |||
| <div class="form-group"> | |||
| <h2 for="password" style="color: #f2f2f2">Contraseña</h2> | |||
| <input style="margin-bottom: 1%" type="password" th:field="*{password}" placeholder="Password"> | |||
| </div> | |||
| <small class="text-muted"><a href="/register">No estas registrado?</a></small> | |||
| <button type="submit" class="btn btn-primary" style="color: #f2f2f2">Submit</button> | |||
| </form> | |||
| </div> | |||
| <!-- | |||
| <main> | |||
| <form id="registerform" th:action="@{/process_register}" th:object="${user}" method="POST" role="form" > | |||
| <h1>Register</h1> | |||
| <input type="text" th:field="*{email}" placeholder="Username"> | |||
| <br> | |||
| <input type="password" th:field="*{password}" placeholder="Password"> | |||
| <hr> | |||
| <button type="submit">Continue</button> | |||
| </form> | |||
| </main> | |||
| --> | |||
| </body> | |||
| </html> | |||
| <!-- | |||
| <div class="container"> | |||
| <div class="row"> | |||
| <div class="col-md-6 col-md-offset-3"> | |||
| <div th:if="${param.exito}"> | |||
| <div class="alert alert-info">Se ha registrado exitosamente a | |||
| la aplicación | |||
| </div> | |||
| </div> | |||
| <h1>Regístrate</h1> | |||
| <form th:action="@{/registro}" method="post" th:object="${usuario}"> | |||
| <form th:action="@{/process_register}" method="post" th:object="${user}" role=""form> | |||
| <div class="form-group"> | |||
| <label class="control-label" for="nombre">Nombre : </label> <input | |||
| id="nombre" type="text" class="form-control" th:field="*{nombre}" | |||
| required autofocus="autofocus"> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label class="control-label" for="password">Password : </label> <input | |||
| type="password" id="password" class="form-control" th:field="*{contrasena}" | |||
| required autofocus="autofocus"> | |||
| </div> | |||
| <div class="form-group"> | |||
| <button type="submit" class="btn btn-success">Registrar</button> | |||
| <span>Si estas registrado <a th:href="@{/login}">inicia sesión aqui</a></span> | |||
| </div> | |||
| </form> | |||
| </div> | |||
| </div> | |||
| </div>--> | |||
| <!-- Latest compiled and minified JavaScript --> | |||
| <script | |||
| src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" | |||
| integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" | |||
| crossorigin="anonymous"></script> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,9 @@ | |||
| <nav class="navbar navbar-expand-md bg-dark navbar-dark"> | |||
| <a class="navbar-brand" href="#">Control de Maquetas</a> | |||
| <div class="collapse navbar-collapse" id="collapsibleNavbar"> | |||
| <ul class="navbar-nav"> | |||
| <li class="nav-item"><a class="nav-link" | |||
| th:href="@{/public/maquetas}">Control de maquetas</a> </li> | |||
| </ul> | |||
| </div> | |||
| </nav> | |||