# package_manager_module.R source("semantic_package_search2.R") # UI function for the Package Manager module packageManagerUI <- function(id) { ns <- NS(id) # Namespace function to avoid ID collisions tabPanel( "Package Manager", fluidPage( # Search Panel with distinct background color div( style = "background-color: #f7f7f7; padding: 20px; border-radius: 5px; margin-bottom: 20px;", fluidRow( column( width = 12, div( style = "margin-bottom: 10px;", tags$label( `for` = ns("task_description"), "Description of the task you want to accomplish", style = "font-weight: bold; margin-right: 10px; white-space: nowrap;" ), textInput( ns("task_description"), label = NULL, width = "100%", placeholder = "Enter a description of your task..." ) ), actionButton(ns("search_button"), "Search Packages", style = "margin-top: 10px;") ) ) ), # Suggestions List fluidRow( column( width = 12, h3("Package Suggestions"), uiOutput(ns("package_list")) ) ) ) ) } # Server function for the Package Manager module packageManagerServer <- function(id) { moduleServer( id, function(input, output, session) { ns <- session$ns # Function to get package suggestions using semantic search getPackageSuggestions <- function(task_description) { # Get results from semantic search results <- semantic_package_search( query = task_description, embeddings_df = embeddings_df, packages_df = packages_df, top_n = 6 # Adjust number of suggestions as needed ) # Convert results to list format expected by UI suggestions <- lapply(1:nrow(results), function(i) { list( name = results$Package[i], description = paste0( results$Title[i], "\n\n", results$Description[i], "\n\nSimilarity score: ", round(results$similarity_score[i], 4) ) ) }) return(suggestions) } # Reactive value to store package suggestions package_suggestions <- reactiveVal(NULL) # Observe the search button to get package suggestions observeEvent(input$search_button, { req(input$task_description) # Ensure input is not empty # Get suggestions using semantic search suggestions <- tryCatch({ getPackageSuggestions(input$task_description) }, error = function(e) { showNotification( paste("Error getting suggestions:", e$message), type = "error" ) NULL }) package_suggestions(suggestions) }) output$package_list <- renderUI({ suggestions <- package_suggestions() if (is.null(suggestions)) { return(NULL) } # Generate UI elements for each package suggestion suggestion_ui <- lapply(seq_along(suggestions), function(i) { pkg <- suggestions[[i]] div( style = "border: 1px solid #ddd; padding: 10px; margin-bottom: 10px; border-radius: 5px; box-shadow: 2px 2px 5px rgba(0,0,0,0.1); display: flex; justify-content: space-between; align-items: center;", div( style = "flex-grow: 1;", h4(pkg$name, style = "margin: 0;"), p(pkg$description, style = "margin: 0; white-space: pre-wrap;") # Added pre-wrap to preserve newlines ), div( style = "flex-shrink: 0;", actionButton(ns(paste0("install_", i)), "Install", style = "margin-left: 40px;") ) ) }) do.call(tagList, suggestion_ui) }) # Observe install buttons observe({ suggestions <- package_suggestions() if (is.null(suggestions)) { return(NULL) } lapply(seq_along(suggestions), function(i) { pkg <- suggestions[[i]] install_btn <- paste0("install_", i) observeEvent(input[[install_btn]], { # For now, we'll just show a notification showNotification(paste("Installing package:", pkg$name)) # Actual installation logic can be added here }) }) }) } ) }