diff --git a/CHANGELOG.md b/CHANGELOG.md index 1882a43..fd217da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,4 @@ ### 0.??.? - ##### features - added checkboxes input form; - added button to reset data in forms; diff --git a/app.R b/app.R index fbeced8..5759129 100644 --- a/app.R +++ b/app.R @@ -54,7 +54,7 @@ SCHEME_MAIN <- readxl::read_xlsx(FILE_SCHEME) %>% # get list of simple inputs inputs_simple_list <- SCHEME_MAIN %>% - dplyr::filter(!form_type %in% c("inline_table", "description")) %>% + dplyr::filter(!form_type %in% c("inline_table", "description", "description_header")) %>% dplyr::distinct(form_id, form_type) %>% tibble::deframe() @@ -179,148 +179,9 @@ inline_tables <- purrr::map( } ) -# создание объектов для ввода -# функция -# create_forms <- function(form_id, form_label, form_type) { -# # check if have condition -# condition <- dplyr::filter(SCHEME_MAIN, form_id == {{ form_id }}) %>% -# dplyr::distinct(condition) %>% -# dplyr::pull() - -# choices <- dplyr::filter(SCHEME_MAIN, form_id == {{ form_id }}) %>% -# dplyr::pull(choices) - -# # simple text or number input -# if (form_type %in% c("text", "number")) { -# form <- shiny::textAreaInput( -# inputId = form_id, -# label = tags$span(style = "color: #444444; font-weight: 550;", form_label), -# rows = 1 -# ) -# } - -# # simple date input -# if (form_type == "date") { -# # supress warning while trying keep data form empty by default -# suppressWarnings({ -# form <- dateInput( -# inputId = form_id, -# label = tags$span(style = "color: #444444; font-weight: 550;", form_label), -# value = NA, # keep empty -# format = "dd.mm.yyyy", -# weekstart = 1, -# language = "ru" -# ) -# }) -# } - -# # еденичный выбор -# if (form_type == "select_one") { -# form <- selectizeInput( -# inputId = form_id, -# label = tags$span(style = "color: #444444; font-weight: 550;", form_label), -# choices = choices, -# selected = NULL, -# options = list( -# create = FALSE, -# onInitialize = I('function() { this.setValue(""); }') -# ) -# ) -# } - -# # множественный выбор -# if (form_type == "select_multiple") { -# form <- selectizeInput( -# inputId = form_id, -# label = tags$span(style = "color: #444444; font-weight: 550;", form_label), -# choices = choices, -# selected = NULL, -# multiple = TRUE, -# options = list( -# create = FALSE, -# onInitialize = I('function() { this.setValue(""); }') -# ) -# ) -# } - -# # множественный выбор -# if (form_type == "radio") { -# form <- radioButtons( -# inputId = form_id, -# label = tags$span(style = "color: #444444; font-weight: 550;", form_label), -# choices = choices, -# selected = character(0) -# ) -# } - -# if (form_type == "checkbox") { -# form <- checkboxGroupInput( -# inputId = form_id, -# # label = tags$span(style = "color: #444444; font-weight: 550;", form_label), -# label = h6(form_label), -# choices = choices, -# selected = character(0) -# ) -# } - -# # вложенная таблица -# if (form_type == "inline_table") { -# form <- rHandsontableOutput(outputId = form_id) -# } - -# # description part -# if (form_type == "description") { -# form <- div(HTML(form_label), style = "color:Gray;font-size: 90%;") -# } - -# # если есть условие создать кондитионал панель -# if (!is.na(condition)) { -# form <- conditionalPanel( -# condition = condition, -# form -# ) -# } - -# form -# } - -# GENERATE UI ================================== -# functions for making cards -# make_cards_fn <- function(sub_group) { - -# subgroups_inputs <- df_forms %>% -# dplyr::filter(subgroup == {{sub_group}}) %>% -# dplyr::distinct(form_id, form_label, form_type) - -# subgroups_inputs2 <- SCHEME_MAIN |> -# dplyr::filter(subgroup == {{sub_group}}) %>% -# dplyr::distinct(form_id, form_label, form_type, condition) - -# print(subgroups_inputs2) - -# bslib::card( -# bslib::card_header(sub_group, container = htmltools::h5), -# full_screen = TRUE, -# width = "4000px", -# bslib::card_body( -# fill = TRUE, -# # передаем все аргументы в функцию для создания елементов -# purrr::pmap( -# .l = subgroups_inputs, -# .f = utils$create_forms, -# scheme = SCHEME_MAIN -# ) -# ) -# ) -# } - # get pages list pages_list <- unique(SCHEME_MAIN$part) -# # get all forms df -# df_forms <- SCHEME_MAIN %>% -# dplyr::distinct(part, subgroup, form_id, form_label, form_type) - # generate nav panels for each page nav_panels_list <- purrr::map( .x = pages_list, @@ -328,38 +189,6 @@ nav_panels_list <- purrr::map( main_scheme = SCHEME_MAIN ) -# nav_panels_list <- purrr::map( -# .x = pages_list, -# .f = \(x_page) { - -# # get info about inputs for current page -# page_forms <- SCHEME_MAIN %>% -# dplyr::filter(part == {{x_page}}) %>% -# dplyr::distinct(subgroup, form_id, form_label, form_type) - -# # get list of columns -# cols_list <- unique(page_forms$subgroup) - -# # making cards -# cards <- purrr::map( -# .x = cols_list, -# .f = utils$make_cards_fn, -# main_scheme = SCHEME_MAIN -# ) - -# # make page wrap -# page_wrap <- bslib::layout_column_wrap( -# # width = "350px", height = NULL, #was 800 -# width = 1 / 4, height = NULL, # was 800 -# fixed_width = TRUE, -# !!!cards # unpack list of cards -# ) - -# # add panel wrap to nav_panel -# bslib::nav_panel(x_page, page_wrap) -# } -# ) - # UI ======================= ui <- page_sidebar( title = config$header, @@ -371,7 +200,9 @@ ui <- page_sidebar( textOutput("status_message2"), actionButton("load_data_button", "Загрузить данные", icon("pencil", lib = "font-awesome")), downloadButton("downloadData", "Экспорт в .xlsx"), - downloadButton("downloadDocx", "get .docx (test only)") + downloadButton("downloadDocx", "get .docx (test only)"), + position = "left", + open = list(mobile = "always") ), # list of rendered panels navset_card_underline( @@ -462,17 +293,20 @@ server <- function(input, output) { # for `number` type: if in `choices` column has values then parsing them to range validation # value `0; 250` -> transform to rule validation value from 0 to 250 if (form_type == "number") { + iv$add_rule(x_input_id, function(x) { # exit if empty if (check_for_empty_data(x)) { return(NULL) } # check for numeric - if (grepl("^[-]?(\\d*\\,\\d+|\\d+\\,\\d*|\\d+)$", x)) NULL else "Значение должно быть числом." + # if (grepl("^[-]?(\\d*\\,\\d+|\\d+\\,\\d*|\\d+)$", x)) NULL else "Значение должно быть числом." + if (grepl("^[+-]?\\d*[\\.|\\,]?\\d+$", x)) NULL else "Значение должно быть числом." }) + # проверка на соответствие диапазону значений if (!is.na(choices)) { - # разделить на числа + # разделить на несколько елементов ranges <- as.integer(stringr::str_split_1(choices, "; ")) # проверка на кол-во значений @@ -482,12 +316,17 @@ server <- function(input, output) { iv$add_rule( x_input_id, function(x) { + + # замена разделителя десятичных цифр + x <- stringr::str_replace(x, ",", ".") + # exit if empty if (check_for_empty_data(x)) { return(NULL) } + # check for currect value - if (between(as.integer(x), ranges[1], ranges[2])) { + if (between(as.double(x), ranges[1], ranges[2])) { NULL } else { glue::glue("Значение должно быть между {ranges[1]} и {ranges[2]}.") diff --git a/configs/schemas/main.xlsx b/configs/schemas/main.xlsx index 4c83c5b..0ea6bf2 100644 Binary files a/configs/schemas/main.xlsx and b/configs/schemas/main.xlsx differ diff --git a/helpers/functions.R b/helpers/functions.R index 7c5aaf4..bd1c908 100644 --- a/helpers/functions.R +++ b/helpers/functions.R @@ -28,6 +28,7 @@ get_dummy_df <- function() { #' #' Needed for proper data validation. check_for_empty_data <- function(value_to_check) { + # for any 0-length if (length(value_to_check) == 0) return(TRUE) diff --git a/modules/utils.R b/modules/utils.R index b988484..f0d60fe 100644 --- a/modules/utils.R +++ b/modules/utils.R @@ -5,7 +5,6 @@ 'Module path: "', basename(box::file()), '"' ) } -# ================ # asdasd #' @export @@ -22,7 +21,7 @@ make_panels <- function(page_name, main_scheme) { # making cards cards <- purrr::map( .x = cols_list, - .f = make_cards_fn, + .f = render_cards_with_forms, main_scheme = main_scheme ) @@ -43,8 +42,27 @@ make_panels <- function(page_name, main_scheme) { } # functions for making cards +# DO THIS INSTEAD !!! #' @export -make_cards_fn <- function(sub_group, main_scheme) { +# make_forms_by_scheme <- function(tool_id, main_scheme, ns) { + +# ns <- NS(ns(tool_id)) + +# main_scheme <<- main_scheme +# subgroup_schema <- main_scheme |> +# dplyr::filter(tool_id == {{tool_id}}) + +# purrr::pmap( +# .l = dplyr::distinct(subgroup_schema, form_id, form_label, form_type), +# .f = render_forms, +# schema = subgroup_schema, +# ns = ns +# ) +# } + +# functions for making cards +#' @export +render_cards_with_forms <- function(sub_group, main_scheme) { main_scheme <<- main_scheme subgroups_inputs <- main_scheme |> @@ -54,13 +72,14 @@ make_cards_fn <- function(sub_group, main_scheme) { bslib::card( bslib::card_header(sub_group, container = htmltools::h5), full_screen = TRUE, + fill = TRUE, width = "4000px", bslib::card_body( fill = TRUE, # передаем все аргументы в функцию для создания елементов purrr::pmap( .l = subgroups_inputs, - .f = create_forms, + .f = render_forms, main_scheme = main_scheme ) ) @@ -70,20 +89,52 @@ make_cards_fn <- function(sub_group, main_scheme) { # UI RELATED ============================ #' @export #' @param TEST s -create_forms <- function( +render_forms <- function( form_id, form_label, form_type, main_scheme ) { + filterd_line <- dplyr::filter(main_scheme, form_id == {{form_id}}) + # check if have condition - condition <- dplyr::filter(main_scheme, form_id == {{form_id}}) |> - dplyr::distinct(condition) |> + condition <- unique(filterd_line$condition) + + # get choices from schema + choices <- filterd_line$choices + + # get choices from schema + description <- unique(filterd_line) |> + dplyr::filter(!is.na(form_description)) |> + dplyr::distinct(form_description) |> dplyr::pull() - choices <- dplyr::filter(main_scheme, form_id == {{form_id}}) |> - dplyr::pull(choices) + # описание + if (length(description) > 1) { + rlang::abort(sprintf( + "%s - более чем 1 уникальный вариант описания:\n%s", form_id, paste0(description, collapse = "\n") + )) + } else if (length(description) == 0) { + description <- NA + } + + # отдельно создаем заголовки + label <- if (is.na(description) && is.na(form_label)) { + NULL + } else { + shiny::tagList( + if (!is.na(form_label)) { + shiny::span(form_label, style = "color: #444444; font-weight: 550; line-height: 1.4;") + # если в схеме есть поле с описанием - добавлеяем его следующей строчкой + }, + if (!is.na(description) && !is.na(form_label)) shiny::br(), + if (!is.na(description)) { + shiny::span(shiny::markdown(description)) |> htmltools::tagAppendAttributes(style = "color:gray; font-size:small; line-height: 1.4;") + # span(description, style = "color:gray; font-size:small;") + } + ) + } # simple text or number input if (form_type == "text") { @@ -93,7 +144,7 @@ create_forms <- function( form <- shiny::textAreaInput( inputId = form_id, - label = shiny::span(style = "color: #444444; font-weight: 550;", form_label), + label = label, rows = rows_to_show ) } @@ -101,7 +152,7 @@ create_forms <- function( if (form_type == "number") { form <- shiny::textAreaInput( inputId = form_id, - label = shiny::span(style = "color: #444444; font-weight: 550;", form_label), + label = label, rows = 1 ) } @@ -112,7 +163,7 @@ create_forms <- function( suppressWarnings({ form <- shiny::dateInput( inputId = form_id, - label = shiny::span(style = "color: #444444; font-weight: 550;", form_label), + label = label, value = NA, # keep empty format = "dd.mm.yyyy", weekstart = 1, @@ -125,7 +176,7 @@ create_forms <- function( if (form_type == "select_one") { form <- shiny::selectizeInput( inputId = form_id, - label = shiny::span(style = "color: #444444; font-weight: 550;", form_label), + label = label, choices = choices, selected = NULL, options = list( @@ -139,7 +190,7 @@ create_forms <- function( if (form_type == "select_multiple") { form <- shiny::selectizeInput( inputId = form_id, - label = shiny::span(style = "color: #444444; font-weight: 550;", form_label), + label = label, choices = choices, selected = NULL, multiple = TRUE, @@ -154,7 +205,7 @@ create_forms <- function( if (form_type == "radio") { form <- shiny::radioButtons( inputId = form_id, - label = shiny::span(style = "color: #444444; font-weight: 550;", form_label), + label = label, choices = choices, selected = character(0) ) @@ -163,7 +214,7 @@ create_forms <- function( if (form_type == "checkbox") { form <- shiny::checkboxGroupInput( inputId = form_id, - # label = shiny::span(style = "color: #444444; font-weight: 550;", form_label), + # label = label, label = shiny::h6(form_label), choices = choices, selected = character(0) @@ -177,7 +228,18 @@ create_forms <- function( # description part if (form_type == "description") { - form <- shiny::div(shiny::HTML(form_label), style = "color:Gray;font-size: 90%;") + if(is.na(form_label)) { + form <- shiny::hr(style = "margin-bottom: -3px;") + } else { + form <- shiny::div(shiny::HTML(form_label), style = "color: Gray; font-size: 90%;") + } + } + + if (form_type == "description_header") { + form <- shiny::h5( + label, + style = "margin-bottom: -8px; margin-top: 10px;" + ) } # если есть условие создать кондитионал панель @@ -187,6 +249,7 @@ create_forms <- function( form ) } + form }