6 Commits

24 changed files with 4010 additions and 11251 deletions
Split View
  1. +3594
    -10844
      package-lock.json
  2. +50
    -48
      package.json
  3. +2
    -2
      pom.xml
  4. BIN
      src/main/bundles/dev.bundle
  5. BIN
      src/main/bundles/prod.bundle
  6. +8
    -180
      src/main/frontend/themes/sistema-mantenimiento/styles.css
  7. +3
    -3
      src/main/java/mx/gob/jumapacelaya/Application.java
  8. +16
    -56
      src/main/java/mx/gob/jumapacelaya/api/RedmineClient.java
  9. +16
    -11
      src/main/java/mx/gob/jumapacelaya/controller/SecurityConfiguration.java
  10. +0
    -1
      src/main/java/mx/gob/jumapacelaya/datasource/MysqlDataSource.java
  11. +0
    -1
      src/main/java/mx/gob/jumapacelaya/datasource/OracleDataSource.java
  12. +33
    -35
      src/main/java/mx/gob/jumapacelaya/services/DatabaseService.java
  13. +1
    -1
      src/main/java/mx/gob/jumapacelaya/services/EmailService.java
  14. +1
    -1
      src/main/java/mx/gob/jumapacelaya/services/LdapService.java
  15. +5
    -12
      src/main/java/mx/gob/jumapacelaya/ui/ActDiariaView.java
  16. +203
    -0
      src/main/java/mx/gob/jumapacelaya/ui/ConfiguracionView.java
  17. +14
    -3
      src/main/java/mx/gob/jumapacelaya/ui/DetallesMantView.java
  18. +27
    -7
      src/main/java/mx/gob/jumapacelaya/ui/MainLayout.java
  19. +6
    -8
      src/main/java/mx/gob/jumapacelaya/ui/MantCorrectivoView.java
  20. +7
    -12
      src/main/java/mx/gob/jumapacelaya/ui/MantenimientoView.java
  21. +19
    -21
      src/main/java/mx/gob/jumapacelaya/ui/PlanAnualView.java
  22. +0
    -3
      src/main/java/mx/gob/jumapacelaya/ui/login/LoginView.java
  23. +4
    -1
      src/main/resources/application.properties
  24. +1
    -1
      tsconfig.json

+ 3594
- 10844
package-lock.json
File diff suppressed because it is too large
View File


+ 50
- 48
package.json View File

@ -4,42 +4,43 @@
"type": "module",
"dependencies": {
"@polymer/polymer": "3.5.2",
"@vaadin/bundles": "24.5.5",
"@vaadin/bundles": "24.8.0",
"@vaadin/common-frontend": "0.0.19",
"@vaadin/polymer-legacy-adapter": "24.5.5",
"@vaadin/react-components": "24.5.5",
"@vaadin/react-components-pro": "24.5.5",
"@vaadin/polymer-legacy-adapter": "24.8.0",
"@vaadin/react-components": "24.8.0",
"@vaadin/react-components-pro": "24.8.0",
"@vaadin/vaadin-development-mode-detector": "2.0.7",
"@vaadin/vaadin-lumo-styles": "24.5.5",
"@vaadin/vaadin-material-styles": "24.5.5",
"@vaadin/vaadin-themable-mixin": "24.5.5",
"@vaadin/vaadin-lumo-styles": "24.8.0",
"@vaadin/vaadin-material-styles": "24.8.0",
"@vaadin/vaadin-themable-mixin": "24.8.0",
"@vaadin/vaadin-usage-statistics": "2.1.3",
"construct-style-sheets-polyfill": "3.1.0",
"date-fns": "2.29.3",
"lit": "3.2.1",
"proj4": "2.12.1",
"lit": "3.3.0",
"proj4": "2.15.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-router-dom": "6.28.0",
"react-router": "7.6.1",
"signature_pad": "4.1.5"
},
"devDependencies": {
"@babel/preset-react": "7.26.3",
"@preact/signals-react-transform": "0.4.0",
"@rollup/plugin-replace": "6.0.1",
"@rollup/pluginutils": "5.1.3",
"@types/react": "18.3.13",
"@types/react-dom": "18.3.1",
"@vitejs/plugin-react": "4.3.3",
"@babel/preset-react": "7.27.1",
"@preact/signals-react-transform": "0.5.1",
"@rollup/plugin-replace": "6.0.2",
"@rollup/pluginutils": "5.1.4",
"@types/react": "18.3.23",
"@types/react-dom": "18.3.7",
"@vitejs/plugin-react": "4.5.0",
"async": "3.2.6",
"glob": "10.4.5",
"glob": "11.0.2",
"magic-string": "0.30.17",
"rollup-plugin-brotli": "3.1.0",
"rollup-plugin-visualizer": "5.12.0",
"rollup-plugin-visualizer": "5.14.0",
"strip-css-comments": "5.0.0",
"transform-ast": "2.4.4",
"typescript": "5.6.3",
"vite": "5.4.11",
"vite-plugin-checker": "0.8.0",
"typescript": "5.8.3",
"vite": "6.3.5",
"vite-plugin-checker": "0.9.3",
"workbox-build": "7.3.0",
"workbox-core": "7.3.0",
"workbox-precaching": "7.3.0"
@ -47,47 +48,48 @@
"vaadin": {
"dependencies": {
"@polymer/polymer": "3.5.2",
"@vaadin/bundles": "24.5.5",
"@vaadin/bundles": "24.8.0",
"@vaadin/common-frontend": "0.0.19",
"@vaadin/polymer-legacy-adapter": "24.5.5",
"@vaadin/react-components": "24.5.5",
"@vaadin/react-components-pro": "24.5.5",
"@vaadin/polymer-legacy-adapter": "24.8.0",
"@vaadin/react-components": "24.8.0",
"@vaadin/react-components-pro": "24.8.0",
"@vaadin/vaadin-development-mode-detector": "2.0.7",
"@vaadin/vaadin-lumo-styles": "24.5.5",
"@vaadin/vaadin-material-styles": "24.5.5",
"@vaadin/vaadin-themable-mixin": "24.5.5",
"@vaadin/vaadin-lumo-styles": "24.8.0",
"@vaadin/vaadin-material-styles": "24.8.0",
"@vaadin/vaadin-themable-mixin": "24.8.0",
"@vaadin/vaadin-usage-statistics": "2.1.3",
"construct-style-sheets-polyfill": "3.1.0",
"date-fns": "2.29.3",
"lit": "3.2.1",
"proj4": "2.12.1",
"lit": "3.3.0",
"proj4": "2.15.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-router-dom": "6.28.0",
"react-router": "7.6.1",
"signature_pad": "4.1.5"
},
"devDependencies": {
"@babel/preset-react": "7.26.3",
"@preact/signals-react-transform": "0.4.0",
"@rollup/plugin-replace": "6.0.1",
"@rollup/pluginutils": "5.1.3",
"@types/react": "18.3.13",
"@types/react-dom": "18.3.1",
"@vitejs/plugin-react": "4.3.3",
"@babel/preset-react": "7.27.1",
"@preact/signals-react-transform": "0.5.1",
"@rollup/plugin-replace": "6.0.2",
"@rollup/pluginutils": "5.1.4",
"@types/react": "18.3.23",
"@types/react-dom": "18.3.7",
"@vitejs/plugin-react": "4.5.0",
"async": "3.2.6",
"glob": "10.4.5",
"glob": "11.0.2",
"magic-string": "0.30.17",
"rollup-plugin-brotli": "3.1.0",
"rollup-plugin-visualizer": "5.12.0",
"rollup-plugin-visualizer": "5.14.0",
"strip-css-comments": "5.0.0",
"transform-ast": "2.4.4",
"typescript": "5.6.3",
"vite": "5.4.11",
"vite-plugin-checker": "0.8.0",
"typescript": "5.8.3",
"vite": "6.3.5",
"vite-plugin-checker": "0.9.3",
"workbox-build": "7.3.0",
"workbox-core": "7.3.0",
"workbox-precaching": "7.3.0"
},
"hash": "6126bd412c2a8696938f50edd1abae217c30c0119a0496af47b9d6ba1762921f"
"hash": "5e2a99194f7c0b939e722574ef486d86e32935203f1b5047346903f60dcb24d6"
},
"overrides": {
"@vaadin/bundles": "$@vaadin/bundles",
@ -99,7 +101,6 @@
"@vaadin/common-frontend": "$@vaadin/common-frontend",
"react-dom": "$react-dom",
"construct-style-sheets-polyfill": "$construct-style-sheets-polyfill",
"react-router-dom": "$react-router-dom",
"lit": "$lit",
"@polymer/polymer": "$@polymer/polymer",
"react": "$react",
@ -108,6 +109,7 @@
"@vaadin/vaadin-themable-mixin": "$@vaadin/vaadin-themable-mixin",
"@vaadin/vaadin-lumo-styles": "$@vaadin/vaadin-lumo-styles",
"@vaadin/vaadin-material-styles": "$@vaadin/vaadin-material-styles",
"signature_pad": "$signature_pad"
"signature_pad": "$signature_pad",
"react-router": "$react-router"
}
}
}

+ 2
- 2
pom.xml View File

@ -11,13 +11,13 @@
<properties>
<java.version>17</java.version>
<vaadin.version>24.5.8</vaadin.version>
<vaadin.version>24.8.0</vaadin.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.8</version>
<version>3.5.8</version>
</parent>
<repositories>


BIN
src/main/bundles/dev.bundle View File


BIN
src/main/bundles/prod.bundle View File


+ 8
- 180
src/main/frontend/themes/sistema-mantenimiento/styles.css View File

@ -1,11 +1,10 @@
@import url('./main-layout.css');
/* ----------- Estilos para el MainLayout.java ----------- */
/* Estilos para el DrawerToggle*/
.drawer-toggle {
background-color: #bc955b;
:root {
--lumo-primary-color: #BC955B;
--lumo-primary-text-color: #BC955B;
--lumo-border-radius: 15px;
--lumo-font-family: 'Montserrat';
}
/* Estilos para el encabezado */
@ -26,12 +25,9 @@
width: 300px;
}
/* Estilos para el fondo de la aplicacion */
.app-layout {
background-image: url('/images/bckgndNvo.png');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
vaadin-grid::part(selected-row-cell) {
background-color: #a02142;
color: white;
}
/* ------------------ FIN -------------------------------------- */
/*
@ -59,19 +55,6 @@
font-size: 18px;
color: #ddc9a3;
}
/* Estilo para el campo de texto nomenclatura */
.nomenclatura-txt {
margin-top: 15px;
margin-right: 15px;
}
/* Estilo para el logo CELAYA */
.celaya-logo {
width: 100px;
margin-left: 15px;
margin-top: 15px;
}
/* ------------------------ FIN -------------------------- */
/*
/*
@ -90,71 +73,8 @@
text-align: center;
}
/* Estilo para el grid */
.act-diaria-grid {
margin-top: 20px;
}
/* ---------------------------- FIN------------------------ */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* Estilos especificos para el TextField, TextArea y Fecha*/
vaadin-text-field::part(label), vaadin-text-area::part(label), vaadin-date-picker::part(label) {
color: #691b31; /* Color de la etiqueta */
}
vaadin-text-field::part(input-field), vaadin-text-area::part(input-field), vaadin-password-field::part(input-field),
vaadin-number-field::part(input-field), vaadin-date-picker::part(input-field) {
border: 1px solid #691b31; /* Color del borde */
color: #691b31; /* Color del texto */
}
vaadin-month-calendar::part(date) {
color: #691b31; /* Color para los dias del calendario */
}
vaadin-button {
border-radius: 10px;
overflow: hidden;
box-shadow: 0 4px 8px rgba(105, 27, 49, 0.28), 0 2px 8px rgba(0, 0, 0, 0.13);
transition: box-shadow 0.2s, border 0.2s;
}
vaadin-button::after {
content: "";
position: absolute;
inset: 0;
background: rgba(240,223,223,0.2);
opacity: 0;
transition: opacity 0.2s;
pointer-events: none;
}
vaadin-button:hover::after {
box-shadow: 0 16px 36px rgba(105,27,49,0.35), 0 4px 16px rgba(0,0,0,0.18);
border-color: #BC955B;
opacity: 1;
}
vaadin-month-calendar::part(date):hover /* Estilos para cuando se posiciona el puntero sobre el dia */{
background-color: #a02142;
opacity: 50%;
border-radius: 5px;
}
vaadin-month-calendar::part(date focused) {
background-color: #ddc9a3; /* Color de la fecha seleccionada */
}
vaadin-date-picker-overlay-content > vaadin-button, vaadin-date-picker-year::part(year-number) {
color: #691b31;
}
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* Estilos específicos para el Upload */
@ -162,104 +82,12 @@ vaadin-upload > vaadin-button {
color: #691b31;
}
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* Estilos específicos para el ComboBox */
vaadin-combo-box::part(input-field) {
background-color: #ddc9a3; /* Color de fondo */
color: #691b31; /* Color del texto */
border: 1px solid #691b31; /* Color del borde */
}
vaadin-combo-box::part(label) {
color: #691b31; /* Color de las etiquetas */
}
vaadin-combo-box::part(dropdown) {
background-color: rgba(221, 201, 163, 1); /* Color del fondo del dropdown */
}
vaadin-combo-box-item::part(checkmark)::before, vaadin-combo-box-item:hover
{
color: #691b31;
}
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) INDICADOR DE CARGA DE LA APLICACION (*)(*) (*)(*) */
.v-loading-indicator { /* Cambiar el color de la barra de carga que sale cuando la aplicacion esta cargando */
background: #691b31 !important;
}
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) ESTILOS PARA LA SIDEBAR (*)(*) (*)(*) */
vaadin-side-nav-item[aria-current="page"]::part(content) {
color: #691b31; /* Color de texto seleccionado */
}
vaadin-side-nav-item:hover::part(content) {
background-color: #ddc9a3; /* Color de fondo al hacer hover*/
fill-opacity: 50%;
border-radius: 5px;
}
vaadin-side-nav-item::part(content) {
color: #a02142; /* Color del texto deseado */
}
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/*Estilos especificos para el Grid */
vaadin-grid::part(selected-row-cell) {
background-color: rgba(221, 201, 163, 0.7);
}
vaadin-grid::part(selected-row) {
color: #691b31;
font-weight: bold;
}
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/*Estilos especificos para los botones */
vaadin-button[theme~="primary"] {
background-color: #691b31;
}
vaadin-button:not([theme]) {
color: #a02142;
}
vaadin-button[theme~="tertiary-inline"], vaadin-button[theme~="icon"] {
color: #a02142;
}
/* Estilos para el theme personalizado 'subir-archivo' */
vaadin-button[theme~="subir-archivo"] {
background-color: #691b31;
color: #ffffff;
}
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/*Estilos especificos para los CheckBox y RadioButtons */
vaadin-checkbox[checked]::part(checkbox) {
background-color: #691b31; /* Cambia el color del CheckBox */
}
vaadin-checkbox-group::part(label), vaadin-radio-group::part(label) {
color: #691b31;
}
vaadin-radio-button[checked]::part(radio) {
background-color: #691b31;
}
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */
/* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */


+ 3
- 3
src/main/java/mx/gob/jumapacelaya/Application.java View File

@ -4,11 +4,11 @@ import com.vaadin.flow.component.page.AppShellConfigurator;
import com.vaadin.flow.component.page.Push;
import com.vaadin.flow.server.PWA;
import com.vaadin.flow.theme.Theme;
import com.vaadin.flow.theme.lumo.Lumo;
import mx.gob.jumapacelaya.services.DatabaseService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
/**
* The entry point of the Spring Boot application.
@ -19,7 +19,7 @@ import org.springframework.boot.autoconfigure.validation.ValidationAutoConfigura
*/
@SpringBootApplication
@Push
@Theme(value = "sistema-mantenimiento")
@Theme(value = "sistema-mantenimiento", variant = Lumo.LIGHT)
@PWA(name = "Aplicacion de Mantenimiento de Equipo de Computo", shortName = "Mantenimiento de Computo", iconPath = "icons/icon.png")
public class Application implements AppShellConfigurator {


+ 16
- 56
src/main/java/mx/gob/jumapacelaya/api/RedmineClient.java View File

@ -7,6 +7,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
@ -84,10 +85,10 @@ public class RedmineClient {
if (response.statusCode() == 200) {
tickets.addAll(parseTickets(response.body()));
} else {
System.err.println("Error en la respuesta: " + response.statusCode());
log.error("Error al obtener tickets. Codigo de estado: {}", response.statusCode());
}
} catch (Exception e) {
e.printStackTrace();
log.error("Ocurrió una excepción al procesar la respuesta del servidor: ", e);
}
return tickets;
@ -135,55 +136,15 @@ public class RedmineClient {
JsonObject jsonObject = JsonParser.parseString(response.body()).getAsJsonObject();
return jsonObject.get("total_count").getAsInt();
} else {
System.err.println("Error en la respuesta: " + response.statusCode());
log.error("Error al obtener los tickets. Codigo de estado: {}", response.statusCode());
}
} catch (Exception e) {
e.printStackTrace();
log.error("Ocurrió un error al procesar l respuesta del servidor", e);
}
return 0;
}
//AQUI OBTENGO LOS TICKETS DESDE REDMINE
/*public List<Ticket> getTicketsAuthor(RedmineUser user, boolean includeClosed) {
List<Ticket> tickets = new ArrayList<>();
HttpClient client = HttpClient.newHttpClient();
int offset = 0;
// Si includeClose es true, incluira todos los tikets si no, incluira solo los que estan abiertos
String statusFilter = includeClosed ? "&status_id=*" : "&status_id=open";
while (true) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(REDMINE_URL + "/issues.json?key=" + user.getKey() + "&author_id=" + user.getId() + statusFilter + "&offset=" + offset))
.header("Content-Type", "application/json")
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
String responseBody = response.body();
List<Ticket> pageTickets = parseTickets(responseBody);
tickets.addAll(pageTickets);
if (pageTickets.size() < PAGE_SIZE) {
break;
}
offset += PAGE_SIZE;
} else {
System.err.println("Error en la respuesta: " + response.statusCode());
break;
}
} catch (Exception e) {
e.printStackTrace();
break;
}
}
System.out.println("Total tickets obtenidos: " + tickets.size());
return tickets;
}*/
// Aquí se parsean todos los tickets que existen y se les da un formato con los campos a mostrarse
private List<Ticket> parseTickets(String json) {
List<Ticket> tickets = new ArrayList<>();
@ -254,11 +215,10 @@ public class RedmineClient {
tickets.add(ticketObj);
}
} else {
System.out.println("La respuesta JSON no contiene la clave 'issues'");
log.info("La respuesta JSON no contiene la clave 'issues'. Respuesta completa: {}", json);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("Ocurrió un error al parsear los tickets: " + e.getMessage());
log.error("Ocurrió un error al parsear los tickets: ", e);
}
return tickets;
}
@ -290,7 +250,7 @@ public class RedmineClient {
//return response.body();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
log.error("Error al obtener la cuenta del usuario: {}", e);
return null;
}
}
@ -331,7 +291,7 @@ public class RedmineClient {
return newUser;
} catch (Exception e) {
e.printStackTrace();
log.error("Error al crear el usuario: {}", e);
return null;
}
}
@ -350,13 +310,13 @@ public class RedmineClient {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
String responseBody = response.body();
System.out.println("Datos del usuario " + responseBody);
log.info("Datos del usuario " + responseBody);
return parseUser(responseBody);
} else {
System.err.println("Error en la respuesta: " + response.statusCode());
log.error("Error en la respuesta {}", response.statusCode());
}
} catch (Exception e) {
e.printStackTrace();
log.error("Error al obtener el usuario por nombre de usuario: {}", e);
}
return null;
}
@ -398,10 +358,10 @@ public class RedmineClient {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 204) {
String responseBody = response.body();
System.out.println("Ticket " + ticketId + " cerrado correctamente.");
log.info("Ticket " + ticketId + " cerrado correctamente.");
} else {
System.err.println("Error al cerrar el ticket: " + response.statusCode());
System.err.println(response.body());
log.error("Error al cerrar el ticket: {}", response.statusCode());
log.error(response.body());
}
}
@ -433,7 +393,7 @@ public class RedmineClient {
return LocalDateTime.parse(dateStr);
}
} catch (DateTimeParseException ex) {
System.err.println("Error al parsear fecha '" + fieldName + "': " + dateStr);
log.error("Error al parsear fecha '" + fieldName + "': " + dateStr);
return null;
}
}


+ 16
- 11
src/main/java/mx/gob/jumapacelaya/controller/SecurityConfiguration.java View File

@ -19,6 +19,21 @@ import org.springframework.ldap.core.support.LdapContextSource;
public class SecurityConfiguration extends VaadinWebSecurity {
@Value("${spring.ldap.domain}")
private String ldapDomain;
@Value("${spring.ldap.urls}")
private String ldapUrls;
@Value("${spring.ldap.url}")
private String ldapUrl;
@Value("${spring.ldap.base}")
private String ldapBase;
@Value("${spring.ldap.password}")
private String ldapPassword;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth
@ -40,23 +55,13 @@ public class SecurityConfiguration extends VaadinWebSecurity {
// !Esta es la real autenticacion con ldap
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider("JUMAPACELAYA.GOB.MX", "ldap://172.16.0.1");
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(ldapDomain, ldapUrl);
provider.setConvertSubErrorCodesToExceptions(true);
provider.setUseAuthenticationRequestCredentials(true);
auth.authenticationProvider(provider);
}
@Value("${spring.ldap.urls}")
private String ldapUrls;
@Value("${spring.ldap.base}")
private String ldapBase;
@Value("${spring.ldap.password}")
private String ldapPassword;
@Bean
public LdapContextSource ldapContextSource() {
LdapContextSource contextSource = new LdapContextSource();


+ 0
- 1
src/main/java/mx/gob/jumapacelaya/datasource/MysqlDataSource.java View File

@ -24,7 +24,6 @@ public class MysqlDataSource {
@Bean(name = "mysqlJdbcTemplate")
@Autowired
public JdbcTemplate mysqlTemplate(@Qualifier("mysqlDB") DataSource mysqlDB) {
return new JdbcTemplate(mysqlDB);
}

+ 0
- 1
src/main/java/mx/gob/jumapacelaya/datasource/OracleDataSource.java View File

@ -20,7 +20,6 @@ public class OracleDataSource {
}
@Bean(name = "oracleTemplate")
@Autowired
public JdbcTemplate oracleJdbcTemplate(@Qualifier("oracleDB") DataSource oracleDB) {
return new JdbcTemplate(oracleDB);
}


+ 33
- 35
src/main/java/mx/gob/jumapacelaya/services/DatabaseService.java View File

@ -4,18 +4,18 @@ import mx.gob.jumapacelaya.models.*;
import mx.gob.jumapacelaya.models.encuestas.MantenimientosSinEncuesta;
import mx.gob.jumapacelaya.models.encuestas.Pregunta;
import mx.gob.jumapacelaya.models.encuestas.Respuesta;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OraclePreparedStatement;
import oracle.sql.CLOB;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.security.interfaces.RSAKey;
import java.sql.*;
import java.time.LocalDate;
import java.util.ArrayList;
@ -25,6 +25,7 @@ import java.util.UUID;
@Service
public class DatabaseService {
private static final Logger logger = LoggerFactory.getLogger(DatabaseService.class);
@Value("${db.url}")
private String dbUrl;
@ -63,7 +64,7 @@ public class DatabaseService {
tiposDeMantenimientos.add(tipo);
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al obtener tipos de mantenimientos: ", e);
}
return tiposDeMantenimientos;
}
@ -84,8 +85,7 @@ public class DatabaseService {
}
} catch (SQLException e) {
e.printStackTrace();
System.err.println("Error al obtener nomenclatura: " + e.getMessage());
logger.error("Error al obtener nomenclatura: ", e);
}
return nomenclatura;
}
@ -109,7 +109,7 @@ public class DatabaseService {
usuarios.add(usuario);
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al obtener usuarios: ", e);
}
return usuarios;
}
@ -131,7 +131,7 @@ public class DatabaseService {
departamentos.add(departamentosModel);
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al obtener departamentos: ", e);
}
return departamentos;
}
@ -153,7 +153,7 @@ public class DatabaseService {
tiposHardware.add(tiposHardwareModel);
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al obtener tipos de hardware: ", e);
}
return tiposHardware;
}
@ -206,7 +206,7 @@ public class DatabaseService {
}
System.out.println("Registros obtenidos: " + planAnualList.size());
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al obtener plan anual: ", e);
}
return planAnualList;
}
@ -257,7 +257,7 @@ public class DatabaseService {
}
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al obtener plan anual por id: ", e);
}
return null;
}
@ -312,7 +312,7 @@ public class DatabaseService {
}
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al obtener detalles del mantenimiento por plan anual id: ", e);
}
return null;
@ -372,7 +372,7 @@ public class DatabaseService {
));
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al obtener mantenimientos sin encuesta respondida por periodo: ", e);
}
return lista;
@ -405,7 +405,7 @@ public class DatabaseService {
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al obtener detalles del hardaware por ID: ", e);
}
return detalles;
}
@ -434,7 +434,7 @@ public class DatabaseService {
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al obtener las actualizaciones de seguridad: ", e);
}
return actualizaciones;
}
@ -480,7 +480,7 @@ public class DatabaseService {
}
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al obtener los mantenimientos correctivos: ", e);
}
return mantCorrectivos;
}
@ -565,14 +565,13 @@ public class DatabaseService {
connection.commit();
} catch (SQLException e) {
System.err.println("Error al insertar mantenimiento: " + e.getMessage());
e.printStackTrace();
logger.error("Error al insertar mantenimiento: ", e);
// En caso de error, se hace rollback
if (connection != null) {
try {
connection.rollback();
} catch (SQLException rollbackEx) {
System.err.println("Error al hacer rollback: " + rollbackEx.getMessage());
logger.error("Error al hacer rollback: ", rollbackEx);
}
}
} finally {
@ -608,7 +607,7 @@ public class DatabaseService {
int rowsAffected = preparedStatement.executeUpdate();
isInserted = rowsAffected > 0;
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al insertar hardware: ", e);
}
return isInserted;
}
@ -624,7 +623,7 @@ public class DatabaseService {
}
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al obtener el ultimo id de mantenimiento: ", e);
}
return ultimoId;
}
@ -832,7 +831,7 @@ public class DatabaseService {
stmt.setInt(2, planAnualId);
return stmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al actualizar el plan anual: ", e);
return false;
}
}
@ -859,7 +858,7 @@ public class DatabaseService {
stmt.setInt(8, mantenimientoId);
return stmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al actualizar el mantenimiento: ", e);
return false;
}
}
@ -875,7 +874,7 @@ public class DatabaseService {
stmt.setInt(4, detalle.getHardwareDetId());
return stmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al actualizar el detalle del hardware: ", e);
return false;
}
}
@ -889,7 +888,7 @@ public class DatabaseService {
stmt.setInt(2, actualizacion.getActualizacionsegId());
return stmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al actualizar la actualización de seguridad: ", e);
return false;
}
}
@ -905,7 +904,7 @@ public class DatabaseService {
stmt.setString(4, motivo);
return stmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al insertar en bitacora: ", e);
return false;
}
}
@ -921,7 +920,7 @@ public class DatabaseService {
stmt.setString(4, motivo);
return stmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al insertar en bitacora de eliminacion de equipos: ", e);
return false;
}
}
@ -940,8 +939,7 @@ public class DatabaseService {
System.out.println("No se encontró el equipo con ID: " + planAnualId);
}
} catch (SQLException e) {
System.err.println("Error al eliminar el equipo de PLANANUAL: " + e.getMessage());
e.printStackTrace();
logger.error("Error al eliminar el equipo de PLANANUAL: ", e);
}
}
@ -971,7 +969,7 @@ public class DatabaseService {
preguntas.add(pregunta);
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al obtener las preguntas de la encuesta: ", e);
}
return preguntas;
}
@ -1053,7 +1051,7 @@ public class DatabaseService {
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al crear el token de encuesta: ", e);
}
return token;
}
@ -1070,7 +1068,7 @@ public class DatabaseService {
return rs.getInt("MANTENIMIENTOID");
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error al validar el token de encuesta: ", e);
}
return null;
}


+ 1
- 1
src/main/java/mx/gob/jumapacelaya/services/EmailService.java View File

@ -36,7 +36,7 @@ public class EmailService {
} catch (Exception e) {
e.printStackTrace();
log.error("Error al enviar el correo: ", e);
throw new RuntimeException("Error al enviar el correo: " + e.getMessage());
}
}


+ 1
- 1
src/main/java/mx/gob/jumapacelaya/services/LdapService.java View File

@ -25,7 +25,7 @@ public class LdapService {
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setReturningAttributes(new String[]{"givenName", "sn", "mail"});
searchControls.setReturningObjFlag(true);
searchControls.setReturningObjFlag(false);
List<CustomUserDetails> result = ldapTemplate.search("", filter.encode(), searchControls, (Attributes attrs) -> {
String firstName = getAttribute(attrs, "givenName");


+ 5
- 12
src/main/java/mx/gob/jumapacelaya/ui/ActDiariaView.java View File

@ -11,9 +11,7 @@ import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.html.Anchor;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.H3;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
@ -22,13 +20,11 @@ import com.vaadin.flow.component.notification.NotificationVariant;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.page.Push;
import com.vaadin.flow.component.popover.Popover;
import com.vaadin.flow.component.popover.PopoverPosition;
import com.vaadin.flow.component.progressbar.ProgressBar;
import com.vaadin.flow.component.richtexteditor.RichTextEditor;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.function.SerializableBiConsumer;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.StreamRegistration;
@ -36,10 +32,8 @@ import com.vaadin.flow.server.StreamResource;
import jakarta.annotation.security.PermitAll;
import mx.gob.jumapacelaya.api.RedmineClient;
import mx.gob.jumapacelaya.api.ServerProperties;
import mx.gob.jumapacelaya.models.ActividadDiaria;
import mx.gob.jumapacelaya.models.RedmineUser;
import mx.gob.jumapacelaya.models.Ticket;
import mx.gob.jumapacelaya.services.LdapService;
import mx.gob.jumapacelaya.services.UserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
@ -50,17 +44,17 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vaadin.lineawesome.LineAwesomeIcon;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Stream;
@ -98,7 +92,7 @@ public class ActDiariaView extends VerticalLayout {
opcionesLyt.getStyle()
.set("box-shadow", "0 4px 8px rgba(0,0,0,0.2)")
.set("border-radius", "10px")
.set("background-color", "white")
//.set("background-color", "white")
.set("padding", "1rem")
.set("margin", "1rem auto");
@ -270,7 +264,6 @@ public class ActDiariaView extends VerticalLayout {
grid.addComponentColumn(ticket -> {
Button btnVer = new Button(new Icon(VaadinIcon.EYE));
btnVer.addClickListener(event -> showDescription(ticket));
btnVer.getStyle().set("color", "#A02142");
return btnVer;
});
@ -395,7 +388,7 @@ public class ActDiariaView extends VerticalLayout {
UI.getCurrent().getPage().executeJs("setTimeout(() => { window.location.reload(); }, 3000);");
} catch (IOException | InterruptedException e) {
e.printStackTrace();
log.error("Error al cerrar el ticket " + ticket.getId(), e);
Notification.show("Error al cerrar el ticket " + ticket.getId());
}
}


+ 203
- 0
src/main/java/mx/gob/jumapacelaya/ui/ConfiguracionView.java View File

@ -0,0 +1,203 @@
package mx.gob.jumapacelaya.ui;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.radiobutton.RadioButtonGroup;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.VaadinSession;
import jakarta.annotation.security.PermitAll;
import java.util.List;
@PermitAll
@PageTitle("Configuración del sistema")
@Route(value = "configuracion", layout = MainLayout.class)
public class ConfiguracionView extends VerticalLayout {
private static final String THEME_LOCALSTORAGE_KEY = "appThemePreference";
private boolean initializing = true;
private final List<ColorOptions> primaryTextColorOptions = List.of(
new ColorOptions("Big Dip O´Ruby", "#A02142"),
new ColorOptions("Claret", "#691B31"),
new ColorOptions("Aztec Gold", "#BC955B"),
new ColorOptions("Lion", "#DDC9A3"),
new ColorOptions("Nickel", "#6F7271")
);
private final List<ColorOptions> primaryColorOptions = List.of(
new ColorOptions("Big Dip O´Ruby", "#A02142"),
new ColorOptions("Claret", "#691B31"),
new ColorOptions("Aztec Gold", "#BC955B"),
new ColorOptions("Lion", "#DDC9A3"),
new ColorOptions("Nickel", "#6F7271")
);
public ConfiguracionView() {
setSpacing(true);
add(new H2("⚙\uFE0F Configuración del Sistema"));
loadCssVariablesFromLocalStorage();
RadioButtonGroup<String> themeSelector = createThemeSelector();
ComboBox<ColorOptions> primaryColor = createColorCombo(
"Color primario",
"--lumo-primary-color",
primaryColorOptions
);
ComboBox<ColorOptions> primaryTextColor = createColorCombo(
"Color de textos",
"--lumo-primary-text-color",
primaryTextColorOptions
);
HorizontalLayout row1 = new HorizontalLayout(themeSelector);
HorizontalLayout row2 = new HorizontalLayout(primaryColor, primaryTextColor);
VerticalLayout layoutPadre = new VerticalLayout(row1, row2);
layoutPadre.getStyle()
.set("border-radius", "10px")
.set("box-shadow", "0 4px 8px rgba(0, 0, 0, 0.2)");
add(layoutPadre);
UI.getCurrent().getPage().executeJs("return true;")
.then(Boolean.class, ok -> initializing = false);
}
/* -------------------- THEME -------------------- */
private RadioButtonGroup<String> createThemeSelector() {
RadioButtonGroup<String> selector = new RadioButtonGroup<>("Modo de interfaz");
selector.setItems("Claro", "Oscuro");
UI.getCurrent().getPage().executeJs(
"return localStorage.getItem($0)", THEME_LOCALSTORAGE_KEY
).then(String.class, theme ->
selector.setValue("dark".equals(theme) ? "Oscuro" : "Claro")
);
selector.addValueChangeListener(e -> {
if (initializing) return;
boolean dark = "Oscuro".equals(e.getValue());
UI.getCurrent().getPage().executeJs(
dark
? "document.documentElement.setAttribute('theme','dark')"
: "document.documentElement.removeAttribute('theme')"
);
UI.getCurrent().getPage().executeJs(
"localStorage.setItem($0,$1)",
THEME_LOCALSTORAGE_KEY,
dark ? "dark" : "light"
);
});
return selector;
}
/* -------------------- COLORS -------------------- */
private ComboBox<ColorOptions> createColorCombo(
String label,
String cssVariable,
List<ColorOptions> options
) {
ComboBox<ColorOptions> combo = new ComboBox<>(label);
combo.setItems(options);
combo.setWidth("250px");
combo.setAllowCustomValue(false);
UI.getCurrent().getPage().executeJs(
"return localStorage.getItem($0)",
"config:" + cssVariable
).then(String.class, saved -> {
options.stream()
.filter(o -> o.getHexValue().equalsIgnoreCase(saved))
.findFirst()
.ifPresent(combo::setValue);
});
combo.addValueChangeListener(e -> {
if (initializing || e.getValue() == null) return;
applyCssVariable(cssVariable, e.getValue().getHexValue());
});
combo.setRenderer(colorRenderer());
return combo;
}
private void applyCssVariable(String variable, String value) {
UI.getCurrent().getPage().executeJs(
"""
document.documentElement.style.setProperty($0,$1);
localStorage.setItem($2,$1);
""",
variable,
value,
"config:" + variable
);
}
private void loadCssVariablesFromLocalStorage() {
UI.getCurrent().getPage().executeJs(
"""
['--lumo-primary-color','--lumo-primary-text-color'].forEach(v=>{
const val = localStorage.getItem('config:'+v);
if(val) document.documentElement.style.setProperty(v,val);
});
"""
);
}
/* -------------------- RENDERER -------------------- */
private ComponentRenderer<Div, ColorOptions> colorRenderer() {
return new ComponentRenderer<>(opt -> {
Div wrapper = new Div();
wrapper.getStyle().set("display","flex").set("align-items","center");
Div dot = new Div();
dot.getStyle()
.set("width","14px")
.set("height","14px")
.set("border-radius","50%")
.set("margin-right","8px")
.set("background-color", opt.getHexValue())
.set("border","1px solid var(--lumo-border-color)");
wrapper.add(dot);
wrapper.add(opt.getName());
return wrapper;
});
}
/* -------------------- MODEL -------------------- */
public static class ColorOptions {
private final String name;
private final String hexValue;
public ColorOptions(String name, String hexValue) {
this.name = name;
this.hexValue = hexValue;
}
public String getName() { return name; }
public String getHexValue() { return hexValue; }
@Override
public String toString() {
return name;
}
}
}

+ 14
- 3
src/main/java/mx/gob/jumapacelaya/ui/DetallesMantView.java View File

@ -9,11 +9,15 @@ import java.util.List;
import java.util.Map;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.html.*;
import com.vaadin.flow.component.page.History;
import com.vaadin.flow.server.StreamRegistration;
import com.vaadin.flow.server.StreamResource;
import mx.gob.jumapacelaya.services.EmailService;
import mx.gob.jumapacelaya.services.ReportService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
@ -53,6 +57,8 @@ import mx.gob.jumapacelaya.services.SecurityService;
@CssImport("./themes/sistema-mantenimiento/styles.css")
public class DetallesMantView extends VerticalLayout implements BeforeEnterObserver {
private static final Logger logger = LoggerFactory.getLogger(DetallesMantView.class);
@Value("${app.base-url}")
private String baseUrl;
@ -75,6 +81,7 @@ public class DetallesMantView extends VerticalLayout implements BeforeEnterObser
private final Button btnCancelar;
private final Button btnGuardar;
private final Button btnEnviarEncuesta = new Button("Enviar encuesta", LineAwesomeIcon.ENVELOPE_SOLID.create());
private final Button btnVolverAtras = new Button(LineAwesomeIcon.ARROW_LEFT_SOLID.create());
private int planAnualIdActual;
private int mantenimientoIdActual;
private Dialog confirmDialog;
@ -102,7 +109,6 @@ public class DetallesMantView extends VerticalLayout implements BeforeEnterObser
mainLayout.getStyle()
.set("box-shadow","0 4px 8px rgba(0,0,0,0.2)")
.set("border-radius", "12px")
.set("background-color", "white")
.set("padding", "1rem")
.set("margin", "1rem auto");
@ -197,9 +203,14 @@ public class DetallesMantView extends VerticalLayout implements BeforeEnterObser
gridActualizaciones.addThemeVariants(GridVariant.LUMO_ROW_STRIPES);
History history = UI.getCurrent().getPage().getHistory();
btnVolverAtras.addClickListener(e -> history.back());
btnVolverAtras.addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE);
btnVolverAtras.setTooltipText("Volver a la lista de mantenimientos");
HorizontalLayout botonesHeaderLyt = new HorizontalLayout();
botonesHeaderLyt.setWidthFull();
botonesHeaderLyt.add(btnImprimirRepo, btnEnviarEncuesta);
botonesHeaderLyt.add(btnVolverAtras, btnImprimirRepo, btnEnviarEncuesta);
HorizontalLayout botonesLayout = new HorizontalLayout();
botonesLayout.setWidthFull();
@ -297,7 +308,7 @@ public class DetallesMantView extends VerticalLayout implements BeforeEnterObser
} catch (Exception ex) {
Notification.show("Error al generar el reporte: " + ex.getMessage(), 4000, Notification.Position.MIDDLE)
.addThemeVariants(NotificationVariant.LUMO_ERROR);
ex.printStackTrace();
logger.error("Error al generar el reporte: ", ex);
}
});


+ 27
- 7
src/main/java/mx/gob/jumapacelaya/ui/MainLayout.java View File

@ -1,5 +1,6 @@
package mx.gob.jumapacelaya.ui;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.applayout.AppLayout;
import com.vaadin.flow.component.applayout.DrawerToggle;
import com.vaadin.flow.component.button.Button;
@ -13,12 +14,15 @@ import com.vaadin.flow.component.orderedlayout.Scroller;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.sidenav.SideNav;
import com.vaadin.flow.component.sidenav.SideNavItem;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.server.menu.MenuConfiguration;
import com.vaadin.flow.theme.lumo.LumoUtility;
import mx.gob.jumapacelaya.services.SecurityService;
@CssImport("./themes/sistema-mantenimiento/styles.css")
public class MainLayout extends AppLayout {
public class MainLayout extends AppLayout implements BeforeEnterObserver {
private H2 viewTitle;
private final SecurityService securityService;
@ -45,7 +49,7 @@ public class MainLayout extends AppLayout {
String u = securityService.getAuthenticatedUser();
Span usrNameLabel = new Span(u);
usrNameLabel.getStyle().set("color", "#691b31");
//usrNameLabel.getStyle().set("color", "#691b31");
usrNameLabel.getStyle().set("font-weight", "bold");
usrNameLabel.getStyle().set("font-size", "20px");
@ -70,7 +74,7 @@ public class MainLayout extends AppLayout {
headerLayout.setPadding(true);
headerLayout.setSpacing(false);
headerLayout.setAlignItems(FlexComponent.Alignment.CENTER);
headerLayout.getStyle().set("background-color", "#DDC9A3");
//headerLayout.getStyle().set("background-color", "#DDC9A3");
Image imgLogo = new Image("images/LOGO_900X160.png", "Logo");
imgLogo.setWidthFull();
@ -78,7 +82,7 @@ public class MainLayout extends AppLayout {
headerLayout.add(imgLogo);
Scroller scroller = new Scroller(createNavigation());
scroller.getStyle().set("background-color", "#691b31");
//scroller.getStyle().set("background-color", "#691b31");
addToDrawer(headerLayout, scroller, createFooter());
}
@ -89,9 +93,9 @@ public class MainLayout extends AppLayout {
nav.addItem(new SideNavItem("Plan Anual", PlanAnualView.class, VaadinIcon.CALENDAR.create()));
nav.addItem(new SideNavItem("Listado de Actividades", ActDiariaView.class, VaadinIcon.EDIT.create()));
nav.addItem(new SideNavItem("Mantenimiento Correctivo", MantCorrectivoView.class, VaadinIcon.WRENCH.create()));
nav.getStyle().set("background-color", "white");
nav.addItem(new SideNavItem("Configuración del sistema", ConfiguracionView.class, VaadinIcon.COG.create()));
nav.getStyle().set("border-radius", "5px");
nav.getStyle().set("opacity", "0.9");
return nav;
}
@ -101,9 +105,25 @@ public class MainLayout extends AppLayout {
return layout;
}
private String getCurrentPageTitle() {
return MenuConfiguration.getPageHeader(getContent()).orElse("");
}
@Override
protected void afterNavigation() {
super.afterNavigation();
viewTitle.setText("Mantenimiento de Hardware");
viewTitle.setText(getCurrentPageTitle());
}
@Override
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
UI.getCurrent().getPage().executeJs("""
const theme = localStorage.getItem('appThemePreference');
if (theme === 'dark') {
document.documentElement.setAttribute('theme', 'dark');
} else {
document.documentElement.removeAttribute('theme');
}
""");
}
}

+ 6
- 8
src/main/java/mx/gob/jumapacelaya/ui/MantCorrectivoView.java View File

@ -1,6 +1,5 @@
package mx.gob.jumapacelaya.ui;
import com.vaadin.flow.component.Text;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
@ -24,9 +23,6 @@ import com.vaadin.flow.component.radiobutton.RadioButtonGroup;
import com.vaadin.flow.component.textfield.TextArea;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.function.ValueProvider;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import de.f0rce.signaturepad.SignaturePad;
@ -36,6 +32,8 @@ import mx.gob.jumapacelaya.services.DatabaseService;
import mx.gob.jumapacelaya.services.EmailService;
import mx.gob.jumapacelaya.services.SecurityService;
import mx.gob.jumapacelaya.services.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vaadin.lineawesome.LineAwesomeIcon;
import java.time.LocalDate;
@ -48,6 +46,8 @@ import java.util.*;
@CssImport("./themes/sistema-mantenimiento/styles.css")
public class MantCorrectivoView extends VerticalLayout {
private static final Logger logger = LoggerFactory.getLogger(MantCorrectivoView.class);
private VerticalLayout mainLayout;
private final SecurityService securityService;
private final VerticalLayout controlsLayout;
@ -96,7 +96,6 @@ public class MantCorrectivoView extends VerticalLayout {
headerLayout.getStyle()
.set("box-shadow", "0 4px 8px rgba(0,0,0,0.2)")
.set("border-radius", "10px")
.set("background-color", "white")
.set("padding", "1rem")
.set("margin", "1rem auto");
@ -107,7 +106,6 @@ public class MantCorrectivoView extends VerticalLayout {
mainLayout.getStyle()
.set("box-shadow", "0 4px 8px rgba(0,0,0,0.2)")
.set("border-radius", "12px")
.set("background-color", "white")
.set("padding", "1rem")
.set("margin", "1rem auto");
@ -594,7 +592,7 @@ public class MantCorrectivoView extends VerticalLayout {
} catch (Exception e) {
Notification.show("Error al enviar el correo", 4000, Notification.Position.MIDDLE)
.addThemeVariants(NotificationVariant.LUMO_ERROR);
e.printStackTrace();
logger.error("Error al enviar correo: ", e);
}
// Limpiar campos
@ -624,7 +622,7 @@ public class MantCorrectivoView extends VerticalLayout {
} catch (Exception ex) {
Notification.show("Ocurrio un error inesperado: " + ex.getMessage(), 5000, Notification.Position.MIDDLE)
.addThemeVariants(NotificationVariant.LUMO_ERROR);
ex.printStackTrace();
logger.error("Error al insertar mantenimiento: ", ex);
}
}


+ 7
- 12
src/main/java/mx/gob/jumapacelaya/ui/MantenimientoView.java View File

@ -1,29 +1,24 @@
package mx.gob.jumapacelaya.ui;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.checkbox.CheckboxGroup;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.html.H1;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.notification.NotificationVariant;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.radiobutton.RadioButtonGroup;
import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.component.textfield.TextArea;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.PageTitle;
@ -35,9 +30,8 @@ import mx.gob.jumapacelaya.services.DatabaseService;
import mx.gob.jumapacelaya.services.EmailService;
import mx.gob.jumapacelaya.services.SecurityService;
import mx.gob.jumapacelaya.services.UserService;
import oracle.net.aso.h;
import org.springframework.beans.factory.annotation.Autowired;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vaadin.lineawesome.LineAwesomeIcon;
import java.time.LocalDate;
@ -50,6 +44,8 @@ import java.util.*;
@CssImport("./themes/sistema-mantenimiento/styles.css")
public class MantenimientoView extends VerticalLayout implements BeforeEnterObserver {
private static final Logger logger = LoggerFactory.getLogger(MantenimientoView.class);
private final SecurityService securityService;
private final VerticalLayout controlsLayout;
private final DatabaseService databaseService;
@ -98,7 +94,6 @@ public class MantenimientoView extends VerticalLayout implements BeforeEnterObse
mainLayout.getStyle()
.set("box-shadow","0 4px 8px rgba(0,0,0,0.2)")
.set("border-radius", "12px")
.set("background-color", "white")
.set("padding", "1rem")
.set("margin", "1rem auto");
@ -718,7 +713,7 @@ public class MantenimientoView extends VerticalLayout implements BeforeEnterObse
} catch (Exception e) {
Notification.show("Error al enviar el correo", 4000, Notification.Position.MIDDLE)
.addThemeVariants(NotificationVariant.LUMO_ERROR);
e.printStackTrace();
logger.error("Error al enviar el correo", e);
}
// Limpiar campos
@ -748,7 +743,7 @@ public class MantenimientoView extends VerticalLayout implements BeforeEnterObse
} catch (Exception ex) {
Notification.show("Ocurrio un error inesperado: " + ex.getMessage(), 5000, Notification.Position.MIDDLE)
.addThemeVariants(NotificationVariant.LUMO_ERROR);
ex.printStackTrace();
logger.error("Error al insertar mantenimiento", ex);
}
}


+ 19
- 21
src/main/java/mx/gob/jumapacelaya/ui/PlanAnualView.java View File

@ -1,19 +1,15 @@
package mx.gob.jumapacelaya.ui;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.checkbox.Checkbox;
import com.vaadin.flow.component.checkbox.CheckboxGroup;
import com.vaadin.flow.component.checkbox.CheckboxGroupVariant;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.confirmdialog.ConfirmDialog;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.grid.HeaderRow;
@ -29,12 +25,10 @@ import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.popover.Popover;
import com.vaadin.flow.component.popover.PopoverPosition;
import com.vaadin.flow.component.radiobutton.RadioButtonGroup;
import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.component.upload.Upload;
import com.vaadin.flow.component.upload.receivers.MemoryBuffer;
import com.vaadin.flow.data.provider.ListDataProvider;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.function.ValueProvider;
@ -48,19 +42,20 @@ import mx.gob.jumapacelaya.models.encuestas.MantenimientosSinEncuesta;
import mx.gob.jumapacelaya.services.DatabaseService;
import mx.gob.jumapacelaya.services.EmailService;
import mx.gob.jumapacelaya.services.ReportService;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.vaadin.lineawesome.LineAwesomeIcon;
import java.io.*;
import java.lang.reflect.Array;
import java.sql.Date;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.Year;
import java.time.format.DateTimeFormatter;
@ -75,6 +70,8 @@ import java.util.stream.IntStream;
@CssImport("./themes/sistema-mantenimiento/styles.css")
public class PlanAnualView extends VerticalLayout {
private static final Logger logger = LoggerFactory.getLogger(PlanAnualView.class);
private final EmailService emailService;
@Value("${app.base-url}")
private String baseUrl;
@ -281,7 +278,6 @@ public class PlanAnualView extends VerticalLayout {
if ("PENDIENTE".equalsIgnoreCase(estado)) {
btn = new Button(new Icon(VaadinIcon.EDIT));
btn.setTooltipText("Realizar mantenimiento");
btn.getStyle().set("color", "#A02142");
btn.addClickListener(event -> {
int idPlananual = planAnual.getNumero();
@ -303,7 +299,6 @@ public class PlanAnualView extends VerticalLayout {
} else if ("REALIZADO".equalsIgnoreCase(estado)) {
btn = new Button(new Icon(VaadinIcon.EYE));
btn.setTooltipText("Ver detalles");
btn.getStyle().set("color", "#A02142");
btn.addClickListener(event -> {
int idPlananual = planAnual.getNumero();
@ -714,7 +709,7 @@ public class PlanAnualView extends VerticalLayout {
} catch (Exception ex) {
Notification.show("Error al genrar el reporte: " + ex.getMessage(), 5000, Notification.Position.MIDDLE)
.addThemeVariants(NotificationVariant.LUMO_ERROR);
ex.printStackTrace();
logger.error("Error al generar el reporte", ex);
}
});
@ -928,7 +923,7 @@ public class PlanAnualView extends VerticalLayout {
} catch (Exception ex) {
Notification.show("Error al generar el reporte: " + ex.getMessage(), 5000, Notification.Position.MIDDLE)
.addThemeVariants(NotificationVariant.LUMO_ERROR);
ex.printStackTrace();
logger.error("Error al generar el reporte", ex);
}
});
@ -1080,7 +1075,7 @@ public class PlanAnualView extends VerticalLayout {
private void showEncuestasDialog(String mes, int anio) {
Dialog dialog = new Dialog();
dialog.setWidth("90%");
dialog.setWidth("95%");
dialog.setHeight("90%");
dialog.setHeaderTitle("Encuestas pendientes por enviar...");
@ -1090,17 +1085,18 @@ public class PlanAnualView extends VerticalLayout {
.setAutoWidth(true);
grid.addColumn(item -> item.getFecha().format(DateTimeFormatter.ofPattern("dd/MM/yyyy")))
.setHeader("Fecha");
.setHeader("Fecha")
.setAutoWidth(true);
grid.addColumn(MantenimientosSinEncuesta::getPeriodo)
.setHeader("Periodo");
.setHeader("Periodo")
.setAutoWidth(true);
grid.addColumn(createStatusRender())
.setHeader("Encuesta");
grid.addColumn(MantenimientosSinEncuesta::getDepartamento)
.setHeader("Departamento")
.setAutoWidth(true);
.setHeader("Departamento");
grid.addColumn(MantenimientosSinEncuesta::getNomUsuario)
.setHeader("Usuario")
@ -1124,11 +1120,13 @@ public class PlanAnualView extends VerticalLayout {
});
return btnEnviar;
}).setHeader("Accion");
}).setHeader("Accion")
.setFrozen(true);
List<MantenimientosSinEncuesta> lista = databaseService.getEncuestPendientes(mes, anio);
grid.setItems(lista);
grid.addThemeVariants(GridVariant.LUMO_WRAP_CELL_CONTENT);
dialog.add(grid);
dialog.getFooter().add(new Button("Cerrar", LineAwesomeIcon.TIMES_SOLID.create(), e -> dialog.close()));


+ 0
- 3
src/main/java/mx/gob/jumapacelaya/ui/login/LoginView.java View File

@ -22,9 +22,6 @@ public class LoginView extends VerticalLayout implements BeforeEnterObserver {
private static final Logger log = LoggerFactory.getLogger(LoginView.class);
private final LoginForm login = new LoginForm();
// Usuario local para demostracion
private final String localUser = "admin";
private final String localPassword = "admin";
public LoginView(){


+ 4
- 1
src/main/resources/application.properties View File

@ -1,6 +1,7 @@
server.port=${PORT:8080}
logging.level.org.atmosphere = warn
spring.profiles.active=dev
server.servlet.session.cookie.secure=true
# Launch the default browser when starting the application in development mode
vaadin.launch-browser=true
@ -12,7 +13,9 @@ spring.jpa.defer-datasource-initialization = true
#Configuracion LDAP
spring.ldap.urls=ldap://172.1.0.1:389
spring.ldap.urls=ldap://172.16.0.1:389
spring.ldap.url=ldap://172.16.0.1
spring.ldap.domain=JUMAPACELAYA.GOB.MX
spring.ldap.base=DC=JUMAPACELAYA,DC=GOB,DC=MX
spring.ldap.username=administrator
spring.ldap.password=Dr3na$134%4guA


+ 1
- 1
tsconfig.json View File

@ -10,7 +10,7 @@
"jsx": "react-jsx",
"inlineSources": true,
"module": "esNext",
"target": "es2020",
"target": "es2022",
"moduleResolution": "bundler",
"strict": true,
"skipLibCheck": true,


Loading…
Cancel
Save