From 9e5aee3ff7e1d21881630a02a8fd36238e97fd5c Mon Sep 17 00:00:00 2001
From: PRijnbeek
Date: Tue, 7 Jan 2025 16:28:44 +0100
Subject: [PATCH] Updated dependencies
---
CSVViewer.Rproj | 1 +
DESCRIPTION | 7 +-
NAMESPACE | 6 ++
R/CSVViewer.R | 26 ++++++
R/Launch.R | 16 ++++
inst/shinyApp/App.R | 196 +++++++++++++++++++++------------------
man/CSVViewer-package.Rd | 23 +++++
7 files changed, 183 insertions(+), 92 deletions(-)
create mode 100644 R/CSVViewer.R
create mode 100644 man/CSVViewer-package.Rd
diff --git a/CSVViewer.Rproj b/CSVViewer.Rproj
index eaa6b81..4dfc464 100644
--- a/CSVViewer.Rproj
+++ b/CSVViewer.Rproj
@@ -1,4 +1,5 @@
Version: 1.0
+ProjectId: 53708426-6ca8-4daa-82a9-880fe451fb94
RestoreWorkspace: Default
SaveWorkspace: Default
diff --git a/DESCRIPTION b/DESCRIPTION
index 3dd03e6..6f103c2 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -13,14 +13,13 @@ BugReports: https://github.com/EHDEN/CSVViewer/issues
Depends:
R (>= 4.0.0)
Imports:
- shiny
-Suggests:
+ shiny,
nextGenShinyApps,
DT,
jsonlite,
rlist,
- knitr,
- markdown
+ markdown,
+ knitr
Encoding: UTF-8
LazyData: true
RoxygenNote: 7.3.2
diff --git a/NAMESPACE b/NAMESPACE
index 6d24660..063a316 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -2,3 +2,9 @@
export(launch)
export(launch_demo)
+import(DT)
+import(jsonlite)
+import(knitr)
+import(markdown)
+import(nextGenShinyApps)
+import(rlist)
diff --git a/R/CSVViewer.R b/R/CSVViewer.R
new file mode 100644
index 0000000..36718ed
--- /dev/null
+++ b/R/CSVViewer.R
@@ -0,0 +1,26 @@
+# Copyright 2024 EHDEN Foundation
+#
+# This file is part of Feasibility
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#' @keywords internal
+"_PACKAGE"
+
+#' @import nextGenShinyApps
+#' @import DT
+#' @import rlist
+#' @import markdown
+#' @import knitr
+#' @import jsonlite
+NULL
diff --git a/R/Launch.R b/R/Launch.R
index e94b6c1..29b9071 100644
--- a/R/Launch.R
+++ b/R/Launch.R
@@ -1,3 +1,19 @@
+# Copyright 2024 EHDEN Foundation
+#
+# This file is part of Feasibility
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
#' Launch the application
#'
#' @param app_port the port on which the app is available
diff --git a/inst/shinyApp/App.R b/inst/shinyApp/App.R
index a002b7c..3f4f4fa 100644
--- a/inst/shinyApp/App.R
+++ b/inst/shinyApp/App.R
@@ -62,8 +62,7 @@ ui <- fluidPage(
resize = "both",
style = "round"
),
- textOutput("status"),
- actionButton(inputId = "save", label = "Save Comments")
+ actionButton(inputId = "save", label = "Save Comments")
)
)
),
@@ -75,6 +74,26 @@ ui <- fluidPage(
style = "margin-top: 20px;",
DTOutput("data_table")
)
+ # Add a modal dialog for unsaved changes
+ # tags$div(id = "unsaved_changes_modal", class = "modal fade", tabindex = "-1", role = "dialog",
+ # div(class = "modal-dialog modal-dialog-centered", role = "document",
+ # div(class = "modal-content",
+ # div(class = "modal-header",
+ # h5(class = "modal-title", "Unsaved Changes"),
+ # tags$button(type = "button", class = "close", `data-dismiss` = "modal", `aria-label` = "Close",
+ # span(`aria-hidden` = "true", "×")
+ # )
+ # ),
+ # div(class = "modal-body",
+ # p("You have unsaved changes. Do you want to discard them and proceed?")
+ # ),
+ # div(class = "modal-footer",
+ # actionButton(inputId = "confirm_discard", label = "Discard and Proceed"),
+ # actionButton(inputId = "cancel_discard", label = "Cancel")
+ # )
+ # )
+ # )
+ # )
)
)
@@ -83,17 +102,6 @@ server <- function(input, output, session) {
# Reactive value to store the list of CSV files
csv_files <- reactiveVal()
- commentsRv <- reactiveValues(changed = FALSE)
- loading <- reactiveVal(TRUE)
-
- output$status <- renderText({
- if (commentsRv$changed && !loading()) {
- "Text changed but not saved"
- } else {
- "Text is saved or unchanged"
- }
- })
-
# Update the list of CSV files when the folder path is changed
observeEvent(input$folder, {
req(input$folder)
@@ -120,10 +128,52 @@ server <- function(input, output, session) {
choices = setNames(file_paths, file_labels), # Use filtered file paths and labels
selected = if (length(file_paths) > 0) file_paths[1] else NULL
)
+
+ load_selected_csv_file()
+ loading(FALSE)
+ print(loading())
}
})
+ # change the list of CSV files when the show_only_data checkbox is changed
+ observeEvent(input$show_only_data, {
+ folder_path <- input$folder
+
+ # Check if folder exists
+ if (!dir.exists(folder_path)) {
+ showNotification("The specified folder does not exist.", type = "error")
+ return()
+ }
+
+ file_paths_labels <- get_file_paths(
+ folder_path,
+ show_only_data = input$show_only_data,
+ max_depth = 5
+ )
+
+ if (!is.null(file_paths_labels)) {
+ file_paths <- file_paths_labels$file_paths
+ file_labels <- file_paths_labels$file_labels
+
+ # Update the reactive value
+ csv_files(file_paths)
+
+ # Update the selectInput with file names only
+ updateSelectInput(
+ session,
+ "csv_file",
+ choices = setNames(file_paths, file_labels),
+ # Use filtered file paths and labels
+ selected = if (length(file_paths) > 0)
+ file_paths[1]
+ else
+ NULL
+ )
+ }
+ }
+ )
+
# Display the name of the selected CSV file
output$selected_file_name <- renderText({
req(input$csv_file)
@@ -151,7 +201,7 @@ server <- function(input, output, session) {
req(input$csv_file)
selected_file <- input$csv_file
req(length(selected_file) == 1)
-
+
# Read the selected CSV file
data <- tryCatch(
read.csv(selected_file, stringsAsFactors = FALSE),
@@ -161,30 +211,13 @@ server <- function(input, output, session) {
}
)
req(!is.null(data))
-
+
# Render the data table
datatable(data, options = list(scrollX = TRUE, searching = TRUE, pageLength = 50))
})
- # Load the comments from the json if selected file is changed
- observeEvent(input$csv_file, {
- req(input$csv_file)
- selected_file <- input$csv_file
- comments_json <- paste0(input$folder,"/comments.json")
-
- comments <- get_comments_by_filename(comments_json, basename(selected_file))
-
- if (!is.null(comments)) {
- loading(TRUE)
- updateTextAreaInput(session, "comments", value = comments)
- loading(FALSE)
- }
- commentsRv$changed <- FALSE
- })
-
+ # Save the comments to the JSON file
observeEvent(input$save, {
-
-
# Retrieve the comments
comments <- input$comments
@@ -192,60 +225,39 @@ server <- function(input, output, session) {
comments_json <- paste0(input$folder,"/comments.json")
new_entry <- list(
- name = basename(input$csv_file),
- comments = comments,
- updated = format(Sys.time(), "%A, %B %d, %Y %I:%M:%S %p")
+ name = basename(input$csv_file),
+ comments = comments,
+ updated = format(Sys.time(), "%A, %B %d, %Y %I:%M:%S %p")
)
# Write comments to the JSON file
update_json_file(comments_json, "files", new_entry, "name")
- # Notify the user
- commentsRv$changed <- FALSE
})
- observeEvent(input$show_only_data, {
- folder_path <- input$folder
-
- # Check if folder exists
- if (!dir.exists(folder_path)) {
- showNotification("The specified folder does not exist.", type = "error")
- return()
- }
-
- file_paths_labels <- get_file_paths(
- folder_path,
- show_only_data = input$show_only_data,
- max_depth = 5
- )
-
- if (!is.null(file_paths_labels)) {
- file_paths <- file_paths_labels$file_paths
- file_labels <- file_paths_labels$file_labels
-
- # Update the reactive value
- csv_files(file_paths)
-
- # Update the selectInput with file names only
- updateSelectInput(
- session,
- "csv_file",
- choices = setNames(file_paths, file_labels),
- # Use filtered file paths and labels
- selected = if (length(file_paths) > 0)
- file_paths[1]
- else
- NULL
- )
- }
- }
- )
-
+ # Check with user if unsaved changes to comments when a new file is selected
observeEvent(input$csv_file, {
- # Update the documentation
+ load_selected_csv_file()
+ })
+
+ # Load the selected CSV file, documentation, and comments
+ load_selected_csv_file <- function() {
+
req(input$csv_file)
selected_file <- input$csv_file
+
+ # update comments
+ comments_json <- paste0(input$folder, "/comments.json")
+ comments <- get_comments_by_filename(comments_json, basename(selected_file))
+
+ if (!is.null(comments)) {
+ updateTextAreaInput(session, "comments", value = comments)
+ } else {
+ updateTextAreaInput(session, "comments", value = "")
+ }
+
+ # update documentation
description <- get_markdown_by_filename(input$folder, selected_file)
-
+
if (is.null(description)) {
output$markdown <- renderUI({
includeMarkdown("**No documentation available for this file.**")
@@ -255,17 +267,25 @@ server <- function(input, output, session) {
includeMarkdown(description)
})
}
- })
-
- # Detect comments field is changed
- observeEvent(input$comments, {
- print("triggered")
- if (!loading()) {
- commentsRv$changed <- TRUE
- } else {
- commentsRv$changed <- FALSE
- }
- })
+
+ # Read the selected CSV file
+ output$data_table <- renderDT({
+ req(length(selected_file) == 1)
+
+ # Read the selected CSV file
+ data <- tryCatch(
+ read.csv(selected_file, stringsAsFactors = FALSE),
+ error = function(e) {
+ showNotification("Failed to read the CSV file.", type = "error")
+ return(NULL)
+ }
+ )
+ req(!is.null(data))
+
+ # Render the data table
+ datatable(data, options = list(scrollX = TRUE, searching = TRUE, pageLength = 50))
+ })
+ }
}
# Run the application using nextGenShinyApps
diff --git a/man/CSVViewer-package.Rd b/man/CSVViewer-package.Rd
new file mode 100644
index 0000000..d2ca916
--- /dev/null
+++ b/man/CSVViewer-package.Rd
@@ -0,0 +1,23 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/CSVViewer.R
+\docType{package}
+\name{CSVViewer-package}
+\alias{CSVViewer}
+\alias{CSVViewer-package}
+\title{CSVViewer: Shiny App to view csv files}
+\description{
+Shiny App to review csv files and add comments on these files. Documentation for each of the csv files can be added and viewed in the app.
+}
+\seealso{
+Useful links:
+\itemize{
+ \item \url{https://github.com/EHDEN/CSVViewer}
+ \item Report bugs at \url{https://github.com/EHDEN/CSVViewer/issues}
+}
+
+}
+\author{
+\strong{Maintainer}: Peter Rijnbeek \email{p.rijnbeek@ehden.eu}
+
+}
+\keyword{internal}