mirror of
https://github.com/agdamsbo/FreesearchR.git
synced 2025-09-12 09:59:39 +02:00
removed
This commit is contained in:
parent
4a962f702e
commit
ecaf5d5fdd
2 changed files with 0 additions and 1120 deletions
|
@ -1,652 +0,0 @@
|
|||
library(readr)
|
||||
library(MASS)
|
||||
library(stats)
|
||||
library(gtsummary)
|
||||
library(gt)
|
||||
library(openxlsx2)
|
||||
library(haven)
|
||||
library(readODS)
|
||||
require(shiny)
|
||||
library(bslib)
|
||||
library(assertthat)
|
||||
library(dplyr)
|
||||
library(quarto)
|
||||
library(here)
|
||||
library(broom)
|
||||
library(broom.helpers)
|
||||
# library(REDCapCAST)
|
||||
library(easystats)
|
||||
library(patchwork)
|
||||
library(DHARMa)
|
||||
library(apexcharter)
|
||||
library(toastui)
|
||||
library(datamods)
|
||||
library(data.table)
|
||||
library(IDEAFilter)
|
||||
library(shinyWidgets)
|
||||
library(DT)
|
||||
# library(freesearcheR)
|
||||
|
||||
# source("functions.R")
|
||||
|
||||
|
||||
|
||||
# light <- custom_theme()
|
||||
#
|
||||
# dark <- custom_theme(bg = "#000",fg="#fff")
|
||||
|
||||
|
||||
server <- function(input, output, session) {
|
||||
## Listing files in www in session start to keep when ending and removing
|
||||
## everything else.
|
||||
files.to.keep <- list.files("www/")
|
||||
|
||||
output$docs_file <- shiny::renderUI({
|
||||
# shiny::includeHTML("www/docs.html")
|
||||
shiny::HTML(readLines("www/docs.html"))
|
||||
})
|
||||
|
||||
##############################################################################
|
||||
#########
|
||||
######### Night mode (just very popular, not really needed)
|
||||
#########
|
||||
##############################################################################
|
||||
|
||||
# observeEvent(input$dark_mode,{
|
||||
# session$setCurrentTheme(
|
||||
# if (isTRUE(input$dark_mode)) dark else light
|
||||
# )})
|
||||
|
||||
# observe({
|
||||
# if(input$dark_mode==TRUE)
|
||||
# session$setCurrentTheme(bs_theme_update(theme = custom_theme(version = 5)))
|
||||
# if(input$dark_mode==FALSE)
|
||||
# session$setCurrentTheme(bs_theme_update(theme = custom_theme(version = 5, bg = "#000",fg="#fff")))
|
||||
# })
|
||||
|
||||
|
||||
##############################################################################
|
||||
#########
|
||||
######### Setting reactive values
|
||||
#########
|
||||
##############################################################################
|
||||
|
||||
rv <- shiny::reactiveValues(
|
||||
list = list(),
|
||||
ds = NULL,
|
||||
local_temp = NULL,
|
||||
ready = NULL,
|
||||
test = "no",
|
||||
data_original = NULL,
|
||||
data = NULL,
|
||||
data_filtered = NULL
|
||||
)
|
||||
|
||||
##############################################################################
|
||||
#########
|
||||
######### Data import section
|
||||
#########
|
||||
##############################################################################
|
||||
|
||||
data_file <- datamods::import_file_server(
|
||||
id = "file_import",
|
||||
show_data_in = "popup",
|
||||
trigger_return = "change",
|
||||
return_class = "data.frame",
|
||||
read_fns = list(
|
||||
ods = function(file) {
|
||||
readODS::read_ods(path = file)
|
||||
},
|
||||
dta = function(file) {
|
||||
haven::read_dta(file = file)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
shiny::observeEvent(data_file$data(), {
|
||||
shiny::req(data_file$data())
|
||||
rv$data_original <- data_file$data()
|
||||
})
|
||||
|
||||
data_redcap <- m_redcap_readServer(
|
||||
id = "redcap_import",
|
||||
output.format = "list"
|
||||
)
|
||||
|
||||
shiny::observeEvent(data_redcap(), {
|
||||
rv$data_original <- purrr::pluck(data_redcap(), "data")()
|
||||
})
|
||||
|
||||
output$redcap_prev <- DT::renderDT(
|
||||
{
|
||||
DT::datatable(head(purrr::pluck(data_redcap(), "data")(), 5),
|
||||
caption = "First 5 observations"
|
||||
)
|
||||
},
|
||||
server = TRUE
|
||||
)
|
||||
|
||||
from_env <- import_globalenv_server(
|
||||
id = "env",
|
||||
trigger_return = "change",
|
||||
btn_show_data = FALSE,
|
||||
reset = reactive(input$hidden)
|
||||
)
|
||||
|
||||
shiny::observeEvent(from_env$data(), {
|
||||
shiny::req(from_env$data())
|
||||
rv$data_original <- from_env$data()
|
||||
})
|
||||
|
||||
|
||||
##############################################################################
|
||||
#########
|
||||
######### Data modification section
|
||||
#########
|
||||
##############################################################################
|
||||
|
||||
shiny::observeEvent(rv$data_original, {
|
||||
rv$data <- rv$data_original |> default_parsing()
|
||||
})
|
||||
|
||||
shiny::observeEvent(input$data_reset, {
|
||||
shinyWidgets::ask_confirmation(
|
||||
inputId = "reset_confirm",
|
||||
title = "Please confirm data reset?"
|
||||
)
|
||||
})
|
||||
|
||||
shiny::observeEvent(input$reset_confirm, {
|
||||
rv$data <- rv$data_original |> default_parsing()
|
||||
})
|
||||
|
||||
######### Overview
|
||||
|
||||
data_summary_server(
|
||||
id = "data_summary",
|
||||
data = shiny::reactive({
|
||||
rv$data_filtered
|
||||
}),
|
||||
color.main = "#2A004E",
|
||||
color.sec = "#C62300"
|
||||
)
|
||||
|
||||
#########
|
||||
######### Modifications
|
||||
#########
|
||||
|
||||
## Using modified version of the datamods::cut_variable_server function
|
||||
## Further modifications are needed to have cut/bin options based on class of variable
|
||||
## Could be defined server-side
|
||||
|
||||
######### Create factor
|
||||
|
||||
shiny::observeEvent(
|
||||
input$modal_cut,
|
||||
modal_cut_variable("modal_cut")
|
||||
)
|
||||
data_modal_cut <- cut_variable_server(
|
||||
id = "modal_cut",
|
||||
data_r = shiny::reactive(rv$data)
|
||||
)
|
||||
shiny::observeEvent(data_modal_cut(), rv$data <- data_modal_cut())
|
||||
|
||||
######### Modify factor
|
||||
|
||||
shiny::observeEvent(
|
||||
input$modal_update,
|
||||
datamods::modal_update_factor(id = "modal_update")
|
||||
)
|
||||
data_modal_update <- datamods::update_factor_server(
|
||||
id = "modal_update",
|
||||
data_r = reactive(rv$data)
|
||||
)
|
||||
shiny::observeEvent(data_modal_update(), {
|
||||
shiny::removeModal()
|
||||
rv$data <- data_modal_update()
|
||||
})
|
||||
|
||||
######### Create column
|
||||
|
||||
shiny::observeEvent(
|
||||
input$modal_column,
|
||||
datamods::modal_create_column(id = "modal_column")
|
||||
)
|
||||
data_modal_r <- datamods::create_column_server(
|
||||
id = "modal_column",
|
||||
data_r = reactive(rv$data)
|
||||
)
|
||||
shiny::observeEvent(data_modal_r(), rv$data <- data_modal_r())
|
||||
|
||||
######### Show result
|
||||
|
||||
output$table_mod <- toastui::renderDatagrid({
|
||||
shiny::req(rv$data)
|
||||
# data <- rv$data
|
||||
toastui::datagrid(
|
||||
# data = rv$data # ,
|
||||
data = data_filter()
|
||||
# bordered = TRUE,
|
||||
# compact = TRUE,
|
||||
# striped = TRUE
|
||||
)
|
||||
})
|
||||
|
||||
output$code <- renderPrint({
|
||||
attr(rv$data, "code")
|
||||
})
|
||||
|
||||
# updated_data <- datamods::update_variables_server(
|
||||
updated_data <- update_variables_server(
|
||||
id = "vars_update",
|
||||
data = reactive(rv$data),
|
||||
return_data_on_init = FALSE
|
||||
)
|
||||
|
||||
output$original_str <- renderPrint({
|
||||
str(rv$data_original)
|
||||
})
|
||||
|
||||
output$modified_str <- renderPrint({
|
||||
str(as.data.frame(rv$data_filtered) |>
|
||||
REDCapCAST::set_attr(
|
||||
label = NULL,
|
||||
attr = "code"
|
||||
))
|
||||
})
|
||||
|
||||
shiny::observeEvent(updated_data(), {
|
||||
rv$data <- updated_data()
|
||||
})
|
||||
|
||||
# IDEAFilter has the least cluttered UI, but might have a License issue
|
||||
data_filter <- IDEAFilter::IDEAFilter("data_filter", data = reactive(rv$data), verbose = TRUE)
|
||||
|
||||
shiny::observeEvent(data_filter(), {
|
||||
rv$data_filtered <- data_filter()
|
||||
})
|
||||
|
||||
output$filtered_code <- shiny::renderPrint({
|
||||
out <- gsub(
|
||||
"filter", "dplyr::filter",
|
||||
gsub(
|
||||
"\\s{2,}", " ",
|
||||
paste0(
|
||||
capture.output(attr(rv$data_filtered, "code")),
|
||||
collapse = " "
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
out <- strsplit(out, "%>%") |>
|
||||
unlist() |>
|
||||
(\(.x){
|
||||
paste(c("data", .x[-1]), collapse = "|> \n ")
|
||||
})()
|
||||
|
||||
cat(out)
|
||||
})
|
||||
|
||||
|
||||
|
||||
##############################################################################
|
||||
#########
|
||||
######### Data analyses section
|
||||
#########
|
||||
##############################################################################
|
||||
|
||||
## Keep these "old" selection options as a simple alternative to the modification pane
|
||||
|
||||
output$include_vars <- shiny::renderUI({
|
||||
shiny::selectizeInput(
|
||||
inputId = "include_vars",
|
||||
selected = NULL,
|
||||
label = "Covariables to include",
|
||||
choices = colnames(rv$data_filtered),
|
||||
multiple = TRUE
|
||||
)
|
||||
})
|
||||
|
||||
output$outcome_var <- shiny::renderUI({
|
||||
shiny::selectInput(
|
||||
inputId = "outcome_var",
|
||||
selected = NULL,
|
||||
label = "Select outcome variable",
|
||||
choices = colnames(rv$data_filtered),
|
||||
multiple = FALSE
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
output$factor_vars <- shiny::renderUI({
|
||||
shiny::selectizeInput(
|
||||
inputId = "factor_vars",
|
||||
selected = colnames(rv$data_filtered)[sapply(rv$data_filtered, is.factor)],
|
||||
label = "Covariables to format as categorical",
|
||||
choices = colnames(rv$data_filtered),
|
||||
multiple = TRUE
|
||||
)
|
||||
})
|
||||
|
||||
base_vars <- shiny::reactive({
|
||||
if (is.null(input$include_vars)) {
|
||||
out <- colnames(rv$data_filtered)
|
||||
} else {
|
||||
out <- unique(c(input$include_vars, input$outcome_var))
|
||||
}
|
||||
return(out)
|
||||
})
|
||||
|
||||
output$strat_var <- shiny::renderUI({
|
||||
shiny::selectInput(
|
||||
inputId = "strat_var",
|
||||
selected = "none",
|
||||
label = "Select variable to stratify baseline",
|
||||
choices = c(
|
||||
"none",
|
||||
rv$data_filtered[base_vars()] |>
|
||||
(\(.x){
|
||||
lapply(.x, \(.c){
|
||||
if (identical("factor", class(.c))) {
|
||||
.c
|
||||
}
|
||||
}) |>
|
||||
dplyr::bind_cols()
|
||||
})() |>
|
||||
colnames()
|
||||
),
|
||||
multiple = FALSE
|
||||
)
|
||||
})
|
||||
|
||||
## Have a look at column filters at some point
|
||||
## There should be a way to use the filtering the filter data for further analyses
|
||||
## Disabled for now, as the JS is apparently not isolated
|
||||
# output$data_table <-
|
||||
# DT::renderDT(
|
||||
# {
|
||||
# DT::datatable(ds()[base_vars()])
|
||||
# },
|
||||
# server = FALSE
|
||||
# )
|
||||
#
|
||||
# output$data.classes <- gt::render_gt({
|
||||
# shiny::req(input$file)
|
||||
# data.frame(matrix(sapply(ds(), \(.x){
|
||||
# class(.x)[1]
|
||||
# }), nrow = 1)) |>
|
||||
# stats::setNames(names(ds())) |>
|
||||
# gt::gt()
|
||||
# })
|
||||
|
||||
shiny::observeEvent(
|
||||
{
|
||||
input$load
|
||||
},
|
||||
{
|
||||
shiny::req(input$outcome_var)
|
||||
# browser()
|
||||
# Assumes all character variables can be formatted as factors
|
||||
# data <- data_filter$filtered() |>
|
||||
tryCatch(
|
||||
{
|
||||
data <- rv$data_filtered |>
|
||||
dplyr::mutate(dplyr::across(dplyr::where(is.character), as.factor)) |>
|
||||
REDCapCAST::fct_drop.data.frame() |>
|
||||
factorize(vars = input$factor_vars) |>
|
||||
remove_na_attr()
|
||||
|
||||
if (input$strat_var == "none") {
|
||||
by.var <- NULL
|
||||
} else {
|
||||
by.var <- input$strat_var
|
||||
}
|
||||
|
||||
data <- data[base_vars()]
|
||||
|
||||
# model <- data |>
|
||||
# regression_model(
|
||||
# outcome.str = input$outcome_var,
|
||||
# auto.mode = input$regression_auto == 1,
|
||||
# formula.str = input$regression_formula,
|
||||
# fun = input$regression_fun,
|
||||
# args.list = eval(parse(text = paste0("list(", input$regression_args, ")")))
|
||||
# )
|
||||
|
||||
models <- list(
|
||||
"Univariable" = regression_model_uv,
|
||||
"Multivariable" = regression_model
|
||||
) |>
|
||||
lapply(\(.fun){
|
||||
do.call(
|
||||
.fun,
|
||||
c(
|
||||
list(data = data),
|
||||
list(outcome.str = input$outcome_var),
|
||||
list(formula.str = input$regression_formula),
|
||||
list(fun = input$regression_fun),
|
||||
list(args.list = eval(parse(text = paste0("list(", input$regression_args, ")"))))
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
rv$list$data <- data
|
||||
|
||||
|
||||
|
||||
rv$list$check <- purrr::pluck(models, "Multivariable") |>
|
||||
performance::check_model()
|
||||
|
||||
rv$list$table1 <- data |>
|
||||
baseline_table(
|
||||
fun.args =
|
||||
list(
|
||||
by = by.var
|
||||
)
|
||||
) |>
|
||||
(\(.x){
|
||||
if (!is.null(by.var)) {
|
||||
.x |> gtsummary::add_overall()
|
||||
} else {
|
||||
.x
|
||||
}
|
||||
})() |>
|
||||
(\(.x){
|
||||
if (input$add_p == "yes") {
|
||||
.x |>
|
||||
gtsummary::add_p() |>
|
||||
gtsummary::bold_p()
|
||||
} else {
|
||||
.x
|
||||
}
|
||||
})()
|
||||
|
||||
rv$list$table2 <- models |>
|
||||
purrr::map(regression_table) |>
|
||||
tbl_merge()
|
||||
|
||||
|
||||
rv$list$input <- input
|
||||
|
||||
|
||||
# rv$list <- list(
|
||||
# data = data,
|
||||
# check = check,
|
||||
# table1 = data |>
|
||||
# baseline_table(
|
||||
# fun.args =
|
||||
# list(
|
||||
# by = by.var
|
||||
# )
|
||||
# ) |>
|
||||
# (\(.x){
|
||||
# if (!is.null(by.var)) {
|
||||
# .x |> gtsummary::add_overall()
|
||||
# } else {
|
||||
# .x
|
||||
# }
|
||||
# })() |>
|
||||
# (\(.x){
|
||||
# if (input$add_p == "yes") {
|
||||
# .x |>
|
||||
# gtsummary::add_p() |>
|
||||
# gtsummary::bold_p()
|
||||
# } else {
|
||||
# .x
|
||||
# }
|
||||
# })(),
|
||||
# table2 = models |>
|
||||
# purrr::map(regression_table) |>
|
||||
# tbl_merge(),
|
||||
# input = input
|
||||
# )
|
||||
|
||||
output$table1 <- gt::render_gt(
|
||||
rv$list$table1 |>
|
||||
gtsummary::as_gt()
|
||||
)
|
||||
|
||||
output$table2 <- gt::render_gt(
|
||||
rv$list$table2 |>
|
||||
gtsummary::as_gt()
|
||||
)
|
||||
|
||||
output$check <- shiny::renderPlot({
|
||||
p <- plot(rv$list$check) +
|
||||
patchwork::plot_annotation(title = "Multivariable regression model checks")
|
||||
p
|
||||
# Generate checks in one column
|
||||
# layout <- sapply(seq_len(length(p)), \(.x){
|
||||
# patchwork::area(.x, 1)
|
||||
# })
|
||||
#
|
||||
# p + patchwork::plot_layout(design = Reduce(c, layout))
|
||||
|
||||
# patchwork::wrap_plots(ncol=1) +
|
||||
# patchwork::plot_annotation(title = 'Multivariable regression model checks')
|
||||
})
|
||||
},
|
||||
warning = function(warn) {
|
||||
showNotification(paste0(warn), type = "warning")
|
||||
},
|
||||
error = function(err) {
|
||||
showNotification(paste0("There was the following error. Inspect your data and adjust settings. Error: ", err), type = "err")
|
||||
}
|
||||
)
|
||||
rv$ready <- "ready"
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
shiny::conditionalPanel(
|
||||
condition = "output.uploaded == 'yes'",
|
||||
)
|
||||
|
||||
# observeEvent(input$act_start, {
|
||||
# nav_show(id = "overview",target = "Import"
|
||||
# )
|
||||
# })
|
||||
|
||||
##############################################################################
|
||||
#########
|
||||
######### Page navigation
|
||||
#########
|
||||
##############################################################################
|
||||
|
||||
shiny::observeEvent(input$act_start, {
|
||||
bslib::nav_select(id = "main_panel", selected = "Data")
|
||||
})
|
||||
|
||||
|
||||
##############################################################################
|
||||
#########
|
||||
######### Reactivity
|
||||
#########
|
||||
##############################################################################
|
||||
|
||||
output$uploaded <- shiny::reactive({
|
||||
if (is.null(rv$ds)) {
|
||||
"no"
|
||||
} else {
|
||||
"yes"
|
||||
}
|
||||
})
|
||||
|
||||
shiny::outputOptions(output, "uploaded", suspendWhenHidden = FALSE)
|
||||
|
||||
output$ready <- shiny::reactive({
|
||||
if (is.null(rv$ready)) {
|
||||
"no"
|
||||
} else {
|
||||
"yes"
|
||||
}
|
||||
})
|
||||
|
||||
shiny::outputOptions(output, "ready", suspendWhenHidden = FALSE)
|
||||
|
||||
# Reimplement from environment at later time
|
||||
# output$has_input <- shiny::reactive({
|
||||
# if (rv$input) {
|
||||
# "yes"
|
||||
# } else {
|
||||
# "no"
|
||||
# }
|
||||
# })
|
||||
|
||||
# shiny::outputOptions(output, "has_input", suspendWhenHidden = FALSE)
|
||||
|
||||
##############################################################################
|
||||
#########
|
||||
######### Downloads
|
||||
#########
|
||||
##############################################################################
|
||||
|
||||
# Could be rendered with other tables or should show progress
|
||||
# Investigate quarto render problems
|
||||
# On temp file handling: https://github.com/quarto-dev/quarto-cli/issues/3992
|
||||
output$report <- downloadHandler(
|
||||
filename = shiny::reactive({
|
||||
paste0("report.", input$output_type)
|
||||
}),
|
||||
content = function(file, type = input$output_type) {
|
||||
## Notification is not progressing
|
||||
## Presumably due to missing
|
||||
shiny::withProgress(message = "Generating the report. Hold on for a moment..", {
|
||||
rv$list |>
|
||||
write_quarto(
|
||||
output_format = type,
|
||||
input = file.path(getwd(), "www/report.qmd")
|
||||
)
|
||||
})
|
||||
file.rename(paste0("www/report.", type), file)
|
||||
}
|
||||
)
|
||||
|
||||
output$data_modified <- downloadHandler(
|
||||
filename = shiny::reactive({
|
||||
paste0("modified_data.", input$data_type)
|
||||
}),
|
||||
content = function(file, type = input$data_type) {
|
||||
if (type == "rds") {
|
||||
readr::write_rds(rv$list$data, file = file)
|
||||
} else {
|
||||
haven::write_dta(as.data.frame(rv$list$data), path = file)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
##############################################################################
|
||||
#########
|
||||
######### Clearing the session on end
|
||||
#########
|
||||
##############################################################################
|
||||
|
||||
session$onSessionEnded(function() {
|
||||
cat("Session Ended\n")
|
||||
files <- list.files("www/")
|
||||
lapply(files[!files %in% files.to.keep], \(.x){
|
||||
unlink(paste0("www/", .x), recursive = FALSE)
|
||||
print(paste(.x, "deleted"))
|
||||
})
|
||||
})
|
||||
}
|
|
@ -1,468 +0,0 @@
|
|||
# ns <- NS(id)
|
||||
|
||||
ui_elements <- list(
|
||||
##############################################################################
|
||||
#########
|
||||
######### Home panel
|
||||
#########
|
||||
##############################################################################
|
||||
"home" = bslib::nav_panel(
|
||||
title = "freesearcheR",
|
||||
shiny::markdown(readLines("www/intro.md")),
|
||||
icon = shiny::icon("home")
|
||||
),
|
||||
##############################################################################
|
||||
#########
|
||||
######### Import panel
|
||||
#########
|
||||
##############################################################################
|
||||
"import" = bslib::nav_panel(
|
||||
title = "Import",
|
||||
shiny::tagList(
|
||||
shiny::h4("Choose your data source"),
|
||||
# shiny::conditionalPanel(
|
||||
# condition = "output.has_input=='yes'",
|
||||
# # Input: Select a file ----
|
||||
# shiny::helpText("Analyses are performed on provided data")
|
||||
# ),
|
||||
# shiny::conditionalPanel(
|
||||
# condition = "output.has_input=='no'",
|
||||
# Input: Select a file ----
|
||||
shinyWidgets::radioGroupButtons(
|
||||
inputId = "source",
|
||||
selected = "env",
|
||||
# label = "Choice: ",
|
||||
choices = c(
|
||||
"File upload" = "file",
|
||||
"REDCap server" = "redcap",
|
||||
"Local data" = "env"
|
||||
),
|
||||
# checkIcon = list(
|
||||
# yes = icon("square-check"),
|
||||
# no = icon("square")
|
||||
# ),
|
||||
width = "100%"
|
||||
),
|
||||
shiny::conditionalPanel(
|
||||
condition = "input.source=='file'",
|
||||
datamods::import_file_ui("file_import",
|
||||
title = "Choose a datafile to upload",
|
||||
file_extensions = c(".csv", ".txt", ".xls", ".xlsx", ".rds", ".fst", ".sas7bdat", ".sav", ".ods", ".dta")
|
||||
)
|
||||
),
|
||||
shiny::conditionalPanel(
|
||||
condition = "input.source=='redcap'",
|
||||
m_redcap_readUI("redcap_import")
|
||||
),
|
||||
shiny::conditionalPanel(
|
||||
condition = "input.source=='env'",
|
||||
import_globalenv_ui(id = "env", title = NULL)
|
||||
),
|
||||
shiny::conditionalPanel(
|
||||
condition = "input.source=='redcap'",
|
||||
DT::DTOutput(outputId = "redcap_prev")
|
||||
),
|
||||
shiny::br(),
|
||||
shiny::actionButton(
|
||||
inputId = "act_start",
|
||||
label = "Start",
|
||||
width = "100%",
|
||||
icon = shiny::icon("play")
|
||||
),
|
||||
shiny::helpText('After importing, hit "Start" or navigate to the desired tab.'),
|
||||
shiny::br(),
|
||||
shiny::br()
|
||||
)
|
||||
),
|
||||
##############################################################################
|
||||
#########
|
||||
######### Data overview panel
|
||||
#########
|
||||
##############################################################################
|
||||
"overview" =
|
||||
# bslib::nav_panel_hidden(
|
||||
bslib::nav_panel(
|
||||
# value = "overview",
|
||||
title = "Data",
|
||||
bslib::navset_bar(
|
||||
fillable = TRUE,
|
||||
bslib::nav_panel(
|
||||
title = "Summary & filter",
|
||||
tags$h3("Data summary and filtering"),
|
||||
fluidRow(
|
||||
shiny::column(
|
||||
width = 9,
|
||||
shiny::tags$p(
|
||||
"Below is a short summary table of the provided data.
|
||||
On the right hand side you have the option to create filters.
|
||||
At the bottom you'll find a raw overview of the original vs the modified data."
|
||||
)
|
||||
)
|
||||
),
|
||||
fluidRow(
|
||||
# column(
|
||||
# width = 3,
|
||||
# shiny::uiOutput("filter_vars"),
|
||||
# shiny::conditionalPanel(
|
||||
# condition = "(typeof input.filter_vars !== 'undefined' && input.filter_vars.length > 0)",
|
||||
# datamods::filter_data_ui("filtering", max_height = "500px")
|
||||
# )
|
||||
# ),
|
||||
# column(
|
||||
# width = 9,
|
||||
# DT::DTOutput(outputId = "filtered_table"),
|
||||
# tags$b("Code dplyr:"),
|
||||
# verbatimTextOutput(outputId = "filtered_code")
|
||||
# ),
|
||||
shiny::column(
|
||||
width = 9,
|
||||
data_summary_ui(id = "data_summary")
|
||||
),
|
||||
shiny::column(
|
||||
width = 3,
|
||||
IDEAFilter::IDEAFilter_ui("data_filter"),
|
||||
shiny::tags$br(),
|
||||
shiny::tags$b("Filter code:"),
|
||||
shiny::verbatimTextOutput(outputId = "filtered_code"),
|
||||
shiny::tags$br()
|
||||
)
|
||||
),
|
||||
fluidRow(
|
||||
column(
|
||||
width = 6,
|
||||
tags$b("Original data:"),
|
||||
# verbatimTextOutput("original"),
|
||||
verbatimTextOutput("original_str")
|
||||
),
|
||||
column(
|
||||
width = 6,
|
||||
tags$b("Modified data:"),
|
||||
# verbatimTextOutput("modified"),
|
||||
verbatimTextOutput("modified_str")
|
||||
)
|
||||
)
|
||||
),
|
||||
# bslib::nav_panel(
|
||||
# title = "Overview",
|
||||
# DT::DTOutput(outputId = "table")
|
||||
# ),
|
||||
bslib::nav_panel(
|
||||
title = "Modify",
|
||||
tags$h3("Subset, rename and convert variables"),
|
||||
fluidRow(
|
||||
shiny::column(
|
||||
width = 9,
|
||||
shiny::tags$p("Below, you can subset the data (by not selecting the variables to exclude on applying changes), rename variables, set new labels (for nicer tables in the analysis report) and change variable classes.
|
||||
Italic text can be edited/changed.
|
||||
On the right, you can create and modify factor/categorical variables as well as resetting the data to the originally imported data.")
|
||||
)
|
||||
),
|
||||
fluidRow(
|
||||
shiny::column(
|
||||
width = 9,
|
||||
update_variables_ui("vars_update"),
|
||||
shiny::tags$br()
|
||||
),
|
||||
shiny::column(
|
||||
width = 3,
|
||||
tags$h4("Create new variables"),
|
||||
shiny::tags$br(),
|
||||
shiny::actionButton(
|
||||
inputId = "modal_cut",
|
||||
label = "Create factor variable",
|
||||
width = "100%"
|
||||
),
|
||||
shiny::tags$br(),
|
||||
shiny::helpText("Create factor/categorical variable from an other value."),
|
||||
shiny::tags$br(),
|
||||
shiny::tags$br(),
|
||||
shiny::actionButton(
|
||||
inputId = "modal_update",
|
||||
label = "Reorder factor levels",
|
||||
width = "100%"
|
||||
),
|
||||
shiny::tags$br(),
|
||||
shiny::helpText("Reorder the levels of factor/categorical variables."),
|
||||
shiny::tags$br(),
|
||||
shiny::tags$br(),
|
||||
shiny::actionButton(
|
||||
inputId = "modal_column",
|
||||
label = "New variable",
|
||||
width = "100%"
|
||||
),
|
||||
shiny::tags$br(),
|
||||
shiny::helpText("Create a new variable/column based on an R-expression."),
|
||||
shiny::tags$br(),
|
||||
shiny::tags$br(),
|
||||
tags$h4("Restore"),
|
||||
shiny::actionButton(
|
||||
inputId = "data_reset",
|
||||
label = "Restore original data",
|
||||
width = "100%"
|
||||
),
|
||||
shiny::tags$br(),
|
||||
shiny::helpText("Reset to original imported dataset. Careful! There is no un-doing."),
|
||||
shiny::tags$br() # ,
|
||||
# shiny::tags$br(),
|
||||
# shiny::tags$br(),
|
||||
# IDEAFilter::IDEAFilter_ui("data_filter") # ,
|
||||
# shiny::actionButton("save_filter", "Apply the filter")
|
||||
)
|
||||
# datamods::update_variables_ui("vars_update")
|
||||
)
|
||||
),
|
||||
bslib::nav_panel(
|
||||
title = "Browser",
|
||||
tags$h3("Browse the provided data"),
|
||||
shiny::tags$p(
|
||||
"Below is a data table with all the modified data provided to browse and understand data."
|
||||
),
|
||||
shinyWidgets::html_dependency_winbox(),
|
||||
# fluidRow(
|
||||
# column(
|
||||
# width = 3,
|
||||
# shiny::uiOutput("filter_vars"),
|
||||
# shiny::conditionalPanel(
|
||||
# condition = "(typeof input.filter_vars !== 'undefined' && input.filter_vars.length > 0)",
|
||||
# datamods::filter_data_ui("filtering", max_height = "500px")
|
||||
# )
|
||||
# ),
|
||||
# column(
|
||||
# width = 9,
|
||||
# DT::DTOutput(outputId = "filtered_table"),
|
||||
# tags$b("Code dplyr:"),
|
||||
# verbatimTextOutput(outputId = "filtered_code")
|
||||
# ),
|
||||
# shiny::column(
|
||||
# width = 8,
|
||||
toastui::datagridOutput(outputId = "table_mod") # ,
|
||||
# shiny::tags$b("Reproducible code:"),
|
||||
# shiny::verbatimTextOutput(outputId = "filtered_code")
|
||||
# ),
|
||||
# shiny::column(
|
||||
# width = 4,
|
||||
# shiny::actionButton("modal_cut", "Create factor from a variable"),
|
||||
# shiny::tags$br(),
|
||||
# shiny::tags$br(),
|
||||
# shiny::actionButton("modal_update", "Reorder factor levels")#,
|
||||
# # shiny::tags$br(),
|
||||
# # shiny::tags$br(),
|
||||
# # IDEAFilter::IDEAFilter_ui("data_filter") # ,
|
||||
# # shiny::actionButton("save_filter", "Apply the filter")
|
||||
# )
|
||||
# )
|
||||
)
|
||||
|
||||
|
||||
# column(
|
||||
# 8,
|
||||
# shiny::verbatimTextOutput("filtered_code"),
|
||||
# DT::DTOutput("filtered_table")
|
||||
# ),
|
||||
# column(4, IDEAFilter::IDEAFilter_ui("data_filter"))
|
||||
)
|
||||
),
|
||||
##############################################################################
|
||||
#########
|
||||
######### Data analyses panel
|
||||
#########
|
||||
##############################################################################
|
||||
"analyze" =
|
||||
# bslib::nav_panel_hidden(
|
||||
bslib::nav_panel(
|
||||
# value = "analyze",
|
||||
title = "Analyses",
|
||||
bslib::navset_bar(
|
||||
title = "",
|
||||
# bslib::layout_sidebar(
|
||||
# fillable = TRUE,
|
||||
sidebar = bslib::sidebar(
|
||||
shiny::helpText(em("Please specify relevant settings for your data, and press 'Analyse'")),
|
||||
shiny::uiOutput("outcome_var"),
|
||||
shiny::radioButtons(
|
||||
inputId = "all",
|
||||
label = "Specify covariables",
|
||||
inline = TRUE, selected = 2,
|
||||
choiceNames = c(
|
||||
"Yes",
|
||||
"No"
|
||||
),
|
||||
choiceValues = c(1, 2)
|
||||
),
|
||||
shiny::conditionalPanel(
|
||||
condition = "input.all==1",
|
||||
shiny::uiOutput("include_vars")
|
||||
),
|
||||
shiny::uiOutput("strat_var"),
|
||||
shiny::helpText("Only factor/categorical variables are available for stratification. Go back to the 'Data' tab to reclass a variable if it's not on the list."),
|
||||
shiny::conditionalPanel(
|
||||
condition = "input.strat_var!='none'",
|
||||
shiny::radioButtons(
|
||||
inputId = "add_p",
|
||||
label = "Compare strata?",
|
||||
selected = "no",
|
||||
inline = TRUE,
|
||||
choices = list(
|
||||
"No" = "no",
|
||||
"Yes" = "yes"
|
||||
)
|
||||
),
|
||||
shiny::helpText("Option to perform statistical comparisons between strata in baseline table.")
|
||||
),
|
||||
shiny::radioButtons(
|
||||
inputId = "specify_factors",
|
||||
label = "Specify categorical variables?",
|
||||
selected = "no",
|
||||
inline = TRUE,
|
||||
choices = list(
|
||||
"Yes" = "yes",
|
||||
"No" = "no"
|
||||
)
|
||||
),
|
||||
shiny::conditionalPanel(
|
||||
condition = "input.specify_factors=='yes'",
|
||||
shiny::uiOutput("factor_vars")
|
||||
),
|
||||
bslib::input_task_button(
|
||||
id = "load",
|
||||
label = "Analyse",
|
||||
icon = shiny::icon("pencil", lib = "glyphicon"),
|
||||
label_busy = "Working...",
|
||||
icon_busy = fontawesome::fa_i("arrows-rotate",
|
||||
class = "fa-spin",
|
||||
"aria-hidden" = "true"
|
||||
),
|
||||
type = "secondary",
|
||||
auto_reset = TRUE
|
||||
),
|
||||
shiny::helpText("If you change the parameters, press 'Analyse' again to update the tables"),
|
||||
# shiny::conditionalPanel(
|
||||
# condition = "output.ready=='yes'",
|
||||
shiny::tags$hr(),
|
||||
shiny::h4("Download results"),
|
||||
shiny::helpText("Choose your favourite output file format for further work, and download, when the analyses are done."),
|
||||
shiny::selectInput(
|
||||
inputId = "output_type",
|
||||
label = "Output format",
|
||||
selected = NULL,
|
||||
choices = list(
|
||||
"MS Word" = "docx",
|
||||
"LibreOffice" = "odt"
|
||||
# ,
|
||||
# "PDF" = "pdf",
|
||||
# "All the above" = "all"
|
||||
)
|
||||
),
|
||||
shiny::br(),
|
||||
# Button
|
||||
shiny::downloadButton(
|
||||
outputId = "report",
|
||||
label = "Download report",
|
||||
icon = shiny::icon("download")
|
||||
),
|
||||
shiny::helpText("If choosing to output to MS Word, please note, that when opening the document, two errors will pop-up. Choose to repair and choose not to update references. The issue is being worked on. You can always choose LibreOffice instead."),
|
||||
shiny::tags$hr(),
|
||||
shiny::h4("Download data"),
|
||||
shiny::helpText("Choose your favourite output data format to download the modified data."),
|
||||
shiny::selectInput(
|
||||
inputId = "data_type",
|
||||
label = "Data format",
|
||||
selected = NULL,
|
||||
choices = list(
|
||||
"R" = "rds",
|
||||
"stata" = "dta"
|
||||
)
|
||||
),
|
||||
shiny::br(),
|
||||
# Button
|
||||
shiny::downloadButton(
|
||||
outputId = "data_modified",
|
||||
label = "Download data",
|
||||
icon = shiny::icon("download")
|
||||
)
|
||||
),
|
||||
bslib::nav_panel(
|
||||
title = "Baseline characteristics",
|
||||
gt::gt_output(outputId = "table1")
|
||||
),
|
||||
bslib::nav_panel(
|
||||
title = "Regression table",
|
||||
gt::gt_output(outputId = "table2")
|
||||
),
|
||||
bslib::nav_panel(
|
||||
title = "Regression checks",
|
||||
shiny::plotOutput(outputId = "check")
|
||||
)
|
||||
)
|
||||
),
|
||||
##############################################################################
|
||||
#########
|
||||
######### Documentation panel
|
||||
#########
|
||||
##############################################################################
|
||||
"docs" = bslib::nav_item(
|
||||
# shiny::img(shiny::icon("book")),
|
||||
shiny::tags$a(
|
||||
href = "https://agdamsbo.github.io/freesearcheR/",
|
||||
"Docs (external)",
|
||||
target = "_blank",
|
||||
rel = "noopener noreferrer"
|
||||
)
|
||||
)
|
||||
# bslib::nav_panel(
|
||||
# title = "Documentation",
|
||||
# # shiny::tags$iframe("www/docs.html", height=600, width=535),
|
||||
# shiny::htmlOutput("docs_file"),
|
||||
# shiny::br()
|
||||
# )
|
||||
)
|
||||
|
||||
# Initial attempt at creating light and dark versions
|
||||
light <- custom_theme()
|
||||
dark <- custom_theme(
|
||||
bg = "#000",
|
||||
fg = "#fff"
|
||||
)
|
||||
|
||||
# Fonts to consider:
|
||||
# https://webdesignerdepot.com/17-open-source-fonts-youll-actually-love/
|
||||
|
||||
ui <- bslib::page_fixed(
|
||||
shiny::tags$head(includeHTML(("www/umami-app.html"))),
|
||||
shiny::tags$style(
|
||||
type = "text/css",
|
||||
# add the name of the tab you want to use as title in data-value
|
||||
shiny::HTML(
|
||||
".container-fluid > .nav > li >
|
||||
a[data-value='freesearcheR'] {font-size: 28px}"
|
||||
)
|
||||
),
|
||||
title = "freesearcheR",
|
||||
theme = light,
|
||||
shiny::useBusyIndicators(),
|
||||
bslib::page_navbar(
|
||||
# title = "freesearcheR",
|
||||
id = "main_panel",
|
||||
# header = shiny::tags$header(shiny::p("Data is only stored temporarily for analysis and deleted immediately afterwards.")),
|
||||
ui_elements$home,
|
||||
ui_elements$import,
|
||||
ui_elements$overview,
|
||||
ui_elements$analyze,
|
||||
bslib::nav_spacer(),
|
||||
ui_elements$docs,
|
||||
# bslib::nav_spacer(),
|
||||
# bslib::nav_item(shinyWidgets::circleButton(inputId = "mode", icon = icon("moon"),status = "primary")),
|
||||
fillable = FALSE,
|
||||
footer = shiny::tags$footer(
|
||||
style = "background-color: #14131326; padding: 4px; text-align: center; bottom: 0; width: 100%;",
|
||||
shiny::p(
|
||||
style = "margin: 1",
|
||||
"Data is only stored for analyses and deleted immediately afterwards."
|
||||
),
|
||||
shiny::p(
|
||||
style = "margin: 1; color: #888;",
|
||||
"Andreas G Damsbo | AGPLv3 license | ", shiny::tags$a("Source on Github", href = "https://github.com/agdamsbo/freesearcheR/", target = "_blank", rel = "noopener noreferrer")
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
Loading…
Add table
Reference in a new issue