Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: ESQapp
Title: Shiny App to edit {esqLABSR} Edit Simulation Scenarios
Version: 2.2.0.9002
Version: 2.2.0.9003
Authors@R: c(
person("Felix", "Mil", email = "felix.mil@esqlabs.com", role = c('cre', 'aut')),
person("Anastasiia", "Kostiv", email = "anastasiia.kostiv.ext@esqlabs.com", role = c("aut"),
Expand Down
2 changes: 1 addition & 1 deletion R/app_server.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ app_server <- function(input, output, session) {
DROPDOWNS <- dropdown_values()
METADATA <- metadata_values()

mod_sidebar_server("sidebar_1", r, DROPDOWNS)
mod_sidebar_server("sidebar_1", r, DROPDOWNS, METADATA)
mod_main_panel_server("main_panel_1", r, DROPDOWNS, METADATA)
mod_warning_server("warning_modal", r) # Call warnings module
mod_pc_block_server("pc_block_1", r)
Expand Down
26 changes: 25 additions & 1 deletion R/data_structure.R
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,21 @@ DataStructure <- R6::R6Class("DataStructure",
self$applications <- reactiveValues(file_path = NA, sheets = NA)
self$plots <- reactiveValues(file_path = NA, sheets = NA)
},
# Reset all data for new project upload
reset = function() {
for (config_file in self$get_config_files()) {
# Remove all sheet data
current_sheets <- self[[config_file]]$sheets
if (!is.null(current_sheets) && !all(is.na(current_sheets))) {
for (sheet in current_sheets) {
self[[config_file]][[sheet]] <- NULL
}
}
# Reset to initial state
self[[config_file]]$file_path <- NA
self[[config_file]]$sheets <- NA
}
},
get_config_files = function() {
c("scenarios", "individuals", "populations", "models", "applications", "plots")
},
Expand Down Expand Up @@ -262,10 +277,19 @@ WarningHandler <- R6::R6Class(
warning_messages = NULL,
invalid_sheets_name = NULL,


# Initialize
initialize = function() {
self$warning_messages <- reactiveValues()
self$invalid_sheets_name <- NULL
},

# Reset for new project
reset = function() {
# Clear values inside existing reactiveValues to preserve observer bindings
for (name in names(self$warning_messages)) {
self$warning_messages[[name]] <- NULL
}
self$invalid_sheets_name <- NULL
},

# Method to add a warning
Expand Down
136 changes: 67 additions & 69 deletions R/mod_export.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@
mod_export_ui <- function(id) {
ns <- NS(id)
tagList(
actionButton(ns("export"), "Export", class = "btn-dark", disabled = TRUE)
tags$div(
style = "display: flex; flex-direction: column; gap: 10px; width: 100%;",
save_dropdown_ui(
ns = ns,
esqapp_id = "downloadEsqapp",
zip_id = "downloadZip",
disabled = TRUE
)
)
)
}

Expand All @@ -21,90 +29,80 @@ mod_export_server <- function(id, r, configuration_path) {
moduleServer(id, function(input, output, session) {
ns <- session$ns

# Enable the export button when the configuration file is loaded first time
# Enable the export and download buttons when the configuration file is loaded first time
observeEvent(configuration_path(),
{
updateActionButton(session, inputId = "export", disabled = FALSE)
shinyjs::enable("downloadButton")
},
once = TRUE
)


# Listen to the export button
observeEvent(input$export, {
message("exporting data")

export_success <- TRUE # Track overall success

for (config_file in r$data$get_config_files()) {
if (!golem::app_prod()) {
export_path <- paste0(fs::path_ext_remove(r$data[[config_file]]$file_path), "_copy.xlsx")
# Download handler for .esqapp file
output$downloadEsqapp <- downloadHandler(
filename = function() {
project_name <- if (!is.null(configuration_path()) && !is.null(configuration_path()$projectName)) {
gsub("[^A-Za-z0-9_-]", "_", configuration_path()$projectName)
} else {
export_path <- r$data[[config_file]]$file_path
"project"
}

message("Exporting modified", config_file, " to ", export_path)

sheet_list <- list()

for (sheet in r$data[[config_file]]$sheets) {
df <- r$data[[config_file]][[sheet]]$modified
# Get columns for this sheet (if any dropdown)
dropdown_cols <- DROPDOWN_COLUMN_TYPE_LIST[[config_file]][[sheet]]
# replace "--NONE--" with NA if it exists
if (!is.null(dropdown_cols)) {
df[dropdown_cols] <- lapply(df[dropdown_cols], function(col) {
replace(col, col == "--NONE--", NA)
})
}
# Convert numeric columns from text to numeric
numeric_cols <- NUMERIC_COLUMN_TYPE_LIST[[config_file]][[sheet]]
if (!is.null(numeric_cols)) {
# Only convert columns that exist in the dataframe
existing_numeric_cols <- intersect(numeric_cols, names(df))
if (length(existing_numeric_cols) > 0) {
df[existing_numeric_cols] <- suppressWarnings(
lapply(df[existing_numeric_cols], function(col) {
as.numeric(as.character(col))
})
)
}
}
# Save data to the `sheet_list`
sheet_list[[sheet]] <- df
paste0(project_name, "_", format(Sys.Date(), "%Y%m%d"), ".esqapp")
},
content = function(file) {
# Get the project root directory
config_path <- configuration_path()
if (!is.null(config_path) && !is.null(config_path$projectConfigurationFilePath)) {
original_project_root <- dirname(config_path$projectConfigurationFilePath)
} else if (!is.null(r$config$project_root)) {
original_project_root <- r$config$project_root
} else {
showNotification("Cannot determine project root directory", type = "error")
return(NULL)
}

# Try exporting and catch any errors
tryCatch(
{
rio::export(
x = sheet_list,
file = export_path
)
message("Export successful: ", export_path)
},
error = function(e) {
message("Error exporting ", config_file, ": File might be open or locked. Please close it and try again.")
r$states$modal_message <- list(
status = "Error: XLSX file might be open",
message = paste0(
"File might be open or locked. Please close ", fs::path_file(export_path),
" and try again."
)
)
export_success <<- FALSE # Mark failure
}
# Use the utility function to create the .esqapp file
create_esqapp_shiny(
original_project_root = original_project_root,
r = r,
output_file = file,
DROPDOWN_COLUMN_TYPE_LIST = DROPDOWN_COLUMN_TYPE_LIST,
NUMERIC_COLUMN_TYPE_LIST = NUMERIC_COLUMN_TYPE_LIST
)
}
)

# Download handler for .zip file
output$downloadZip <- downloadHandler(
filename = function() {
project_name <- if (!is.null(configuration_path()) && !is.null(configuration_path()$projectName)) {
gsub("[^A-Za-z0-9_-]", "_", configuration_path()$projectName)
} else {
"project"
}
paste0(project_name, "_", format(Sys.Date(), "%Y%m%d"), ".zip")
},
content = function(file) {
# Get the project root directory
config_path <- configuration_path()
if (!is.null(config_path) && !is.null(config_path$projectConfigurationFilePath)) {
original_project_root <- dirname(config_path$projectConfigurationFilePath)
} else if (!is.null(r$config$project_root)) {
original_project_root <- r$config$project_root
} else {
showNotification("Cannot determine project root directory", type = "error")
return(NULL)
}

# Set success message if no errors occurred
if (export_success) {
r$states$modal_message <- list(
status = "Success",
message = "Export completed successfully!"
# Use the utility function to create the .zip file (same as .esqapp, just different extension)
create_esqapp_shiny(
original_project_root = original_project_root,
r = r,
output_file = file,
DROPDOWN_COLUMN_TYPE_LIST = DROPDOWN_COLUMN_TYPE_LIST,
NUMERIC_COLUMN_TYPE_LIST = NUMERIC_COLUMN_TYPE_LIST
)
}
})
)
})
}

Expand Down
Loading