From 25bb34b3c11f0cc247120ed8422a6786d3cadbcb Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Wed, 20 Mar 2019 13:18:20 -0400 Subject: [PATCH 01/27] :hammer: update generate_css_dist_html to support locally served CSS --- R/dash.R | 16 ++++++++++++---- R/utils.R | 21 ++++++++++++++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/R/dash.R b/R/dash.R index 0af6ed7c..1821b7d2 100644 --- a/R/dash.R +++ b/R/dash.R @@ -577,9 +577,17 @@ Dash <- R6::R6Class( dep })) - css <- paste(c(vapply(self$config$external_stylesheets, generate_css_dist_html, FUN.VALUE=character(1)), - render_dependencies(depsCSS, local = private$serve_locally, prefix=self$config$requests_pathname_prefix)), - collapse="\n") + css_tags <- paste(c(vapply(self$config$external_stylesheets, + generate_css_dist_html, + FUN.VALUE=character(1)), + render_dependencies(depsCSS, + local = private$serve_locally, + prefix=self$config$requests_pathname_prefix)), + generate_css_dist_html(href = names(private$css), + local = TRUE, + local_path = private$css, + prefix = self$config$requests_pathname_prefix), + collapse="\n") private$.index <- sprintf( ' @@ -602,7 +610,7 @@ Dash <- R6::R6Class( ', private$name, - css, + css_tags, to_JSON(self$config), render_dependencies(depsScripts, local = private$serve_locally, prefix=self$config$requests_pathname_prefix) ) diff --git a/R/utils.R b/R/utils.R index 4e481760..9b5eed75 100644 --- a/R/utils.R +++ b/R/utils.R @@ -489,11 +489,22 @@ get_mimetype <- function(filename) { return(NULL) } -generate_css_dist_html <- function(url) { - if (grepl("^(?:http(s)?:\\/\\/)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$", url, perl=TRUE)) { - sprintf("", url) +generate_css_dist_html <- function(href, + local = FALSE, + local_path = NULL, + prefix = NULL) { + if (!(local)) { + if (grepl("^(?:http(s)?:\\/\\/)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$", href, perl=TRUE)) { + sprintf("", url) + } + else + stop(sprintf("Invalid URL supplied in external_stylesheets. Please check the syntax used for this parameter."), call. = FALSE) + } else { + modified <- as.integer(file.mtime(local_path)) + sprintf("", + prefix, + href, + modified) } - else - stop(sprintf("Invalid URL supplied in external_stylesheets. Please check the syntax used for this parameter."), call. = FALSE) } From 16759b40c8f1da2d9245c91a4cfab6305df28dce Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Wed, 20 Mar 2019 13:49:39 -0400 Subject: [PATCH 02/27] :sparkles: add generate_js_dist_html function, refactor to call it in index --- R/dash.R | 14 +++++++++++++- R/utils.R | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/R/dash.R b/R/dash.R index 1821b7d2..eac3c05e 100644 --- a/R/dash.R +++ b/R/dash.R @@ -589,6 +589,18 @@ Dash <- R6::R6Class( prefix = self$config$requests_pathname_prefix), collapse="\n") + js_tags <- paste(c(vapply(self$config$external_scripts, + generate_js_dist_html, + FUN.VALUE=character(1)), + render_dependencies(depsScripts, + local = private$serve_locally, + prefix=self$config$requests_pathname_prefix)), + generate_js_dist_html(href = names(private$scripts), + local = TRUE, + local_path = private$scripts, + prefix = self$config$requests_pathname_prefix), + collapse="\n") + private$.index <- sprintf( ' @@ -612,7 +624,7 @@ Dash <- R6::R6Class( private$name, css_tags, to_JSON(self$config), - render_dependencies(depsScripts, local = private$serve_locally, prefix=self$config$requests_pathname_prefix) + js_tags ) } diff --git a/R/utils.R b/R/utils.R index 9b5eed75..3486ca47 100644 --- a/R/utils.R +++ b/R/utils.R @@ -506,5 +506,23 @@ generate_css_dist_html <- function(href, href, modified) } +generate_js_dist_html <- function(href, + local = FALSE, + local_path = NULL, + prefix = NULL) { + if (!(local)) { + if (grepl("^(?:http(s)?:\\/\\/)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$", href, perl=TRUE)) { + sprintf("", url) + } + else + stop(sprintf("Invalid URL supplied. Please check the syntax used for this parameter."), call. = FALSE) + } else { + modified <- as.integer(file.mtime(local_path)) + sprintf("", + prefix, + href, + modified) + } +} } From a642a1ce06a41506a288855cba7c6ce6ac62a0de Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Wed, 20 Mar 2019 13:58:23 -0400 Subject: [PATCH 03/27] :sparkles: add initial support for asset serving --- R/dash.R | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ R/utils.R | 42 +++++++++++++ 2 files changed, 217 insertions(+) diff --git a/R/dash.R b/R/dash.R index eac3c05e..7eb1d07a 100644 --- a/R/dash.R +++ b/R/dash.R @@ -7,6 +7,9 @@ #' name = "dash", #' server = fiery::Fire$new(), #' static_folder = NULL, +#' assets_folder = 'assets', +#' assets_url_path = '/assets', +#' assets_ignore = '', #' serve_locally = TRUE, #' routes_pathname_prefix = '/', #' requests_pathname_prefix = '/' @@ -27,6 +30,8 @@ #' `routes_pathname_prefix` \tab \tab a prefix applied to the backend routes.\cr #' `requests_pathname_prefix` \tab \tab a prefix applied to request endpoints #' made by Dash's front-end.\cr +#' `external_scripts` \tab \tab An optional list of valid URLs from which +#' to serve JavaScript source for rendered pages.\cr #' `external_stylesheets` \tab \tab An optional list of valid URLs from which #' to serve CSS for rendered pages.\cr #' `suppress_callback_exceptions` \tab \tab Whether to relay warnings about @@ -116,9 +121,13 @@ Dash <- R6::R6Class( initialize = function(name = "dash", server = fiery::Fire$new(), static_folder = NULL, + assets_folder = 'assets', + assets_url_path = '/assets', + assets_ignore = '', serve_locally = TRUE, routes_pathname_prefix = NULL, requests_pathname_prefix = NULL, + external_scripts = NULL, external_stylesheets = NULL, suppress_callback_exceptions = FALSE, components_cache_max_age = 2678400) { @@ -132,11 +141,15 @@ Dash <- R6::R6Class( # save relevant args as private fields private$name <- name private$serve_locally <- serve_locally + private$assets_folder <- assets_folder + private$assets_url_path <- assets_url_path + private$assets_ignore <- assets_ignore private$suppress_callback_exceptions <- suppress_callback_exceptions # config options self$config$routes_pathname_prefix <- resolve_prefix(routes_pathname_prefix, "DASH_ROUTES_PATHNAME_PREFIX") self$config$requests_pathname_prefix <- resolve_prefix(requests_pathname_prefix, "DASH_REQUESTS_PATHNAME_PREFIX") + self$config$external_scripts <- external_scripts self$config$external_stylesheets <- external_stylesheets # produce a true copy of the fiery server, since we don't want our @@ -168,6 +181,20 @@ Dash <- R6::R6Class( router$add_route(static_route, 'static_route') } + if (!is.null(private$assets_folder)) { + if (!(dir.exists(private$assets_folder))) { + warning( + "The supplied assets folder, '%s' could not be found in the project directory.", + paste(private$assets_folder, collapse = "', '"), + call. = FALSE + ) + } else { + private$asset_map <- private$walk_assets_directory(private$assets_folder) + private$css <- private$asset_map$css + private$scripts <- private$asset_map$scripts + private$other <- private$asset_map$other + } + } # ------------------------------------------------------------------------ # Set a sensible default logger @@ -314,6 +341,57 @@ Dash <- R6::R6Class( TRUE }) + dash_assets <- paste0(self$config$routes_pathname_prefix, private$assets_folder, "/*") + route$add_handler("get", dash_assets, function(request, response, keys, ...) { + # unfortunately, keys do not exist for wildcard headers in routr -- URL must be parsed + # e.g. for "http://127.0.0.1:8080/assets/stylesheet.css?m=1552591104" + # + # the following regex pattern will return "assets/stylesheet.css": + assets_pattern <- paste0(gsub("/", + "\\\\/", + assets_dir), + "([^?])+" + ) + + # now, identify vector positions for asset string matching pattern above + asset_match <- gregexpr(pattern = assets_pattern, request$url, perl=TRUE) + # use regmatches to retrieve only the substring including assets/... + asset_to_match <- unlist(regmatches(request$url, asset_match)) + + # now that we've parsed the URL, attempt to match the subpath in the map, + # then return the local absolute path to the asset + asset_path <- get_asset_path(private$asset_map, + asset_to_match) + + # the following codeblock attempts to determine whether the requested + # content exists, if the data should be encoded as plain text or binary, + # and opens/closes a file handle if the type is assumed to be binary + if (file.exists(asset_path)) { + response$type <- request$headers[["Content-Type"]] %||% + mime::guess_type(asset_to_match, + empty = "application/octet-stream") + + if (grepl("text|javascript", response$type)) { + response$body <- readLines(asset_path, + warn = FALSE, + encoding = "UTF-8") + } else { + file_handle <- file(asset_path, "rb") + response$body <- readBin(file_handle, + raw(), + file.info(asset_path)$size) + close(file_handle) + } + + response$set_header('Cache-Control', + sprintf('public, max-age=%s', + components_cache_max_age) + ) + response$status <- 200L + } + TRUE + }) + # Add a 'catchall' handler to redirect other requests to the index dash_catchall <- paste0(self$config$routes_pathname_prefix, "*") route$add_handler('get', dash_catchall, function(request, response, keys, ...) { @@ -427,10 +505,18 @@ Dash <- R6::R6Class( # private fields defined on initiation name = NULL, serve_locally = NULL, + assets_folder = NULL, + assets_url_path = NULL, + assets_ignore = NULL, routes_pathname_prefix = NULL, requests_pathname_prefix = NULL, suppress_callback_exceptions = NULL, + asset_map = NULL, + css = NULL, + scripts = NULL, + other = NULL, + # fields for tracking HTML dependencies dependencies = list(), dependencies_user = list(), @@ -525,6 +611,95 @@ Dash <- R6::R6Class( layout }, + walk_assets_directory = function(assets_dir = private$assets_dir) { + # obtain the full canonical path + asset_path <- normalizePath(file.path(assets_dir)) + + # remove multiple slashes if present + asset_path <- gsub("//+", + "/", + asset_path) + + # collect all the file paths to all files in assets, walk + # directory tree recursively + files <- list.files(path = asset_path, + full.names = TRUE, + recursive = TRUE) + + # if the user supplies an assets_ignore filter regex, use this + # to filter the file map to exclude anything that matches + if (private$assets_ignore != "") { + files <- files[grepl(pattern = private$assets_ignore, + files, + perl = TRUE)] + } + + # regex to match substring of absolute path + # the following lines escape out slashes + assets_pattern <- paste0(gsub("/", + "\\\\/", + assets_dir), + ".+$" + ) + + # if file extension is .css, add to stylesheets + sheet_paths <- files[tools::file_ext(files) == "css"] + + # if file extension is .js, add to scripts + script_paths <- files[tools::file_ext(files) == "js"] + + # file_paths includes all assets that are neither CSS nor JS + # this is to avoid duplicate entries in the map when flattened + file_paths <- files[!(tools::file_ext(files) %in% c("css", "js"))] + + # for CSS, JavaScript, and everything to be served in assets, construct + # a map -- a list of three character string vectors, in which the elements + # are absolute (local system) paths to the assets being served, and the + # names attribute of the elements matches the relative asset path + if (length(sheet_paths)) { + # first, sort the filenames alphanumerically + sheet_paths <- sheet_paths[order(basename(sheet_paths))] + # now, identify vector positions for asset strings matching pattern above + match_sheets <- gregexpr(pattern = assets_pattern, sheet_paths, perl=TRUE) + # use regmatches to retrieve only the substring including assets/... + sheet_names <- regmatches(sheet_paths, match_sheets) + # assign names for matched assets corresponding to substring + css_map <- setNames(sheet_paths, sheet_names %||% "/") + } else { + css_map <- NULL + } + + if (length(script_paths)) { + # first, sort the filenames alphanumerically + script_paths <- script_paths[order(basename(script_paths))] + # now, identify vector positions for asset strings matching pattern above + match_scripts <- gregexpr(pattern = assets_pattern, script_paths, perl=TRUE) + # use regmatches to retrieve only the substring including assets/... + script_names <- regmatches(script_paths, match_scripts) + # assign names for matched assets corresponding to substring + scripts_map <- setNames(script_paths, script_names %||% "/") + } else { + scripts_map <- NULL + } + + if (length(file_paths)) { + # first, sort the filenames alphanumerically + file_paths <- file_paths[order(basename(file_paths))] + # now, identify vector positions for asset strings matching pattern above + match_all <- gregexpr(pattern = assets_pattern, file_paths, perl=TRUE) + # use regmatches to retrieve only the substring including assets/... + file_names <- regmatches(file_paths, match_all) + # assign names for matched assets corresponding to substring + other_files_map <- setNames(file_paths, file_names %||% "/") + } else { + other_files_map <- NULL + } + + return(list(css = css_map, + scripts = scripts_map, + other = other_files_map)) + }, + componentify = function(x) { if (is.component(x)) return(x) if (all(vapply(x, is.component, logical(1)))) return(x) diff --git a/R/utils.R b/R/utils.R index 3486ca47..3f5c818d 100644 --- a/R/utils.R +++ b/R/utils.R @@ -524,5 +524,47 @@ generate_js_dist_html <- function(href, modified) } } + +# This function takes the list object containing asset paths +# for all stylesheets and scripts, as well as the URL path +# to search, then returns the absolute local path (when +# present) to the requested asset +# +# e.g. assets_map is a named list potentially containing +# $css, a list of absolute paths as character strings +# for all locally supplied CSS assets, named with their +# assets pathname (i.e. "assets/stylesheet.css"), and +# $scripts, a list of character strings formatted +# identically to $css, also named with subpaths. +# +get_asset_path <- function(assets_map, asset_path) { + unlist(setNames(assets_map, NULL))[asset_path] } +# This function returns the URL corresponding to assets +# included in the asset map, with the request prefix +# prepended, e.g. when asset_path is +# +# assets/stylesheet.css +# "/Users/testuser/assets/stylesheet.css" +# +# ... the function will return +# +# "/assets/stylesheet.css" +# +get_asset_url <- function(asset_path, prefix = "/") { + # the subpath is stored in the names attribute + # of the return object from get_asset_path, so + # we can retrieve it using names() + asset <- names(asset_path) + + # strip one or more trailing slashes, since we'll + # introduce one when we concatenate the prefix and + # asset path + prefix <- gsub(pattern = "/+$", + replacement = "", + x = prefix) + + # prepend the asset name with the route prefix + return(paste(prefix, asset, sep="/")) +} From f25952cc25a2c819e7d51605b4fff5569d97d188 Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Wed, 20 Mar 2019 14:02:36 -0400 Subject: [PATCH 04/27] :tshirt: fix hanging whitespace --- R/dash.R | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/R/dash.R b/R/dash.R index 7eb1d07a..fbc1a581 100644 --- a/R/dash.R +++ b/R/dash.R @@ -151,7 +151,7 @@ Dash <- R6::R6Class( self$config$requests_pathname_prefix <- resolve_prefix(requests_pathname_prefix, "DASH_REQUESTS_PATHNAME_PREFIX") self$config$external_scripts <- external_scripts self$config$external_stylesheets <- external_stylesheets - + # produce a true copy of the fiery server, since we don't want our # attachments/modifications having unintended side-effects # https://github.com/thomasp85/fiery/issues/30 @@ -276,14 +276,14 @@ Dash <- R6::R6Class( # # https://cran.r-project.org/doc/FAQ/R-FAQ.html#Others: callback_args <- list() - + for (input_element in request$body$inputs) { if(is.null(input_element$value)) callback_args <- c(callback_args, list(list(NULL))) else callback_args <- c(callback_args, input_element$value) } - + if (length(request$body$state)) { for (state_element in request$body$state) { if(is.null(state_element$value)) @@ -292,7 +292,7 @@ Dash <- R6::R6Class( callback_args <- c(callback_args, state_element$value) } } - + output_value <- do.call(callback, callback_args) # have to format the response body like this @@ -309,7 +309,7 @@ Dash <- R6::R6Class( TRUE }) - # This endpoint supports dynamic dependency loading + # This endpoint supports dynamic dependency loading # during `_dash-update-component` -- for reference: # https://github.com/plotly/dash/blob/1249ffbd051bfb5fdbe439612cbec7fa8fff5ab5/dash/dash.py#L488 # https://docs.python.org/3/library/pkgutil.html#pkgutil.get_data @@ -319,22 +319,22 @@ Dash <- R6::R6Class( dep_list <- c(private$dependencies_internal, private$dependencies, - private$dependencies_user) - - dep_pkg <- get_package_mapping(filename, + private$dependencies_user) + + dep_pkg <- get_package_mapping(filename, keys$package_name, - clean_dependencies(dep_list) + clean_dependencies(dep_list) ) - dep_path <- system.file(dep_pkg$rpkg_path, + dep_path <- system.file(dep_pkg$rpkg_path, package = dep_pkg$rpkg_name) response$body <- readLines(dep_path, - warn = FALSE, + warn = FALSE, encoding = "UTF-8") response$status <- 200L - response$set_header('Cache-Control', - sprintf('public, max-age=%s', + response$set_header('Cache-Control', + sprintf('public, max-age=%s', components_cache_max_age) ) response$type <- get_mimetype(filename) @@ -511,7 +511,6 @@ Dash <- R6::R6Class( routes_pathname_prefix = NULL, requests_pathname_prefix = NULL, suppress_callback_exceptions = NULL, - asset_map = NULL, css = NULL, scripts = NULL, @@ -801,7 +800,7 @@ Dash <- R6::R6Class( to_JSON(self$config), js_tags ) - + } ) ) From fe32e1582ff06d4503dba2f3ae15933028303d5e Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Wed, 20 Mar 2019 14:03:05 -0400 Subject: [PATCH 05/27] change default for static_folder to 'static' --- R/dash.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/dash.R b/R/dash.R index fbc1a581..0e32fd1d 100644 --- a/R/dash.R +++ b/R/dash.R @@ -6,7 +6,7 @@ #' app <- Dash$new( #' name = "dash", #' server = fiery::Fire$new(), -#' static_folder = NULL, +#' static_folder = 'static', #' assets_folder = 'assets', #' assets_url_path = '/assets', #' assets_ignore = '', From 5a773a618863bd76ae909a84bd0cb79218c159de Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Wed, 20 Mar 2019 14:03:21 -0400 Subject: [PATCH 06/27] :bug: insert missing parenthesis --- R/utils.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/R/utils.R b/R/utils.R index 3f5c818d..e8c5f9d3 100644 --- a/R/utils.R +++ b/R/utils.R @@ -506,6 +506,8 @@ generate_css_dist_html <- function(href, href, modified) } +} + generate_js_dist_html <- function(href, local = FALSE, local_path = NULL, From 2de3fc832b92a277a3d25b06df0f3ee4f6e31c4c Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Thu, 21 Mar 2019 14:42:15 -0400 Subject: [PATCH 07/27] :hammer: refactor index tag generation to avoid :hankey: --- R/dash.R | 122 ++++++++++++++++++++++++++++++++++++------------------ R/utils.R | 8 ++-- 2 files changed, 86 insertions(+), 44 deletions(-) diff --git a/R/dash.R b/R/dash.R index 0e32fd1d..fe1768c9 100644 --- a/R/dash.R +++ b/R/dash.R @@ -183,9 +183,9 @@ Dash <- R6::R6Class( if (!is.null(private$assets_folder)) { if (!(dir.exists(private$assets_folder))) { - warning( + warning(sprintf( "The supplied assets folder, '%s' could not be found in the project directory.", - paste(private$assets_folder, collapse = "', '"), + private$assets_folder), call. = FALSE ) } else { @@ -195,7 +195,7 @@ Dash <- R6::R6Class( private$other <- private$asset_map$other } } - + # ------------------------------------------------------------------------ # Set a sensible default logger # ------------------------------------------------------------------------ @@ -349,7 +349,7 @@ Dash <- R6::R6Class( # the following regex pattern will return "assets/stylesheet.css": assets_pattern <- paste0(gsub("/", "\\\\/", - assets_dir), + private$assets_folder), "([^?])+" ) @@ -366,7 +366,7 @@ Dash <- R6::R6Class( # the following codeblock attempts to determine whether the requested # content exists, if the data should be encoded as plain text or binary, # and opens/closes a file handle if the type is assumed to be binary - if (file.exists(asset_path)) { + if (!(is.null(asset_path)) && file.exists(asset_path)) { response$type <- request$headers[["Content-Type"]] %||% mime::guess_type(asset_to_match, empty = "application/octet-stream") @@ -379,7 +379,7 @@ Dash <- R6::R6Class( file_handle <- file(asset_path, "rb") response$body <- readBin(file_handle, raw(), - file.info(asset_path)$size) + file.size(asset_path)) close(file_handle) } @@ -628,16 +628,16 @@ Dash <- R6::R6Class( # if the user supplies an assets_ignore filter regex, use this # to filter the file map to exclude anything that matches if (private$assets_ignore != "") { - files <- files[grepl(pattern = private$assets_ignore, - files, - perl = TRUE)] + files <- files[!grepl(pattern = private$assets_ignore, + files, + perl = TRUE)] } # regex to match substring of absolute path # the following lines escape out slashes assets_pattern <- paste0(gsub("/", "\\\\/", - assets_dir), + private$assets_folder), ".+$" ) @@ -724,56 +724,98 @@ Dash <- R6::R6Class( # akin to https://github.com/plotly/dash/blob/d2ebc837/dash/dash.py#L338 # note discussion here https://github.com/plotly/dash/blob/d2ebc837/dash/dash.py#L279-L284 .index = NULL, - index = function() { - # collect and resolve dependencies + + collect_resources = function() { + # collect and resolve package dependencies depsAll <- compact(c( private$react_deps()[private$react_versions() %in% private$react_version_enabled()], private$dependencies, private$dependencies_user, private$dependencies_internal[names(private$dependencies_internal) %in% 'dash-renderer'] )) - + # normalizes local paths and keeps newer versions of duplicates depsAll <- htmltools::resolveDependencies(depsAll, FALSE) - + # styleheets always go in header - depsCSS <- compact(lapply(depsAll, function(dep) { + css_deps <- compact(lapply(depsAll, function(dep) { if (is.null(dep$stylesheet)) return(NULL) dep$script <- NULL dep })) - + + css_deps <- render_dependencies(css_deps, + local = private$serve_locally, + prefix=self$config$requests_pathname_prefix) + # scripts go after dash-renderer dependencies (i.e., React), # but before dash-renderer itself - depsScripts <- compact(lapply(depsAll, function(dep) { + scripts_deps <- compact(lapply(depsAll, function(dep) { if (is.null(dep$script)) return(NULL) dep$stylesheet <- NULL dep })) - - css_tags <- paste(c(vapply(self$config$external_stylesheets, - generate_css_dist_html, - FUN.VALUE=character(1)), - render_dependencies(depsCSS, - local = private$serve_locally, - prefix=self$config$requests_pathname_prefix)), - generate_css_dist_html(href = names(private$css), - local = TRUE, - local_path = private$css, - prefix = self$config$requests_pathname_prefix), - collapse="\n") - js_tags <- paste(c(vapply(self$config$external_scripts, - generate_js_dist_html, - FUN.VALUE=character(1)), - render_dependencies(depsScripts, - local = private$serve_locally, - prefix=self$config$requests_pathname_prefix)), - generate_js_dist_html(href = names(private$scripts), + scripts_deps <- render_dependencies(scripts_deps, + local = private$serve_locally, + prefix=self$config$requests_pathname_prefix) + + # collect CSS assets from dependencies + if (!(is.null(private$css))) { + css_assets <- generate_css_dist_html(href = names(private$css), local = TRUE, - local_path = private$scripts, - prefix = self$config$requests_pathname_prefix), - collapse="\n") + local_path = private$css, + prefix = self$config$requests_pathname_prefix) + } else { + css_assets <- NULL + } + + # collect CSS assets from external_stylesheets + css_external <- vapply(self$config$external_stylesheets, + generate_css_dist_html, + FUN.VALUE=character(1), + local = FALSE) + + # collect JS assets from dependencies + # + if (!(is.null(private$scripts))) { + scripts_assets <- generate_js_dist_html(href = names(private$scripts), + local = TRUE, + local_path = private$scripts, + prefix = self$config$requests_pathname_prefix) + } else { + scripts_assets <- NULL + } + + # collect JS assets from external_scripts + scripts_external <- vapply(self$config$external_scripts, + generate_js_dist_html, + FUN.VALUE=character(1)) + + # serving order of CSS and JS tags: package -> external -> assets + css_tags <- paste(c(css_deps, + css_external, + css_assets), + collapse = "\n") + + scripts_tags <- paste(c(scripts_deps, + scripts_external, + scripts_assets), + collapse = "\n") + + return(list(css_tags = css_tags, + scripts_tags = scripts_tags)) + }, + + index = function() { + # generate tags for all assets + all_tags <- private$collect_resources() + + # retrieve CSS tags for serving in the index + css_tags <- all_tags[["css_tags"]] + + # retrieve script tags for serving in the index + scripts_tags <- all_tags[["scripts_tags"]] private$.index <- sprintf( ' @@ -798,7 +840,7 @@ Dash <- R6::R6Class( private$name, css_tags, to_JSON(self$config), - js_tags + scripts_tags ) } diff --git a/R/utils.R b/R/utils.R index e8c5f9d3..3037c4ae 100644 --- a/R/utils.R +++ b/R/utils.R @@ -559,14 +559,14 @@ get_asset_url <- function(asset_path, prefix = "/") { # of the return object from get_asset_path, so # we can retrieve it using names() asset <- names(asset_path) - + # strip one or more trailing slashes, since we'll # introduce one when we concatenate the prefix and # asset path - prefix <- gsub(pattern = "/+$", - replacement = "", + prefix <- gsub(pattern = "/+$", + replacement = "", x = prefix) - + # prepend the asset name with the route prefix return(paste(prefix, asset, sep="/")) } From b7676b73a54c86ca1d7f68a4b7ce0957583d4f4c Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Fri, 22 Mar 2019 12:12:12 -0400 Subject: [PATCH 08/27] Add mime package to list of imports --- DESCRIPTION | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 2b21a124..df0f44ca 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -14,7 +14,8 @@ Imports: htmltools, assertthat, digest, - base64enc + base64enc, + mime Suggests: dashHtmlComponents (>= 0.13.5), dashCoreComponents (>= 0.42.1), From 8e4e2cf8f9b448ea7a0db742569f7e573874e538 Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Fri, 5 Apr 2019 15:57:59 -0400 Subject: [PATCH 09/27] version bump to 0.0.6 --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index df0f44ca..b724ab29 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: dashR Title: An interface to the dash ecosystem for authoring reactive web applications -Version: 0.0.4 +Version: 0.0.6 Authors@R: c(person("Ryan", "Kyle", role = c("aut", "cre"), email = "ryan@plot.ly"), person("Carson", "Sievert", role = c("aut"))) Description: An interface to the dash ecosystem for authoring reactive web applications. Depends: From 16c4efa9d9c08a0b07c3b6483bb0ba220f589303 Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Fri, 5 Apr 2019 16:01:09 -0400 Subject: [PATCH 10/27] :hocho: remove static_folder --- R/dash.R | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/R/dash.R b/R/dash.R index fe1768c9..8ed9575a 100644 --- a/R/dash.R +++ b/R/dash.R @@ -6,7 +6,6 @@ #' app <- Dash$new( #' name = "dash", #' server = fiery::Fire$new(), -#' static_folder = 'static', #' assets_folder = 'assets', #' assets_url_path = '/assets', #' assets_ignore = '', @@ -21,10 +20,6 @@ #' of the HTML page).\cr #' `server` \tab \tab The web server used to power the application. #' Must be a [fiery::Fire] object.\cr -#' `static_folder` \tab \tab A character vector of directories for serving -#' with the application (the default, `NULL`, means don't serve additional -#' directories). If provided, the names attribute defines corresponding url -#' path, otherwise it defaults to '/'.\cr #' `serve_locally` \tab \tab Whether to serve HTML dependencies locally or #' remotely (via URL).\cr #' `routes_pathname_prefix` \tab \tab a prefix applied to the backend routes.\cr @@ -120,7 +115,6 @@ Dash <- R6::R6Class( # i.e., the Dash$new() method initialize = function(name = "dash", server = fiery::Fire$new(), - static_folder = NULL, assets_folder = 'assets', assets_url_path = '/assets', assets_ignore = '', @@ -162,25 +156,6 @@ Dash <- R6::R6Class( # ------------------------------------------------------------ router <- routr::RouteStack$new() - if (!is.null(static_folder)) { - local_path <- normalizePath(static_folder, mustWork = TRUE) - - # these should all be directories, right? - if (!all(dir_exists(local_path))) { - warning( - "One or more of the following paths is not a directory, '%s'", - paste(static_folder, collapse = "', '"), - call. = FALSE - ) - } - - # default to '/' if no url path is specified (via name attribute) - resource_map <- setNames(local_path, names(static_folder) %||% "/") - - static_route <- do.call(routr::ressource_route, as.list(resource_map)) - router$add_route(static_route, 'static_route') - } - if (!is.null(private$assets_folder)) { if (!(dir.exists(private$assets_folder))) { warning(sprintf( From fd821fd4bcef02e2bba25afe8708cef55cbdc2d1 Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Sun, 7 Apr 2019 04:41:45 -0400 Subject: [PATCH 11/27] asset serving now supports distinct asset paths and folders --- R/dash.R | 32 ++++++++++++++++++++------------ R/utils.R | 6 +++++- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/R/dash.R b/R/dash.R index 0dc573af..a1809940 100644 --- a/R/dash.R +++ b/R/dash.R @@ -136,7 +136,8 @@ Dash <- R6::R6Class( private$name <- name private$serve_locally <- serve_locally private$assets_folder <- assets_folder - private$assets_url_path <- assets_url_path + # remove trailing slash in assets_url_path, if present + private$assets_url_path <- sub("/$", "", assets_url_path) private$assets_ignore <- assets_ignore private$suppress_callback_exceptions <- suppress_callback_exceptions @@ -316,21 +317,26 @@ Dash <- R6::R6Class( TRUE }) - dash_assets <- paste0(self$config$routes_pathname_prefix, private$assets_folder, "/*") + dash_assets <- paste0(self$config$routes_pathname_prefix, private$assets_url_path, "/*") + + # ensure slashes are not doubled + dash_assets <- sub("//", "/", dash_assets) + route$add_handler("get", dash_assets, function(request, response, keys, ...) { # unfortunately, keys do not exist for wildcard headers in routr -- URL must be parsed # e.g. for "http://127.0.0.1:8080/assets/stylesheet.css?m=1552591104" # - # the following regex pattern will return "assets/stylesheet.css": - assets_pattern <- paste0(gsub("/", + # the following regex pattern will return "/stylesheet.css": + assets_pattern <- paste0("(?<=", + gsub("/", "\\\\/", - private$assets_folder), - "([^?])+" + private$assets_url_path), + ")([^?])+" ) # now, identify vector positions for asset string matching pattern above asset_match <- gregexpr(pattern = assets_pattern, request$url, perl=TRUE) - # use regmatches to retrieve only the substring including assets/... + # use regmatches to retrieve only the substring following assets_url_path asset_to_match <- unlist(regmatches(request$url, asset_match)) # now that we've parsed the URL, attempt to match the subpath in the map, @@ -609,11 +615,13 @@ Dash <- R6::R6Class( } # regex to match substring of absolute path - # the following lines escape out slashes - assets_pattern <- paste0(gsub("/", + # the following lines escape out slashes, keeping subpath + # but without private$assets_folder included + assets_pattern <- paste0("(?<=", + gsub("/", "\\\\/", private$assets_folder), - ".+$" + ")([^?])+" ) # if file extension is .css, add to stylesheets @@ -737,7 +745,7 @@ Dash <- R6::R6Class( # collect CSS assets from dependencies if (!(is.null(private$css))) { - css_assets <- generate_css_dist_html(href = names(private$css), + css_assets <- generate_css_dist_html(href = paste0(private$assets_url_path, names(private$css)), local = TRUE, local_path = private$css, prefix = self$config$requests_pathname_prefix) @@ -754,7 +762,7 @@ Dash <- R6::R6Class( # collect JS assets from dependencies # if (!(is.null(private$scripts))) { - scripts_assets <- generate_js_dist_html(href = names(private$scripts), + scripts_assets <- generate_js_dist_html(href = paste0(private$assets_url_path, names(private$scripts)), local = TRUE, local_path = private$scripts, prefix = self$config$requests_pathname_prefix) diff --git a/R/utils.R b/R/utils.R index 3037c4ae..dcf22f6b 100644 --- a/R/utils.R +++ b/R/utils.R @@ -495,11 +495,13 @@ generate_css_dist_html <- function(href, prefix = NULL) { if (!(local)) { if (grepl("^(?:http(s)?:\\/\\/)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$", href, perl=TRUE)) { - sprintf("", url) + sprintf("", href) } else stop(sprintf("Invalid URL supplied in external_stylesheets. Please check the syntax used for this parameter."), call. = FALSE) } else { + # strip leading slash from href if present + href <- sub("^/", "", href) modified <- as.integer(file.mtime(local_path)) sprintf("", prefix, @@ -519,6 +521,8 @@ generate_js_dist_html <- function(href, else stop(sprintf("Invalid URL supplied. Please check the syntax used for this parameter."), call. = FALSE) } else { + # strip leading slash from href if present + href <- sub("^/", "", href) modified <- as.integer(file.mtime(local_path)) sprintf("", prefix, From 74392b10c6696e0286222201c5ff8552ae2b0fc9 Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Sun, 7 Apr 2019 10:12:27 -0400 Subject: [PATCH 12/27] :sparkles: added favicon support --- R/dash.R | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/R/dash.R b/R/dash.R index a1809940..2b2ee57c 100644 --- a/R/dash.R +++ b/R/dash.R @@ -373,6 +373,27 @@ Dash <- R6::R6Class( TRUE }) + dash_favicon <- paste0(self$config$routes_pathname_prefix, "_favicon.ico") + + route$add_handler("get", dash_favicon, function(request, response, keys, ...) { + asset_path <- get_asset_path(private$asset_map, + "/favicon.ico") + + file_handle <- file(asset_path, "rb") + response$body <- readBin(file_handle, + raw(), + file.size(asset_path)) + close(file_handle) + + response$set_header('Cache-Control', + sprintf('public, max-age=%s', + components_cache_max_age) + ) + response$type <- 'image/x-icon' + response$status <- 200L + TRUE + }) + # Add a 'catchall' handler to redirect other requests to the index dash_catchall <- paste0(self$config$routes_pathname_prefix, "*") route$add_handler('get', dash_catchall, function(request, response, keys, ...) { @@ -774,6 +795,14 @@ Dash <- R6::R6Class( scripts_external <- vapply(self$config$external_scripts, generate_js_dist_html, FUN.VALUE=character(1)) + + # create tag for favicon, if present + # other_files_map[names(other_files_map) %in% "/favicon.ico"] + if ("/favicon.ico" %in% names(private$other)) { + favicon <- sprintf("") + } else { + favicon <- NULL + } # serving order of CSS and JS tags: package -> external -> assets css_tags <- paste(c(css_deps, @@ -787,19 +816,23 @@ Dash <- R6::R6Class( collapse = "\n") return(list(css_tags = css_tags, - scripts_tags = scripts_tags)) + scripts_tags = scripts_tags, + favicon = favicon)) }, index = function() { # generate tags for all assets all_tags <- private$collect_resources() + # retrieve favicon tag for serving in the index + favicon <- all_tags[["favicon"]] + # retrieve CSS tags for serving in the index css_tags <- all_tags[["css_tags"]] # retrieve script tags for serving in the index scripts_tags <- all_tags[["scripts_tags"]] - + private$.index <- sprintf( ' @@ -807,6 +840,7 @@ Dash <- R6::R6Class( %s %s + %s @@ -821,6 +855,7 @@ Dash <- R6::R6Class( ', private$name, + favicon, css_tags, to_JSON(self$config), scripts_tags From 3a26274be6e17ce2071d0ef30c410c4c1a8bb82d Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 15:44:04 -0400 Subject: [PATCH 13/27] :hocho: dash-app-stylesheets --- .../dash-app-stylesheets/analytics-report.css | 401 ----------------- .../diamonds-explorer.css | 22 - inst/lib/dash-app-stylesheets/docs-base.css | 404 ------------------ inst/lib/dash-app-stylesheets/docs-custom.css | 237 ---------- .../docs-tutorial-stylesheet1.css | 393 ----------------- .../docs-tutorial-stylesheet2.css | 0 .../drug-discovery-demo-stylesheet.css | 25 -- .../goldman-sachs-report-js.js | 7 - .../goldman-sachs-report.css | 107 ----- inst/lib/dash-app-stylesheets/hello-world.css | 53 --- .../dash-app-stylesheets/loading-state.css | 54 --- .../logo-by-plotly-stripe.png | Bin 5734 -> 0 bytes inst/lib/dash-app-stylesheets/oil-and-gas.css | 393 ----------------- .../dash-app-stylesheets/stock-tickers.css | 33 -- .../technical-charting.css | 399 ----------------- .../dash-app-stylesheets/uber-ride-demo.css | 131 ------ .../dash-app-stylesheets/wind-streaming.css | 138 ------ 17 files changed, 2797 deletions(-) delete mode 100644 inst/lib/dash-app-stylesheets/analytics-report.css delete mode 100644 inst/lib/dash-app-stylesheets/diamonds-explorer.css delete mode 100644 inst/lib/dash-app-stylesheets/docs-base.css delete mode 100644 inst/lib/dash-app-stylesheets/docs-custom.css delete mode 100644 inst/lib/dash-app-stylesheets/docs-tutorial-stylesheet1.css delete mode 100644 inst/lib/dash-app-stylesheets/docs-tutorial-stylesheet2.css delete mode 100644 inst/lib/dash-app-stylesheets/drug-discovery-demo-stylesheet.css delete mode 100644 inst/lib/dash-app-stylesheets/goldman-sachs-report-js.js delete mode 100644 inst/lib/dash-app-stylesheets/goldman-sachs-report.css delete mode 100644 inst/lib/dash-app-stylesheets/hello-world.css delete mode 100644 inst/lib/dash-app-stylesheets/loading-state.css delete mode 100644 inst/lib/dash-app-stylesheets/logo-by-plotly-stripe.png delete mode 100644 inst/lib/dash-app-stylesheets/oil-and-gas.css delete mode 100644 inst/lib/dash-app-stylesheets/stock-tickers.css delete mode 100644 inst/lib/dash-app-stylesheets/technical-charting.css delete mode 100644 inst/lib/dash-app-stylesheets/uber-ride-demo.css delete mode 100644 inst/lib/dash-app-stylesheets/wind-streaming.css diff --git a/inst/lib/dash-app-stylesheets/analytics-report.css b/inst/lib/dash-app-stylesheets/analytics-report.css deleted file mode 100644 index 2267e61d..00000000 --- a/inst/lib/dash-app-stylesheets/analytics-report.css +++ /dev/null @@ -1,401 +0,0 @@ -/* Table of contents -–––––––––––––––––––––––––––––––––––––––––––––––––– -- Grid -- Base Styles -- Typography -- Links -- Buttons -- Forms -- Lists -- Code -- Tables -- Spacing -- Utilities -- Clearing -- Media Queries -*/ - -/* PLotly.js -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* plotly.js's modebar's z-index is outta the roof by default - lower it down */ -.js-plotly-plot .plotly .modebar { - z-index: 0 important!; -} - -/* Grid -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.container { - position: relative; - width: 100%; - max-width: 960px; - margin: 0 auto; - padding: 0 20px; - box-sizing: border-box; } -.column, -.columns { - width: 100%; - float: left; - box-sizing: border-box; } - -/* For devices larger than 400px */ -@media (min-width: 400px) { - .container { - width: 85%; - padding: 0; } -} - -/* For devices larger than 750px */ -@media (min-width: 750px) { - .container { - width: 80%; } - .column, - .columns { - margin-left: 1%; } - .column:first-child, - .columns:first-child { - margin-left: 0; } - - .one.column, - .one.columns { width: 7.41666666667%; } - .two.columns { width: 15.8333333333%; } - .three.columns { width: 24.25%; } - .four.columns { width: 32.6666666667%; } - .five.columns { width: 41.0833333333%; } - .six.columns { width: 49.5%; } - .seven.columns { width: 57.9166666667%; } - .eight.columns { width: 66.3333333333%; } - .nine.columns { width: 74.75% } - .ten.columns { width: 83.1666666667%; } - .eleven.columns { width: 91.5833333333%; } - .twelve.columns { width: 100%; margin-left: 0; } - - .one-third.column { width: 32.6666666667%; } - .two-thirds.column { width: 66.3333333333%; } - - .one-half.column { width: 49.5%; } - - /* Offsets */ - .offset-by-one.column, - .offset-by-one.columns { margin-left: 8.66666666667%; } - .offset-by-two.column, - .offset-by-two.columns { margin-left: 17.3333333333%; } - .offset-by-three.column, - .offset-by-three.columns { margin-left: 26%; } - .offset-by-four.column, - .offset-by-four.columns { margin-left: 34.6666666667%; } - .offset-by-five.column, - .offset-by-five.columns { margin-left: 43.3333333333%; } - .offset-by-six.column, - .offset-by-six.columns { margin-left: 52%; } - .offset-by-seven.column, - .offset-by-seven.columns { margin-left: 60.6666666667%; } - .offset-by-eight.column, - .offset-by-eight.columns { margin-left: 69.3333333333%; } - .offset-by-nine.column, - .offset-by-nine.columns { margin-left: 78.0%; } - .offset-by-ten.column, - .offset-by-ten.columns { margin-left: 86.6666666667%; } - .offset-by-eleven.column, - .offset-by-eleven.columns { margin-left: 95.3333333333%; } - - .offset-by-one-third.column, - .offset-by-one-third.columns { margin-left: 34.6666666667%; } - .offset-by-two-thirds.column, - .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } - - .offset-by-one-half.column, - .offset-by-one-half.columns { margin-left: 52%; } - -} - - -/* Base Styles -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* NOTE -html is set to 62.5% so that all the REM measurements throughout Skeleton -are based on 10px sizing. So basically 1.5rem = 15px :) */ -html { - font-size: 62.5%; } -body { - font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ - line-height: 1.6; - font-weight: 400; - font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; - color: rgb(50, 50, 50); } - - -/* Typography -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -h1, h2, h3, h4, h5, h6 { - margin-top: 0; - margin-bottom: 0; - font-weight: 300; } -h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } -h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} -h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} -h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} -h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} -h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} - -p { - margin-top: 0; } - - -/* Blockquotes -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -blockquote { - border-left: 4px lightgrey solid; - padding-left: 1rem; - margin-top: 2rem; - margin-bottom: 2rem; - margin-left: 0rem; -} - - -/* Links -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -a { - color: #1EAEDB; - cursor: pointer; - text-decoration: underline;} -a:hover { - color: #0FA0CE; } - - -/* Buttons -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.button, -button, -input[type="submit"], -input[type="reset"], -input[type="button"] { - display: inline-block; - height: 38px; - padding: 0 30px; - color: #555; - text-align: center; - font-size: 11px; - font-weight: 600; - line-height: 38px; - letter-spacing: .1rem; - text-transform: uppercase; - text-decoration: none; - white-space: nowrap; - background-color: transparent; - border-radius: 4px; - border: 1px solid #bbb; - cursor: pointer; - box-sizing: border-box; } -.button:hover, -button:hover, -input[type="submit"]:hover, -input[type="reset"]:hover, -input[type="button"]:hover, -.button:focus, -button:focus, -input[type="submit"]:focus, -input[type="reset"]:focus, -input[type="button"]:focus { - color: #333; - border-color: #888; - outline: 0; } -.button.button-primary, -button.button-primary, -input[type="submit"].button-primary, -input[type="reset"].button-primary, -input[type="button"].button-primary { - color: #FFF; - background-color: #33C3F0; - border-color: #33C3F0; } -.button.button-primary:hover, -button.button-primary:hover, -input[type="submit"].button-primary:hover, -input[type="reset"].button-primary:hover, -input[type="button"].button-primary:hover, -.button.button-primary:focus, -button.button-primary:focus, -input[type="submit"].button-primary:focus, -input[type="reset"].button-primary:focus, -input[type="button"].button-primary:focus { - color: #FFF; - background-color: #1EAEDB; - border-color: #1EAEDB; } - - -/* Forms -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -input[type="email"], -input[type="number"], -input[type="search"], -input[type="text"], -input[type="tel"], -input[type="url"], -input[type="password"], -textarea, -select { - height: 38px; - padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ - background-color: #fff; - border: 1px solid #D1D1D1; - border-radius: 4px; - box-shadow: none; - box-sizing: border-box; - font-family: inherit; - font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} -/* Removes awkward default styles on some inputs for iOS */ -input[type="email"], -input[type="number"], -input[type="search"], -input[type="text"], -input[type="tel"], -input[type="url"], -input[type="password"], -textarea { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; } -textarea { - min-height: 65px; - padding-top: 6px; - padding-bottom: 6px; } -input[type="email"]:focus, -input[type="number"]:focus, -input[type="search"]:focus, -input[type="text"]:focus, -input[type="tel"]:focus, -input[type="url"]:focus, -input[type="password"]:focus, -textarea:focus, -select:focus { - border: 1px solid #33C3F0; - outline: 0; } -label, -legend { - display: block; - margin-bottom: 0px; } -fieldset { - padding: 0; - border-width: 0; } -input[type="checkbox"], -input[type="radio"] { - display: inline; } -label > .label-body { - display: inline-block; - margin-left: .5rem; - font-weight: normal; } - - -/* Lists -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -ul { - list-style: circle inside; } -ol { - list-style: decimal inside; } -ol, ul { - padding-left: 0; - margin-top: 0; } -ul ul, -ul ol, -ol ol, -ol ul { - margin: 1.5rem 0 1.5rem 3rem; - font-size: 90%; } -li { - margin-bottom: 1rem; } - - -/* Tables -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -th, -td { - padding: 12px 15px; - text-align: left; - border-bottom: 1px solid #E1E1E1; } -th:first-child, -td:first-child { - padding-left: 0; } -th:last-child, -td:last-child { - padding-right: 0; } - - -/* Spacing -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -button, -.button { - margin-bottom: 0rem; } -input, -textarea, -select, -fieldset { - margin-bottom: 0rem; } -pre, -dl, -figure, -table, -form { - margin-bottom: 0rem; } -p, -ul, -ol { - margin-bottom: 0.75rem; } - -/* Utilities -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.u-full-width { - width: 100%; - box-sizing: border-box; } -.u-max-full-width { - max-width: 100%; - box-sizing: border-box; } -.u-pull-right { - float: right; } -.u-pull-left { - float: left; } - - -/* Misc -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -hr { - margin-top: 3rem; - margin-bottom: 3.5rem; - border-width: 0; - border-top: 1px solid #E1E1E1; } - - -/* Clearing -–––––––––––––––––––––––––––––––––––––––––––––––––– */ - -/* Self Clearing Goodness */ -.container:after, -.row:after, -.u-cf { - content: ""; - display: table; - clear: both; } - - -/* Media Queries -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* -Note: The best way to structure the use of media queries is to create the queries -near the relevant code. For example, if you wanted to change the styles for buttons -on small devices, paste the mobile query code up in the buttons section and style it -there. -*/ - - -/* Larger than mobile */ -@media (min-width: 400px) {} - -/* Larger than phablet (also point when grid becomes active) */ -@media (min-width: 750px) {} - -/* Larger than tablet */ -@media (min-width: 750px) {} - -/* Larger than desktop */ -@media (min-width: 1000px) {} - -/* Larger than Desktop HD */ -@media (min-width: 1200px) {} diff --git a/inst/lib/dash-app-stylesheets/diamonds-explorer.css b/inst/lib/dash-app-stylesheets/diamonds-explorer.css deleted file mode 100644 index 0c7d8eab..00000000 --- a/inst/lib/dash-app-stylesheets/diamonds-explorer.css +++ /dev/null @@ -1,22 +0,0 @@ -p { - margin-bottom: 0; - margin-top: 2.5em; -} - -._dash-app-content{ - margin-left: -10px; - margin-top: -10px; -} - -.app{ - margin-left: -10px; - margin-top: -10px; -} - -._dash-undo-redo{ - visibility: hidden; -} - -body { - background: #FBFBFB; -} diff --git a/inst/lib/dash-app-stylesheets/docs-base.css b/inst/lib/dash-app-stylesheets/docs-base.css deleted file mode 100644 index bec6b768..00000000 --- a/inst/lib/dash-app-stylesheets/docs-base.css +++ /dev/null @@ -1,404 +0,0 @@ -/* Table of contents -–––––––––––––––––––––––––––––––––––––––––––––––––– -- Grid -- Base Styles -- Typography -- Links -- Buttons -- Forms -- Lists -- Code -- Tables -- Spacing -- Utilities -- Clearing -- Media Queries -*/ - -/* PLotly.js -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* plotly.js's modebar's z-index is outta the roof by default - lower it down */ -.js-plotly-plot .plotly .modebar { - z-index: 0 important!; -} - -/* Grid -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.container { - position: relative; - width: 100%; - max-width: 960px; - margin: 0 auto; - padding: 0 20px; - box-sizing: border-box; } -.column, -.columns { - width: 100%; - float: left; - box-sizing: border-box; } - -/* For devices larger than 400px */ -@media (min-width: 400px) { - .container { - width: 85%; - padding: 0; } -} - -/* For devices larger than 550px */ -@media (min-width: 550px) { - .container { - width: 80%; } - .column, - .columns { - margin-left: 4%; } - .column:first-child, - .columns:first-child { - margin-left: 0; } - - .one.column, - .one.columns { width: 4.66666666667%; } - .two.columns { width: 13.3333333333%; } - .three.columns { width: 22%; } - .four.columns { width: 30.6666666667%; } - .five.columns { width: 39.3333333333%; } - .six.columns { width: 48%; } - .seven.columns { width: 56.6666666667%; } - .eight.columns { width: 65.3333333333%; } - .nine.columns { width: 74.0%; } - .ten.columns { width: 82.6666666667%; } - .eleven.columns { width: 91.3333333333%; } - .twelve.columns { width: 100%; margin-left: 0; } - - .one-third.column { width: 30.6666666667%; } - .two-thirds.column { width: 65.3333333333%; } - - .one-half.column { width: 48%; } - - /* Offsets */ - .offset-by-one.column, - .offset-by-one.columns { margin-left: 8.66666666667%; } - .offset-by-two.column, - .offset-by-two.columns { margin-left: 17.3333333333%; } - .offset-by-three.column, - .offset-by-three.columns { margin-left: 26%; } - .offset-by-four.column, - .offset-by-four.columns { margin-left: 34.6666666667%; } - .offset-by-five.column, - .offset-by-five.columns { margin-left: 43.3333333333%; } - .offset-by-six.column, - .offset-by-six.columns { margin-left: 52%; } - .offset-by-seven.column, - .offset-by-seven.columns { margin-left: 60.6666666667%; } - .offset-by-eight.column, - .offset-by-eight.columns { margin-left: 69.3333333333%; } - .offset-by-nine.column, - .offset-by-nine.columns { margin-left: 78.0%; } - .offset-by-ten.column, - .offset-by-ten.columns { margin-left: 86.6666666667%; } - .offset-by-eleven.column, - .offset-by-eleven.columns { margin-left: 95.3333333333%; } - - .offset-by-one-third.column, - .offset-by-one-third.columns { margin-left: 34.6666666667%; } - .offset-by-two-thirds.column, - .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } - - .offset-by-one-half.column, - .offset-by-one-half.columns { margin-left: 52%; } - -} - - -/* Base Styles -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* NOTE -html is set to 62.5% so that all the REM measurements throughout Skeleton -are based on 10px sizing. So basically 1.5rem = 15px :) */ -html { - font-size: 62.5%; } -body { - font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ - line-height: 1.6; - font-weight: 400; - font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; - color: rgb(50, 50, 50); } - - -/* Typography -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -h1, h2, h3, h4, h5, h6 { - margin-top: 0; - margin-bottom: 0; - font-weight: 300; } -h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } -h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} -h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} -h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} -h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} -h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} - -p { - margin-top: 0; } - - -/* Blockquotes -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -blockquote { - border-left: 4px lightgrey solid; - padding-left: 1rem; - margin-top: 2rem; - margin-bottom: 2rem; - margin-left: 0rem; -} - - -/* Links -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -a { - color: #1EAEDB; - cursor: pointer; - text-decoration: underline;} -a:hover { - color: #0FA0CE; } - - -/* Buttons -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.button, -button, -input[type="submit"], -input[type="reset"], -input[type="button"] { - display: inline-block; - height: 38px; - padding: 0 30px; - color: #555; - text-align: center; - font-size: 11px; - font-weight: 600; - line-height: 38px; - letter-spacing: .1rem; - text-transform: uppercase; - text-decoration: none; - white-space: nowrap; - background-color: transparent; - border-radius: 4px; - border: 1px solid #bbb; - cursor: pointer; - box-sizing: border-box; } -.button:hover, -button:hover, -input[type="submit"]:hover, -input[type="reset"]:hover, -input[type="button"]:hover, -.button:focus, -button:focus, -input[type="submit"]:focus, -input[type="reset"]:focus, -input[type="button"]:focus { - color: #333; - border-color: #888; - outline: 0; } -.button.button-primary, -button.button-primary, -input[type="submit"].button-primary, -input[type="reset"].button-primary, -input[type="button"].button-primary { - color: #FFF; - background-color: #33C3F0; - border-color: #33C3F0; } -.button.button-primary:hover, -button.button-primary:hover, -input[type="submit"].button-primary:hover, -input[type="reset"].button-primary:hover, -input[type="button"].button-primary:hover, -.button.button-primary:focus, -button.button-primary:focus, -input[type="submit"].button-primary:focus, -input[type="reset"].button-primary:focus, -input[type="button"].button-primary:focus { - color: #FFF; - background-color: #1EAEDB; - border-color: #1EAEDB; } - - -/* Forms -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -input, -input[type="email"], -input[type="number"], -input[type="search"], -input[type="text"], -input[type="tel"], -input[type="url"], -input[type="password"], -textarea, -select { - height: 38px; - padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ - background-color: #fff; - border: 1px solid #D1D1D1; - border-radius: 4px; - box-shadow: none; - box-sizing: border-box; - font-family: inherit; - font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} -/* Removes awkward default styles on some inputs for iOS */ -input, -input[type="email"], -input[type="number"], -input[type="search"], -input[type="text"], -input[type="tel"], -input[type="url"], -input[type="password"], -textarea { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; } -textarea { - min-height: 65px; - padding-top: 6px; - padding-bottom: 6px; } -input:focus, -input[type="email"]:focus, -input[type="number"]:focus, -input[type="search"]:focus, -input[type="text"]:focus, -input[type="tel"]:focus, -input[type="url"]:focus, -input[type="password"]:focus, -textarea:focus, -select:focus { - border: 1px solid #33C3F0; - outline: 0; } -label, -legend { - display: block; - margin-bottom: 0px; } -fieldset { - padding: 0; - border-width: 0; } -input[type="checkbox"], -input[type="radio"] { - display: inline; } -label > .label-body { - display: inline-block; - margin-left: .5rem; - font-weight: normal; } - - -/* Lists -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -ul { - list-style: circle inside; } -ol { - list-style: decimal inside; } -ol, ul { - padding-left: 0; - margin-top: 0; } -ul ul, -ul ol, -ol ol, -ol ul { - margin: 1.5rem 0 1.5rem 3rem; - font-size: 90%; } -li { - margin-bottom: 1rem; } - - -/* Tables -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -th, -td { - padding: 12px 15px; - text-align: left; - border-bottom: 1px solid #E1E1E1; } -th:first-child, -td:first-child { - padding-left: 0; } -th:last-child, -td:last-child { - padding-right: 0; } - - -/* Spacing -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -button, -.button { - margin-bottom: 0rem; } -input, -textarea, -select, -fieldset { - margin-bottom: 0rem; } -pre, -dl, -figure, -table, -form { - margin-bottom: 0rem; } -p, -ul, -ol { - margin-bottom: 0.75rem; } - -/* Utilities -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.u-full-width { - width: 100%; - box-sizing: border-box; } -.u-max-full-width { - max-width: 100%; - box-sizing: border-box; } -.u-pull-right { - float: right; } -.u-pull-left { - float: left; } - - -/* Misc -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -hr { - margin-top: 3rem; - margin-bottom: 3.5rem; - border-width: 0; - border-top: 1px solid #E1E1E1; } - - -/* Clearing -–––––––––––––––––––––––––––––––––––––––––––––––––– */ - -/* Self Clearing Goodness */ -.container:after, -.row:after, -.u-cf { - content: ""; - display: table; - clear: both; } - - -/* Media Queries -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* -Note: The best way to structure the use of media queries is to create the queries -near the relevant code. For example, if you wanted to change the styles for buttons -on small devices, paste the mobile query code up in the buttons section and style it -there. -*/ - - -/* Larger than mobile */ -@media (min-width: 400px) {} - -/* Larger than phablet (also point when grid becomes active) */ -@media (min-width: 550px) {} - -/* Larger than tablet */ -@media (min-width: 750px) {} - -/* Larger than desktop */ -@media (min-width: 1000px) {} - -/* Larger than Desktop HD */ -@media (min-width: 1200px) {} diff --git a/inst/lib/dash-app-stylesheets/docs-custom.css b/inst/lib/dash-app-stylesheets/docs-custom.css deleted file mode 100644 index 58c36766..00000000 --- a/inst/lib/dash-app-stylesheets/docs-custom.css +++ /dev/null @@ -1,237 +0,0 @@ -body { - color: #506784; - background: - linear-gradient( - rgba(255, 255, 255, 0.6), - rgba(255, 255, 255, 0.6) - ), - url("https://github.com/plotly/dash-docs/raw/master/images/dash-pattern.png"); - margin: 0px; -} - -._dash-loading { - text-align: center; - margin-top: 50px; -} - -/* Header */ -.header { - height: 60px; - -webkit-box-shadow: 0px 5px 5px 0px rgba(100, 100, 100, 0.1); - -moz-box-shadow: 0px 5px 5px 0px rgba(100, 100, 100, 0.1); - box-shadow: 0px 5px 5px 0px rgba(100, 100, 100, 0.1); - margin-bottom: 50px; - background-color: white; -} - -.header .links { - display: inline-block; - float: right; - text-transform: uppercase; - font-weight: 500; - letter-spacing: 0.5px; - color: rgb(81, 104, 131); - font-size: 16px; - vertical-align: middle; -} - -.header .links .link { - margin-left: 20px; - line-height: 60px; - display: inline-block; - color: #506784; - cursor: pointer; - background-color: white; - text-decoration: none; -} - -.header .links .link:hover { - color: #0D67BF; - text-decoration: none; -} - -.header .links .link.active { - border-bottom: #119DFF 2px solid; - color: #2A3F5F; - height: 59px; -} - -.header .links .link:hover { - border-bottom: #119DFF 2px solid; - color: #2A3F5F; - height: 59px; -} - - -.header .logo { - height: 95%; -} - -.header .logo-link { - background-color: white; -} - -/* Example Container */ - -.example-container { - border: thin lightgrey solid; - padding: 15px; - overflow-x: scroll; -} - -/* Fonts */ -h1, h2, h3, h4, h5, h6 { - font-family: Dosis, 'HelveticaNeue', 'Helvetica Neue', Helvetica, Arial, sans-serif; - font-weight: 400; - color: #2A3F5F; -} - -.example-container h1, -.example-container h2, -.example-container h3, -.example-container h4, -.example-container h5, -.example-container h6 { - font-weight: 300; - font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; - color: rgb(50, 50, 50); -} - -.gallery .image-link { - background-color: white; -} - -.gallery img { - width: 100%; - border: thin lightgrey solid; - border-radius: 5px; - margin-left: auto; - margin-right: auto; - display: block; -} - -.toc ul li a { - background-color: white; - color: #506784; - font-family: Dosis, 'HelveticaNeue', 'Helvetica Neue', Helvetica, Arial, sans-serif; -} - -.toc ul li { - font-size: 26px; - color: #506784; -} - -.toc ul ul li { - font-size: 18px; - color: #506784; - display: none; -} - -.toc ul ul ul li { - font-size: 14px; - color: #506784; - font-weight: 200; -} - -/* Links -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.content a { - color: #506784; - background-color: rgb(245, 245, 245); - text-decoration: none; - padding-left: 4px; - padding-right: 4px; - border-radius: 1px; -} - -.content a:hover { - color: #0D67BF; - text-decoration: underline;} - -.content a > img:hover { - border: thin #119DFF solid; - cursor: pointer; -} - - -.content p > code, -.content li > code{ - background-color: rgb(243, 246, 251); - border: 0.5px rgb(224, 232, 242) solid; - border-radius: 4px; - font-size: 1.8rem; - padding-left: 3px; - padding-right: 3px; -} - -.toc li { - list-style: none; -} - -.content-container { - background-color: white; - border-radius: 5px; - font-size: 1.7rem; - box-shadow: rgb(240, 240, 240) 5px 5px 5px 0px; - border: thin solid rgb(240, 240, 240); - margin-bottom: 100px; -} - -@media (min-width: 0px) { - .content { - margin-left: 20px; - margin-right: 20px; - margin-top: 20px; - margin-bottom: 40px; - } - - .container-width { - width: 100%; - margin-left: auto; - margin-right: auto; - } - - .toc-chapters { - column-count: 1; - } - - .header .links { - display: none; - } -} - -._dash-undo-redo { - display: none; -} - -@media (min-width: 450px) { - .header .links { - display: block; - } -} - -@media (min-width: 750px) { - .content { - margin-left: 60px; - margin-right: 60px; - margin-top: 20px; - margin-bottom: 40px; - } - - .container-width { - width: 90%; - margin-left: auto; - margin-right: auto; - } - - .toc-chapters { - column-count: 2; - } -} - -@media (min-width: 900px) { - .container-width { - width: 80%; - max-width: 960px; - } -} diff --git a/inst/lib/dash-app-stylesheets/docs-tutorial-stylesheet1.css b/inst/lib/dash-app-stylesheets/docs-tutorial-stylesheet1.css deleted file mode 100644 index 28f93aa2..00000000 --- a/inst/lib/dash-app-stylesheets/docs-tutorial-stylesheet1.css +++ /dev/null @@ -1,393 +0,0 @@ -/* Table of contents -–––––––––––––––––––––––––––––––––––––––––––––––––– -- Grid -- Base Styles -- Typography -- Links -- Buttons -- Forms -- Lists -- Code -- Tables -- Spacing -- Utilities -- Clearing -- Media Queries -*/ - - -/* Grid -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.container { - position: relative; - width: 100%; - max-width: 960px; - margin: 0 auto; - padding: 0 20px; - box-sizing: border-box; } -.column, -.columns { - width: 100%; - float: left; - box-sizing: border-box; } - -/* For devices larger than 400px */ -@media (min-width: 400px) { - .container { - width: 85%; - padding: 0; } -} - -/* For devices larger than 550px */ -@media (min-width: 550px) { - .container { - width: 80%; } - .column, - .columns { - margin-left: 4%; } - .column:first-child, - .columns:first-child { - margin-left: 0; } - - .one.column, - .one.columns { width: 4.66666666667%; } - .two.columns { width: 13.3333333333%; } - .three.columns { width: 22%; } - .four.columns { width: 30.6666666667%; } - .five.columns { width: 39.3333333333%; } - .six.columns { width: 48%; } - .seven.columns { width: 56.6666666667%; } - .eight.columns { width: 65.3333333333%; } - .nine.columns { width: 74.0%; } - .ten.columns { width: 82.6666666667%; } - .eleven.columns { width: 91.3333333333%; } - .twelve.columns { width: 100%; margin-left: 0; } - - .one-third.column { width: 30.6666666667%; } - .two-thirds.column { width: 65.3333333333%; } - - .one-half.column { width: 48%; } - - /* Offsets */ - .offset-by-one.column, - .offset-by-one.columns { margin-left: 8.66666666667%; } - .offset-by-two.column, - .offset-by-two.columns { margin-left: 17.3333333333%; } - .offset-by-three.column, - .offset-by-three.columns { margin-left: 26%; } - .offset-by-four.column, - .offset-by-four.columns { margin-left: 34.6666666667%; } - .offset-by-five.column, - .offset-by-five.columns { margin-left: 43.3333333333%; } - .offset-by-six.column, - .offset-by-six.columns { margin-left: 52%; } - .offset-by-seven.column, - .offset-by-seven.columns { margin-left: 60.6666666667%; } - .offset-by-eight.column, - .offset-by-eight.columns { margin-left: 69.3333333333%; } - .offset-by-nine.column, - .offset-by-nine.columns { margin-left: 78.0%; } - .offset-by-ten.column, - .offset-by-ten.columns { margin-left: 86.6666666667%; } - .offset-by-eleven.column, - .offset-by-eleven.columns { margin-left: 95.3333333333%; } - - .offset-by-one-third.column, - .offset-by-one-third.columns { margin-left: 34.6666666667%; } - .offset-by-two-thirds.column, - .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } - - .offset-by-one-half.column, - .offset-by-one-half.columns { margin-left: 52%; } - -} - - -/* Base Styles -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* NOTE -html is set to 62.5% so that all the REM measurements throughout Skeleton -are based on 10px sizing. So basically 1.5rem = 15px :) */ -html { - font-size: 62.5%; } -body { - font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ - line-height: 1.6; - font-weight: 400; - font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; - color: rgb(50, 50, 50); } - - -/* Typography -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -h1, h2, h3, h4, h5, h6 { - margin-top: 0; - margin-bottom: 0; - font-weight: 300; } -h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } -h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} -h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} -h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} -h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} -h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} - -p { - margin-top: 0; } - - -/* Blockquotes -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -blockquote { - border-left: 4px lightgrey solid; - padding-left: 1rem; - margin-top: 2rem; - margin-bottom: 2rem; - margin-left: 0rem; -} - - -/* Links -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -a { - color: #1EAEDB; } -a:hover { - color: #0FA0CE; } - - -/* Buttons -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.button, -button, -input[type="submit"], -input[type="reset"], -input[type="button"] { - display: inline-block; - height: 38px; - padding: 0 30px; - color: #555; - text-align: center; - font-size: 11px; - font-weight: 600; - line-height: 38px; - letter-spacing: .1rem; - text-transform: uppercase; - text-decoration: none; - white-space: nowrap; - background-color: transparent; - border-radius: 4px; - border: 1px solid #bbb; - cursor: pointer; - box-sizing: border-box; } -.button:hover, -button:hover, -input[type="submit"]:hover, -input[type="reset"]:hover, -input[type="button"]:hover, -.button:focus, -button:focus, -input[type="submit"]:focus, -input[type="reset"]:focus, -input[type="button"]:focus { - color: #333; - border-color: #888; - outline: 0; } -.button.button-primary, -button.button-primary, -input[type="submit"].button-primary, -input[type="reset"].button-primary, -input[type="button"].button-primary { - color: #FFF; - background-color: #33C3F0; - border-color: #33C3F0; } -.button.button-primary:hover, -button.button-primary:hover, -input[type="submit"].button-primary:hover, -input[type="reset"].button-primary:hover, -input[type="button"].button-primary:hover, -.button.button-primary:focus, -button.button-primary:focus, -input[type="submit"].button-primary:focus, -input[type="reset"].button-primary:focus, -input[type="button"].button-primary:focus { - color: #FFF; - background-color: #1EAEDB; - border-color: #1EAEDB; } - - -/* Forms -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -input[type="email"], -input[type="number"], -input[type="search"], -input[type="text"], -input[type="tel"], -input[type="url"], -input[type="password"], -textarea, -select { - height: 38px; - padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ - background-color: #fff; - border: 1px solid #D1D1D1; - border-radius: 4px; - box-shadow: none; - box-sizing: border-box; - font-family: inherit; - font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} -/* Removes awkward default styles on some inputs for iOS */ -input[type="email"], -input[type="number"], -input[type="search"], -input[type="text"], -input[type="tel"], -input[type="url"], -input[type="password"], -textarea { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; } -textarea { - min-height: 65px; - padding-top: 6px; - padding-bottom: 6px; } -input[type="email"]:focus, -input[type="number"]:focus, -input[type="search"]:focus, -input[type="text"]:focus, -input[type="tel"]:focus, -input[type="url"]:focus, -input[type="password"]:focus, -textarea:focus, -select:focus { - border: 1px solid #33C3F0; - outline: 0; } -label, -legend { - display: block; - margin-bottom: 0px; } -fieldset { - padding: 0; - border-width: 0; } -input[type="checkbox"], -input[type="radio"] { - display: inline; } -label > .label-body { - display: inline-block; - margin-left: .5rem; - font-weight: normal; } - - -/* Lists -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -ul { - list-style: circle inside; } -ol { - list-style: decimal inside; } -ol, ul { - padding-left: 0; - margin-top: 0; } -ul ul, -ul ol, -ol ol, -ol ul { - margin: 1.5rem 0 1.5rem 3rem; - font-size: 90%; } -li { - margin-bottom: 1rem; } - - -/* Tables -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -th, -td { - padding: 12px 15px; - text-align: left; - border-bottom: 1px solid #E1E1E1; } -th:first-child, -td:first-child { - padding-left: 0; } -th:last-child, -td:last-child { - padding-right: 0; } - - -/* Spacing -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -button, -.button { - margin-bottom: 0rem; } -input, -textarea, -select, -fieldset { - margin-bottom: 0rem; } -pre, -dl, -figure, -table, -form { - margin-bottom: 0rem; } -p, -ul, -ol { - margin-bottom: 0.75rem; } - -/* Utilities -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.u-full-width { - width: 100%; - box-sizing: border-box; } -.u-max-full-width { - max-width: 100%; - box-sizing: border-box; } -.u-pull-right { - float: right; } -.u-pull-left { - float: left; } - - -/* Misc -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -hr { - margin-top: 3rem; - margin-bottom: 3.5rem; - border-width: 0; - border-top: 1px solid #E1E1E1; } - - -/* Clearing -–––––––––––––––––––––––––––––––––––––––––––––––––– */ - -/* Self Clearing Goodness */ -.container:after, -.row:after, -.u-cf { - content: ""; - display: table; - clear: both; } - - -/* Media Queries -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* -Note: The best way to structure the use of media queries is to create the queries -near the relevant code. For example, if you wanted to change the styles for buttons -on small devices, paste the mobile query code up in the buttons section and style it -there. -*/ - - -/* Larger than mobile */ -@media (min-width: 400px) {} - -/* Larger than phablet (also point when grid becomes active) */ -@media (min-width: 550px) {} - -/* Larger than tablet */ -@media (min-width: 750px) {} - -/* Larger than desktop */ -@media (min-width: 1000px) {} - -/* Larger than Desktop HD */ -@media (min-width: 1200px) {} diff --git a/inst/lib/dash-app-stylesheets/docs-tutorial-stylesheet2.css b/inst/lib/dash-app-stylesheets/docs-tutorial-stylesheet2.css deleted file mode 100644 index e69de29b..00000000 diff --git a/inst/lib/dash-app-stylesheets/drug-discovery-demo-stylesheet.css b/inst/lib/dash-app-stylesheets/drug-discovery-demo-stylesheet.css deleted file mode 100644 index e83db436..00000000 --- a/inst/lib/dash-app-stylesheets/drug-discovery-demo-stylesheet.css +++ /dev/null @@ -1,25 +0,0 @@ -body{ - background: whitesmoke; -} - -.container{ - margin: 0 auto; - background: white; - padding: 40px; - max-width: 1200px; - overflow: hidden; - box-shadow: rgb(240, 240, 240) 5px 5px 5px 0px; -} - -p{ - overflow-x: hidden; -} - -td{ - word-break: break-all; - font-size: 12px; -} - -table{ - width: 100%; -} diff --git a/inst/lib/dash-app-stylesheets/goldman-sachs-report-js.js b/inst/lib/dash-app-stylesheets/goldman-sachs-report-js.js deleted file mode 100644 index 97d81891..00000000 --- a/inst/lib/dash-app-stylesheets/goldman-sachs-report-js.js +++ /dev/null @@ -1,7 +0,0 @@ -$( document ).ready(function() { - setTimeout(function(){ - $( ".button" ).click(function() { - window.print(); - }); - }, 4000); -}); diff --git a/inst/lib/dash-app-stylesheets/goldman-sachs-report.css b/inst/lib/dash-app-stylesheets/goldman-sachs-report.css deleted file mode 100644 index 7b008a44..00000000 --- a/inst/lib/dash-app-stylesheets/goldman-sachs-report.css +++ /dev/null @@ -1,107 +0,0 @@ -body { - width: 100%; - height: 100%; - margin: 0; - padding: 0; - background-color: #FAFAFA; - font-size: 1.1rem; - line-height: 1.3; - } - * { - box-sizing: border-box; - -moz-box-sizing: border-box; - } - .page { - position: relative; - width: 210mm; - min-height: 297mm; - padding: 0mm; - margin: 10mm auto; - /* border: 1px #D3D3D3 solid; */ - border-radius: 5px; - background: white; - /* box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); */ - } - .subpage { - padding: 1cm; - border: 5px #ccc solid; - height: 257mm; - outline: 2cm whitesmoke solid; - } - - @page { - size: A4; - margin: 0; - } - @media print { - html, body { - width: 210mm; - height: 297mm; - } - .page { - margin: 0; - border: initial; - border-radius: initial; - width: initial; - min-height: initial; - box-shadow: initial; - background: initial; - page-break-after: always; - } - .no-print, .no-print * { - display: none !important; - } - } - -p{ margin-bottom: 1rem } - -.iframe{ border: none; } - -.gs-header{ color: white !important; -webkit-print-color-adjust: exact; } - -.gs-text-header{ background: #2C3859 !important; -webkit-print-color-adjust: exact; } - -.gs-table-header{ background: #7F91AC !important; -webkit-print-color-adjust: exact; } - -.gs-accent-header{ background: #65201F !important; -webkit-print-color-adjust: exact; } - -div.padded{ padding: 10px; } - -h6.padded, p.padded{ - padding: 2px 5px; - margin-top: 10px; - margin-bottom: 2px; -} - -.blue-text{ color: #8496B8; } - -table{ width: 100% } - -td{ padding: 2px 0px } - -tr:nth-child(even) { background-color: #D7DBE1; } - -table.reversed tr:nth-child(odd) { background-color: #D7DBE1; } -table.reversed tr:nth-child(even) { background-color: white; } - -table{ - font-size: 0.95rem; - border-spacing: 0; - border-collapse: collapse; -} - -table.tiny-header tr:first-child{ - font-size: 8px; -} - -.columns{ margin-left: 0 !important; } - -.row > .columns:not(:first-child){ - padding-left: 20px; -} - -td, th { border: 0 } - -h1, h5, h6{ margin: 0 } - -h6{ font-size: 1.425rem } diff --git a/inst/lib/dash-app-stylesheets/hello-world.css b/inst/lib/dash-app-stylesheets/hello-world.css deleted file mode 100644 index e4c1b2ba..00000000 --- a/inst/lib/dash-app-stylesheets/hello-world.css +++ /dev/null @@ -1,53 +0,0 @@ -html { - font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: 200; - height: 100%; - position: relative; - box-sizing: border-box; - margin: 0; - padding: 0; -} - -/* plotly.js's modebar's z-index is outta the roof by default - lower it down */ -.js-plotly-plot .plotly .modebar { - z-index: 0 !important; -} - -.container { - padding: 10px; - margin: 20px; -} - -body, -div { - box-sizing: border-box; - margin: 0; - padding: 0; -} - -._dash-loading { - position: absolute; - overflow: hidden; - box-sizing: border-box; - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - color: #506784; - font-size: 14px; - height: 100%; - width: 100%; -} - -._dash-loading::before { - content: ''; - box-sizing: border-box; - overflow: hidden; - border-radius: 8px; - height: 50px; - width: 50px; - transform: translateX(-4px); - background: url('https://plot.ly/static/webapp/images/plotly-logo-loop.gif') no-repeat center center; - background-size: cover; - margin-bottom: 10px; -} diff --git a/inst/lib/dash-app-stylesheets/loading-state.css b/inst/lib/dash-app-stylesheets/loading-state.css deleted file mode 100644 index b8b83f51..00000000 --- a/inst/lib/dash-app-stylesheets/loading-state.css +++ /dev/null @@ -1,54 +0,0 @@ -._dash-loading-callback { - font-family: sans-serif; - padding-top: 50px; - color: rgb(90, 90, 90); - - -webkit-animation: fadein 0.5s ease-in 7s forwards; /* Safari, Chrome and Opera > 12.1 */ - -moz-animation: fadein 0.5s; /* Firefox < 16 */ - -ms-animation: fadein 0.5s; /* Internet Explorer */ - -o-animation: fadein 0.5s; /* Opera < 12.1 */ - animation: fadein 0.5s ease-in 7s forwards; - - - - /* The banner */ - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(255, 255, 255, 0.5); - text-align: center; - cursor: progress; -} - - -@keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} - -/* Firefox < 16 */ -@-moz-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} - -/* Safari, Chrome and Opera > 12.1 */ -@-webkit-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} - -/* Internet Explorer */ -@-ms-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} - -/* Opera < 12.1 */ -@-o-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} - diff --git a/inst/lib/dash-app-stylesheets/logo-by-plotly-stripe.png b/inst/lib/dash-app-stylesheets/logo-by-plotly-stripe.png deleted file mode 100644 index 121b2a9032077fa1dd8a0afc3ed1f3c414586dfe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5734 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 .label-body { - display: inline-block; - margin-left: .5rem; - font-weight: normal; } - - -/* Lists -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -ul { - list-style: circle inside; } -ol { - list-style: decimal inside; } -ol, ul { - padding-left: 0; - margin-top: 0; } -ul ul, -ul ol, -ol ol, -ol ul { - margin: 1.5rem 0 1.5rem 3rem; - font-size: 90%; } -li { - margin-bottom: 1rem; } - - -/* Tables -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -th, -td { - padding: 12px 15px; - text-align: left; - border-bottom: 1px solid #E1E1E1; } -th:first-child, -td:first-child { - padding-left: 0; } -th:last-child, -td:last-child { - padding-right: 0; } - - -/* Spacing -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -button, -.button { - margin-bottom: 0rem; } -input, -textarea, -select, -fieldset { - margin-bottom: 0rem; } -pre, -dl, -figure, -table, -form { - margin-bottom: 0rem; } -p, -ul, -ol { - margin-bottom: 0.75rem; } - -/* Utilities -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.u-full-width { - width: 100%; - box-sizing: border-box; } -.u-max-full-width { - max-width: 100%; - box-sizing: border-box; } -.u-pull-right { - float: right; } -.u-pull-left { - float: left; } - - -/* Misc -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -hr { - margin-top: 3rem; - margin-bottom: 3.5rem; - border-width: 0; - border-top: 1px solid #E1E1E1; } - - -/* Clearing -–––––––––––––––––––––––––––––––––––––––––––––––––– */ - -/* Self Clearing Goodness */ -.container:after, -.row:after, -.u-cf { - content: ""; - display: table; - clear: both; } - - -/* Media Queries -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* -Note: The best way to structure the use of media queries is to create the queries -near the relevant code. For example, if you wanted to change the styles for buttons -on small devices, paste the mobile query code up in the buttons section and style it -there. -*/ - - -/* Larger than mobile */ -@media (min-width: 400px) {} - -/* Larger than phablet (also point when grid becomes active) */ -@media (min-width: 550px) {} - -/* Larger than tablet */ -@media (min-width: 750px) {} - -/* Larger than desktop */ -@media (min-width: 1000px) {} - -/* Larger than Desktop HD */ -@media (min-width: 1200px) {} diff --git a/inst/lib/dash-app-stylesheets/stock-tickers.css b/inst/lib/dash-app-stylesheets/stock-tickers.css deleted file mode 100644 index 8f14fdfd..00000000 --- a/inst/lib/dash-app-stylesheets/stock-tickers.css +++ /dev/null @@ -1,33 +0,0 @@ -html { - font-family: "Arial"; - font-weight: 200; - font-size: 62.5%; - color: #111111; -} - -.container { - background-color: white; - border-radius: 5px; - font-size: 1.7rem; - box-shadow: rgb(240, 240, 240) 5px 5px 5px 0px; - border: thin solid rgb(240, 240, 240); - padding-top: 10px; - padding-bottom: 10px; - margin-left: auto; - margin-right: auto; - - padding-left: 80px; - padding-right: 80px; - width: 80%; - - @media (max-width: 500px) { - padding-left: 10px; - padding-right: 10px; - width: 100%; - } - - @media (max-width: 800px) { - padding-left: 60px; - padding-right: 60px; - } -} diff --git a/inst/lib/dash-app-stylesheets/technical-charting.css b/inst/lib/dash-app-stylesheets/technical-charting.css deleted file mode 100644 index 373c71b2..00000000 --- a/inst/lib/dash-app-stylesheets/technical-charting.css +++ /dev/null @@ -1,399 +0,0 @@ -/* Table of contents -–––––––––––––––––––––––––––––––––––––––––––––––––– -- Grid -- Base Styles -- Typography -- Links -- Buttons -- Forms -- Lists -- Code -- Tables -- Spacing -- Utilities -- Clearing -- Media Queries -*/ - -/* PLotly.js -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* plotly.js's modebar's z-index is outta the roof by default - lower it down */ -.js-plotly-plot .plotly .modebar { - z-index: 0 important!; -} - -/* Grid -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.container { - position: relative; - width: 100%; - max-width: 960px; - margin: 0 auto; - padding: 0 20px; - box-sizing: border-box; } -.column, -.columns { - width: 100%; - float: left; - box-sizing: border-box; } - -/* For devices larger than 400px */ -@media (min-width: 400px) { - .container { - width: 85%; - padding: 0; } -} - -/* For devices larger than 550px */ -@media (min-width: 550px) { - .container { - width: 80%; } - .column, - .columns { - margin-left: 4%; } - .column:first-child, - .columns:first-child { - margin-left: 0; } - - .one.column, - .one.columns { width: 4.66666666667%; } - .two.columns { width: 13.3333333333%; } - .three.columns { width: 22%; } - .four.columns { width: 30.6666666667%; } - .five.columns { width: 39.3333333333%; } - .six.columns { width: 48%; } - .seven.columns { width: 56.6666666667%; } - .eight.columns { width: 65.3333333333%; } - .nine.columns { width: 74.0%; } - .ten.columns { width: 82.6666666667%; } - .eleven.columns { width: 91.3333333333%; } - .twelve.columns { width: 100%; margin-left: 0; } - - .one-third.column { width: 30.6666666667%; } - .two-thirds.column { width: 65.3333333333%; } - - .one-half.column { width: 48%; } - - /* Offsets */ - .offset-by-one.column, - .offset-by-one.columns { margin-left: 8.66666666667%; } - .offset-by-two.column, - .offset-by-two.columns { margin-left: 17.3333333333%; } - .offset-by-three.column, - .offset-by-three.columns { margin-left: 26%; } - .offset-by-four.column, - .offset-by-four.columns { margin-left: 34.6666666667%; } - .offset-by-five.column, - .offset-by-five.columns { margin-left: 43.3333333333%; } - .offset-by-six.column, - .offset-by-six.columns { margin-left: 52%; } - .offset-by-seven.column, - .offset-by-seven.columns { margin-left: 60.6666666667%; } - .offset-by-eight.column, - .offset-by-eight.columns { margin-left: 69.3333333333%; } - .offset-by-nine.column, - .offset-by-nine.columns { margin-left: 78.0%; } - .offset-by-ten.column, - .offset-by-ten.columns { margin-left: 86.6666666667%; } - .offset-by-eleven.column, - .offset-by-eleven.columns { margin-left: 95.3333333333%; } - - .offset-by-one-third.column, - .offset-by-one-third.columns { margin-left: 34.6666666667%; } - .offset-by-two-thirds.column, - .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } - - .offset-by-one-half.column, - .offset-by-one-half.columns { margin-left: 52%; } - -} - - -/* Base Styles -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* NOTE -html is set to 62.5% so that all the REM measurements throughout Skeleton -are based on 10px sizing. So basically 1.5rem = 15px :) */ -html { - font-size: 62.5%; } -body { - font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ - line-height: 1.6; - font-weight: 400; - font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; - color: rgb(50, 50, 50); } - - -/* Typography -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -h1, h2, h3, h4, h5, h6 { - margin-top: 0; - margin-bottom: 0; - font-weight: 300; } -h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } -h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} -h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} -h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} -h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} -h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} - -p { - margin-top: 0; } - - -/* Blockquotes -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -blockquote { - border-left: 4px lightgrey solid; - padding-left: 1rem; - margin-top: 2rem; - margin-bottom: 2rem; - margin-left: 0rem; -} - - -/* Links -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -a { - color: #1EAEDB; } -a:hover { - color: #0FA0CE; } - - -/* Buttons -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.button, -button, -input[type="submit"], -input[type="reset"], -input[type="button"] { - display: inline-block; - height: 38px; - padding: 0 30px; - color: #555; - text-align: center; - font-size: 11px; - font-weight: 600; - line-height: 38px; - letter-spacing: .1rem; - text-transform: uppercase; - text-decoration: none; - white-space: nowrap; - background-color: transparent; - border-radius: 4px; - border: 1px solid #bbb; - cursor: pointer; - box-sizing: border-box; } -.button:hover, -button:hover, -input[type="submit"]:hover, -input[type="reset"]:hover, -input[type="button"]:hover, -.button:focus, -button:focus, -input[type="submit"]:focus, -input[type="reset"]:focus, -input[type="button"]:focus { - color: #333; - border-color: #888; - outline: 0; } -.button.button-primary, -button.button-primary, -input[type="submit"].button-primary, -input[type="reset"].button-primary, -input[type="button"].button-primary { - color: #FFF; - background-color: #33C3F0; - border-color: #33C3F0; } -.button.button-primary:hover, -button.button-primary:hover, -input[type="submit"].button-primary:hover, -input[type="reset"].button-primary:hover, -input[type="button"].button-primary:hover, -.button.button-primary:focus, -button.button-primary:focus, -input[type="submit"].button-primary:focus, -input[type="reset"].button-primary:focus, -input[type="button"].button-primary:focus { - color: #FFF; - background-color: #1EAEDB; - border-color: #1EAEDB; } - - -/* Forms -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -input[type="email"], -input[type="number"], -input[type="search"], -input[type="text"], -input[type="tel"], -input[type="url"], -input[type="password"], -textarea, -select { - height: 38px; - padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ - background-color: #fff; - border: 1px solid #D1D1D1; - border-radius: 4px; - box-shadow: none; - box-sizing: border-box; - font-family: inherit; - font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} -/* Removes awkward default styles on some inputs for iOS */ -input[type="email"], -input[type="number"], -input[type="search"], -input[type="text"], -input[type="tel"], -input[type="url"], -input[type="password"], -textarea { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; } -textarea { - min-height: 65px; - padding-top: 6px; - padding-bottom: 6px; } -input[type="email"]:focus, -input[type="number"]:focus, -input[type="search"]:focus, -input[type="text"]:focus, -input[type="tel"]:focus, -input[type="url"]:focus, -input[type="password"]:focus, -textarea:focus, -select:focus { - border: 1px solid #33C3F0; - outline: 0; } -label, -legend { - display: block; - margin-bottom: 0px; } -fieldset { - padding: 0; - border-width: 0; } -input[type="checkbox"], -input[type="radio"] { - display: inline; } -label > .label-body { - display: inline-block; - margin-left: .5rem; - font-weight: normal; } - - -/* Lists -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -ul { - list-style: circle inside; } -ol { - list-style: decimal inside; } -ol, ul { - padding-left: 0; - margin-top: 0; } -ul ul, -ul ol, -ol ol, -ol ul { - margin: 1.5rem 0 1.5rem 3rem; - font-size: 90%; } -li { - margin-bottom: 1rem; } - - -/* Tables -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -th, -td { - padding: 12px 15px; - text-align: left; - border-bottom: 1px solid #E1E1E1; } -th:first-child, -td:first-child { - padding-left: 0; } -th:last-child, -td:last-child { - padding-right: 0; } - - -/* Spacing -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -button, -.button { - margin-bottom: 0rem; } -input, -textarea, -select, -fieldset { - margin-bottom: 0rem; } -pre, -dl, -figure, -table, -form { - margin-bottom: 0rem; } -p, -ul, -ol { - margin-bottom: 0.75rem; } - -/* Utilities -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.u-full-width { - width: 100%; - box-sizing: border-box; } -.u-max-full-width { - max-width: 100%; - box-sizing: border-box; } -.u-pull-right { - float: right; } -.u-pull-left { - float: left; } - - -/* Misc -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -hr { - margin-top: 3rem; - margin-bottom: 3.5rem; - border-width: 0; - border-top: 1px solid #E1E1E1; } - - -/* Clearing -–––––––––––––––––––––––––––––––––––––––––––––––––– */ - -/* Self Clearing Goodness */ -.container:after, -.row:after, -.u-cf { - content: ""; - display: table; - clear: both; } - - -/* Media Queries -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* -Note: The best way to structure the use of media queries is to create the queries -near the relevant code. For example, if you wanted to change the styles for buttons -on small devices, paste the mobile query code up in the buttons section and style it -there. -*/ - - -/* Larger than mobile */ -@media (min-width: 400px) {} - -/* Larger than phablet (also point when grid becomes active) */ -@media (min-width: 550px) {} - -/* Larger than tablet */ -@media (min-width: 750px) {} - -/* Larger than desktop */ -@media (min-width: 1000px) {} - -/* Larger than Desktop HD */ -@media (min-width: 1200px) {} diff --git a/inst/lib/dash-app-stylesheets/uber-ride-demo.css b/inst/lib/dash-app-stylesheets/uber-ride-demo.css deleted file mode 100644 index ddfb71f6..00000000 --- a/inst/lib/dash-app-stylesheets/uber-ride-demo.css +++ /dev/null @@ -1,131 +0,0 @@ -.graphSlider .rc-slider{ - margin-top: 5px; - position: relative; - bottom: 20px; - height: 14px; - padding: 5px 0; - width: 100%; - border-radius: 6px; - box-sizing: border-box; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} - -.graphSlider .rc-slider-dot-active{ - border-color: #e9e9e9; - color: black; -} - -.graphSlider .rc-slider-track{ - background: none; -} - -.graphSlider .rc-slider-mark-text{ - color: #828282; -} - -.graphSlider .rc-slider-handle{ - margin-left: -10px; - margin-top: -8px; - width: 20px; - height: 20px; -} - -.graphSlider .totalRides{ - display: block; - z-index: 1; - position: relative; - top: 110px; - left: 20px; - color: white; - cursor: default; - margin-bottom: 0px; -} - -.graphSlider .totalRideSelection{ - display: inline-block; - margin-bottom: 0; - position: relative; - top: 108px; - left: 19px; - z-index: 1; - right: 133px; - color: white; -} - -.graphSlider .dateValue{ - position: relative; - display: block; - top: 785px; - left: 20px; - color: white; - cursor: default; - z-index: 1; - margin-bottom: 0px; -} - -.graphSlider .graph .js-plotly-plot .cursor-pointer{ - cursor: crosshair; -} - -._dash-app-content { - overflow-x: hidden; - overflow-y: hidden; - position: relative; - /* bottom: 100px; */ -} - -body { - overflow-x: hidden; -} - -.mapControls{ - display: inline; - position: absolute; - top: 140px; - left: 45%; - z-index: 1; - color: white; -} - -.graphSlider h2{ - top: 30px; - padding-left: 7px; - position: absolute; -} - -.graphSlider .explanationParagraph{ - margin: auto auto; - top: 75px; - padding-left: 11px; - position: absolute; -} - -.source { - padding-top: 30px; -} - -.popupAnnotation { - margin: 0; - position: relative; - z-index: 1; - bottom: 250px; - padding-left: 15px; - color: white; - display: block; - cursor: default; - display: inline; -} - -.Select{ - padding-left: 10px; - /*padding-right: 9px;*/ - z-index: 2; -} - -.Select-menu-outer{ - width: 99.5%; -} - -.month-picker .Select-clear{ - visibility: hidden; -} diff --git a/inst/lib/dash-app-stylesheets/wind-streaming.css b/inst/lib/dash-app-stylesheets/wind-streaming.css deleted file mode 100644 index d57b32fb..00000000 --- a/inst/lib/dash-app-stylesheets/wind-streaming.css +++ /dev/null @@ -1,138 +0,0 @@ -body{ - font-size: 1.5em; - line-height: 1.6; - font-weight: 400; - font-family: Raleway,HelveticaNeue,"Helvetica Neue",Helvetica,Arial,sans-serif; - color: #222; -} - -.banner { - height: 75px; - margin: 0px -10px 10px; - background-color: rgb(66, 196, 247); - border-radius: 2px; -} - -.banner h2{ - color: white; - padding-top: 10px; - margin-left: 2%; - display: inline-block; -} - -.banner Img{ - position: relative; - float: right; - right: 10px; - height: 75px; -} - -.wind-speed-row .Title{ - border-bottom: 1px solid rgb(216, 216, 216); -} - -.wind-speed-row .Title h3{ - font-size: 1.75rem; - color: rgb(66, 196, 247); - border-bottom: rgb(216, 216, 216); - margin-top: 3px; - margin-left: 10px; - margin-bottom: 3px; -} - -.wind-speed-row { - border-radius: 5px; - border-width: 1px 1px 0px; - border-top-style: solid; - border-right-style: solid; - border-bottom-style: initial; - border-left-style: solid; - border-top-color: rgb(216, 216, 216); - border-right-color: rgb(216, 216, 216); - border-bottom-color: initial; - border-left-color: rgb(216, 216, 216); - border-image: initial; -} - -.wind-histo-polar .wind-histogram .Title h3{ - font-size: 1.75rem; - color: rgb(66, 196, 247); - border-bottom: rgb(216, 216, 216); - margin-top: 3px; - margin-left: 10px; - margin-bottom: 3px; -} - -.wind-histo-polar .wind-histogram .Title{ - border-bottom: 1px solid rgb(216, 216, 216); -} - -.histogram-slider { - top: 40px; - z-index: 1000000; - width: 65%; - position: relative; - margin: 0px auto; - left: 25px; -} - -.wind-histo-polar .wind-histogram .bin-size { - font-size: small; - right: 65px; - top: 50px; - float: right; - z-index: 10000000; - position: relative; - font-family: Raleway; - margin: 0px; - display: inline-block; -} - -.wind-histo-polar .wind-histogram .bin-auto{ - font-size: small; - top: 45px; - z-index: 1000000; - position: relative; - display: inline-block; - left: 90px; -} - -.wind-histo-polar .wind-histogram .js-plotly-plot .plot-container .svg-container .modebar{ - z-index: -100; -} - -.wind-speed-row .wind-speed .js-plotly-plot .plot-container .svg-container .modebar{ - z-index: -100; -} - -.wind-histo-polar .wind-histogram{ - border-radius: 5px; - width: 68.4%; - border: 1px solid rgb(216, 216, 216); -} - -.wind-histo-polar .wind-polar .Title h3{ - font-size: 1.75rem; - color: rgb(66, 196, 247); - border-bottom: rgb(216, 216, 216); - margin-top: 3px; - margin-left: 10px; - margin-bottom: 3px; -} - -.wind-histo-polar .wind-polar .Title{ - border-bottom: 1px solid rgb(216, 216, 216); -} - -.wind-histo-polar .wind-polar { - border-radius: 5px; - float: right; - height: 532px; - width: 280px; - margin-left: 0px; - border: 1px solid rgb(216, 216, 216); -} - -.wind-histo-polar{ - margin-bottom: 0px; -} From cdf36acfb2b4d516230e7d6b3c331c26b3ea6984 Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 15:45:11 -0400 Subject: [PATCH 14/27] :hocho: dash-css export --- DESCRIPTION | 3 +-- NAMESPACE | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index b724ab29..0d22da66 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -28,13 +28,12 @@ Collate: 'dash.R' 'imports.R' 'print.R' - 'css.R' 'heroku.R' 'internal.R' License: MIT + file LICENSE Encoding: UTF-8 LazyData: true -RoxygenNote: 6.0.1.9000 +RoxygenNote: 6.1.1 Roxygen: list(markdown = TRUE) URL: https://github.com/plotly/dashR BugReports: https://github.com/plotly/dashR/issues diff --git a/NAMESPACE b/NAMESPACE index 283a3503..b2cb085b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,7 +2,6 @@ S3method(print,dash_component) export(Dash) -export(dash_css) export(heroku_app_deploy) export(heroku_app_template) export(input) From 9c3169a9c4a1250d0be2f62bfa707195276b7c91 Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 15:45:27 -0400 Subject: [PATCH 15/27] :hocho: css.R --- R/css.R | 44 -------------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 R/css.R diff --git a/R/css.R b/R/css.R deleted file mode 100644 index 43ba1c26..00000000 --- a/R/css.R +++ /dev/null @@ -1,44 +0,0 @@ -#' Dash app stylesheets -#' -#' Use the 'official' Dash stylesheet in your dashR applications -#' . To learn how -#' to use the default style ("docs-base"), see -#' -#' @param filenames css filenames to use -#' @export -#' @example inst/tutorial/examples/style-dash-css.R -#' @md -#' - - -# For better performance, consider placing CSS in the of the HTML -# document (via app$dependencies_set(), which automatically places css in ) -dash_css <- function(filenames = "docs-base") { - - cssDir <- system.file("lib", "dash-app-stylesheets", package = "dashR") - cssNames <- sub("\\.css$", "", list.files(cssDir)) - missingFiles <- setdiff(filenames, cssNames) - if (length(missingFiles)) { - stop( - sprintf( - "Couldn't find the css file(s) named: '%s' \n\n", - paste(missingFiles, collapse = "', '") - ), - "Valid file names are: '%s'", - paste(cssNames, collapse = "', '"), - call. = FALSE - ) - } - - htmltools::htmlDependency( - name = "dash-app-stylesheets", - version = "1.0.0", - package = "dashR", - src = c( - href = "https://cdn.rawgit.com/plotly/dash-app-stylesheets/master/", - file = "lib/dash-app-stylesheets" - ), - stylesheet = paste0(filenames, ".css"), - all_files = FALSE - ) -} From 6a56f7270e5b12134c78093bc29deeddb8a9e16d Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 15:45:49 -0400 Subject: [PATCH 16/27] :hocho: htmltools.R example --- demo/htmltools.R | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 demo/htmltools.R diff --git a/demo/htmltools.R b/demo/htmltools.R deleted file mode 100644 index 08d672c3..00000000 --- a/demo/htmltools.R +++ /dev/null @@ -1,26 +0,0 @@ -# Example of using htmltools::tags in a dasher app -- based on demo/urls.R -library(dashR) -library(htmltools) - -app <- Dash$new() -app$layout_set( - # represents the URL bar, doesn't render anything - coreLocation('url', refresh = FALSE), - - tags$link('Navigate to "/"', href = '/'), - tags$br(), - tags$link('Navigate to "/page-2"', href = '/page-2'), - - # content will be rendered in this element - htmlDiv(id = "container", "A simple container div", tags$div(id = 'page-content')) -) - -app$callback( - function(pathname = input("url", "pathname")) { - htmlH3(paste("You are on page", pathname)) - }, - output("page-content") -) - -app$dependencies_set(dash_css()) -app$run_server(showcase = TRUE) From 38611539599e5a22546e46184484239f3b83df18 Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 15:46:57 -0400 Subject: [PATCH 17/27] :hocho: examples, will replace --- R/dash.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/dash.R b/R/dash.R index 2b2ee57c..e0b5d925 100644 --- a/R/dash.R +++ b/R/dash.R @@ -157,7 +157,7 @@ Dash <- R6::R6Class( # ------------------------------------------------------------ router <- routr::RouteStack$new() - if (!is.null(private$assets_folder)) { + if (!is.null(private$assets_folder) && gsub("/+", "", assets_folder) != "assets") { if (!(dir.exists(private$assets_folder))) { warning(sprintf( "The supplied assets folder, '%s' could not be found in the project directory.", From f85d5535779987f78fbd03a9c96f736f00634bf2 Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 15:47:26 -0400 Subject: [PATCH 18/27] updated R documentation --- man/Dash.Rd | 30 ++++++++++-------------------- man/dashR-package.Rd | 5 +++++ man/dependencies.Rd | 9 +++------ 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/man/Dash.Rd b/man/Dash.Rd index 7c61e079..8ec3306e 100644 --- a/man/Dash.Rd +++ b/man/Dash.Rd @@ -9,7 +9,9 @@ app <- Dash$new( name = "dash", server = fiery::Fire$new(), - static_folder = NULL, + assets_folder = 'assets', + assets_url_path = '/assets', + assets_ignore = '', serve_locally = TRUE, routes_pathname_prefix = '/', requests_pathname_prefix = '/' @@ -25,19 +27,21 @@ Description coming soon of the HTML page).\cr \code{server} \tab \tab The web server used to power the application. Must be a \link[fiery:Fire]{fiery::Fire} object.\cr -\code{static_folder} \tab \tab A character vector of directories for serving -with the application (the default, \code{NULL}, means don't serve additional -directories). If provided, the names attribute defines corresponding url -path, otherwise it defaults to '/'.\cr \code{serve_locally} \tab \tab Whether to serve HTML dependencies locally or remotely (via URL).\cr \code{routes_pathname_prefix} \tab \tab a prefix applied to the backend routes.\cr \code{requests_pathname_prefix} \tab \tab a prefix applied to request endpoints made by Dash's front-end.\cr +\code{external_scripts} \tab \tab An optional list of valid URLs from which +to serve JavaScript source for rendered pages.\cr +\code{external_stylesheets} \tab \tab An optional list of valid URLs from which +to serve CSS for rendered pages.\cr \code{suppress_callback_exceptions} \tab \tab Whether to relay warnings about possible layout mis-specifications when registering a callback. For an example of when it is ok to suppress these callbacks, see -\code{runTutorial("urls-part-2.R")} +\code{components_cache_max_age} \tab \tab An integer value specifying the time +interval prior to expiring cached assets. The default is 2678400 seconds, +or 31 calendar days. } } @@ -55,13 +59,6 @@ Users shouldn't need to alter any of these options unless they are constructing their own authorization front-end or otherwise need to know where the application is making API calls. } -\item{\code{exclude_plotly_bundle}}{ -Whether or not to exclude the plotly.js bundle when "core components" exist, -but \link[dashCoreComponents:coreGraph]{dashCoreComponents::coreGraph} is not provided to the \code{layout()} -method (i.e., the initial layout). -The only time \code{exclude_plotly_bundle} should be \code{TRUE} is if you don't want -a \code{coreGraph()} in the initial layout, but want to insert one via a callback. -} } } @@ -106,13 +103,6 @@ for running the app on Heroku. } } -\examples{ - -app <- runTutorial("urls-part-2.R") -app$server$stop() - - -} \seealso{ \url{https://plot.ly/dashR/} } diff --git a/man/dashR-package.Rd b/man/dashR-package.Rd index 2c685b1a..0a27dc02 100644 --- a/man/dashR-package.Rd +++ b/man/dashR-package.Rd @@ -19,4 +19,9 @@ Useful links: \author{ \strong{Maintainer}: Ryan Kyle \email{ryan@plot.ly} +Authors: +\itemize{ + \item Carson Sievert +} + } diff --git a/man/dependencies.Rd b/man/dependencies.Rd index f7502923..1e62f62c 100644 --- a/man/dependencies.Rd +++ b/man/dependencies.Rd @@ -5,16 +5,13 @@ \alias{output} \alias{input} \alias{state} -\alias{event} \title{Input/Output/State definitions} \usage{ -output(id = NULL, property = "children") +output(id, property) -input(id = NULL, property = "value") +input(id, property) -state(id = NULL, property = "value") - -event(id = NULL, property = "value") +state(id, property) } \arguments{ \item{id}{a component id} From fe542cb49dc18c658356f48b9972e440a515a5fc Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 15:47:42 -0400 Subject: [PATCH 19/27] :hocho: dash_css.Rd --- man/dash_css.Rd | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 man/dash_css.Rd diff --git a/man/dash_css.Rd b/man/dash_css.Rd deleted file mode 100644 index 01f3935a..00000000 --- a/man/dash_css.Rd +++ /dev/null @@ -1,29 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/css.R -\name{dash_css} -\alias{dash_css} -\title{Dash app stylesheets} -\usage{ -dash_css(filenames = "docs-base") -} -\arguments{ -\item{filenames}{css filenames to use} -} -\description{ -Use the 'official' Dash stylesheet in your dashR applications -\url{https://github.com/plotly/dash-app-stylesheets}. To learn how -to use the default style ("docs-base"), see \url{https://codepen.io/chriddyp/pen/bWLwgP} -} -\examples{ -library(dashR) - -app <- Dash$new() - -app$layout_set( - coreInput(id = 'inputID', value = 'initial value', type = "text"), - htmlDiv(id = 'outputID') -) - -app$dependencies_set(dash_css()) -app -} From 6b8687d5a678980133eb9634bff90da8fbe5a447 Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 16:02:42 -0400 Subject: [PATCH 20/27] :hocho: outdated roxygen documentation statements --- R/dash.R | 7 ------- 1 file changed, 7 deletions(-) diff --git a/R/dash.R b/R/dash.R index e0b5d925..ee3883c4 100644 --- a/R/dash.R +++ b/R/dash.R @@ -32,7 +32,6 @@ #' `suppress_callback_exceptions` \tab \tab Whether to relay warnings about #' possible layout mis-specifications when registering a callback. For an #' example of when it is ok to suppress these callbacks, see -#' `runTutorial("urls-part-2.R")`\cr #' `components_cache_max_age` \tab \tab An integer value specifying the time #' interval prior to expiring cached assets. The default is 2678400 seconds, #' or 31 calendar days. @@ -95,14 +94,8 @@ #' @export #' @docType class #' @format An [R6::R6Class] generator object -#' @author Carson Sievert #' @seealso #' -#' @examples -#' -#' app <- runTutorial("urls-part-2.R") -#' app$server$stop() -#' #' Dash <- R6::R6Class( From 696523be7db9c37cd57ae94797a21b754a26bbd5 Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 16:05:24 -0400 Subject: [PATCH 21/27] updated online help --- man/Dash.Rd | 3 --- 1 file changed, 3 deletions(-) diff --git a/man/Dash.Rd b/man/Dash.Rd index 8ec3306e..134847f8 100644 --- a/man/Dash.Rd +++ b/man/Dash.Rd @@ -106,7 +106,4 @@ for running the app on Heroku. \seealso{ \url{https://plot.ly/dashR/} } -\author{ -Carson Sievert -} \keyword{datasets} From 8afced37fb795fcf33a01a637c31487637f571fe Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 16:14:48 -0400 Subject: [PATCH 22/27] :bug: fix issues with documentation not rendering correctly --- R/dash.R | 3 +-- man/Dash.Rd | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/R/dash.R b/R/dash.R index ee3883c4..230b57eb 100644 --- a/R/dash.R +++ b/R/dash.R @@ -30,8 +30,7 @@ #' `external_stylesheets` \tab \tab An optional list of valid URLs from which #' to serve CSS for rendered pages.\cr #' `suppress_callback_exceptions` \tab \tab Whether to relay warnings about -#' possible layout mis-specifications when registering a callback. For an -#' example of when it is ok to suppress these callbacks, see +#' possible layout mis-specifications when registering a callback. \cr #' `components_cache_max_age` \tab \tab An integer value specifying the time #' interval prior to expiring cached assets. The default is 2678400 seconds, #' or 31 calendar days. diff --git a/man/Dash.Rd b/man/Dash.Rd index 134847f8..2a050161 100644 --- a/man/Dash.Rd +++ b/man/Dash.Rd @@ -37,8 +37,7 @@ to serve JavaScript source for rendered pages.\cr \code{external_stylesheets} \tab \tab An optional list of valid URLs from which to serve CSS for rendered pages.\cr \code{suppress_callback_exceptions} \tab \tab Whether to relay warnings about -possible layout mis-specifications when registering a callback. For an -example of when it is ok to suppress these callbacks, see +possible layout mis-specifications when registering a callback. \cr \code{components_cache_max_age} \tab \tab An integer value specifying the time interval prior to expiring cached assets. The default is 2678400 seconds, or 31 calendar days. From 2b299a8becd68649bc6960c1062dc351824e69ad Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 20:31:48 -0400 Subject: [PATCH 23/27] :bug: change NULL to double quotes when not serving favicon --- R/dash.R | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/R/dash.R b/R/dash.R index 230b57eb..7b2db331 100644 --- a/R/dash.R +++ b/R/dash.R @@ -127,7 +127,8 @@ Dash <- R6::R6Class( # save relevant args as private fields private$name <- name private$serve_locally <- serve_locally - private$assets_folder <- assets_folder + # remove leading and trailing slash(es) if present + private$assets_folder <- gsub("^/+|/+$", "", assets_folder) # remove trailing slash in assets_url_path, if present private$assets_url_path <- sub("/$", "", assets_url_path) private$assets_ignore <- assets_ignore @@ -149,14 +150,14 @@ Dash <- R6::R6Class( # ------------------------------------------------------------ router <- routr::RouteStack$new() - if (!is.null(private$assets_folder) && gsub("/+", "", assets_folder) != "assets") { - if (!(dir.exists(private$assets_folder))) { + if (!(is.null(private$assets_folder))) { + if (!(dir.exists(private$assets_folder)) && gsub("/+", "", assets_folder) != "assets") { warning(sprintf( "The supplied assets folder, '%s' could not be found in the project directory.", private$assets_folder), call. = FALSE ) - } else { + } else if (dir.exists(private$assets_folder)) { private$asset_map <- private$walk_assets_directory(private$assets_folder) private$css <- private$asset_map$css private$scripts <- private$asset_map$scripts @@ -604,7 +605,11 @@ Dash <- R6::R6Class( layout_ }, - walk_assets_directory = function(assets_dir = private$assets_dir) { + walk_assets_directory = function(assets_dir = private$assets_folder) { + if (!(dir.exists(private$assets_folder))) { + return + } + # obtain the full canonical path asset_path <- normalizePath(file.path(assets_dir)) @@ -793,7 +798,7 @@ Dash <- R6::R6Class( if ("/favicon.ico" %in% names(private$other)) { favicon <- sprintf("") } else { - favicon <- NULL + favicon <- "" } # serving order of CSS and JS tags: package -> external -> assets From f603cd42af2dce9f9133700f0a44bfd965422baf Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 20:32:14 -0400 Subject: [PATCH 24/27] updated DESCRIPTION --- DESCRIPTION | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 0d22da66..eb31c781 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: dashR -Title: An interface to the dash ecosystem for authoring reactive web applications +Title: An interface to the Dash ecosystem for authoring reactive web applications Version: 0.0.6 -Authors@R: c(person("Ryan", "Kyle", role = c("aut", "cre"), email = "ryan@plot.ly"), person("Carson", "Sievert", role = c("aut"))) -Description: An interface to the dash ecosystem for authoring reactive web applications. +Authors@R: c(person("Ryan", "Kyle", role = c("aut", "cre", "trl"), email = "ryan@plot.ly"), person("Chris", "Parmer", role = c("aut"), email = "chris@plot.ly"), person("Carson", "Sievert", role = c("aut")), person(family = "Plotly", role = "cph")) +Description: An interface to the Dash ecosystem for authoring reactive web applications. Depends: R (>= 3.0.2) Imports: From b23ff9b2c1cc4d11e88f81014b96de62ba93abaf Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 20:36:51 -0400 Subject: [PATCH 25/27] removed unneeded codeblock --- R/dash.R | 4 ---- 1 file changed, 4 deletions(-) diff --git a/R/dash.R b/R/dash.R index 7b2db331..22d65e23 100644 --- a/R/dash.R +++ b/R/dash.R @@ -606,10 +606,6 @@ Dash <- R6::R6Class( }, walk_assets_directory = function(assets_dir = private$assets_folder) { - if (!(dir.exists(private$assets_folder))) { - return - } - # obtain the full canonical path asset_path <- normalizePath(file.path(assets_dir)) From 5c4e23fe7680e8124e3401b47273127178c1640b Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 20:39:33 -0400 Subject: [PATCH 26/27] add missing comma in warning --- R/dash.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/dash.R b/R/dash.R index 22d65e23..e96dd655 100644 --- a/R/dash.R +++ b/R/dash.R @@ -153,7 +153,7 @@ Dash <- R6::R6Class( if (!(is.null(private$assets_folder))) { if (!(dir.exists(private$assets_folder)) && gsub("/+", "", assets_folder) != "assets") { warning(sprintf( - "The supplied assets folder, '%s' could not be found in the project directory.", + "The supplied assets folder, '%s', could not be found in the project directory.", private$assets_folder), call. = FALSE ) From 756954f8b4d0ba3db14292727854a53a940bf7d9 Mon Sep 17 00:00:00 2001 From: Ryan Patrick Kyle Date: Mon, 8 Apr 2019 20:53:19 -0400 Subject: [PATCH 27/27] add check for character(0) --- R/dash.R | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/R/dash.R b/R/dash.R index e96dd655..0351b216 100644 --- a/R/dash.R +++ b/R/dash.R @@ -133,7 +133,7 @@ Dash <- R6::R6Class( private$assets_url_path <- sub("/$", "", assets_url_path) private$assets_ignore <- assets_ignore private$suppress_callback_exceptions <- suppress_callback_exceptions - + gsub("^/+|/+$", "", assets_folder) # config options self$config$routes_pathname_prefix <- resolve_prefix(routes_pathname_prefix, "DASH_ROUTES_PATHNAME_PREFIX") self$config$requests_pathname_prefix <- resolve_prefix(requests_pathname_prefix, "DASH_REQUESTS_PATHNAME_PREFIX") @@ -150,7 +150,8 @@ Dash <- R6::R6Class( # ------------------------------------------------------------ router <- routr::RouteStack$new() - if (!(is.null(private$assets_folder))) { + # ensure that assets_folder is neither NULL nor character(0) + if (!(is.null(private$assets_folder)) & length(private$assets_folder) != 0) { if (!(dir.exists(private$assets_folder)) && gsub("/+", "", assets_folder) != "assets") { warning(sprintf( "The supplied assets folder, '%s', could not be found in the project directory.",