-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Storing state of the app as a bookmark #659
Conversation
… param. This is required to save state.
…the server side - not in the URL.
sorted |
sorted |
This looks like great progress Ali, thanks. @nikolai-b let us know if this works on the test server so we can play with getting bookmarks for a range of locations / settings. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, a few questions that are mainly style but overall seems pretty clean. Nice work!
} else { | ||
"isle-of-wight" | ||
|
||
if(!is.null(region$state_region) && !is.na(region$state_region)){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why we need to do both na
and null
checks? I get confused which to use in R
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null
when it's not initialized - ran before the initialization of the region
variable, and na
when there is no saved state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about
if (is.character(region$state_region)){
region$current <- region$state_region
}
regions_www/m/server.R
Outdated
|
||
region$state_lng <<- state$input$map_center$lng | ||
region$state_lat <<- state$input$map_center$lat | ||
region$state_mzoom <<- state$input$map_zoom |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need <<-
? I know we use them but we need to stop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. No, I don't need it. Have now removed it. At some point, we should rid of all of them.
lng = region$state_lng, | ||
lat = region$state_lat, | ||
zoom = region$state_mzoom | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be done in onRestore
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it can't be done there. onRestore
runs before any observe block is executed - since leaflet variable hasn't been initialized, this can't work.
I now have moved this block to the onRestored
function which is run after all observe blocks are executed.
Thanks @nikolai-b for your feedback - have now replied to your comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After having another think sadly we need to use the url
store unless you can think of another way of doing it.
Sorry I was slow at replying.
} else { | ||
"isle-of-wight" | ||
|
||
if(!is.null(region$state_region) && !is.na(region$state_region)){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about
if (is.character(region$state_region)){
region$current <- region$state_region
}
regions_www/m/server.R
Outdated
@@ -22,6 +22,9 @@ | |||
## Functions | |||
source("pct_shiny_funs.R", local = T) | |||
|
|||
## Enable bookmarking at the server side | |||
enableBookmarking(store = "server") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, sadly this won't work. We need to store the state in the URL. For one we have multiple servers so if you share a link from the London server and the request is handled by the Cambridge server it will fail. Also when we deploy we are likely to wipe these.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a fair point. The only big problem is (apart from a messy URL for a specific states), the URL keeps changing when someone uses the app and they are not even interested to save or restore the app's state. On the bright side, it's easier to manage, as the servers don't need to remember anything.
I still believe that server-side bookmarking is much neater. I can think of two solutions here:
- We don't care about app's state not saved on a specific server
- For the two servers, we routinely mirror their saved states. This requires writing a routine which runs periodically to manage.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean with
the URL keeps changing when someone uses the app
I've switched to store = "url"
and in my browser the URL doesn't change when I'm moving around. Does it in yours?
Does solution (1) mean we provide a bookmark system that works 50% of the time? Not sure I like that.
Solution (2) is possible but I've not got budgeted time to do it, also I think it is likely to be a hacky fix. Even per server we have multiple instances of R running which could well interact in surprising ways.
Server side results in a neater URL but a much messier code.
I've pushed fdd151b as a WIP but really I think it might be easier with the long messy URL sadly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work @nikolai-b
I've switched to store = "url" and in my browser the URL doesn't change when I'm moving around. Does it in yours?
No, it doesn't. Sorry for the confusion. It keeps changing in another app, so I thought it will behave the same here.
You've convinced me to use the url
bookmarking, so thanks (as long as we can provide a tiny URL). However I am unable to test your code in fdd151b
When I debug the state
variable used in the function:
pct-shiny/regions_www/m/server.R
Lines 81 to 91 in fdd151b
oldEncodeShinySaveState <- getFromNamespace("encodeShinySaveState", "shiny") | |
shortEncodeShinySaveState <- function(state){ | |
res <- oldEncodeShinySaveState(state) | |
r <- httr::POST( | |
"https://www.googleapis.com/urlshortener/v1/url?key=AIzaSyBLGLnQojQm2WQu9Urri2mmVTQolrLuJBc", | |
body = list(longUrl = paste0("http://www.pct.bike/?", res)), encode = "json" | |
) | |
return(httr::content(r)$id) | |
} | |
assignInNamespace("encodeShinySaveState", shortEncodeShinySaveState, ns="shiny") |
I see that it's NULL
- see below:
Do I need to test it on the shiny-server?
regions_www/m/server.R
Outdated
# (including zoom from the saved state of the app) | ||
onRestored(function(state) { | ||
|
||
if(!is.null(region$state_region) && !is.na(region$state_region)){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is needed. For onRestored
to be called then the state_region
must be set, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, Nikolai. Have removed these checks.
Appears wrong on link, exposes our API key
shortEncodeShinySaveState <- function(state){ | ||
res <- oldEncodeShinySaveState(state) | ||
r <- httr::POST( | ||
"https://www.googleapis.com/urlshortener/v1/url?key=AIzaSyBLGLnQojQm2WQu9Urri2mmVTQolrLuJBc", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I generally suggest saving API keys in the .Renviron
file, as described here: https://csgillespie.github.io/efficientR/set-up.html#renviron in this case. Is there no issue with rate limits? Maybe no issue sharing this with the world in that case... Another compromise, in this case between the + of short urls and the + of reducing dependencies. In this case I'd lean slightly towards reducing dependencies although can understand the desire to keep URLs short.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nudge on this @nikolai-b - suggest not publicising the key in the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for spotting @Robinlovelace ! Very late response sorry I just saw this. You can see the commit message is
Dummy attempt at keeping URL short
Appears wrong on link, exposes our API key
This API key was locked down to only work from pct.bike and I disabled a few days after posting it here (was just so others could try it) but it just shows what we could do...
Since then the whole goo shortner has been deprecated so to be completely clear this is not the approach I'd suggest it was just to show it was possible to hack the URL to make it shorter, I think using assignInNamespace
is probably a bad idea!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never come across assignInMyNamespace
. The standard way for users to handle API keys now is:
usethis::edit_r_environ()
# add new line like KEY=XYZ
# Restart R
Sys.getenv("KEY")
Would that approach work on the server (if we ever did want to use API keys)?
Late response to a late response!
Any update on the status of this @usr110 and @nikolai-b ? Not a priority atm so I would suggest we close this and look to re-open after the schools layer (and maybe near market) features are added. |
Closing for now as it's gone stale. |
Note this is work in progress
This pertains to the issue I created yesterday - see #658
Allows user to save the state of the app on the server.
I've added a bookmark button in the input panel. Please see the screenshot below:
This button opens up a pop-up window with a URL to copy.
This might not work with the older version of shiny, so you may update it to the latest version (I am using
shiny_1.0.5
)In terms of shortcomings:
Would appreciate your comments @nikolai-b and @Robinlovelace