@@ -22,9 +22,9 @@ CM <- local({ # _C_hecked _M_odule
22
22
app_creator_feedback_ui <- function (id , ui ) {
23
23
id <- paste(c(id , " validator" ), collapse = " -" )
24
24
ns <- shiny :: NS(id )
25
-
25
+
26
26
hide <- function (e ) shiny :: tags [[" div" ]](e , style = " display: none" )
27
-
27
+
28
28
res <- list (
29
29
shiny :: uiOutput(ns(" ui" )),
30
30
hide(shiny :: checkboxInput(inputId = ns(" show_ui" ), label = NULL )),
@@ -56,7 +56,7 @@ CM <- local({ # _C_hecked _M_odule
56
56
return (res )
57
57
})
58
58
shiny :: outputOptions(output , " ui" , suspendWhenHidden = FALSE )
59
-
59
+
60
60
if (length(error_messages ) == 0 ) {
61
61
shiny :: updateCheckboxInput(inputId = " show_ui" , value = TRUE )
62
62
}
@@ -154,67 +154,67 @@ CM <- local({ # _C_hecked _M_odule
154
154
error_count_by_dataset [[i_dataset ]] <- length(info [[" errors" ]])
155
155
error_count <- error_count + length(info [[" errors" ]])
156
156
}
157
-
157
+
158
158
as_items <- function (x ) htmltools :: p(htmltools :: HTML(paste(" \u 2022" , x )))
159
-
159
+
160
160
if (error_count == 0 ) NULL
161
161
else if (dataset_count == 1 ) {
162
162
# single dataset
163
163
res <- res_by_dataset [[1 ]]
164
164
res [[" errors" ]] <- Map(as_items , res [[" errors" ]])
165
165
} else {
166
166
# multiple datasets
167
-
167
+
168
168
# FIXME(miguel): We don't do merge "warnings" here because it's a feature that goes unused and we will
169
169
# remove it soon. We can't remove it _now_ because it would still require minor fixes
170
170
# in at least five different packages and we want to roll a CM bugfix (unrelated to
171
171
# the "multiple dataset" feature reporting) while avoiding cascading work.
172
172
errors <- list ()
173
-
173
+
174
174
dataset_names <- names(afmm [[" datasets" ]])
175
-
175
+
176
176
errors <- c(
177
177
list (htmltools :: p(htmltools :: HTML(
178
178
" Issues have been grouped by input dataset. Expand/collapse the elements below to inspect them:"
179
179
)))
180
180
)
181
-
181
+
182
182
details_extra <- " open"
183
183
for (i_dataset in seq_len(dataset_count )){
184
184
if (error_count_by_dataset [[i_dataset ]] == 0 ) next
185
-
185
+
186
186
details_pre <- htmltools :: HTML(
187
187
sprintf('
188
188
<details %s>
189
189
<summary style="display:list-item"><b>%s</b></summary>
190
190
' , details_extra , names(afmm [[" data" ]]))[[i_dataset ]]
191
191
)
192
192
details_extra <- " "
193
-
193
+
194
194
details_post <- htmltools :: HTML(" </details>" )
195
-
195
+
196
196
errors <- c(errors , list (details_pre ))
197
-
197
+
198
198
errors <- c(
199
- errors ,
199
+ errors ,
200
200
list (htmltools :: HTML(" <div style='padding: 0.5rem; margin-bottom: 1rem; background-color: #FFFFFF55;
201
201
border: 1px solid #AAAAAA; border-radius: 4px;'>" )),
202
202
Map(as_items , res_by_dataset [[i_dataset ]][[" errors" ]]),
203
203
list (htmltools :: HTML(" </div>" ))
204
204
)
205
-
205
+
206
206
errors <- c(errors , list (details_post ))
207
-
207
+
208
208
res [[" errors" ]] <- errors
209
209
}
210
210
}
211
211
}
212
-
212
+
213
213
return (res )
214
214
})
215
215
216
216
app_creator_feedback_server(
217
- id = module_id , warning_messages = fb [[" warnings" ]], error_messages = fb [[" errors" ]],
217
+ id = module_id , warning_messages = fb [[" warnings" ]], error_messages = fb [[" errors" ]],
218
218
preface = fb [[" preface" ]]
219
219
)
220
220
@@ -223,7 +223,7 @@ CM <- local({ # _C_hecked _M_odule
223
223
afmm_and_args <- append(list (afmm = afmm ), args )
224
224
afmm <- do.call(map_afmm_fn , afmm_and_args )
225
225
}
226
-
226
+
227
227
res <- try(module_server(afmm ), silent = TRUE )
228
228
}
229
229
@@ -387,37 +387,37 @@ CM <- local({ # _C_hecked _M_odule
387
387
388
388
return (NULL )
389
389
}
390
-
390
+
391
391
generate_map_afmm_function <- function (spec , module_name ) {
392
392
stopifnot(spec $ kind == " group" )
393
-
393
+
394
394
# TODO: At the time of writing, this code generator is only used by dv.explorer.parameter and it covers its needs.
395
395
# It modifies afmm[["filtered_dataset"]] based on parameters flagged as "map_character_to_factor"
396
396
# so that specific columns of target datasets are transformed to factors prior to going into a module.
397
397
#
398
398
# In order to complete this functionality, we would have to map afmm[["unfiltered_dataset"]] as well
399
- # as afmm[["data"]]. Moreover, we would have to look for "map_character_to_factor" flags inside possibly
399
+ # as afmm[["data"]]. Moreover, we would have to look for "map_character_to_factor" flags inside possibly
400
400
# nested column definitions, such as those used in papo.
401
-
401
+
402
402
res <- character (0 )
403
-
403
+
404
404
push <- function (s ) res <<- c(res , s )
405
405
push(" function(afmm, " )
406
406
param_names <- paste(names(spec $ elements ), collapse = " ," )
407
407
push(param_names )
408
408
push(" ){\n " )
409
-
409
+
410
410
push(" res <- afmm\n " )
411
-
411
+
412
412
elements_that_require_mapping <- character (0 )
413
413
for (elem_name in names(spec $ elements ))
414
414
if (isTRUE(attr(spec $ elements [[elem_name ]], " map_character_to_factor" )))
415
415
elements_that_require_mapping <- c(elements_that_require_mapping , elem_name )
416
-
416
+
417
417
if (length(elements_that_require_mapping )) {
418
418
push(" mapping_summary <- character(0)\n " )
419
419
push(" for(ds_name in names(afmm[['data']])){\n " )
420
- push(" ds <- afmm[['data']][[ds_name]]\n " )
420
+ push(" ds <- afmm[['data']][[ds_name]]\n " )
421
421
for (elem_name in elements_that_require_mapping ){
422
422
elem <- spec $ elements [[elem_name ]]
423
423
stopifnot(elem $ kind == " col" )
@@ -429,9 +429,9 @@ CM <- local({ # _C_hecked _M_odule
429
429
push(" }\n " )
430
430
}
431
431
push(" }\n " )
432
-
432
+
433
433
push(" if(length(mapping_summary)){\n " )
434
-
434
+
435
435
push(
436
436
paste0(
437
437
" warning_message <- paste0('[" , module_name ,
@@ -441,25 +441,25 @@ CM <- local({ # _C_hecked _M_odule
441
441
" warning(warning_message)\n "
442
442
)
443
443
)
444
-
444
+
445
445
push(" res[['filtered_dataset']] <- shiny::reactive({\n " )
446
446
push(" res <- afmm[['filtered_dataset']]()\n " )
447
-
447
+
448
448
for (elem_name in elements_that_require_mapping ){
449
449
elem <- spec $ elements [[elem_name ]]
450
450
dataset_name <- elem [[" dataset_name" ]]
451
-
451
+
452
452
push(sprintf(" if (is.character(res[[%s]][[%s]])) {\n " , dataset_name , elem_name ))
453
453
push(sprintf(" res[[%s]][[%s]] <- " , dataset_name , elem_name ))
454
454
push(sprintf(" as.factor(res[[%s]][[%s]])\n " , dataset_name , elem_name ))
455
455
push(" }\n " )
456
456
}
457
-
457
+
458
458
push(" return(res)\n " )
459
459
push(" })\n " )
460
460
push(" }\n " )
461
461
}
462
-
462
+
463
463
push(" return(res)\n " )
464
464
push(" }\n " )
465
465
@@ -480,10 +480,10 @@ CM <- local({ # _C_hecked _M_odule
480
480
denamespaced_spec_name <- strsplit(spec_name , " ::" )[[1 ]][[2 ]]
481
481
map_afmm_function_name <- paste0(" map_afmm_" , denamespaced_spec_name , " _auto" )
482
482
res <- c(res , sprintf(" \n\n # %s\n " , spec_name ))
483
-
483
+
484
484
res <- c(
485
485
res ,
486
- c(map_afmm_function_name , " <-" ,
486
+ c(map_afmm_function_name , " <-" ,
487
487
generate_map_afmm_function(specs [[spec_name ]], module_name = denamespaced_spec_name )) | > style_code()
488
488
)
489
489
}
@@ -570,10 +570,10 @@ CM <- local({ # _C_hecked _M_odule
570
570
return (TRUE )
571
571
}
572
572
573
- ok <- assert(err , is.character(value ),
573
+ ok <- assert(err , is.character(value ),
574
574
paste(sprintf(" The value assigned to parameter `%s` should be of type `character`" , name ),
575
575
sprintf(" and it's instead of type `%s`." , class(value )[[1 ]])))
576
-
576
+
577
577
valid_column_names <- list_columns_of_kind(dataset_value , subkind )
578
578
invalid_column_names <- value [! value %in% valid_column_names ]
579
579
wrong_subkind_column_names <- invalid_column_names [invalid_column_names %in% names(dataset_value )]
@@ -587,12 +587,12 @@ CM <- local({ # _C_hecked _M_odule
587
587
paste(
588
588
sprintf(" Variables assigned to parameter <b>`%s`</b> should refer to columns of dataset <b>`%s`</b>" ,
589
589
name , dataset_name ),
590
- sprintf(" of type `%s`, but some (<b>%s</b>) have other types (%s)." ,
590
+ sprintf(" of type `%s`, but some (<b>%s</b>) have other types (%s)." ,
591
591
type_desc , cnames , types_found_desc )
592
592
)
593
593
}
594
594
)
595
-
595
+
596
596
ok <- ok && assert(
597
597
err , length(invalid_column_names ) == 0 , {
598
598
cnames <- paste(sprintf(' "%s"' , invalid_column_names ), collapse = " , " )
@@ -609,7 +609,7 @@ CM <- local({ # _C_hecked _M_odule
609
609
if (zero_or_one_or_more ) {
610
610
min_len <- 0
611
611
if (one_or_more ) min_len <- 1
612
-
612
+
613
613
ok <- ok && assert(
614
614
err ,
615
615
length(value ) > = min_len , {
@@ -761,7 +761,7 @@ CM <- local({ # _C_hecked _M_odule
761
761
762
762
unique_cat_par_combinations <- unique(dataset [c(cat , par )])
763
763
dup_mask <- duplicated(unique_cat_par_combinations [par ])
764
-
764
+
765
765
ok <- assert(err , ! any(dup_mask ), {
766
766
unique_repeat_params <- unique_cat_par_combinations [[par ]][dup_mask ]
767
767
dups <- df_to_string(
@@ -776,8 +776,8 @@ CM <- local({ # _C_hecked _M_odule
776
776
)
777
777
)
778
778
)
779
- prefix_repeat_params_command <-
780
- sprintf(' %s <- dv.explorer.parameter::prefix_repeat_parameters(%s, cat_var = "%s", par_var = "%s")' ,
779
+ prefix_repeat_params_command <-
780
+ sprintf(' %s <- dv.explorer.parameter::prefix_repeat_parameters(%s, cat_var = "%s", par_var = "%s")' ,
781
781
ds_value , ds_value , cat , par )
782
782
783
783
mask <- unique_cat_par_combinations [[par ]] %in% unique_repeat_params
@@ -791,7 +791,7 @@ CM <- local({ # _C_hecked _M_odule
791
791
})
792
792
793
793
paste0(
794
- sprintf(' The dataset provided by %s ("%s") contains parameter names that repeat across categories.' ,
794
+ sprintf(' The dataset provided by %s ("%s") contains parameter names that repeat across categories.' ,
795
795
format_inline_asis(ds_name ), ds_value ),
796
796
" This module expects them to be unique. This is the list of duplicates:" ,
797
797
paste0(" <pre>" , dups , " </pre>" ),
@@ -817,34 +817,34 @@ CM <- local({ # _C_hecked _M_odule
817
817
first_duplicates <- head(supposedly_unique [dup_mask , ], 5 )
818
818
names(first_duplicates ) <- paste(prefixes , names(first_duplicates ))
819
819
dups <- df_to_string(first_duplicates )
820
-
820
+
821
821
unique_repeats <- unique(supposedly_unique [dup_mask , ])
822
822
target <- unique_repeats [1 , ]
823
823
target_rows <- which(supposedly_unique [[sub ]] == target [[sub ]] & supposedly_unique [[cat ]] == target [[cat ]] &
824
824
supposedly_unique [[par ]] == target [[par ]] & supposedly_unique [[vis ]] == target [[vis ]])
825
-
825
+
826
826
row_a <- dataset [target_rows [[1 ]], ]
827
827
row_b <- dataset [target_rows [[2 ]], ]
828
828
diff_cols <- character (0 )
829
829
for (col in names(row_a )) if (! identical(row_a [[col ]], row_b [[col ]])) diff_cols <- c(diff_cols , col )
830
-
831
- col_diff_report <- " are identical."
832
- if (length(diff_cols )) {
830
+
831
+ col_diff_report <- " are identical."
832
+ if (length(diff_cols )) {
833
833
col_diff_report <- paste0(
834
834
" have indeed identical subject, category, parameter and visit values, but differ in columns: " ,
835
835
paste(diff_cols , collapse = " , " ), " ." ,
836
- " <pre>" ,
836
+ " <pre>" ,
837
837
df_to_string(dataset [target_rows [1 : 2 ], c(sub , cat , par , vis , diff_cols )]),
838
838
" </pre>"
839
839
)
840
840
}
841
-
841
+
842
842
paste(
843
843
sprintf(" The dataset provided by `%s` (%s) contains repeated rows with identical subject, category, parameter" , ds_name , ds_value ),
844
844
sprintf(" and visit values. This module expects them to be unique. There are a total of %d duplicates." , sum(dup_mask )),
845
845
" Here are the first few:" ,
846
846
paste0(" <pre>" , dups , " </pre>" ),
847
- sprintf(" These findings can be partially confirmed by examining that rows <b>%d</b> and <b>%d</b> of that dataset" ,
847
+ sprintf(" These findings can be partially confirmed by examining that rows <b>%d</b> and <b>%d</b> of that dataset" ,
848
848
target_rows [[1 ]], target_rows [[2 ]]),
849
849
col_diff_report
850
850
)
0 commit comments