From 16c333e7df41420a5be1b4af755aab9b6ae59862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Antonio=20Ram=C3=ADrez=20Galv=C3=A1n?= Date: Tue, 28 May 2024 13:26:13 -0600 Subject: [PATCH] Se agrego la funcion para permitir adjuntar algun archivo a la peticion, ademas de correccion de algunos errores --- .../example/application/api/ApiRedmine.java | 54 ++++++++++- .../CrearnuevoTicketView.java | 96 ++++++++++++------- 2 files changed, 109 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/example/application/api/ApiRedmine.java b/src/main/java/com/example/application/api/ApiRedmine.java index bcfd9ad..d4921d0 100644 --- a/src/main/java/com/example/application/api/ApiRedmine.java +++ b/src/main/java/com/example/application/api/ApiRedmine.java @@ -6,7 +6,10 @@ import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class ApiRedmine { private static final String REDMINE_URL = "http://localhost:3000"; @@ -14,12 +17,25 @@ public class ApiRedmine { public static final Gson GSON = new Gson(); public static String createIssue(Map issueDetails) { + return createIssue(issueDetails, null); + } + + public static String createIssue(Map issueDetails, String fileUploadToken) { Map payload = new HashMap<>(); payload.put("issue", issueDetails); + + if (fileUploadToken != null) { + List> uploads = new ArrayList<>(); + Map fileTokenMap = new HashMap<>(); + fileTokenMap.put("token", fileUploadToken); + uploads.add(fileTokenMap); + payload.put("uploads", uploads); + } + String jsonPayload = GSON.toJson(payload); try { - //Crear la solicitud HTTP POST + // Crear la solicitud HTTP POST HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(REDMINE_URL + "/issues.json")) .header("Content-Type", "application/json") @@ -27,14 +43,14 @@ public class ApiRedmine { .POST(HttpRequest.BodyPublishers.ofString(jsonPayload)) .build(); - //Enviar la solicitud + // Enviar la solicitud HttpClient client = HttpClient.newHttpClient(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); return response.body(); } catch (Exception e) { e.printStackTrace(); - return "Error: "+e.getMessage(); + return "Error: " + e.getMessage(); } } @@ -72,4 +88,34 @@ public class ApiRedmine { } return names; } + + public static String uploadFile(byte[] fileContent, String fileName) { + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(REDMINE_URL + "/uploads.json")) + .header("Content-Type", "application/octet-stream") + .header("X-Redmine-API-Key", API_KEY) + .header("Content-Disposition", "attachment; filename=\"" + fileName + "\"") + .POST(HttpRequest.BodyPublishers.ofByteArray(fileContent)) + .build(); + + try { + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == 201) { + JsonObject jsonResponse = JsonParser.parseString(response.body()).getAsJsonObject(); + return jsonResponse.get("upload").getAsJsonObject().get("token").getAsString(); + } else { + System.err.println("Error en la subida del archivo: " + response.statusCode()); + System.err.println("Response body: " + response.body()); + return null; + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public static String createIssueWithAttachment(Map issueDetails, String fileUploadToken) { + return createIssue(issueDetails, fileUploadToken); + } } 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 e28b5b5..94ada58 100644 --- a/src/main/java/com/example/application/views/crearnuevoticket/CrearnuevoTicketView.java +++ b/src/main/java/com/example/application/views/crearnuevoticket/CrearnuevoTicketView.java @@ -20,95 +20,117 @@ import com.vaadin.flow.component.upload.receivers.MemoryBuffer; import com.vaadin.flow.router.Route; import jakarta.annotation.security.PermitAll; +import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; - -@Route(value="", layout = MainLayout.class) +@Route(value = "", layout = MainLayout.class) @PermitAll public class CrearnuevoTicketView extends VerticalLayout { - public CrearnuevoTicketView() { + private MemoryBuffer buffer; + private Upload uploadFile; - //Combo de los tipos de tickets + public CrearnuevoTicketView() { + // Combo de los tipos de tickets ComboBox tipoTickets = new ComboBox<>("Tipo de ticket"); ApiRedmine api = new ApiRedmine(); List types = api.getTicketTypes(); tipoTickets.setItems(types); - - //Campo de texto para el asunto + // Campo de texto para el asunto TextField asunto = new TextField("Asunto"); asunto.setWidth("700px"); - - //Campo de texto para la descripcion + // Campo de texto para la descripcion TextArea descripcion = new TextArea("Descripcion"); descripcion.setWidth("1000px"); descripcion.setHeight("250px"); - - //Campo para adjuntar archivos - MemoryBuffer buffer = new MemoryBuffer(); - Upload uploadFile = new Upload(); + // Campo para adjuntar archivos + buffer = new MemoryBuffer(); + uploadFile = new Upload(buffer); uploadFile.setUploadButton(new Button("Cargar archivo")); + uploadFile.setMaxFiles(1); + uploadFile.addFailedListener(event -> { + Notification.show("Error al cargar el archivo: " + event.getReason().getMessage(), 5000, Notification.Position.MIDDLE); + }); - - //Respuestas Json para verificar posibles errores al enviar los nuevos tickets no visibles en la interfaz + // Respuestas Json para verificar posibles errores al enviar los nuevos tickets no visibles en la interfaz TextArea jsonOutput = new TextArea("JSON Output"); jsonOutput.setReadOnly(true); TextArea responseField = new TextArea("Response"); responseField.setReadOnly(true); - - //Boton para crear los tickets + // Boton para crear los tickets Button createButton = new Button("Enviar ticket", event -> { Map issueDetails = new HashMap<>(); issueDetails.put("project_id", "proyecto-de-prueba"); issueDetails.put("subject", asunto.getValue()); issueDetails.put("description", descripcion.getValue()); - String response = ApiRedmine.createIssue(issueDetails); - if (response.startsWith("{\"issue\":")) { - //Aqui extraigo el numero del ticket de la respuesta json - JsonObject jsonResponse = JsonParser.parseString(response).getAsJsonObject(); - int issueNumber = jsonResponse.getAsJsonObject("issue").get("id").getAsInt(); - - String notificationMessage = "¡Su ticket se ha enviado corrrectamente! Numero de ticket: #" + issueNumber; - Notification issueNtf = new Notification(notificationMessage, 5000, Notification.Position.MIDDLE); - issueNtf.addThemeVariants(NotificationVariant.LUMO_SUCCESS); - issueNtf.open(); - - //Limpiando los campos - asunto.clear(); - descripcion.clear(); - tipoTickets.clear(); + String fileUploadToken = null; + if (buffer.getFileData() != null) { + try { + byte[] fileContent = buffer.getInputStream().readAllBytes(); + String fileName = buffer.getFileName(); + fileUploadToken = ApiRedmine.uploadFile(fileContent, fileName); + } catch (IOException e) { + Notification.show("Error al cargar el archivo: " + e.getMessage(), 5000, Notification.Position.MIDDLE) + .addThemeVariants(NotificationVariant.LUMO_WARNING); + } + } + + String response; + if (fileUploadToken != null) { + response = ApiRedmine.createIssue(issueDetails, fileUploadToken); } else { - Notification errNtf = Notification.show("Ha ocurrido un error al enviar el ticket: "+response, 5000, Notification.Position.MIDDLE); - errNtf.addThemeVariants(NotificationVariant.LUMO_ERROR); + response = ApiRedmine.createIssue(issueDetails, fileUploadToken); } + handleResponse(response, asunto, descripcion, tipoTickets); }); + createButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); VerticalLayout fieldsLayout = new VerticalLayout(descripcion); fieldsLayout.setAlignItems(Alignment.CENTER); - HorizontalLayout firstFields = new HorizontalLayout(tipoTickets, asunto); - VerticalLayout buttonLayout = new VerticalLayout(createButton); buttonLayout.setAlignItems(Alignment.END); buttonLayout.setMargin(true); - VerticalLayout uploadLayout = new VerticalLayout(uploadFile); add(new H2("Crear nuevo ticket"), firstFields, fieldsLayout, uploadLayout, buttonLayout/*,jsonOutput,responseField*/); } + private void handleResponse(String response, TextField asunto, TextArea descripcion, ComboBox tipoTickets) { + if (response.startsWith("{\"issue\":")) { + JsonObject jsonResponse = JsonParser.parseString(response).getAsJsonObject(); + int issueNumber = jsonResponse.getAsJsonObject("issue").get("id").getAsInt(); + Notification.show("Su ticket se ha enviado correctamente! Numero de ticket: #" + issueNumber, 5000, Notification.Position.MIDDLE) + .addThemeVariants(NotificationVariant.LUMO_SUCCESS); + + resetForm(asunto, descripcion, tipoTickets); + } else { + Notification.show("Ha ocurrido un error al enviar el ticket: " + response, 5000, Notification.Position.MIDDLE) + .addThemeVariants(NotificationVariant.LUMO_ERROR); + } + } - //Metodo para convertir un Map a json usando la libreria GSON + // Metodo para convertir un Map a json usando la libreria GSON private static String mapToJson(Map map) { Gson gson = new Gson(); return gson.toJson(map); } + + // Metodo para resetear el formulario + private void resetForm(TextField asunto, TextArea descripcion, ComboBox tipoTickets) { + asunto.clear(); + descripcion.clear(); + tipoTickets.clear(); + buffer = new MemoryBuffer(); + uploadFile.setReceiver(buffer); + uploadFile.clearFileList(); + } }