diff --git a/.flow-node-tasks.lock b/.flow-node-tasks.lock
deleted file mode 100644
index 3aef278..0000000
--- a/.flow-node-tasks.lock
+++ /dev/null
@@ -1,2 +0,0 @@
-19228
-
diff --git a/pom.xml b/pom.xml
index bcd7a9e..59b0699 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,6 +90,10 @@
slf4j-api
2.0.13
+
+ ch.qos.logback
+ logback-classic
+
@@ -179,7 +183,7 @@
org.apache.maven.plugins
-
+ maven-failsafe-plugin
diff --git a/src/main/bundles/prod.bundle b/src/main/bundles/prod.bundle
new file mode 100644
index 0000000..f5ed287
Binary files /dev/null and b/src/main/bundles/prod.bundle differ
diff --git a/src/main/java/com/example/application/Application.java b/src/main/java/com/example/application/Application.java
index dafa6c7..4aa9fce 100644
--- a/src/main/java/com/example/application/Application.java
+++ b/src/main/java/com/example/application/Application.java
@@ -1,8 +1,11 @@
package com.example.application;
import com.vaadin.flow.component.dependency.JsModule;
+import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.page.AppShellConfigurator;
import com.vaadin.flow.theme.Theme;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
@@ -19,8 +22,27 @@ import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConf
@JsModule("@vaadin/vaadin-lumo-styles/presets/compact.js")
public class Application implements AppShellConfigurator {
+ private static final Logger logger = LoggerFactory.getLogger(Main.class);
+
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
+
+ logger.info("Inicio de la aplicacion");
+
+ conectToService("localhost:8080");
+
+ logger.info("Aplicacion iniciada con exito");
+ }
+
+ private static void conectToService(String url) {
+ logger.debug("Intentando conectar la aplicacion a {} ", url);
+
+ try {
+ Thread.sleep(2000);
+ logger.debug("Conexion exitosa a {}", url);
+ } catch (InterruptedException e) {
+ logger.error("Error en la conexion a {}", url, e);
+ }
}
}
diff --git a/src/main/java/com/example/application/api/RedmineClient.java b/src/main/java/com/example/application/api/RedmineClient.java
index 9a9b8a0..19a4e63 100644
--- a/src/main/java/com/example/application/api/RedmineClient.java
+++ b/src/main/java/com/example/application/api/RedmineClient.java
@@ -12,6 +12,7 @@ import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
/*Esta clase se encarga de obtener los tickets desde redmine
para poder mostrarlo en la vista de visualizacion de tickets*/
@@ -23,10 +24,13 @@ public class RedmineClient {
private static final int PAGE_SIZE = 25;
static String REDMINE_URL;
static String API_KEY;
+ //private final RestTemplate restTemplate;
+
public RedmineClient(String redmineUrl, String apiKey) {
REDMINE_URL = redmineUrl;
API_KEY = apiKey;
+ //this.restTemplate = new RestTemplate();
}
public List getTickets() {
@@ -36,7 +40,7 @@ public class RedmineClient {
while (true) {
HttpRequest request = HttpRequest.newBuilder()
- .uri(URI.create(REDMINE_URL + "/issues.json?limit=" + PAGE_SIZE + "&offset=" + offset))
+ .uri(URI.create(REDMINE_URL + "/issues.json?key=" + PAGE_SIZE + "&offset=" + offset))
.header("Content-Type", "application/json")
.header("X-Redmine-API-Key", API_KEY)
.build();
@@ -60,6 +64,7 @@ public class RedmineClient {
break;
}
}
+ System.out.println("Total tickets obtenidos: " + tickets.size());
return tickets;
}
@@ -73,8 +78,37 @@ public class RedmineClient {
String subject = issue.get("subject").getAsString();
String description = issue.has("description") ? issue.get("description").getAsString() : "";
String status = issue.getAsJsonObject("status").get("name").getAsString();
- tickets.add(new Ticket(id, subject, description, status));
+
+ JsonObject authorJson = issue.getAsJsonObject("author");
+ Ticket.User author = null;
+ if (authorJson != null) {
+ String username = authorJson.get("name").getAsString();
+ author = new Ticket.User(username);
+ }
+ tickets.add(new Ticket(id, subject, description, status, author));
}
return tickets;
}
+
+ public List getTicketsCreatedBy(String username) {
+ List allTickets = getTickets();
+ List filteredTickets = allTickets.stream()
+ .filter(ticket -> ticket.getAuthor() != null && username.equals(ticket.getAuthor().getUsername()))
+ .collect(Collectors.toList());
+ System.out.println("Total de tickets creados por " + username + ": " + filteredTickets.size());
+ return filteredTickets;
+ }
+
+
+ private static class TicketResponse {
+ private List isues;
+
+ public List getIssues() {
+ return isues;
+ }
+
+ public void setIssues(List issues) {
+ this.isues = issues;
+ }
+ }
}
diff --git a/src/main/java/com/example/application/models/Ticket.java b/src/main/java/com/example/application/models/Ticket.java
index 6b662a5..ac27b50 100644
--- a/src/main/java/com/example/application/models/Ticket.java
+++ b/src/main/java/com/example/application/models/Ticket.java
@@ -2,18 +2,22 @@ package com.example.application.models;
/*Esta clase obtiene los detalles de los tickets*/
+
public class Ticket {
private int id;
private String subject;
private String description;
private String status;
+ private User author;
- public Ticket(int id, String subject, String description, String status) {
+ public Ticket(int id, String subject, String description, String status, User author) {
this.id = id;
this.subject = subject;
this.description = description;
this.status = status;
+ this.author = author;
+
}
public int getId() {
@@ -31,4 +35,28 @@ public class Ticket {
public String getStatus() {
return status;
}
+
+ public User getAuthor() {
+ return author;
+ }
+
+ public void setAuthor(User author) {
+ this.author = author;
+ }
+
+ public static class User {
+ private String username;
+
+ public User(String username) {
+ this.username = username;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+ }
}
diff --git a/src/main/java/com/example/application/views/MainLayout.java b/src/main/java/com/example/application/views/MainLayout.java
index 0aee71b..cce994c 100644
--- a/src/main/java/com/example/application/views/MainLayout.java
+++ b/src/main/java/com/example/application/views/MainLayout.java
@@ -2,6 +2,7 @@ package com.example.application.views;
import com.example.application.api.SecurityService;
import com.example.application.views.crearnuevoticket.CrearnuevoTicketView;
+import com.example.application.views.tickets.AllTicketsView;
import com.example.application.views.tickets.MisTicketsView;
import com.vaadin.flow.component.applayout.AppLayout;
import com.vaadin.flow.component.applayout.DrawerToggle;
@@ -84,6 +85,7 @@ public class MainLayout extends AppLayout {
nav.addItem(new SideNavItem("Crear nuevo ticket", CrearnuevoTicketView.class, LineAwesomeIcon.EDIT.create()));
nav.addItem(new SideNavItem("Mis tickets", MisTicketsView.class, LineAwesomeIcon.TICKET_ALT_SOLID.create()));
+ nav.addItem(new SideNavItem("Todos los tickets", AllTicketsView.class, LineAwesomeIcon.TICKET_ALT_SOLID.create()));
return nav;
diff --git a/src/main/java/com/example/application/views/crearnuevoticket/CrearnuevoTicketView.java b/src/main/java/com/example/application/views/crearnuevoticket/CrearnuevoTicketView.java
index 418f0a9..bdf44f3 100644
--- a/src/main/java/com/example/application/views/crearnuevoticket/CrearnuevoTicketView.java
+++ b/src/main/java/com/example/application/views/crearnuevoticket/CrearnuevoTicketView.java
@@ -18,6 +18,7 @@ import com.vaadin.flow.component.textfield.TextArea;
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.router.PageTitle;
import com.vaadin.flow.router.Route;
import jakarta.annotation.security.PermitAll;
@@ -28,6 +29,7 @@ import java.util.Map;
@Route(value = "", layout = MainLayout.class)
@PermitAll
+@PageTitle("Nuevo ticket")
public class CrearnuevoTicketView extends VerticalLayout {
private MemoryBuffer buffer;
diff --git a/src/main/java/com/example/application/views/tickets/AllTicketsView.java b/src/main/java/com/example/application/views/tickets/AllTicketsView.java
new file mode 100644
index 0000000..6b5d463
--- /dev/null
+++ b/src/main/java/com/example/application/views/tickets/AllTicketsView.java
@@ -0,0 +1,79 @@
+package com.example.application.views.tickets;
+
+import com.example.application.api.RedmineClient;
+import com.example.application.api.ServerPrpperties;
+import com.example.application.models.Ticket;
+import com.example.application.views.MainLayout;
+import com.vaadin.flow.component.grid.Grid;
+import com.vaadin.flow.component.html.Span;
+import com.vaadin.flow.component.orderedlayout.VerticalLayout;
+import com.vaadin.flow.data.renderer.ComponentRenderer;
+import com.vaadin.flow.router.PageTitle;
+import com.vaadin.flow.router.Route;
+import com.vaadin.flow.server.auth.AnonymousAllowed;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.List;
+
+@Route(value="tickets", layout = MainLayout.class)
+@AnonymousAllowed
+@PageTitle("Todos los tickets")
+public class AllTicketsView extends VerticalLayout {
+
+ private final RedmineClient redmineClient;
+ private final Grid grid;
+
+ @Autowired
+ public AllTicketsView(ServerPrpperties prpperties) {
+ this.redmineClient = new RedmineClient(prpperties.REDMINE_URL, prpperties.API_KEY);
+ this.grid = new Grid<>(Ticket.class, false);
+
+ grid.addColumn(Ticket::getId).setHeader("No.")
+ .setWidth("4em").setFlexGrow(0);
+ grid.addColumn(Ticket::getSubject).setHeader("Asunto")
+ .setAutoWidth(true).setFlexGrow(1);
+ grid.addColumn(createStatusRender()).setHeader("Estado")
+ .setWidth("7em").setFlexGrow(1);
+ grid.addColumn(Ticket::getDescription).setHeader("Descripción")
+ .setAutoWidth(true).setFlexGrow(1);
+
+
+ // Ajustar tamaño del Grid y Layout
+ grid.setSizeFull();
+ setSizeFull();
+ setPadding(false);
+ setMargin(false);
+ setSpacing(false);
+
+ add(grid);
+ expand(grid);
+
+ loadTickets();
+ }
+
+ private void loadTickets() {
+ List tickets = redmineClient.getTickets();
+ grid.setItems(tickets);
+ }
+
+ private ComponentRenderer createStatusRender() {
+ return new ComponentRenderer<>(ticket -> {
+ Span span = new Span(ticket.getStatus());
+ switch (ticket.getStatus().toLowerCase()) {
+ case "en curso":
+ span.getElement().getStyle().set("color","purple");
+ break;
+ case "comentarios":
+ span.getElement().getStyle().set("color","orange");
+ break;
+ case "resuelta":
+ span.getElement().getStyle().set("color","green");
+ break;
+ default:
+ span.getElement().getStyle().set("color","blue");
+ break;
+ }
+ return span;
+ });
+ }
+}
diff --git a/src/main/java/com/example/application/views/tickets/MisTicketsView.java b/src/main/java/com/example/application/views/tickets/MisTicketsView.java
index d53254c..a770b8d 100644
--- a/src/main/java/com/example/application/views/tickets/MisTicketsView.java
+++ b/src/main/java/com/example/application/views/tickets/MisTicketsView.java
@@ -1,34 +1,44 @@
package com.example.application.views.tickets;
import com.example.application.api.RedmineClient;
+import com.example.application.api.SecurityService;
import com.example.application.api.ServerPrpperties;
import com.example.application.models.Ticket;
import com.example.application.views.MainLayout;
import com.vaadin.flow.component.grid.Grid;
+import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
+import com.vaadin.flow.data.renderer.ComponentRenderer;
+import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.auth.AnonymousAllowed;
+import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Route(value="mytickets", layout = MainLayout.class)
@AnonymousAllowed
+@PageTitle("Mis tickets")
public class MisTicketsView extends VerticalLayout {
private final RedmineClient redmineClient;
private final Grid grid;
+ private final SecurityService securityService;
- public MisTicketsView(ServerPrpperties prpperties) {
+
+ @Autowired
+ public MisTicketsView(ServerPrpperties prpperties, SecurityService securityService) {
this.redmineClient = new RedmineClient(prpperties.REDMINE_URL, prpperties.API_KEY);
this.grid = new Grid<>(Ticket.class, false);
+ this.securityService = securityService;
// Definir columnas en el orden deseado
- grid.addColumn(Ticket::getId).setHeader("NO")
+ grid.addColumn(Ticket::getId).setHeader("No.")
.setWidth("4em").setFlexGrow(0);
grid.addColumn(Ticket::getSubject).setHeader("Asunto")
.setAutoWidth(true).setFlexGrow(1);
- grid.addColumn(Ticket::getStatus).setHeader("Estado")
+ grid.addColumn(createStatusRender()).setHeader("Estado")
.setWidth("7em").setFlexGrow(1);
grid.addColumn(Ticket::getDescription).setHeader("Descripción")
.setAutoWidth(true).setFlexGrow(1);
@@ -44,11 +54,39 @@ public class MisTicketsView extends VerticalLayout {
add(grid);
expand(grid);
- loadTickets();
+ loadTickets(getAuthenticatedUsername());
}
- private void loadTickets() {
- List tickets = redmineClient.getTickets();
+ private void loadTickets(String authenticatedUsername) {
+ List tickets = redmineClient.getTicketsCreatedBy(authenticatedUsername );
+ System.out.println("Tickets para mostrar: " + tickets.size());
grid.setItems(tickets);
}
+
+ private String getAuthenticatedUsername() {
+ String username = securityService.getAuthenticatedUser().getUsername();
+ System.out.println("Usuario autenticado: " + username);
+ return username;
+ }
+
+ private ComponentRenderer createStatusRender() {
+ return new ComponentRenderer<>(ticket -> {
+ Span span = new Span(ticket.getStatus());
+ switch (ticket.getStatus().toLowerCase()) {
+ case "open":
+ span.getElement().getStyle().set("color","green");
+ break;
+ case "closed":
+ span.getElement().getStyle().set("color","red");
+ break;
+ case "in progress":
+ span.getElement().getStyle().set("color","orange");
+ break;
+ default:
+ span.getElement().getStyle().set("color","green");
+ break;
+ }
+ return span;
+ });
+ }
}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 2b907bd..16d91d8 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -13,12 +13,12 @@ spring.jpa.defer-datasource-initialization = true
spring:
ldap:
urls: ldap://172.16.0.1:389
-base: DC=JUMAPACELAYA, DC=GOB, DC=MX
+base: DC=JUMAPACELAYA, DC=GOB, DC=MX
username: administrator
password: Dr3na%134$4guA
####################################################
-redmine.url=http://localhost:3000
-redmine.api_key=cf3be6168e66c99892c6212ea0bc64e8ab1c6848
\ No newline at end of file
+redmine.url=http://localhost:3000/
+redmine.api_key=35164d2320404b66a71df90d514107790bc1aed6
\ No newline at end of file
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 0000000..8e9c833
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+