diff --git a/R/lib.R b/R/lib.R index 2034818..2070314 100644 --- a/R/lib.R +++ b/R/lib.R @@ -1,48 +1,51 @@ -## extract code from the ggplot object -## Deprecated: This function is not used anymore -# fd_extract_ggplot_code = function(g) { -# ## Extract the original code from ggplot object -# code = constructive:::.cstr_construct(g$mapping) -# code = constructive:::pipe_to_layers(code, g$layers, plot_env = g$plot_env, one_liner = TRUE) -# code = constructive:::pipe_to_facets(code, g$facet, one_liner = TRUE) -# code = constructive:::pipe_to_labels(code, g$labels, g$mapping, g$layers, one_liner = TRUE) -# code = constructive:::pipe_to_scales(code, g$scales, one_liner = TRUE) -# code = constructive:::pipe_to_theme(code, g$theme, one_liner = TRUE) -# code = constructive:::pipe_to_coord(code, g$coordinates, one_liner = TRUE) -# code = constructive:::repair_attributes_ggplot(g, code, one_liner = TRUE) -# code = paste0("ggplot(data) + ", gsub("ggplot2::", "", code)) -# code -# } +## Update the figure name +fd_change_name = function(id, name, fdObj) { + fd_update(fdObj) + lock = lock(file.path(fdObj$dir, "/db.lock"), exclusive = TRUE) + if (id %in% names(fdObj$env)) { + fdObj$env[[id]]$name = name + fdObj$env[[id]]$updated_date = Sys.time() + } + unlock(lock) +} ## Update fdObj by reading the data **from the disk** fd_update = function(fdObj_loc, do_lock = TRUE) { + + ## Get the fdObj name in the parent environment of the parent environment fdObj_global = as.character(substitute(fdObj, env = parent.frame(n = 1))) + ## Get the fdObj name in the parent environment fdObj_parent = as.character(substitute(fdObj)) - # print(fdObj_global) + if (do_lock) { lock = lock(file.path(fdObj_loc$dir, "/db.lock"), exclusive = FALSE) } if (!dir.exists(fdObj_loc$dir)) { stop("Directory does not exist") } + + ## Load the env env = readr::read_rds(file.path(fdObj_loc$dir, "env.rds")) fdObj_loc$env = env if (do_lock) { unlock(lock) } + + ## Update the fdObj in the environments assign(fdObj_global, fdObj_loc, envir = parent.frame(n = 2)) assign(fdObj_parent, fdObj_loc, envir = parent.frame(n = 1)) } ## Update the ggfigdone database changes **to the disk** fd_save = function(fdObj) { - message("Saving the ggfigdone data to the disk...") + message("Automatic saving the ggfigdone data to the disk ...") lock = lock(file.path(fdObj$dir, "/db.lock"), exclusive = TRUE) readr::write_rds(fdObj$env, file.path(fdObj$dir, "env.rds")) unlock(lock) } +## Get the data structure of the data used in ggplot object fd_str_data = function(fdObj, id) { fd_update(fdObj) status = "error" @@ -58,6 +61,7 @@ fd_str_data = function(fdObj, id) { )) } +## Save the data to a temporary csv file for downloading in the UI fd_generate_data = function(fdObj, id) { fd_update(fdObj) status = "error" @@ -76,6 +80,7 @@ fd_generate_data = function(fdObj, id) { )) } +## Generate pdf for downloading in the UI fd_generate_pdf = function(fdObj, id) { fd_update(fdObj) status = "error" @@ -98,7 +103,7 @@ fd_generate_pdf = function(fdObj, id) { )) } -## Save the figure png example to the disk +## Generate png for displaying in the UI fd_plot = function(fdObj, id) { file_path = file.path(fdObj$dir, "figures", paste0(id, ".png")) canvas_options = fdObj$env[[id]]$canvas_options @@ -116,11 +121,11 @@ fd_plot = function(fdObj, id) { #' Initiates the ggfigdone database #' -#' This function creates a directory serves as a database for ggfigdone. +#' This function generates a folder that serves as a database for ggfigdone. #' -#' @param dir A character string of the directory path -#' @param recursive A logical value. If TRUE, the function creates the directory and its parent directories if they do not exist. If FALSE, the function creates the directory only if its parent directory exists. -#' @return An object of class `fdObj` +#' @param dir A character string specifying the directory path. +#' @param recursive A logical value. If TRUE, the function will create the directory along with any necessary parent directories if they do not already exist. If FALSE, the function will create the directory only if its parent directory already exists. +#' @return An object of class `fdObj`. #' @examples #' library(ggplot2) #' ## create ggfigdone database in a temporary directory @@ -173,8 +178,8 @@ fd_init = function(dir, recursive = TRUE, ...) { #' #' This function loads the ggfigdone database from the disk. #' -#' @param dir A character string of the directory path -#' @return An object of class `fdObj` +#' @param dir A character string representing the directory path. +#' @return An object of class `fdObj`. #' @examples #' library(ggplot2) #' ## create ggfigdone database in a temporary directory @@ -227,31 +232,24 @@ fd_load = function(dir, auto_database_upgrade = TRUE) { class(obj) = "fdObj" - # message("==================\nfdObj is loaded successfully...\nSave the ggfigdone data to the disk using fd_save function.\nIf you forgot, no worries.\nit will be saved automatically when you exit the R session.\n==================") - - # reg.finalizer(.GlobalEnv, function(e) { - # message("Saving the ggfigdone data to the disk...") - # fd_save(obj) - # message("Done Bye Bye ..") - # },onexit=TRUE) obj } #' Add a ggplot object to the ggfigdone database #' -#' This function adds a ggplot object to the ggfigdone database, which also can be used to update the figure given the figure id. +#' This function adds a ggplot object to the ggfigdone database. It can also be utilized to update an existing figure using its figure ID. #' -#' @param g A ggplot object -#' @param name A character string of the figure name -#' @param fdObj An object of class `fdObj` -#' @param width A numeric value of the width of the canvas -#' @param height A numeric value of the height of the canvas -#' @param units A character string of the units of the canvas -#' @param dpi A numeric value of the dpi of the canvas -#' @param overwrite A logical value. If TRUE, the function overwrites the figure if it already exists. If FALSE, the function stops with an error message. -#' @param id A character string of the figure id. If not provided, the function generates a random id. Otherwise, you can give an existing id to update the corresponding figure. -#' @return An object of class `fdObj` +#' @param g A ggplot object. +#' @param name A character string representing the figure name. +#' @param fdObj An object of class `fdObj`. +#' @param width A numeric value specifying the width of the canvas. +#' @param height A numeric value specifying the height of the canvas. +#' @param units A character string indicating the units of the canvas. +#' @param dpi A numeric value denoting the dpi of the canvas. +#' @param overwrite A logical value. If set to TRUE, the function will overwrite the figure if it already exists. If set to FALSE, the function will terminate with an error message. +#' @param id A character string representing the figure ID. If not provided, the function will generate a random ID. Alternatively, an existing ID can be provided to update the corresponding figure. +#' @return An object of class `fdObj`. #' @examples #' library(ggplot2) #' @@ -337,21 +335,22 @@ print.fdObj = function(fdObj) { #' List the figures #' -#' This function returns figures with their parameters. +#' This function provides a list of figures along with their associated parameters. +#' #' The parameters include: -#' - id: the figure id -#' - name: the figure name -#' - created_date: the created date -#' - updated_date: the updated date -#' - width: the width of the canvas -#' - height: the height of the canvas -#' - units: the units of the canvas -#' - dpi: the dpi of the canvas -#' - file_name: the file name -#' - plot_labels: the plot labels +#' - id: The unique identifier for the figure +#' - name: The name of the figure +#' - created_date: The date the figure was created +#' - updated_date: The date the figure was last updated +#' - width: The width of the canvas +#' - height: The height of the canvas +#' - units: The units of measurement for the canvas +#' - dpi: The dots per inch (DPI) of the canvas +#' - file_name: The name of the file +#' - plot_labels: The labels used in the plot #' -#' @param fdObj An object of class `fdObj` -#' @return A list of the figures with their parameters +#' @param fdObj An instance of the `fdObj` class. +#' @return A list containing the figures along with their respective parameters. #' @export fd_ls = function(fdObj) { fd_update(fdObj) @@ -380,8 +379,8 @@ fd_ls = function(fdObj) { #' #' This function removes a figure from the ggfigdone database. #' -#' @param id A character string of the figure id -#' @param fdObj An object of class `fdObj` +#' @param id A character string representing the figure ID. +#' @param fdObj An object of class `fdObj`. #' @export fd_rm = function(id, fdObj) { fd_update(fdObj) @@ -398,26 +397,6 @@ fd_rm = function(id, fdObj) { } } -## TODO: Add function to recover the original figure -fd_back_to_origin = function(id, fdObj) { - fd_update(fdObj) - if (id %in% names(fdObj$env)) { - fdObj$env[[id]]$update_histroy = c() - fdObj$env[[id]]$updated_date = Sys.time() - fd_plot(fdObj, id) - } -} - -fd_change_name = function(id, name, fdObj) { - fd_update(fdObj) - lock = lock(file.path(fdObj$dir, "/db.lock"), exclusive = TRUE) - if (id %in% names(fdObj$env)) { - fdObj$env[[id]]$name = name - fdObj$env[[id]]$updated_date = Sys.time() - } - unlock(lock) -} - #' Update a figure using ggplot expression #' #' This function updates a figure using a ggplot expression. @@ -456,13 +435,14 @@ fd_update_fig = function(id, expr, fdObj) { #' Update the figure canvas size #' -#' This function updates the figure canvas size. +#' This function is designed to update the size of the figure canvas. #' -#' @param id A character string of the figure id -#' @param fdObj An object of class `fdObj` -#' @param width A numeric value of the width of the canvas -#' @param height A numeric value of the height of the canvas -#' @param units A character string of the units of the canvas, e.g., "cm", "in", "mm", "px" +#' @param id A character string representing the figure ID. +#' @param fdObj An object of class `fdObj`. +#' @param width A numeric value specifying the width of the canvas. +#' @param height A numeric value specifying the height of the canvas. +#' @param units A character string indicating the units of measurement for the canvas, such as "cm", "in", "mm", or "px". +#' @param dpi A numeric value denoting the dots per inch (DPI) of the canvas. #' @export fd_canvas = function( id, @@ -483,4 +463,31 @@ fd_canvas = function( } } +## extract code from the ggplot object +## Deprecated: This function is not used anymore, wait the {constuctive} package to be improved +# fd_extract_ggplot_code = function(g) { +# ## Extract the original code from ggplot object +# code = constructive:::.cstr_construct(g$mapping) +# code = constructive:::pipe_to_layers(code, g$layers, plot_env = g$plot_env, one_liner = TRUE) +# code = constructive:::pipe_to_facets(code, g$facet, one_liner = TRUE) +# code = constructive:::pipe_to_labels(code, g$labels, g$mapping, g$layers, one_liner = TRUE) +# code = constructive:::pipe_to_scales(code, g$scales, one_liner = TRUE) +# code = constructive:::pipe_to_theme(code, g$theme, one_liner = TRUE) +# code = constructive:::pipe_to_coord(code, g$coordinates, one_liner = TRUE) +# code = constructive:::repair_attributes_ggplot(g, code, one_liner = TRUE) +# code = paste0("ggplot(data) + ", gsub("ggplot2::", "", code)) +# code +# } + +## TODO: Add function to recover the original figure +# fd_back_to_origin = function(id, fdObj) { +# fd_update(fdObj) +# if (id %in% names(fdObj$env)) { +# fdObj$env[[id]]$update_histroy = c() +# fdObj$env[[id]]$updated_date = Sys.time() +# fd_plot(fdObj, id) +# } +# } + + diff --git a/R/pkg_ggfigdone.R b/R/pkg_ggfigdone.R index 010acd1..22b4513 100644 --- a/R/pkg_ggfigdone.R +++ b/R/pkg_ggfigdone.R @@ -1,8 +1,12 @@ #' ggfigdone #' -#' ggfigdone: Manage & Modify ggplot figures using ggfigdone +#' ggfigdone: Manage & Modify ggplot figures easily #' -#' When you prepare a presentation or a report, you often need to manage a large number of ggplot figures. You need to change the figure size, modify the title, label, themes, etc. It is inconvinient to go back to the original code to make these changes. This package provides a simple way to manage ggplot figures. You can easily add the figure to the database and update them later using CLI (command line interface) or GUI (graphical user interface). +#' When preparing a presentation or report, it is often necessary to manage a substantial number of ggplot figures. +#' Adjustments such as changing the figure size, modifying titles, labels, and themes may be required. +#' Returning to the original code to implement these changes can be inconvenient. +#' This package offers a straightforward method for managing ggplot figures. +#' Figures can be easily added to the database and subsequently updated using either a GUI (graphical user interface) and/or CLI (command line interface). #' #' @name ggfigdone #' @import ggplot2 diff --git a/R/server.R b/R/server.R index 12b6707..7574cf6 100644 --- a/R/server.R +++ b/R/server.R @@ -144,12 +144,30 @@ response_fd_rm = function(fo, req) { ) } -#' Start a server for ggfigdone +#' Initiates a server for ggfigdone +#' +#' This function initiates a server for ggfigdone, which can be accessed through a web browser. +#' The web application enables users to manage and modify ggplot figures with ease. +#' Users have the ability to: +#' - Update the ggplot code by adding new components. +#' - Adjust the figure size. +#' - Download the figure as a PDF. +#' - Download the data used to create the figure. #' -#' @param dir The directory to save the figures -#' @param port The port of the server, default is 8080 +#' By default the function will open a web browser to access the server. +#' +#' You can configure the web browser by setting the options: +#' +#' ```{r} +#' options(browser = "firefox") # Set Firefox as the default +#' ``` +#' +#' @param dir The directory of the ggfigdone database. +#' @param host The host on which the server will run; the default is '0.0.0.0'. +#' @param port The port on which the server will run; the default is 8080. +#' @param auto_open A logical value indicating whether the server should be opened in a web browser; the default is TRUE. #' @export -fd_server = function(dir, port = 8080) { +fd_server = function(dir, host = '0.0.0.0', port = 8080, auto_open = TRUE) { fo = fd_load(dir) # print(fd_ls(fo)) @@ -209,9 +227,16 @@ fd_server = function(dir, port = 8080) { ) # start the server - message_text = paste0("Start service: http://localhost:", port, "/index.html") + url = paste0("http://", host, ":", port, "/index.html") + message_text = paste0("Start service: ", url) message(message_text) - runServer(host = "0.0.0.0", port = port, app = app) + # runServer(host = "0.0.0.0", port = port, app = app) + server <- startServer(host = host, port = port, app = app) + if (auto_open) { + browseURL(url) + } + on.exit(stopServer(server)) + service(0) } diff --git a/man/fd_add.Rd b/man/fd_add.Rd index 800903c..877f11a 100644 --- a/man/fd_add.Rd +++ b/man/fd_add.Rd @@ -11,35 +11,35 @@ fd_add( width = 5, height = 5, units = "cm", - dpi = 600, + dpi = 200, overwrite = F, id = uuid::UUIDgenerate() ) } \arguments{ -\item{g}{A ggplot object} +\item{g}{A ggplot object.} -\item{name}{A character string of the figure name} +\item{name}{A character string representing the figure name.} -\item{fdObj}{An object of class \code{fdObj}} +\item{fdObj}{An object of class \code{fdObj}.} -\item{width}{A numeric value of the width of the canvas} +\item{width}{A numeric value specifying the width of the canvas.} -\item{height}{A numeric value of the height of the canvas} +\item{height}{A numeric value specifying the height of the canvas.} -\item{units}{A character string of the units of the canvas} +\item{units}{A character string indicating the units of the canvas.} -\item{dpi}{A numeric value of the dpi of the canvas} +\item{dpi}{A numeric value denoting the dpi of the canvas.} -\item{overwrite}{A logical value. If TRUE, the function overwrites the figure if it already exists. If FALSE, the function stops with an error message.} +\item{overwrite}{A logical value. If set to TRUE, the function will overwrite the figure if it already exists. If set to FALSE, the function will terminate with an error message.} -\item{id}{A character string of the figure id. If not provided, the function generates a random id. Otherwise, you can give an existing id to update the corresponding figure.} +\item{id}{A character string representing the figure ID. If not provided, the function will generate a random ID. Alternatively, an existing ID can be provided to update the corresponding figure.} } \value{ -An object of class \code{fdObj} +An object of class \code{fdObj}. } \description{ -This function adds a ggplot object to the ggfigdone database, which also can be used to update the figure given the figure id. +This function adds a ggplot object to the ggfigdone database. It can also be utilized to update an existing figure using its figure ID. } \examples{ library(ggplot2) diff --git a/man/fd_canvas.Rd b/man/fd_canvas.Rd index a779e7f..b94c5b6 100644 --- a/man/fd_canvas.Rd +++ b/man/fd_canvas.Rd @@ -9,20 +9,23 @@ fd_canvas( fdObj, width = fdObj$env[[id]]$canvas_options$width, height = fdObj$env[[id]]$canvas_options$height, - units = fdObj$env[[id]]$canvas_options$units + units = fdObj$env[[id]]$canvas_options$units, + dpi = fdObj$env[[id]]$canvas_options$dpi ) } \arguments{ -\item{id}{A character string of the figure id} +\item{id}{A character string representing the figure ID.} -\item{fdObj}{An object of class \code{fdObj}} +\item{fdObj}{An object of class \code{fdObj}.} -\item{width}{A numeric value of the width of the canvas} +\item{width}{A numeric value specifying the width of the canvas.} -\item{height}{A numeric value of the height of the canvas} +\item{height}{A numeric value specifying the height of the canvas.} -\item{units}{A character string of the units of the canvas, e.g., "cm", "in", "mm", "px"} +\item{units}{A character string indicating the units of measurement for the canvas, such as "cm", "in", "mm", or "px".} + +\item{dpi}{A numeric value denoting the dots per inch (DPI) of the canvas.} } \description{ -This function updates the figure canvas size. +This function is designed to update the size of the figure canvas. } diff --git a/man/fd_init.Rd b/man/fd_init.Rd index cdb5617..adbb551 100644 --- a/man/fd_init.Rd +++ b/man/fd_init.Rd @@ -7,15 +7,15 @@ fd_init(dir, recursive = TRUE, ...) } \arguments{ -\item{dir}{A character string of the directory path} +\item{dir}{A character string specifying the directory path.} -\item{recursive}{A logical value. If TRUE, the function creates the directory and its parent directories if they do not exist. If FALSE, the function creates the directory only if its parent directory exists.} +\item{recursive}{A logical value. If TRUE, the function will create the directory along with any necessary parent directories if they do not already exist. If FALSE, the function will create the directory only if its parent directory already exists.} } \value{ -An object of class \code{fdObj} +An object of class \code{fdObj}. } \description{ -This function creates a directory serves as a database for ggfigdone. +This function generates a folder that serves as a database for ggfigdone. } \examples{ library(ggplot2) diff --git a/man/fd_load.Rd b/man/fd_load.Rd index d90bdad..4a6f718 100644 --- a/man/fd_load.Rd +++ b/man/fd_load.Rd @@ -7,10 +7,10 @@ fd_load(dir, auto_database_upgrade = TRUE) } \arguments{ -\item{dir}{A character string of the directory path} +\item{dir}{A character string representing the directory path.} } \value{ -An object of class \code{fdObj} +An object of class \code{fdObj}. } \description{ This function loads the ggfigdone database from the disk. diff --git a/man/fd_ls.Rd b/man/fd_ls.Rd index ccf16f4..5e529fe 100644 --- a/man/fd_ls.Rd +++ b/man/fd_ls.Rd @@ -7,24 +7,26 @@ fd_ls(fdObj) } \arguments{ -\item{fdObj}{An object of class \code{fdObj}} +\item{fdObj}{An instance of the \code{fdObj} class.} } \value{ -A list of the figures with their parameters +A list containing the figures along with their respective parameters. } \description{ -This function returns figures with their parameters. +This function provides a list of figures along with their associated parameters. +} +\details{ The parameters include: \itemize{ -\item id: the figure id -\item name: the figure name -\item created_date: the created date -\item updated_date: the updated date -\item width: the width of the canvas -\item height: the height of the canvas -\item units: the units of the canvas -\item dpi: the dpi of the canvas -\item file_name: the file name -\item plot_labels: the plot labels +\item id: The unique identifier for the figure +\item name: The name of the figure +\item created_date: The date the figure was created +\item updated_date: The date the figure was last updated +\item width: The width of the canvas +\item height: The height of the canvas +\item units: The units of measurement for the canvas +\item dpi: The dots per inch (DPI) of the canvas +\item file_name: The name of the file +\item plot_labels: The labels used in the plot } } diff --git a/man/fd_rm.Rd b/man/fd_rm.Rd index bd5b75c..e8353e5 100644 --- a/man/fd_rm.Rd +++ b/man/fd_rm.Rd @@ -7,9 +7,9 @@ fd_rm(id, fdObj) } \arguments{ -\item{id}{A character string of the figure id} +\item{id}{A character string representing the figure ID.} -\item{fdObj}{An object of class \code{fdObj}} +\item{fdObj}{An object of class \code{fdObj}.} } \description{ This function removes a figure from the ggfigdone database. diff --git a/man/fd_server.Rd b/man/fd_server.Rd index a2e8cfe..625845b 100644 --- a/man/fd_server.Rd +++ b/man/fd_server.Rd @@ -2,15 +2,35 @@ % Please edit documentation in R/server.R \name{fd_server} \alias{fd_server} -\title{Start a server for ggfigdone} +\title{Initiates a server for ggfigdone} \usage{ -fd_server(dir, port = 8080) +fd_server(dir, host = "localhost", port = 8080, auto_open = TRUE) } \arguments{ -\item{dir}{The directory to save the figures} +\item{dir}{The directory of the ggfigdone database.} -\item{port}{The port of the server, default is 8080} +\item{host}{The host on which the server will run; the default is 'localhost'.} + +\item{port}{The port on which the server will run; the default is 8080.} + +\item{auto_open}{A logical value indicating whether the server should be opened in a web browser; the default is TRUE.} } \description{ -Start a server for ggfigdone +This function initiates a server for ggfigdone, which can be accessed through a web browser. +The web application enables users to manage and modify ggplot figures with ease. +Users have the ability to: +\itemize{ +\item Update the ggplot code by adding new components. +\item Adjust the figure size. +\item Download the figure as a PDF. +\item Download the data used to create the figure. +} +} +\details{ +By default the function will open a web browser to access the server. + +You can configure the web browser by setting the options: + +\if{html}{\out{