From 887eaadf81f8e25f8af94a707122ada8c62f78ae Mon Sep 17 00:00:00 2001 From: mramirezg Date: Tue, 25 Mar 2025 12:25:39 -0600 Subject: [PATCH 1/3] Cambios visuales --- src/main/bundles/prod.bundle | Bin 746215 -> 746215 bytes .../gob/jumapacelaya/api/RedmineClient.java | 121 ++++++++++++------ .../mx/gob/jumapacelaya/models/Ticket.java | 25 +++- .../CrearnuevoTicketView.java | 11 +- .../views/tickets/AllTicketsView.java | 37 +++++- .../views/tickets/MisTicketsView.java | 22 +++- src/main/resources/application.properties | 2 +- 7 files changed, 159 insertions(+), 59 deletions(-) diff --git a/src/main/bundles/prod.bundle b/src/main/bundles/prod.bundle index 8a1c77bb1c2e3200d0f54c0ee44f51650af72963..2253e3a768306cb175023cd82303e2acd2cb9ab8 100644 GIT binary patch delta 515 zcmaEURQLH&UETn1W)=|!4h{~6TcITrc}z`-CTKfe_IrP3-MYnmD#UY2swR2{!ayG*@GrAW%mX0}{}gUf9GWK0P6cn`^p2 z5;x!W^^ds9ioqIycAsMcvw+Sk1hb~+$8bwe?}+9W2Z>K#6wU1fW;~DPb^|jEVz_O< z44^_IFk=Z!zvA0yE~sa$ABKH)5e`q~f?If<@NFaZdp=T;sVT zz>Ed)+|gjhzj*FYFe5AhDz!0zI}t1*n#i33X4E8dhkzNE6S>2|4BaHCuGS>(BmllK B#LEBx delta 515 zcmaEURQLH&UETn1W)=|!4h{~6$ja1-ye7;*YNLzRHxRwK@Y@VVFoWku7zcCoiSIxt28u152jaF*c)|?C zEI`b response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() == 200) { - String responseBody = response.body(); + responseBody = response.body(); List 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; - } - - //AQUI OBTENGO LOS TICKETS DESDE REDMINE - public List getTicketsAuthor(RedmineUser user) { - List tickets = new ArrayList<>(); - HttpClient client = HttpClient.newHttpClient(); - int offset = 0; - - while (true) { - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(REDMINE_URL + "/issues.json?key=" + user.getKey() + "&author_id=" + user.getId() + "&offset=" + offset)) - .header("Content-Type", "application/json") - .build(); + // **Imprimir los tickets y sus comentarios** + for (Ticket ticket : pageTickets) { + System.out.println("-------------------------------------------------"); + System.out.println("Ticket ID: " + ticket.getId()); + System.out.println("Asunto: " + ticket.getSubject()); + System.out.println("Descripción: " + ticket.getDescription()); + System.out.println("Estado: " + ticket.getStatus()); + System.out.println("Fecha de creación: " + ticket.getDateCreate()); + + // Imprimir comentarios si existen + if (ticket.getComments() != null && !ticket.getComments().isEmpty()) { + System.out.println("Comentarios:"); + for (String comment : ticket.getComments()) { + System.out.println(" - " + comment); + } + } else { + System.out.println("No hay comentarios."); + } + } - try { - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - if (response.statusCode() == 200) { - String responseBody = response.body(); - List pageTickets = parseTickets(responseBody); - tickets.addAll(pageTickets); if (pageTickets.size() < PAGE_SIZE) { break; } @@ -164,9 +152,32 @@ public class RedmineClient { } } + List comments = new ArrayList<>(); + if (issue.has("journals") && !issue.get("journals").isJsonNull()) { + JsonArray journals = issue.getAsJsonArray("journals"); + for (JsonElement journalElement : journals) { + JsonObject journal = journalElement.getAsJsonObject(); + if (journal.has("notes") && !journal.get("notes").isJsonNull()) { + String note = journal.get("notes").getAsString(); + if (!note.trim().isEmpty()) { + comments.add(note); // Agregar solo comentarios no vacíos + } + } + } + } + + if (comments.isEmpty()) { + System.out.println("No hay comentarios para este ticket."); + } else { + System.out.println("Comentarios:"); + for (String comment : comments) { + System.out.println(" - " + comment); + } + } + // Agrega el ticket a la lista - tickets.add(new Ticket(id, subject, description, status, date != null ? date.toString() : "", trackerId)); + tickets.add(new Ticket(id, subject, description, status, date != null ? date.toString() : "", trackerId, comments)); } } else { System.out.println("La respuesta JSON no contiene la clave 'issues'"); @@ -178,6 +189,42 @@ public class RedmineClient { return tickets; } + //AQUI OBTENGO LOS TICKETS DESDE REDMINE + public List getTicketsAuthor(RedmineUser user) { + List tickets = new ArrayList<>(); + HttpClient client = HttpClient.newHttpClient(); + int offset = 0; + + + while (true) { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(REDMINE_URL + "/issues.json?key=" + user.getKey() + "&author_id=" + user.getId() + "&offset=" + offset)) + .header("Content-Type", "application/json") + .build(); + + try { + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == 200) { + String responseBody = response.body(); + List 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; + } + diff --git a/src/main/java/mx/gob/jumapacelaya/models/Ticket.java b/src/main/java/mx/gob/jumapacelaya/models/Ticket.java index bb4f9f4..bf2c073 100644 --- a/src/main/java/mx/gob/jumapacelaya/models/Ticket.java +++ b/src/main/java/mx/gob/jumapacelaya/models/Ticket.java @@ -4,6 +4,7 @@ package mx.gob.jumapacelaya.models; import java.sql.Date; import java.time.LocalDate; +import java.util.List; public class Ticket { @@ -15,9 +16,12 @@ public class Ticket { private LocalDate dateCreate; private User author; private Integer trackerId; + private List comments; - public Ticket(int id, String subject, String description, String status, String dateCreate, Integer trackerId) { + + + public Ticket(int id, String subject, String description, String status, String dateCreate, Integer trackerId, List comments) { this.id = id; this.subject = subject; this.description = description; @@ -25,6 +29,7 @@ public class Ticket { this.dateCreate = LocalDate.parse(dateCreate); this.author = author; this.trackerId = trackerId; + this.comments = comments; } public int getId() { @@ -86,18 +91,26 @@ public class Ticket { } switch (trackerId) { - case 1,3,4,7: + case 5,7,8,11,12: return "1-2 dias Max"; - case 2,12: + case 2,14,16: return "2 hrs Max"; - case 5: + case 10: return "5 dias aprox."; - case 8,11: + case 15: return "2-6 hrs Max"; - case 9,10: + case 6,13: return "2 hrs Max"; default: return "N/A"; } } + + public List getComments() { + return comments; + } + + public void setComments(List comments) { + this.comments = comments; + } } diff --git a/src/main/java/mx/gob/jumapacelaya/views/crearnuevoticket/CrearnuevoTicketView.java b/src/main/java/mx/gob/jumapacelaya/views/crearnuevoticket/CrearnuevoTicketView.java index f07da99..afaf8eb 100644 --- a/src/main/java/mx/gob/jumapacelaya/views/crearnuevoticket/CrearnuevoTicketView.java +++ b/src/main/java/mx/gob/jumapacelaya/views/crearnuevoticket/CrearnuevoTicketView.java @@ -31,10 +31,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; @Route(value = "", layout = MainLayout.class) @PermitAll @@ -159,13 +156,13 @@ public class CrearnuevoTicketView extends VerticalLayout { tipoTickets.setPlaceholder("Seleccione un tipo de ticket"); Map ticketTypesMap = api.getTicketTypes(); - Set ticketTypesSet = Set.of("Acceso/Permiso/Bajas", "Soporte de Software", "Capacitacion de Software", + /*Set ticketTypesSet = Set.of("Acceso/Permiso/Bajas", "Soporte de Software", "Capacitacion de Software", "Configuracion de Software", "Digitalizacion GIS", "Documento", "Funcionalidad", "Reporte", "Mantenimiento Correctivo", "Desarrollo de Software", "Actividad","Entrega de Consumibles","Instalación/Configuracion GIS"); List filteredTicketTypes = ticketTypesMap.keySet().stream() .filter(ticketTypesSet::contains) - .collect(Collectors.toList()); - tipoTickets.setItems(filteredTicketTypes); + .collect(Collectors.toList());*/ + tipoTickets.setItems(ticketTypesMap.keySet()); tipoTickets.addValueChangeListener(event -> { String selectedType = event.getValue(); @@ -240,7 +237,7 @@ public class CrearnuevoTicketView extends VerticalLayout { issueDetails.put("project_id", "soporte-tecnico-t-i"); issueDetails.put("subject", asunto.getValue()); String areaValue = area.getValue().trim(); - String descriptionCompleta = descripcion.getValue() + ("Area: " + areaValue + "\n\n"); // Concatenamos el valor del campo Area a la descripcion del ticket + String descriptionCompleta = descripcion.getValue() + (" \n" + " Area: " + areaValue + "\n\n"); // Concatenamos el valor del campo Area a la descripcion del ticket issueDetails.put("description", descriptionCompleta); issueDetails.put("tracker_id", selectedTrackerId); diff --git a/src/main/java/mx/gob/jumapacelaya/views/tickets/AllTicketsView.java b/src/main/java/mx/gob/jumapacelaya/views/tickets/AllTicketsView.java index 82d1074..72fca9f 100644 --- a/src/main/java/mx/gob/jumapacelaya/views/tickets/AllTicketsView.java +++ b/src/main/java/mx/gob/jumapacelaya/views/tickets/AllTicketsView.java @@ -6,6 +6,8 @@ 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.Span; +import com.vaadin.flow.component.icon.Icon; +import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.orderedlayout.FlexComponent; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout; @@ -63,9 +65,10 @@ public class AllTicketsView extends VerticalLayout { grid.addColumn(ticket -> ticket.tiempoEst(ticket.getTrackerId())).setHeader("Tiempo estimado de atencion").setAutoWidth(false); grid.addComponentColumn(ticket -> { - Button btnVer = new Button("Ver"); + Button btnVer = new Button("Ver", new Icon(VaadinIcon.EYE)); + btnVer.setTooltipText("Ver descripción"); btnVer.addClickListener(event -> showDescription(ticket)); - btnVer.getStyle().set("color", "#691b31"); + btnVer.getStyle().set("color", "#A02142"); return btnVer; }).setHeader("Descripcion").setAutoWidth(true); @@ -98,11 +101,14 @@ public class AllTicketsView extends VerticalLayout { textEditor.setValue(ticket.getDescription()); textEditor.setReadOnly(true); + Button verNotas = new Button("Comentarios"); + verNotas.addClickListener(event -> showComents(ticket)); + Button closeButton = new Button("Cerrar"); closeButton.addThemeVariants(ButtonVariant.LUMO_ERROR); closeButton.addClickListener(e -> dialog.close()); - HorizontalLayout buttonLayout = new HorizontalLayout(closeButton); + HorizontalLayout buttonLayout = new HorizontalLayout(verNotas, closeButton); buttonLayout.setWidthFull(); buttonLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.END); buttonLayout.add(closeButton); @@ -112,6 +118,31 @@ public class AllTicketsView extends VerticalLayout { dialog.open(); } + private void showComents(Ticket ticket) { + Dialog comentDialog = new Dialog(); + comentDialog.getElement().setAttribute("arial-label", "Add note"); + comentDialog.setMaxHeight("500px"); + comentDialog.setMaxWidth("1100px"); + + VerticalLayout layout = new VerticalLayout(); + + List comments = ticket.getComments(); // Obtiene los comentarios + boolean hasComments = comments != null && !comments.isEmpty(); + + if (hasComments) { + for (String comment : comments) { + if (comment != null && !comment.trim().isEmpty()) { + layout.add(new Span(comment)); // Agrega cada comentario + } + } + } else { + layout.add(new Span("No hay comentarios disponibles.")); // Mensaje si no hay comentarios + } + + comentDialog.add(layout); + comentDialog.open(); + } + private void loadTickets() { try { List tickets = redmineClient.getTickets(userService.getRedmineUser(), true); diff --git a/src/main/java/mx/gob/jumapacelaya/views/tickets/MisTicketsView.java b/src/main/java/mx/gob/jumapacelaya/views/tickets/MisTicketsView.java index 077c076..9b4f294 100644 --- a/src/main/java/mx/gob/jumapacelaya/views/tickets/MisTicketsView.java +++ b/src/main/java/mx/gob/jumapacelaya/views/tickets/MisTicketsView.java @@ -6,6 +6,8 @@ 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.Span; +import com.vaadin.flow.component.icon.Icon; +import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.orderedlayout.FlexComponent; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout; @@ -68,9 +70,10 @@ public class MisTicketsView extends VerticalLayout { grid.addColumn(ticket -> ticket.tiempoEst(ticket.getTrackerId())).setHeader("Tiempo estimado de atencion").setAutoWidth(false); grid.addComponentColumn(ticket -> { - Button btnVer = new Button("Ver"); + Button btnVer = new Button("Ver", new Icon(VaadinIcon.EYE)); + btnVer.setTooltipText("Ver descripción"); btnVer.addClickListener(event -> showDescription(ticket)); - btnVer.getStyle().set("color", "#691b31"); + btnVer.getStyle().set("color", "#A02142"); return btnVer; }).setHeader("Descripcion").setAutoWidth(true); @@ -132,13 +135,22 @@ public class MisTicketsView extends VerticalLayout { Span span = new Span(ticket.getStatus()); switch (ticket.getStatus().toLowerCase()) { case "análisis": - span.getElement().getStyle().set("color","purple"); + span.getElement().getStyle().set("color","orange"); break; case "desarrollo": - span.getElement().getStyle().set("color","green"); + span.getElement().getStyle().set("color","blue"); + break; + case "rechazada": + span.getElement().getStyle().set("color","red"); + break; + case "cerrada": + span.getElement().getStyle().set("color","grey"); + break; + case "solicitado": + span.getElement().getStyle().set("color","purple"); break; default: - span.getElement().getStyle().set("color","blue"); + span.getElement().getStyle().set("color","green"); break; } return span; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 68c14c2..4e1161b 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -19,7 +19,7 @@ spring.ldap.password=Dr3na$134%4guA ########PRODUCTIVO################################# redmine.url=https://proyman.jumapacelaya.gob.mx/ -redmine.api_key=98158784609a110b3f9e837ac961d73b9ec58271 +redmine.api_key=69be2a5df9bacce02722f566fdf0731d728a1b86 ########LOCAL###################################### From 94ca8c4034931ffc17fdf4b1887ea3c1bcb84f49 Mon Sep 17 00:00:00 2001 From: mramirezg Date: Fri, 28 Mar 2025 15:25:15 -0600 Subject: [PATCH 2/3] Correcion del login que hace que no permita acceder y los devuelve al login --- .../gob/jumapacelaya/api/SecurityConfig.java | 22 ++++++++++--------- .../mx/gob/jumapacelaya/models/Journals.java | 4 ++++ .../jumapacelaya/services/UserService.java | 12 ++++++---- src/main/resources/application.properties | 2 +- 4 files changed, 25 insertions(+), 15 deletions(-) create mode 100644 src/main/java/mx/gob/jumapacelaya/models/Journals.java diff --git a/src/main/java/mx/gob/jumapacelaya/api/SecurityConfig.java b/src/main/java/mx/gob/jumapacelaya/api/SecurityConfig.java index fb692aa..a429a78 100644 --- a/src/main/java/mx/gob/jumapacelaya/api/SecurityConfig.java +++ b/src/main/java/mx/gob/jumapacelaya/api/SecurityConfig.java @@ -49,20 +49,22 @@ public class SecurityConfig extends VaadinWebSecurity { ) .formLogin(formLogin -> formLogin .loginPage("/login") - /*.successHandler((request, response, authentication) -> { - //String username = authentication.getName(); + .successHandler((request, response, authentication) -> { + String username = authentication.getName(); log.debug("Configure:loginSuccess: {}", authentication.getName()); - if (userService.getAuthenticatedRedmineUser() == null) { - log.debug("Configure:getAuthenticatedRedmineUser Error: {}", authentication.getName()); - response.sendRedirect("/login"); - } //else { - //response.sendRedirect(""); - //} - })*/ + var user = userService.getAuthenticatedRedmineUser(); + log.debug("Authenticated user: {}", user); + + if (user == null) { + log.warn("Usuario autenticado pero no encontrado en Redmine. Redirigiendo a página de error."); + response.sendRedirect(""); + } else { + response.sendRedirect(""); + } + }) .failureUrl("/login?error=true") // Corrigiendo la URL de fallo ); super.configure(http); - setLoginView(http, LoginView.class); } diff --git a/src/main/java/mx/gob/jumapacelaya/models/Journals.java b/src/main/java/mx/gob/jumapacelaya/models/Journals.java new file mode 100644 index 0000000..b6d0824 --- /dev/null +++ b/src/main/java/mx/gob/jumapacelaya/models/Journals.java @@ -0,0 +1,4 @@ +package mx.gob.jumapacelaya.models; + +public class Journals { +} diff --git a/src/main/java/mx/gob/jumapacelaya/services/UserService.java b/src/main/java/mx/gob/jumapacelaya/services/UserService.java index f8d12a1..b042bb2 100644 --- a/src/main/java/mx/gob/jumapacelaya/services/UserService.java +++ b/src/main/java/mx/gob/jumapacelaya/services/UserService.java @@ -1,5 +1,7 @@ package mx.gob.jumapacelaya.services; +import com.vaadin.flow.component.notification.Notification; +import com.vaadin.flow.component.notification.NotificationVariant; import com.vaadin.flow.server.VaadinService; import mx.gob.jumapacelaya.api.RedmineClient; import mx.gob.jumapacelaya.api.SecurityService; @@ -39,8 +41,8 @@ public class UserService { CustomUserDetails userDetails = ldapService.getUserDetails(username); if (userDetails != null) { if (userDetails.getEmail() == null || userDetails.getEmail().isEmpty()) { - logger.error("El usuario: " + username + " no tiene correo electronico."); - return null; + logger.warn("El usuario {} no tiene correo electrónico. Asignando uno por defecto.", username); + userDetails.setEmail(username + "@jumapacelaya.gob.mx"); // Asigna un correo por defecto } RedmineUser newUser = RedmineClient.createRedmineUser( username, @@ -48,6 +50,7 @@ public class UserService { userDetails.getLastName(), userDetails.getEmail() ); + if (newUser != null) { logger.info("Usuario creado en Redmine: " + newUser); return newUser; @@ -89,8 +92,9 @@ public class UserService { } } }else{ - logger.error("No se pudo obtener al usuario autenticado en Redmine"); - securityService.logout(); + logger.error("No se pudo obtener al usuario autenticado en Redmine. Permitiendo acceso limitado"); + Notification.show("No se pudo obtener al usuario autenticado en Redmine. Permitiendo acceso limitado") + .addThemeVariants(NotificationVariant.LUMO_WARNING); } } return userclient; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 4e1161b..5997237 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -34,4 +34,4 @@ spring.servlet.multipart.max-request-size=10MB ##############TIEMPO DE DURACION DE LA SESION################# server.servlet.session.timeout=30m -vaadin.session.expiration=30m +server.servlet.session.cookie.secure=true From 5a40585bb4350cab9b55c8b8e5a1b112ebf097a6 Mon Sep 17 00:00:00 2001 From: mramirezg Date: Sat, 29 Mar 2025 22:01:33 -0600 Subject: [PATCH 3/3] Se agrego un boton en el dialog de las descripciones que muestra los comentarios que se han hecho en el ticket --- .../gob/jumapacelaya/api/RedmineClient.java | 86 +++++++++---------- .../mx/gob/jumapacelaya/models/Journals.java | 4 - .../mx/gob/jumapacelaya/models/Ticket.java | 2 +- .../views/tickets/AllTicketsView.java | 31 ++++--- .../views/tickets/MisTicketsView.java | 38 +++++++- 5 files changed, 98 insertions(+), 63 deletions(-) delete mode 100644 src/main/java/mx/gob/jumapacelaya/models/Journals.java diff --git a/src/main/java/mx/gob/jumapacelaya/api/RedmineClient.java b/src/main/java/mx/gob/jumapacelaya/api/RedmineClient.java index 7cf4061..fdf682f 100644 --- a/src/main/java/mx/gob/jumapacelaya/api/RedmineClient.java +++ b/src/main/java/mx/gob/jumapacelaya/api/RedmineClient.java @@ -48,13 +48,11 @@ public class RedmineClient { // Si includeClose es true, incluira todos los tikets si no, incluira solo los que estan abiertos String statusFilter = includeClosed ? "&status_id=*" : "&status_id=open"; - String includeJournals = "&include=journals"; // <-- Agregar los journals (comentarios/Notas) - String responseBody = null; while (true) { HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(REDMINE_URL + "/issues.json?key=" + user.getKey() + statusFilter + includeJournals + "&offset=" + offset)) + .uri(URI.create(REDMINE_URL + "/issues.json?key=" + user.getKey() + statusFilter + "&offset=" + offset)) .header("Content-Type", "application/json") .build(); @@ -65,26 +63,6 @@ public class RedmineClient { List pageTickets = parseTickets(responseBody); tickets.addAll(pageTickets); - // **Imprimir los tickets y sus comentarios** - for (Ticket ticket : pageTickets) { - System.out.println("-------------------------------------------------"); - System.out.println("Ticket ID: " + ticket.getId()); - System.out.println("Asunto: " + ticket.getSubject()); - System.out.println("Descripción: " + ticket.getDescription()); - System.out.println("Estado: " + ticket.getStatus()); - System.out.println("Fecha de creación: " + ticket.getDateCreate()); - - // Imprimir comentarios si existen - if (ticket.getComments() != null && !ticket.getComments().isEmpty()) { - System.out.println("Comentarios:"); - for (String comment : ticket.getComments()) { - System.out.println(" - " + comment); - } - } else { - System.out.println("No hay comentarios."); - } - } - if (pageTickets.size() < PAGE_SIZE) { break; } @@ -152,32 +130,10 @@ public class RedmineClient { } } - List comments = new ArrayList<>(); - if (issue.has("journals") && !issue.get("journals").isJsonNull()) { - JsonArray journals = issue.getAsJsonArray("journals"); - for (JsonElement journalElement : journals) { - JsonObject journal = journalElement.getAsJsonObject(); - if (journal.has("notes") && !journal.get("notes").isJsonNull()) { - String note = journal.get("notes").getAsString(); - if (!note.trim().isEmpty()) { - comments.add(note); // Agregar solo comentarios no vacíos - } - } - } - } - - if (comments.isEmpty()) { - System.out.println("No hay comentarios para este ticket."); - } else { - System.out.println("Comentarios:"); - for (String comment : comments) { - System.out.println(" - " + comment); - } - } // Agrega el ticket a la lista - tickets.add(new Ticket(id, subject, description, status, date != null ? date.toString() : "", trackerId, comments)); + tickets.add(new Ticket(id, subject, description, status, date != null ? date.toString() : "", trackerId)); } } else { System.out.println("La respuesta JSON no contiene la clave 'issues'"); @@ -486,4 +442,42 @@ public class RedmineClient { return null; } } + + public List getTicketComments(int ticketId, RedmineUser user) { + List comments = new ArrayList<>(); + HttpClient client = HttpClient.newHttpClient(); + + String url = REDMINE_URL + "/issues/" + ticketId + ".json?include=journals&key=" + user.getKey(); + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(url)) + .header("Content-Type", "application/json") + .build(); + + try { + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + if (response.statusCode() == 200) { + String responseBody = response.body(); + JsonObject jsonResponse = JsonParser.parseString(responseBody).getAsJsonObject(); + JsonArray journals = jsonResponse.getAsJsonObject("issue").getAsJsonArray("journals"); + + for (JsonElement journalElement : journals) { + JsonObject journal = journalElement.getAsJsonObject(); + if (journal.has("notes") && !journal.get("notes").isJsonNull()) { + String note = journal.get("notes").getAsString().trim(); + if (!note.isEmpty()) { + comments.add(note); + } + } + } + } else { + System.err.println("Error en la respuesta al obtener los comentarios: " + response.statusCode()); + } + } catch (Exception e) { + e.printStackTrace(); + } + return comments; + } + } diff --git a/src/main/java/mx/gob/jumapacelaya/models/Journals.java b/src/main/java/mx/gob/jumapacelaya/models/Journals.java deleted file mode 100644 index b6d0824..0000000 --- a/src/main/java/mx/gob/jumapacelaya/models/Journals.java +++ /dev/null @@ -1,4 +0,0 @@ -package mx.gob.jumapacelaya.models; - -public class Journals { -} diff --git a/src/main/java/mx/gob/jumapacelaya/models/Ticket.java b/src/main/java/mx/gob/jumapacelaya/models/Ticket.java index bf2c073..cc825f7 100644 --- a/src/main/java/mx/gob/jumapacelaya/models/Ticket.java +++ b/src/main/java/mx/gob/jumapacelaya/models/Ticket.java @@ -21,7 +21,7 @@ public class Ticket { - public Ticket(int id, String subject, String description, String status, String dateCreate, Integer trackerId, List comments) { + public Ticket(int id, String subject, String description, String status, String dateCreate, Integer trackerId) { this.id = id; this.subject = subject; this.description = description; diff --git a/src/main/java/mx/gob/jumapacelaya/views/tickets/AllTicketsView.java b/src/main/java/mx/gob/jumapacelaya/views/tickets/AllTicketsView.java index 72fca9f..c75c9cd 100644 --- a/src/main/java/mx/gob/jumapacelaya/views/tickets/AllTicketsView.java +++ b/src/main/java/mx/gob/jumapacelaya/views/tickets/AllTicketsView.java @@ -101,6 +101,7 @@ public class AllTicketsView extends VerticalLayout { textEditor.setValue(ticket.getDescription()); textEditor.setReadOnly(true); + Button verNotas = new Button("Comentarios"); verNotas.addClickListener(event -> showComents(ticket)); @@ -120,25 +121,33 @@ public class AllTicketsView extends VerticalLayout { private void showComents(Ticket ticket) { Dialog comentDialog = new Dialog(); - comentDialog.getElement().setAttribute("arial-label", "Add note"); + comentDialog.getElement().setAttribute("arial-label", "Comentarios del ticket"); comentDialog.setMaxHeight("500px"); comentDialog.setMaxWidth("1100px"); VerticalLayout layout = new VerticalLayout(); - - List comments = ticket.getComments(); // Obtiene los comentarios - boolean hasComments = comments != null && !comments.isEmpty(); - - if (hasComments) { - for (String comment : comments) { - if (comment != null && !comment.trim().isEmpty()) { - layout.add(new Span(comment)); // Agrega cada comentario - } + layout.setPadding(true); + layout.setSpacing(true); + + // Obtenemos los comentarios desde Proyman + List comentarios = redmineClient.getTicketComments(ticket.getId(), userService.getRedmineUser()); + + if (comentarios != null && !comentarios.isEmpty()) { + for (String comentario : comentarios) { + Span commentSpan = new Span(comentario); + commentSpan.getElement().getStyle().set("background", "#f1f1f1"); + commentSpan.getElement().getStyle().set("padding", "10px"); + commentSpan.getElement().getStyle().set("border-radius", "5px"); + layout.add(commentSpan); } } else { - layout.add(new Span("No hay comentarios disponibles.")); // Mensaje si no hay comentarios + layout.add(new Span("No hay comentarios para este ticket.")); } + Button closeButton = new Button("Cerrar", event -> comentDialog.close()); + closeButton.addThemeVariants(ButtonVariant.LUMO_ERROR); + + layout.add(closeButton); comentDialog.add(layout); comentDialog.open(); } diff --git a/src/main/java/mx/gob/jumapacelaya/views/tickets/MisTicketsView.java b/src/main/java/mx/gob/jumapacelaya/views/tickets/MisTicketsView.java index 9b4f294..5ef122c 100644 --- a/src/main/java/mx/gob/jumapacelaya/views/tickets/MisTicketsView.java +++ b/src/main/java/mx/gob/jumapacelaya/views/tickets/MisTicketsView.java @@ -105,11 +105,14 @@ public class MisTicketsView extends VerticalLayout { textEditor.setValue(ticket.getDescription()); textEditor.setReadOnly(true); + Button verNotas = new Button("Comentarios"); + verNotas.addClickListener(event -> showComents(ticket)); + Button closeButton = new Button("Cerrar"); closeButton.addThemeVariants(ButtonVariant.LUMO_ERROR); closeButton.addClickListener(e -> dialog.close()); - HorizontalLayout buttonLayout = new HorizontalLayout(closeButton); + HorizontalLayout buttonLayout = new HorizontalLayout(verNotas, closeButton); buttonLayout.setWidthFull(); buttonLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.END); buttonLayout.add(closeButton); @@ -119,6 +122,39 @@ public class MisTicketsView extends VerticalLayout { dialog.open(); } + private void showComents(Ticket ticket) { + Dialog comentDialog = new Dialog(); + comentDialog.getElement().setAttribute("arial-label", "Comentarios del ticket"); + comentDialog.setMaxHeight("500px"); + comentDialog.setMaxWidth("1100px"); + + VerticalLayout layout = new VerticalLayout(); + layout.setPadding(true); + layout.setSpacing(true); + + // Obtenemos los comentarios desde Proyman + List comentarios = redmineClient.getTicketComments(ticket.getId(), userService.getRedmineUser()); + + if (comentarios != null && !comentarios.isEmpty()) { + for (String comentario : comentarios) { + Span commentSpan = new Span(comentario); + commentSpan.getElement().getStyle().set("background", "#f1f1f1"); + commentSpan.getElement().getStyle().set("padding", "10px"); + commentSpan.getElement().getStyle().set("border-radius", "5px"); + layout.add(commentSpan); + } + } else { + layout.add(new Span("No hay comentarios para este ticket.")); + } + + Button closeButton = new Button("Cerrar", event -> comentDialog.close()); + closeButton.addThemeVariants(ButtonVariant.LUMO_ERROR); + + layout.add(closeButton); + comentDialog.add(layout); + comentDialog.open(); + } + private void loadTickets() { try { List tickets = redmineClient.getTicketsAuthor(userService.getRedmineUser());