diff --git a/R/ASM_Server.R b/R/ASM_Server.R index c8e74fd..72c5f86 100644 --- a/R/ASM_Server.R +++ b/R/ASM_Server.R @@ -33,6 +33,9 @@ ASM_Server <- function(id, mod_ids) { moduleServer(id, function(input, output, session) { + # Used to trigger messages from download button + toMessage = reactiveValues() + #------------------------------------ # Create ui outputs here: output$ui_asm_save_name_text = renderUI({ @@ -155,16 +158,45 @@ ASM_Server <- function(id, # mod_ids = mod_ids), # c("ws_res")) - tcres = FM_tc(cmd = "ws_res = ASM_save_state(state=state, session=session, file_path=file, pll=NULL)", + if((any(c("ShinySession", "session_proxy") %in% class(session)))){ + if(system.file(package = "shinybusy") !=""){ + shinybusy::show_modal_spinner(text=state[["MC"]][["labels"]][["busy"]][["saving_state"]]) + } + } + + tmp_cmd = "ws_res = ASM_save_state(state=state, session=session, file_path=file, pll=NULL)" + tcres = FM_tc(cmd = tmp_cmd, tc_env = list(state = state, session = session, file = file), capture = c("ws_res")) + if((any(c("ShinySession", "session_proxy") %in% class(session)))){ + if(system.file(package = "shinybusy") !=""){ + shinybusy::remove_modal_spinner() + } + } + + if(!tcres$isgood){ FM_le(state, "Failed to write state") + FM_le(state, tmp_cmd) FM_le(state, tcres$msgs) + + state = FM_set_notification( + state = state, + notify_text = state[["MC"]][["errors"]][["save_failed"]], + notify_id = "ASM save failed", + type = "failure") + + state = FM_set_ui_msg(state, tcres$msgs) + FM_set_mod_state(session, id, state) + + toMessage[["message"]] = TRUE + notify_res = + FM_notify(state = state, + session = session) } } ) @@ -294,6 +326,7 @@ ASM_Server <- function(id, output$ui_asm_msg = renderText({ input[["button_state_save"]] input[["input_load_state"]] + toMessage$message state = ASM_fetch_state(id = id, input = input, session = session, @@ -1197,12 +1230,6 @@ ASM_save_state = function(state, session, file_path, pll = NULL){ isgood = TRUE msgs = c() - if((any(c("ShinySession", "session_proxy") %in% class(session)))){ - if(system.file(package = "shinybusy") !=""){ - shinybusy::show_modal_spinner(text=state[["MC"]][["labels"]][["busy"]][["saving_state"]]) - } - } - # If pll is null then we generate it here: if(is.null(pll)){ mkp_res = FM_mk_app_preload(session) @@ -1296,11 +1323,6 @@ ASM_save_state = function(state, session, file_path, pll = NULL){ } } - if((any(c("ShinySession", "session_proxy") %in% class(session)))){ - if(system.file(package = "shinybusy") !=""){ - shinybusy::remove_modal_spinner() - } - } # Zipping everything up into an archive zip::zip(zipfile=file_path, diff --git a/R/DW_Server.R b/R/DW_Server.R index 64d72b4..c242ccf 100644 --- a/R/DW_Server.R +++ b/R/DW_Server.R @@ -1772,6 +1772,7 @@ DW_fetch_state = function(id, input, session, # From the original view we copy both the WDS and elements_table fields new_view[["WDS"]] = original_view[["WDS"]] new_view[["elements_table"]] = original_view[["elements_table"]] + new_view[["elements_list"]] = original_view[["elements_list"]] state = DW_set_current_view(state, new_view) # Setting hold for views select @@ -3401,18 +3402,21 @@ DW_mk_preload = function(state){ tmp_source_ele[["elements_list"]][[tmp_key]][["pll"]]) FM_le(state, paste0(" -> ",tmp_key, ": ", tmp_source_ele[["elements_list"]][[tmp_key]][["pll"]][["action"]]) ) } else { - err_msg = c(err_msg, paste0("missing preload list (pll) for key: ", tmp_key)) + tmp_err_msg = paste0(" -> missing preload list (pll) for key: ", tmp_key) + FM_le(state, tmp_err_msg, entry_type="danger") + err_msg = c(err_msg, tmp_err_msg) isgood = FALSE } } else { - err_msg = c(err_msg, paste0("missing key: ", tmp_key)) + tmp_err_msg = paste0(" -> missing key: ", tmp_key) + FM_le(state, tmp_err_msg, entry_type="danger") + err_msg = c(err_msg, tmp_err_msg) isgood = FALSE } comp_idx = comp_idx + 1 } } - # Appending element ylist[["elements"]][[ele_idx]] = list(element = tmp_element) ele_idx = ele_idx + 1 @@ -3425,7 +3429,6 @@ DW_mk_preload = function(state){ yaml_list[[ state[["id"]] ]] = ylist if(!isgood && !is.null(err_msg)){ - formods::FM_le(state,err_msg,entry_type="danger") msgs = c(msgs, err_msg) } diff --git a/R/FG_Server.R b/R/FG_Server.R index dbe6785..d9d2ef0 100644 --- a/R/FG_Server.R +++ b/R/FG_Server.R @@ -1360,7 +1360,7 @@ FG_Server <- function(id, #' \item{msgs: Any messages generated when building the #' figure.} #' \item{notes: Figure notes (user editable)} -#' \item{num_pages: Number of pages in the figure.} +#' \item{num_pages: Number of pages in the figure.} #' \item{page: The currently selected figure page.} #' } #' } @@ -1734,6 +1734,7 @@ FG_fetch_state = function(id, # new_fig[["DW_checksum" ]] = old_fig[["DW_checksum" ]] # new_fig[["DSV_checksum" ]] = old_fig[["DSV_checksum" ]] new_fig[["elements_table"]] = old_fig[["elements_table"]] + new_fig[["elements_list" ]] = old_fig[["elements_list" ]] new_fig[["code" ]] = old_fig[["code" ]] new_fig[["fobj" ]] = old_fig[["fobj" ]] new_fig[["code_previous" ]] = old_fig[["code_previous" ]] @@ -1853,7 +1854,7 @@ FG_init_state = function(FM_yaml_file, MOD_yaml_file, id, id_UD, id_DW, session) text_component_xlab = "xlab", text_component_ylab = "ylab", text_component_ggtitle = "title")), - scales = list( + scales = list( mapping = list( select_component_xscale = "xscale", select_component_yscale = "yscale", @@ -2186,12 +2187,12 @@ fers_builder = function(state){ # Number of rows if(!(ui[["select_component_facet_nrow"]] %in% state[["MC"]][["formatting"]][["components"]][["facet_dims"]][["nrow"]][["choices"]])){ - ui[["select_component_facet_nrow"]] = state[["MC"]][["formatting"]][["components"]][["facet_dims"]][["nrow"]][["default"]] + ui[["select_component_facet_nrow"]] = state[["MC"]][["formatting"]][["components"]][["facet_dims"]][["nrow"]][["default"]] } # Number of columns if(!(ui[["select_component_facet_ncol"]] %in% state[["MC"]][["formatting"]][["components"]][["facet_dims"]][["ncol"]][["choices"]])){ - ui[["select_component_facet_ncol"]] = state[["MC"]][["formatting"]][["components"]][["facet_dims"]][["ncol"]][["default"]] + ui[["select_component_facet_ncol"]] = state[["MC"]][["formatting"]][["components"]][["facet_dims"]][["ncol"]][["default"]] } # The faceting command will depend on the number of columns selected @@ -2227,8 +2228,8 @@ fers_builder = function(state){ # Defining the preload options for faceting for(uiname in names(state[["FG"]][["manual_elements"]][[element]][["mapping"]])){ - pll[["options"]][[ - state[["FG"]][["manual_elements"]][[element]][["mapping"]][[ uiname ]] + pll[["options"]][[ + state[["FG"]][["manual_elements"]][[element]][["mapping"]][[ uiname ]] ]] = ui[[uiname]] } @@ -2291,8 +2292,8 @@ fers_builder = function(state){ # Defining the preload options for faceting for(uiname in names(state[["FG"]][["manual_elements"]][[element]][["mapping"]])){ - pll[["options"]][[ - state[["FG"]][["manual_elements"]][[element]][["mapping"]][[ uiname ]] + pll[["options"]][[ + state[["FG"]][["manual_elements"]][[element]][["mapping"]][[ uiname ]] ]] = ui[[uiname]] } @@ -2330,8 +2331,8 @@ fers_builder = function(state){ # Defining the preload options for faceting for(uiname in names(state[["FG"]][["manual_elements"]][[element]][["mapping"]])){ - pll[["options"]][[ - state[["FG"]][["manual_elements"]][[element]][["mapping"]][[ uiname ]] + pll[["options"]][[ + state[["FG"]][["manual_elements"]][[element]][["mapping"]][[ uiname ]] ]] = ui[[uiname]] } @@ -2535,7 +2536,7 @@ FG_build = function(state, # Adding to the list current_fig[["elements_list"]][[fge_key]][["pll"]] = pll - + # Incrementing the counter current_fig[["fge_cntr"]] = current_fig[["fge_cntr"]] + 1 @@ -2952,7 +2953,7 @@ res} #'@title Populate Session Data for Module Testing #'@description Populates the supplied session variable for testing. #'@param session Shiny session variable (in app) or a list (outside of app) -#'@return The FG portion of the `all_sess_res` returned from \code{\link{FM_app_preload}} +#'@return The FG portion of the `all_sess_res` returned from \code{\link{FM_app_preload}} #'@examples #' sess_res = FG_test_mksession() #'@seealso \code{\link{FM_app_preload}} @@ -2973,10 +2974,10 @@ res} #'@description Populates the supplied session variable with information from #'list of sources. #'@param session Shiny session variable (in app) or a list (outside of app) -#'@param src_list List of preload data (all read together with module IDs at the top level) +#'@param src_list List of preload data (all read together with module IDs at the top level) #'@param yaml_res List data from module yaml config -#'@param mod_ID Module ID of the module being loaded. -#'@param react_state Reactive shiny object (in app) or a list (outside of app) used to trigger reactions. +#'@param mod_ID Module ID of the module being loaded. +#'@param react_state Reactive shiny object (in app) or a list (outside of app) used to trigger reactions. #'@param quickload Logical \code{TRUE} to load reduced analysis \code{FALSE} to load the full analysis #'@return list with the following elements #' \itemize{ @@ -3039,9 +3040,9 @@ FG_preload = function(session, src_list, yaml_res, mod_ID=NULL, react_state = l while(state[["FG"]][["fig_cntr"]] < max(enumeric)){ state = FG_new_fig(state) } - # culling any unneeded views + # culling any unneeded views for(fig_id in names(state[["FG"]][["figs"]])){ - # This is a view that doesn't exist in elements so + # This is a view that doesn't exist in elements so # we need to cull it if(!(fig_id %in% names(element_map))){ # Setting the view to be deleted as the current view @@ -3056,7 +3057,7 @@ FG_preload = function(session, src_list, yaml_res, mod_ID=NULL, react_state = l # This contains all plot types: plot_elements = state[["MC"]][["elements"]] - # these are the elements defined by aesthetics + # these are the elements defined by aesthetics aes_elements = state[["FG"]][["aes_elements"]] # ui elements that are automatically generated @@ -3075,7 +3076,7 @@ FG_preload = function(session, src_list, yaml_res, mod_ID=NULL, react_state = l # Making the current element element id active state[["FG"]][["current_fig"]] = element_id - # Getting the numeric position in the list corresponding + # Getting the numeric position in the list corresponding # to the current element id ele_idx = element_map[[element_id]] @@ -3098,12 +3099,12 @@ FG_preload = function(session, src_list, yaml_res, mod_ID=NULL, react_state = l # Attaching data source if(!is.null(elements[[ele_idx]][["element"]][["data_source"]][["id"]]) & !is.null(elements[[ele_idx]][["element"]][["data_source"]][["idx"]])){ - tmp_DSV = DSV[["catalog"]][c(DSV[["catalog"]][["id"]] == elements[[ele_idx]][["element"]][["data_source"]][["id"]] & + tmp_DSV = DSV[["catalog"]][c(DSV[["catalog"]][["id"]] == elements[[ele_idx]][["element"]][["data_source"]][["id"]] & DSV[["catalog"]][["idx"]] == elements[[ele_idx]][["element"]][["data_source"]][["idx"]]), ] if(nrow(tmp_DSV) == 1){ FM_le(state, paste0("setting data source: ", tmp_DSV[["object"]][1]) ) current_ele = FG_fetch_current_fig(state) - current_ele[["fig_dsview"]] = tmp_DSV[["object"]][1] + current_ele[["fig_dsview"]] = tmp_DSV[["object"]][1] state = FG_set_current_fig(state, current_ele) } else { FM_le(state, paste0("error locating data source, expecting 1 source found ", nrow(tmp_DSV)), entry_type="danger") @@ -3192,7 +3193,7 @@ FG_preload = function(session, src_list, yaml_res, mod_ID=NULL, react_state = l } if(add_component){ - # Adding aesthetics + # Adding aesthetics if(!is.null(tmp_component[["aes"]])){ for(cname in names( tmp_component[["aes"]])){ cname_ui = paste0("select_component_", cname) @@ -3243,7 +3244,7 @@ FG_preload = function(session, src_list, yaml_res, mod_ID=NULL, react_state = l } else { add_component = FALSE isgood = FALSE - tmp_msg = paste0("unknown plot component type: ", tmp_component[["type"]] ) + tmp_msg = paste0("unknown plot component type: ", tmp_component[["type"]] ) msgs = c(msgs, tmp_msg) FM_le(state,tmp_msg,entry_type="danger") } @@ -3297,13 +3298,13 @@ FG_preload = function(session, src_list, yaml_res, mod_ID=NULL, react_state = l session = FM_set_mod_state(session, mod_ID, state) } - res = list(isgood = isgood, + res = list(isgood = isgood, msgs = msgs, session = session, input = input, react_state = react_state, state = state) - + res} #'@export @@ -3322,13 +3323,13 @@ res} #' res = FG_mk_preload(state) FG_mk_preload = function(state){ isgood = TRUE - msgs = c() + msgs = c() err_msg = c() ylist = list( fm_yaml = file.path("config", basename(state[["FM_yaml_file"]])), mod_yaml = file.path("config", basename(state[["MOD_yaml_file"]])), - elements = list() + elements = list() ) @@ -3339,9 +3340,9 @@ FG_mk_preload = function(state){ # Walking through each element: for(element_id in names(state[["FG"]][["figs"]])){ tmp_source_ele = state[["FG"]][["figs"]][[element_id]] - + # Finding the data source: - dsv_row = + dsv_row = DSV[["catalog"]][ DSV[["catalog"]][["object"]] == tmp_source_ele[["fig_dsview"]], ] ds_id = dsv_row[["id"]] @@ -3356,9 +3357,9 @@ FG_mk_preload = function(state){ id = ds_id, idx = ds_idx), components = list()) - + FM_le(state, paste0("saving element (", tmp_source_ele[["idx"]], ") ", tmp_source_ele[["key"]])) - + # Adding components: if(is.data.frame(tmp_source_ele[["elements_table"]])){ comp_idx = 1 @@ -3369,17 +3370,21 @@ FG_mk_preload = function(state){ tmp_source_ele[["elements_list"]][[tmp_key]][["pll"]]) FM_le(state, paste0(" -> ",tmp_key, ": ", tmp_source_ele[["elements_list"]][[tmp_key]][["pll"]][["type"]]) ) } else { - err_msg = c(err_msg, paste0("missing preload list (pll) for key: ", tmp_key)) + tmp_err_msg =paste0("missing preload list (pll) for key: ", tmp_key) + err_msg = c(err_msg, tmp_err_msg) + FM_le(state, tmp_err_msg, entry_type="danger") isgood = FALSE } } else { - err_msg = c(err_msg, paste0("missing key: ", tmp_key)) + tmp_err_msg = paste0(" -> missing key: ",tmp_key) + err_msg = c(err_msg, tmp_err_msg) + FM_le(state, tmp_err_msg, entry_type="danger") isgood = FALSE } comp_idx = comp_idx + 1 } } - + # Appending element ylist[["elements"]][[ele_idx]] = list(element = tmp_element) ele_idx = ele_idx + 1 @@ -3392,10 +3397,9 @@ FG_mk_preload = function(state){ yaml_list[[ state[["id"]] ]] = ylist if(!isgood && !is.null(err_msg)){ - formods::FM_le(state,err_msg,entry_type="danger") msgs = c(msgs, err_msg) } - + res = list( isgood = isgood, msgs = msgs, diff --git a/R/formods.R b/R/formods.R index 1784f50..37e9135 100644 --- a/R/formods.R +++ b/R/formods.R @@ -253,7 +253,7 @@ autocast = function(ui_input, quote_char=TRUE){ # x[na] = NA_real_ # x #} - + if(any(is.na(ui_input_num)) | (length(ui_input_num) == 0)){ res = as.character(ui_input) if(quote_char){ @@ -2408,7 +2408,7 @@ res} #'@export #'@title Determine if Object is Shiny Session Object #'@description Determines if the specified object is a shiny session object. -#'@param session Session object +#'@param session Session object #'@return Logical indicating if the object is a shiny session object or not #'@examples #' is_shiny(session = list()) @@ -2416,7 +2416,7 @@ is_shiny = function(session=list()){ res = FALSE if(any(c("ShinySession", "session_proxy") %in% class(session))){ - res = TRUE + res = TRUE } res} @@ -2743,7 +2743,7 @@ linspace = function(a, b, n=100){ #'@export #'@title Evaluate R Code in String #'@description Attempts to evaluate a string as a chunk of R code. If that -#'succeeds it will return the result. If not it will return the original text. +#'succeeds it will return the result. If not it will return the original text. #'@param estr String to render. #'@return String containing the evaled as a character or the original string #'@examples @@ -2766,7 +2766,7 @@ render_str <- function(estr=""){ #'@export #'@title Preload Data Into App #'@description Populates session data for testing or to load a specific -#'analysis. +#'analysis. #'@param session Shiny session variable (in app) or a list (outside of app) #'@param sources Vector of at corresponds with the ID used to call the modules UI elements #'@param react_state Reactive shiny object (in app) or a list (outside of app) used to trigger reactions @@ -2788,7 +2788,7 @@ FM_app_preload = function(session, sources=NULL, react_state = list(), quickload err_msgs = c() all_sess_res = list() - # This is created in an eval below so we define + # This is created in an eval below so we define # it here to prevent errors in check sess_res = NULL @@ -2802,7 +2802,7 @@ FM_app_preload = function(session, sources=NULL, react_state = list(), quickload msgs = c(msgs, ras_res[["msgs"]]) } - # Making sure they are ordered based on dependencies + # Making sure they are ordered based on dependencies deps_found = c() IDs_proc = c() IDs_found = names(yaml_res) @@ -2811,7 +2811,7 @@ FM_app_preload = function(session, sources=NULL, react_state = list(), quickload while(idx <= length(IDs_found)){ for(mod_ID in IDs_found){ - # we only consider the ID if it hasn't + # we only consider the ID if it hasn't # been processed yet: if(!(mod_ID %in% IDs_proc)){ yaml_res[[mod_ID]][["mod_cfg"]][["module"]] @@ -2828,7 +2828,7 @@ FM_app_preload = function(session, sources=NULL, react_state = list(), quickload } } - # This will break out of the loop if we've found the + # This will break out of the loop if we've found the # order for all of the modules if(all(IDs_found %in% IDs_proc)){ idx = length(IDs_found) + 1 @@ -2844,7 +2844,7 @@ FM_app_preload = function(session, sources=NULL, react_state = list(), quickload if(isgood){ - # Looping through each ID and loading + # Looping through each ID and loading for(mod_ID in IDs_proc){ MOD_FUNC = paste0(yaml_res[[mod_ID]][["mod_cfg"]][["MC"]][["module"]][["type"]], "_preload") @@ -2854,7 +2854,7 @@ FM_app_preload = function(session, sources=NULL, react_state = list(), quickload eval(parse(text=FUNC_CALL)) - # Capturing any loading errors that may have occurred: + # Capturing any loading errors that may have occurred: if(!sess_res[["isgood"]]){ isgood = FALSE msgs = c(msgs, sess_res[["msgs"]]) @@ -2867,7 +2867,7 @@ FM_app_preload = function(session, sources=NULL, react_state = list(), quickload # Storing the results of the individual session loaded all_sess_res[[mod_ID]] = sess_res - # If we're running at the scripting level we need to pull + # If we're running at the scripting level we need to pull # the session information and react_state out of result if(!formods::is_shiny(session)){ session = sess_res[["session"]] @@ -2892,7 +2892,7 @@ FM_app_preload = function(session, sources=NULL, react_state = list(), quickload } - res=list(isgood =isgood, + res=list(isgood =isgood, msgs = msgs, all_sess_res = all_sess_res, session = session) @@ -2902,7 +2902,7 @@ res} #'@export #'@title Preload Data Into App #'@description Populates session data for testing or to load a specific -#'analysis. +#'analysis. #'@param session Shiny session variable (in app) or a list (outside of app) #'@return list with the following elements #' \itemize{ @@ -2944,18 +2944,18 @@ FM_mk_app_preload = function(session){ if(mk_res[["isgood"]]){ # Saving module yaml component yaml_list = c(yaml_list, mk_res[["yaml_list"]]) - + } else { - # Capturing any genration errors that may have occurred: + # Capturing any genration errors that may have occurred: isgood = FALSE msgs = c(msgs, mk_res[["msgs"]]) - FM_message(line=paste0("Failure to preload module ID: ", mod_ID), entry_type="danger") - for(tmp_line in mk_res[["msgs"]]){ + FM_message(line=paste0("Failure to make preload for module ID: ", mod_ID), entry_type="danger") + for(tmp_line in c(FUNC_CALL, mk_res[["msgs"]])){ FM_message(line=tmp_line, entry_type="danger") } } } else { - tmp_msg = paste0("No mk preload function found: ", MOD_FUNC, "() for ID: ", mod_ID) + tmp_msg = paste0("No mk preload function found: ", MOD_FUNC, "() for ID: ", mod_ID) FM_message(line=tmp_msg, entry_type="warning") } @@ -2963,7 +2963,7 @@ FM_mk_app_preload = function(session){ #browser() - res=list(isgood = isgood, + res=list(isgood = isgood, msgs = msgs, yaml_list = yaml_list, session = session) @@ -2973,7 +2973,7 @@ res} #'@title Resets the App State #'@description Removes formods data from the app. #'@param session Shiny session variable. -#'@return session variable with app data removed. +#'@return session variable with app data removed. #'@examples #' # We need a Shiny session object to use this function: #' sess_res = UD_test_mksession() diff --git a/inst/templates/ASM.yaml b/inst/templates/ASM.yaml index 9bb4436..98643fe 100644 --- a/inst/templates/ASM.yaml +++ b/inst/templates/ASM.yaml @@ -57,6 +57,7 @@ MC: errors: bad_input: "Input error message" load_failed: "Failed to load analysis" + save_failed: "Failed to save analysis" tooltips: # Set to FALSE to disable tool tips for this module include: TRUE diff --git a/inst/templates/FM_compact.R b/inst/templates/FM_compact.R index b47c165..ff0257f 100644 --- a/inst/templates/FM_compact.R +++ b/inst/templates/FM_compact.R @@ -119,11 +119,11 @@ server <- function(input, output, session) { react_FM = reactiveValues() #Uncomment to populate with test data - # sources = c(system.file(package="formods", "preload", "ASM_preload.yaml"), - # system.file(package="formods", "preload", "UD_preload.yaml"), - # system.file(package="formods", "preload", "DW_preload.yaml"), - # system.file(package="formods", "preload", "FG_preload.yaml")) - # res = FM_app_preload(session=session, sources=sources) + sources = c(system.file(package="formods", "preload", "ASM_preload.yaml"), + system.file(package="formods", "preload", "UD_preload.yaml"), + system.file(package="formods", "preload", "DW_preload.yaml"), + system.file(package="formods", "preload", "FG_preload.yaml")) + res = FM_app_preload(session=session, sources=sources) if(file.exists("preload.yaml")){ shinybusy::show_modal_spinner(text="Preloading analysis, be patient", session=session)