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 3ca5d2b..8f882dd 100644 --- a/src/main/java/mx/gob/jumapacelaya/views/crearnuevoticket/CrearnuevoTicketView.java +++ b/src/main/java/mx/gob/jumapacelaya/views/crearnuevoticket/CrearnuevoTicketView.java @@ -33,8 +33,6 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -import static org.atmosphere.annotation.AnnotationUtil.logger; - @Route(value = "", layout = MainLayout.class) @PermitAll @PageTitle("Nuevo ticket") @@ -50,15 +48,44 @@ public class CrearnuevoTicketView extends VerticalLayout { this.api = api; this.userService = service; this.buffer = new MultiFileMemoryBuffer(); - this.uploadFile = new Upload(buffer); - this.uploadFile.setMaxFiles(5); //Numero maximo de archivos permitido - this.uploadFile.setDropAllowed(true); - this.uploadFile.setAcceptedFileTypes("image/jpeg", "image/png", "application/pdf", "image/gif", "image/svg", "text/plain", - "application/zip", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); //Tipos de archivos permitidos + this.uploadFile = createUploadComponent(); RedmineUser user = userService.getRedmineUser(); + ComboBox tipoTickets = createTicketTypeComboBox(); + TextField asunto = createTextField("Asunto", "700px"); + TextArea descripcion = createTextArea("Descripcion", "1000px", "250px"); + + // Marcar campos como obligatorios + tipoTickets.setRequiredIndicatorVisible(true); + asunto.setRequiredIndicatorVisible(true); + descripcion.setRequiredIndicatorVisible(true); + + uploadFile.addSucceededListener(event -> handleFileUpload(event.getFileName())); + + Button createButton = new Button("Enviar ticket", event -> handleCreateButton(user, tipoTickets, asunto, descripcion)); + + createButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + + VerticalLayout fieldsLayout = new VerticalLayout(descripcion, uploadFile); + fieldsLayout.setAlignItems(Alignment.CENTER); + HorizontalLayout firstFields = new HorizontalLayout(tipoTickets, asunto); + VerticalLayout buttonLayout = new VerticalLayout(createButton); + buttonLayout.setAlignItems(Alignment.END); + buttonLayout.setMargin(true); + + add(new H2("Crear nuevo ticket"), firstFields, fieldsLayout, buttonLayout); + } + + private Upload createUploadComponent() { + MultiFileMemoryBuffer buffer = new MultiFileMemoryBuffer(); + Upload uploadFile = new Upload(buffer); + uploadFile.setMaxFiles(5); + uploadFile.setDropAllowed(true); + uploadFile.setAcceptedFileTypes("image/jpeg", "image/png", "application/pdf", "image/gif", "image/svg", "text/plain", + "application/zip", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + UploadI18N i18N = new UploadI18N(); UploadI18N.Uploading uploading = i18N.getUploading(); if (uploading == null) { @@ -72,128 +99,107 @@ public class CrearnuevoTicketView extends VerticalLayout { uploading.setError(error); } - error.setUnexpectedServerError("No se pudo cargar el archivo. Por favor, intentalo de nuevo"); error.setServerUnavailable("El archivo es demasiado grande. El tamaño máximo permitido es de 10 MB."); error.setForbidden("Archivo no permitido"); - uploadFile.setI18n(i18N); + return uploadFile; + } - // ComboBox para los tipos de tickets + private ComboBox createTicketTypeComboBox() { ComboBox tipoTickets = new ComboBox<>("Tipo de ticket"); + tipoTickets.setPlaceholder("Seleccione un tipo de ticket"); + Map ticketTypesMap = api.getTicketTypes(); - Set ticketTypesSet = Set.of("Acceso/Permiso/Bajas","Soporte de Software", "Capacitacion de Software","Configuracion de Software", - "Digitalizacion GIS","Documento","Funcionalidad","Reporte","Soporte o Mantenimiento"); + Set ticketTypesSet = Set.of("Acceso/Permiso/Bajas", "Soporte de Software", "Capacitacion de Software", + "Configuracion de Software", "Digitalizacion GIS", "Documento", "Funcionalidad", "Reporte", + "Soporte o Mantenimiento"); List filteredTicketTypes = ticketTypesMap.keySet().stream() - .filter(ticketTypesSet::contains) - .toList(); + .filter(ticketTypesSet::contains) + .collect(Collectors.toList()); tipoTickets.setItems(filteredTicketTypes); tipoTickets.addValueChangeListener(event -> selectedTrackerId = ticketTypesMap.get(event.getValue())); + return tipoTickets; + } - // Campo de texto para el asunto - TextField asunto = new TextField("Asunto"); - asunto.setWidth("700px"); - - // Campo de texto para la descripcion - TextArea descripcion = new TextArea("Descripcion"); - descripcion.setWidth("1000px"); - descripcion.setHeight("250px"); - - // Listener para manejar el evento de subida exitosa de archivos - uploadFile.addSucceededListener(event -> { - String fileName = event.getFileName(); - InputStream inputStream = buffer.getInputStream(fileName); - - if (fileName != null && inputStream != null) { - try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { - byte[] bufferArray = new byte[1024]; - int bytesRead; - while ((bytesRead = inputStream.read(bufferArray)) != -1) { - outputStream.write(bufferArray, 0, bytesRead); - } - byte[] fileContent = outputStream.toByteArray(); - - } catch (IOException e) { - Notification.show("Error al leer el archivo: " + e.getMessage(), 3000, Notification.Position.MIDDLE); - logger.error("Error al leer el archivo: " + e.getMessage()); - } finally { - try { - inputStream.close(); - } catch (IOException e) { - Notification.show("Error al cerrar el InputStream: " + e.getMessage()) - .addThemeVariants(NotificationVariant.LUMO_ERROR); - } - } - } else { - Notification.show("Error: Nombre de archivo o contenido nulos", 3000, Notification.Position.MIDDLE); - logger.error("Error: Nombre de archivo o contenido nulos"); - } - }); + private TextField createTextField(String label, String width) { + TextField textField = new TextField(label); + textField.setWidth(width); + return textField; + } + private TextArea createTextArea(String label, String width, String height) { + TextArea textArea = new TextArea(label); + textArea.setWidth(width); + textArea.setHeight(height); + return textArea; + } - // Boton para crear los tickets - Button createButton = new Button("Enviar ticket", event -> { - if (user.getKey() == null || user.getKey().isEmpty()) { - Notification.show("No se encontró la API key en la sesión.", 5000, Notification.Position.MIDDLE) - .addThemeVariants(NotificationVariant.LUMO_ERROR); - return; - } + private void handleFileUpload(String fileName) { + try (InputStream inputStream = buffer.getInputStream(fileName); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { - // Obtener el tipo de ticket seleccionado - if (selectedTrackerId == null) { - Notification.show("Por favor seleccione un tipo de ticket.", 3000, Notification.Position.MIDDLE) - .addThemeVariants(NotificationVariant.LUMO_WARNING); - return; + byte[] bufferArray = new byte[1024]; + int bytesRead; + while ((bytesRead = inputStream.read(bufferArray)) != -1) { + outputStream.write(bufferArray, 0, bytesRead); } + } catch (IOException e) { + Notification.show("Error al leer el archivo: " + e.getMessage(), 3000, Notification.Position.MIDDLE) + .addThemeVariants(NotificationVariant.LUMO_ERROR); + } + } - Map issueDetails = new HashMap<>(); - issueDetails.put("project_id", "soporte-tecnico-t-i"); - issueDetails.put("subject", asunto.getValue()); - issueDetails.put("description", descripcion.getValue()); - issueDetails.put("tracker_id", selectedTrackerId); // Añadir el tracker_id - - // Process uploaded files - List> uploads = buffer.getFiles().stream() - .map(fileName -> { - Map fileDetails = new HashMap<>(); - try { - byte[] fileContent = buffer.getInputStream(fileName).readAllBytes(); - String fileToken = api.uploadFile(fileContent, fileName); - fileDetails.put("token", fileToken); - fileDetails.put("filename", fileName); - fileDetails.put("content_type", buffer.getFileData(fileName).getMimeType()); - } catch (IOException e) { - logger.error("Error al cargar el archivo: " + e.getMessage()); - } - return fileDetails; - }) - .collect(Collectors.toList()); - - JsonArray uploadsJsonArray = new JsonArray(); - for (Map upload : uploads) { - JsonObject uploadJson = new JsonObject(); - uploadJson.addProperty("token", upload.get("token")); - uploadJson.addProperty("filename", upload.get("filename")); - uploadJson.addProperty("content_type", upload.get("content_type")); - uploadsJsonArray.add(uploadJson); - } + private void handleCreateButton(RedmineUser user, ComboBox tipoTickets, TextField asunto, TextArea descripcion) { + if (user.getKey() == null || user.getKey().isEmpty()) { + Notification.show("No se encontró la API key en la sesión.", 5000, Notification.Position.MIDDLE) + .addThemeVariants(NotificationVariant.LUMO_ERROR); + return; + } - String response = api.createIssue(issueDetails, uploadsJsonArray, user.getKey()); + if (selectedTrackerId == null) { + Notification.show("Por favor seleccione un tipo de ticket.", 3000, Notification.Position.MIDDLE) + .addThemeVariants(NotificationVariant.LUMO_WARNING); + return; + } - handleResponse(response, asunto, descripcion, tipoTickets); - }); + if (asunto.isEmpty()) { + Notification.show("El asunto es obligatorio.", 3000, Notification.Position.MIDDLE) + .addThemeVariants(NotificationVariant.LUMO_WARNING); + return; + } - createButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + if (descripcion.isEmpty()) { + Notification.show("La descripción es obligatoria.", 3000, Notification.Position.MIDDLE) + .addThemeVariants(NotificationVariant.LUMO_WARNING); + return; + } - VerticalLayout fieldsLayout = new VerticalLayout(descripcion, uploadFile); - fieldsLayout.setAlignItems(Alignment.CENTER); - HorizontalLayout firstFields = new HorizontalLayout(tipoTickets, asunto); - VerticalLayout buttonLayout = new VerticalLayout(createButton); - buttonLayout.setAlignItems(Alignment.END); - buttonLayout.setMargin(true); + Map issueDetails = new HashMap<>(); + issueDetails.put("project_id", "soporte-tecnico-t-i"); + issueDetails.put("subject", asunto.getValue()); + issueDetails.put("description", descripcion.getValue()); + issueDetails.put("tracker_id", selectedTrackerId); + + JsonArray uploadsJsonArray = new JsonArray(); + buffer.getFiles().forEach(fileName -> { + try (InputStream inputStream = buffer.getInputStream(fileName)) { + byte[] fileContent = inputStream.readAllBytes(); + String fileToken = api.uploadFile(fileContent, fileName); + JsonObject uploadJson = new JsonObject(); + uploadJson.addProperty("token", fileToken); + uploadJson.addProperty("filename", fileName); + uploadJson.addProperty("content_type", buffer.getFileData(fileName).getMimeType()); + uploadsJsonArray.add(uploadJson); + } catch (IOException e) { + Notification.show("Error al cargar el archivo: " + e.getMessage(), 3000, Notification.Position.MIDDLE) + .addThemeVariants(NotificationVariant.LUMO_ERROR); + } + }); - add(new H2("Crear nuevo ticket"), firstFields, fieldsLayout, buttonLayout); + String response = api.createIssue(issueDetails, uploadsJsonArray, user.getKey()); + handleResponse(response, asunto, descripcion, tipoTickets); } private void handleResponse(String response, TextField asunto, TextArea descripcion, ComboBox tipoTickets) { @@ -202,10 +208,9 @@ public class CrearnuevoTicketView extends VerticalLayout { 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("Error al enviar el ticket. No tiene los permisos necesarios", 5000, Notification.Position.MIDDLE) + Notification.show("Error al crear el ticket: " + response, 5000, Notification.Position.MIDDLE) .addThemeVariants(NotificationVariant.LUMO_ERROR); } } @@ -214,6 +219,11 @@ public class CrearnuevoTicketView extends VerticalLayout { asunto.clear(); descripcion.clear(); tipoTickets.clear(); + + asunto.setInvalid(false); + descripcion.setInvalid(false); + tipoTickets.setInvalid(false); + buffer = new MultiFileMemoryBuffer(); uploadFile.setReceiver(buffer); uploadFile.clearFileList(); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f80ff87..a490922 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -18,13 +18,13 @@ spring.ldap.password=Dr3na%134$4guA ########PRODUCTIVO################################# -redmine.url=https://proyman.jumapacelaya.gob.mx/ -redmine.api_key=9cc9e89cbbf08a6252045d56bd3d3ffec90adbad +#redmine.url=https://proyman.jumapacelaya.gob.mx/ +#redmine.api_key=9cc9e89cbbf08a6252045d56bd3d3ffec90adbad ########LOCAL###################################### -#redmine.url=http://localhost:3000 -#redmine.api_key=9cc9e89cbbf08a6252045d56bd3d3ffec90adbad +redmine.url=http://localhost:3000 +redmine.api_key=9cc9e89cbbf08a6252045d56bd3d3ffec90adbad ###CONFIGURACION DEL TAMANO MAXIMO PERMITIDO PARA ARCHIVOS###