From 6abbfb86f9025e1a3d53410eafd04b91f5150d0f Mon Sep 17 00:00:00 2001 From: Sia Mirza <30539650+nautilus69@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:27:04 +0100 Subject: [PATCH] integrate validators 3-tier warning style --- R/data_structure.R | 43 ++++++++++++++++- R/mod_export.R | 29 ++++++++++++ R/mod_import.R | 45 +++++++++++++++++- R/mod_warning_modal.R | 107 +++++++++++++++++++++++++++++++----------- 4 files changed, 195 insertions(+), 29 deletions(-) diff --git a/R/data_structure.R b/R/data_structure.R index ef6f260..2c7b741 100644 --- a/R/data_structure.R +++ b/R/data_structure.R @@ -260,12 +260,14 @@ WarningHandler <- R6::R6Class( # Store warning messages warning_messages = NULL, + # Store critical error messages + critical_messages = NULL, invalid_sheets_name = NULL, - # Initialize initialize = function() { self$warning_messages <- reactiveValues() + self$critical_messages <- reactiveValues() }, # Method to add a warning @@ -277,7 +279,46 @@ WarningHandler <- R6::R6Class( if (!is.null(warning_code)) { self$invalid_sheets_name[[config_file]] <- c(self$invalid_sheets_name[[config_file]], sheet_name) } + }, + + # Method to add a critical error + add_critical_error = function(config_file, category, message) { + self$critical_messages$config_files <- c(self$critical_messages$config_files, config_file) + error_msg <- sprintf("[%s] %s", category, message) + self$critical_messages[[config_file]] <- c(self$critical_messages[[config_file]], error_msg) + }, + # Check if any critical errors exist + has_critical_errors = function() { + length(self$critical_messages$config_files) > 0 + }, + + # Clear all warnings and critical errors + clear = function() { + self$warning_messages <- reactiveValues() + self$critical_messages <- reactiveValues() + self$invalid_sheets_name <- NULL + }, + + # Populate from esqlabsR validationResults + populate_from_validation = function(validationResults) { + for (file_name in names(validationResults)) { + result <- validationResults[[file_name]] + if (!inherits(result, "validationResult")) next + + for (err in result$critical_errors) { + self$add_critical_error(file_name, err$category, err$message) + } + for (warn in result$warnings) { + self$warning_messages$config_files <- c( + self$warning_messages$config_files, file_name + ) + warning_msg <- sprintf("[%s] %s", warn$category, warn$message) + self$warning_messages[[file_name]] <- c( + self$warning_messages[[file_name]], warning_msg + ) + } + } } ) ) diff --git a/R/mod_export.R b/R/mod_export.R index cf56fef..fc515c7 100644 --- a/R/mod_export.R +++ b/R/mod_export.R @@ -30,8 +30,37 @@ mod_export_server <- function(id, r, configuration_path) { ) + # Disable export when critical errors exist + observeEvent(r$states$has_critical_errors, { + if (isTRUE(r$states$has_critical_errors)) { + updateActionButton(session, inputId = "export", disabled = TRUE) + } else { + updateActionButton(session, inputId = "export", disabled = FALSE) + } + }) + # Listen to the export button observeEvent(input$export, { + # Re-validate before exporting + if (!is.null(r$config$projectConfiguration)) { + validationResults <- esqlabsR::validateAllConfigurations( + r$config$projectConfiguration + ) + if (esqlabsR::isAnyCriticalErrors(validationResults)) { + r$warnings$clear() + r$warnings$populate_from_validation(validationResults) + r$states$has_critical_errors <- TRUE + r$states$modal_message <- list( + status = "Export Blocked", + message = paste( + "Critical validation errors found.", + "Please fix the errors and try again." + ) + ) + return() + } + } + message("exporting data") export_success <- TRUE # Track overall success diff --git a/R/mod_import.R b/R/mod_import.R index 41f8b68..5041a01 100644 --- a/R/mod_import.R +++ b/R/mod_import.R @@ -130,7 +130,7 @@ mod_import_server <- function(id, r, DROPDOWNS) { ) # Clear warnings before reload - r$warnings$warning_messages <- reactiveValues() + r$warnings$clear() # Re-read all files and reset modified data for (config_file in r$data$get_config_files()) { @@ -160,6 +160,22 @@ mod_import_server <- function(id, r, DROPDOWNS) { # Update dropdowns with fresh data runAfterConfig() + # Re-run esqlabsR validators + validationResults <- esqlabsR::validateAllConfigurations( + r$config$projectConfiguration + ) + r$warnings$populate_from_validation(validationResults) + + if (esqlabsR::isAnyCriticalErrors(validationResults)) { + r$states$has_critical_errors <- TRUE + showNotification( + "Critical validation errors found. Export is blocked.", + type = "error" + ) + } else { + r$states$has_critical_errors <- FALSE + } + # Trigger UI refresh to update the tables r$ui_triggers$selected_sheet <- runif(1) @@ -214,6 +230,33 @@ mod_import_server <- function(id, r, DROPDOWNS) { # if no data file or no sheets runAfterConfig() + + # Run esqlabsR validators + validationResults <- esqlabsR::validateAllConfigurations(pc) + r$warnings$populate_from_validation(validationResults) + + if (esqlabsR::isAnyCriticalErrors(validationResults)) { + summary <- esqlabsR::validationSummary(validationResults) + r$states$has_critical_errors <- TRUE + showModal(modalDialog( + title = "Critical Validation Errors", + tagList( + tags$p(tags$strong(paste0( + summary$total_critical_errors, " critical error(s) found." + ))), + tags$p( + "The imported configuration has critical errors that must be", + "fixed before you can export. Click the", + icon("circle-exclamation"), + "icon to view details." + ) + ), + easyClose = TRUE, + footer = modalButton("OK") + )) + } else { + r$states$has_critical_errors <- FALSE + } }) # Show confirmation modal when reload button is clicked diff --git a/R/mod_warning_modal.R b/R/mod_warning_modal.R index 70aa794..2233734 100644 --- a/R/mod_warning_modal.R +++ b/R/mod_warning_modal.R @@ -31,7 +31,7 @@ mod_warning_server <- function(id, r) { observeEvent(input$open_warning_modal, { showModal( modalDialog( - title = "Warning", + title = "Validation Results", uiOutput(ns("warning_accordion")), easyClose = TRUE, footer = tagList( @@ -41,41 +41,48 @@ mod_warning_server <- function(id, r) { ) }) - observeEvent(r$warnings$warning_messages$config_files, { + # Watch for critical errors + observeEvent(r$warnings$critical_messages$config_files, { updateActionButton( session = session, inputId = "open_warning_modal", - icon = icon("warning"), + icon = icon("circle-exclamation"), disabled = FALSE ) showNotification( - HTML(paste("Warnings found in config files. Press the", icon("warning"), "to view them")), - type = "warning", - duration = 7 + HTML(paste( + "Critical errors found in config files. Press the", + icon("circle-exclamation"), "to view them" + )), + type = "error", + duration = 10 ) - output$warning_accordion <- renderUI({ - items <- lapply(unique(r$warnings$warning_messages$config_files), function(x) { - # Check if there are messages for the current config file - if (length(r$warnings$warning_messages[[x]]) > 0) { - # Loop through each message inside the vector and create a list item - bullet_list <- sapply(r$warnings$warning_messages[[x]], function(msg) { - paste0("