Skip to content

Commit

Permalink
Auto open browser & Improve documents
Browse files Browse the repository at this point in the history
  • Loading branch information
wenjie1991 committed Aug 8, 2024
1 parent d3099f0 commit 7e61764
Show file tree
Hide file tree
Showing 11 changed files with 203 additions and 138 deletions.
173 changes: 90 additions & 83 deletions R/lib.R
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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"
Expand All @@ -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"
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
#'
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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.
Expand Down Expand Up @@ -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,
Expand All @@ -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)
# }
# }



8 changes: 6 additions & 2 deletions R/pkg_ggfigdone.R
Original file line number Diff line number Diff line change
@@ -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
Expand Down
37 changes: 31 additions & 6 deletions R/server.R
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)
}


Loading

0 comments on commit 7e61764

Please sign in to comment.