Resources

Dr. Uli Muellner & Nick Snellgrove | Shiny modularization, Leaflet for R and Leaflet JS extensions

video
Jun 1, 2022
57:50

image: thumbnail.jpg

Transcript#

This transcript was generated automatically and may contain errors.

Hi, everyone. Thanks so much for joining us today. Welcome to the RStudio Enterprise community meetup. I'm Rachel. I'm calling in from Boston. It's afternoon for me here, but morning for our friends on the call. If you just joined now, feel free to introduce yourselves through the chat window and say hello, maybe where you're calling in from.

Just to go through a brief agenda, we'll have some short introductions of the meetup and code of conduct, but Uli and Nick will share a behind-the-scenes look at their road trip app, which I got a first glimpse of last holiday season and was super impressed from it and wanted to see how it worked behind the scenes. We'll also have lots of time for questions after the presentation as well. But with that, I am so excited to turn it over to, I think Uli, you're starting first, to Uli first and then Nick.

Yeah. Hey, Rachel. Yeah, thanks for the intro and I'm really excited to actually chip in with that meetup and to get to know you all.

Yeah, thanks for joining and title for today's session is Under the Hood of Aotearoa Road Trip and provide a bit of an intro who we are and how we came to creating the app we demo today.

So we are Epi-interactive and we are based in New Zealand or the Maori name or the, yeah, so the original name of New Zealand is Aotearoa. And so we are a company here in Wellington in the capital of New Zealand and we, yeah, work a lot with R and also R Shiny. And so what we are known for, so we create more complex or sophisticated apps which often connect research and science with decision making. So as you do the last couple of years, for example, we are part of the New Zealand COVID-19 response. So we created a lot of dashboards to help response services and also create a dashboard for the general public. Or another example you see here is, so we work together with the Minnesota Aquatic Invasive Species Research Centre. So, and to help decision making around the spread of aquatic invasive species in Minnesota because they are known for their 10,000 lakes. So they're two examples of the apps we produce.

And yeah, we are a small team here. So we got some photos here. So Petra and I, so we are directors and we, yeah, so we founded Epi-interactive and we have a software development team. So and our developer team, so currently five staff and Nick is one of them. I saw also Shana joining. So she heads our design UI and UX team. And we also have, yeah, Chris who looks after the admin.

So depending which map you use, so we are actually in the centre of the world. So you see that in the middle and meaning we are reasonably close to a lot of other locations, but the closest we are probably to Australian. So, but unfortunately when you look at some other maps, so we often drop off into the right corner there. So a small country in the Pacific, but yeah, so I'm not too sure who've kind of looked a bit closer into New Zealand, but maybe some of you guys have already travelled there. It's actually a really beautiful country. So we've got, it's divided into islands. So we've got the North Island and we've got the South Island. The top, there are some pictures of the South Island. So we've got the Southern Alps and great skiing there and a really beautiful landscape. We've got nice beaches. So I think in the middle is Golden Bay close to Nelson. And yeah, on some days you can go skiing in the morning and go for surf in the afternoon. So great country to live in. So I'm originally from, disclosure, disclosure, I'm originally from Germany, but I moved to New Zealand around 17 years ago and it's home right now.

Introducing the Aotearoa Road Trip app

So the, I should see that. So latest one is the road trip, but there are also other sort of fun apps there. So I'd like to show you the app, so show you a little bit around. And so it's a simple app, but what we'd like to demo today is in particular, the JavaScript integration and Nick will dive into it. And our Shiny provides actually a really cool framework to integrate that and to work on those finer, let's say finer things. And we used in the app, which make it, I think, really, really fun to look at and to use.

So it's relatively simple. So we, yeah, we always brainstorm a little bit what we, what we're going to do with the app and sort of how we came to it as we kind of used a big whiteboard. And then we decided on locations to go on a road trip. And of course, last year, New Zealand was still closed. And so we had to confine the road trip basically to New Zealand. And we selected a couple of really iconic locations. And so, and you can actually go on the trip. So let's start that one. And so we, we start basically from the south of New Zealand and then work our way up north. So we, we start with Otago Peninsula. So we, it's, yeah, very known for the yellow-eyed penguins. And then, so how the app is built up, we show postcards and then we have, yeah, a car on the location, which then moves along. So we programmed it in a way so you can click to the next stop and you move to the different location and get a short explanation of the location there.

So let's maybe just click through it. So start with Otago Peninsula and then move up to Wanaka. So that's, yeah, really beautiful landscape there. It's in the southern Alps. And then we, yeah, carry on what you see already there. So we, the car moves and then we also move the map alongside. So Nick will explain a little bit how we, how we did that. And there are also really subtle things in it. So for instance, the, the direction of the car is moving and, and you see the car wobbling a little bit. So that's kind of a fun, fun little thing, which makes it, makes it nicer to interact with.

So move our way up. So go over to, to Christchurch. And for those of you now, so Christchurch was in a big earthquake in 2011. And so they rebuilt the city. And so quite famous is that cardboard cathedral. So you can move further up to Kaikoura. Kaikoura really famous for dolphin watching and whale watching. And then go to Wellington on the North Island. So southern tip of the North Island. So that's where we've got our office set up. It's the capital of New Zealand and government is located there as well. And then next one up is Oakune. So it's a bit of a ski town, kind of base of Mount Ruapehu. And it's really famous for, for carrots. So because they grow a lot of carrots there. And next stop is Taranaki and New Plymouth. So it's my favourite spot probably to go, go for surfing in New Zealand. Just been there last, last week actually. So really great location. Move up. And then famous Hobbiton from Lord of the Rings. I think that was Nick's favourite location to add to the app. And then last one up in Auckland. And that ends the journey basically.

So these are the ones. Yeah. So a bit of background to it. And these are the postcards with design. So when you look at the app, you will also see the app is fully mobile responsive because we also, of course, when you, when you send out the link and people look at it, so a lot of people this days look, check out the app on their phones. So there was also requirement to have that working. So we stacked that. And so we did, we, in parallel, we created the, the app for larger screens, but also for mobile devices in there. So when you look at the codes, you will also see kind of how, how that's done.

Under the hood: application structure

All right. Thanks for that Uli. Hopefully the microphone's coming through, the screen share's coming through, everything working okay. Thumbs up. That's perfect. All right. So we'll go now and get a little bit under the hood, get into the weeds of the application itself and how that's built up. So this will be a little bit swapping between the presentation that we have here, kind of a general overview, and then going into RStudio and looking into the code itself. So starting off kind of some high level details under the hood.

So we built up this application, application using R version 4.0.5. So at the time, I think 4.1.2 had just come out around the time when we started putting this together, if I remember right, but we decided to stick with that version because, you know, it was, it was stable and we were familiar with it. And so we just kind of used that as our jumping off point. So we also used Shiny 1.6.0 for this one. Just generally we try to keep reasonably up to date with the versions of the packages that we're using and with Shiny that being kind of like the backbone of the application. So we try to keep that, you know, relatively up to date. With the hosting, so we have that running on an AWS instance and we have several applications running on that server.

So we have running on that server, we're using the open source Shiny server. So that's what, you know, allows us to run the application and hook that up so that you can access it from the browser. And then with the packages that we're using, it's a relatively confined list there. So we're using dplyr to kind of help with a little bit of the filtering from our location data. We're using HTML tools and HTML widgets to help to handle the Leaflet JavaScript plugin, which we'll get into a bit later. Obviously we use Leaflet to build up kind of the map that we use as the foundation of our road trip. Then we use Shiny to build up the application structure itself. We use Shiny Router to handle multiple pages in the application because we have our splash page and we have the actual map page. And then we use ShinyJS to help us link in the events and the functionality from our Shiny application and so linking that up to JavaScript functionality as well.

So kind of the key ideas behind the code base that we're going to talk about today are to do with modularization of the code base. So that's splitting out our file structure, but also using modules from Shiny to separate responsibilities a little bit. The Leaflet plugins and JavaScript and how we did that for the map is kind of a big part of it. And so that's a little bit extending Leaflet beyond the basic functionality of Leaflet for R. We also use reactivity so we can so we kind of stage our reactives and then that helps us deal with our UI quite easily. And then the last thing which we'll look at is a little bit of user experience. So the little changes that we can make along the way to add up to noticeable improvements for the user.

Modularization and file structure

Starting off then with the modularization and the file structure of the application. So as a general rule, whenever we do a Shiny application, we try to follow this UI server and global pattern as opposed to, you can also put it into kind of one file and just use like an app.r and put all of your UI, all of your server into this one file. We like to split it out into these three separate files so that there's a really clear separation of responsibilities. And for some apps, as they get larger, having it split out into those separate files then makes it easier for us to come back later on and debug where things might be going wrong.

Important distinction is that we also try to keep the UI and the server quite minimal. So you'll see when we jump over to the code base in a moment that there's really not that much happening in these top level files. They're kind of setting up the basic, like the core functionality, the core structure of the application, but we generally prefer to push out most of the work that's happening in these applications to the different page modules that we're using or different sub modules. So trying to keep those as minimal as possible. So we use Shiny Router, as I mentioned, to handle multiple pages and that allows us to have meaningful URLs so that when you're on the splash page, you have your home link and then when you're on the map page, you have another link. So if you wanted to send, if you wanted to get someone to go to a specific page, you can just send them that URL and you know they're going to end up in the right place.

From that, we also use these page level modules. So in our little diagram here, so we have our splash page and our map page and we have those kind of set up as these page level modules, which we then split out into UI and server files. Again, just so that we can separate those responsibilities for those different components. What we also like to do is to have kind of nested UI outputs, which we'll see when we jump into the code in a moment, but overall the kind of the main idea with this is that we want to try and keep it simple. You know, there's more complicated ways that we could set up kind of the overall like modularization and the structure of the application, but you know, we want to kind of keep it simple because that's going to make it easier for us to come back to it later as well.

So if I bring up the, if I bring up my RStudio window, is that coming through okay? It's good. Good, awesome. Okay, so starting off first with the UI and server and global. So you can see what I mean here in that there's not really a lot going on in this UI.R here. So we're setting up the page, we're loading different resources that we might need, and then we're setting up the router and essentially that's it. That's all we're doing in the UI. So we're pushing most of that work out to these page modules, which we'll look at soon. A similar story in the server, all we're doing in here is actually calling the modules for the different pages. So we're calling for our splash page and our map page. We have this event here to set up so that when we change pages, you know, we scroll up to the top and then we set up the kind of the functionality of the router.

And then in global here, so this is just where we're setting up the libraries that we're using. We are sourcing the different R files that we need. We have some stuff in here for the plugin, which we'll talk about a bit later, but otherwise we're just setting up kind of our global variables in here so that we can then access them throughout the application elsewhere. So you can see we've got like a header set up here. This is where we set up the routes for our Shiny router so that we can then create it in the UI and the server here. And so with the UI, so with the nested UI outputs, so we have the router being created there and then I'll use the splash page as an example. So what we said about having like nested UI outputs, so even in the splash page UI, this is still relatively minimal compared to what we actually see on the app. So we just have, you know, we're setting up the structure of it and then we have this UI output for the page here. And so we actually create that over here in the splash page server. And this is quite a common thing that we like to do, is to throw the UI parts of the application. So pushing that responsibility over to the server, so this is where we're actually creating the bulk of the UI for that page, is here in the server in this render UI block. And so we do that so that, as we'll see in a little bit later on, we can take advantage of reactivity and using reactives to kind of help build our UI and update, you know, without us having to do too much.

Leaflet setup and the moving marker plugin

So I guess moving on to the next point, the next part of the application, the most interesting part, I think, which would be the leaflet. So setting up our, the map, which you'll be using for the road trip. And so we set up the map using relatively standard Leaflet for R, which we'll have a look at shortly. But then we do a few other things to kind of get it to the point where it is in the application. So one thing you may notice if you're tinkering around with the application is that you can't manually move the map, so you can't click and drag on the map. And that's because we have this, we have that disabled so that the movement is just linked up to you pressing, you know, the go forward and go back buttons, so that you don't get lost anywhere on the map. And then with, so with the movement on the map, so for the car, which we'll look at shortly, so that's kind of a combination of things which are going together to do that. So we're using a Leaflet JavaScript plugin, which we sourced from GitHub. And we're also using ObserveEvent and several utility functions, and we're using ShinyJS to kind of link those two together.

So I'll just jump back over to the code base here and how we actually set up the map. So that's happening obviously in map page server here. So if I can find my map, so we have this render leaflet here, and so we have this location data. So this is a reactive which we have set up, which holds, you know, the detail about the different locations and the coordinates and things like that. And we start off with our first position, so we're isolating that because we only want this to change when you move.

And so the first time, you know, the first time we're creating this, we want to use those first coordinates. So the current location data is for the first location there. And then we're setting up the, we're setting up a JavaScript command here, which we'll use, which we'll talk about in a little bit, which is how we actually create the car on the map. So we're setting that up here, but then actually creating the map, so which is called to leaflet. And we set some options here, so minimum zoom, maximum zoom. And then we also disable dragging there so that you can't, you know, manually move the camera on the map as it were. We set the view, so we're setting that as our current position, which is the first location in our location data. So we're setting that view here, and we're just adding default tiles. You know, there is the option to kind of customize what tiles we're using, but we figured for this one, because we're not zooming in that far anyway, the default tiles that would do quite nicely actually. And then we have the register plugin, which we'll talk about soon. But we also set up the markers, so the, yeah, the Xs at the different locations on the map. So we are setting that up from our location data, and we're setting an offset as well, and that'll come in a little bit later so that the, so that the car doesn't appear underneath those markers. And then we're adding the lines in between all the markers.

So the interesting part, I guess, well, the more interesting part about this application specifically is how we hooked it up to these Leaflet JavaScript plugins, because there are limitations to what Leaflet for R can do out of the box. So when we're putting this together, we were looking around for ways that we could extend that, and we found a way that we can use these JavaScript plugins, we can add those onto our Leaflet for R maps, so that we can actually access that functionality. So for this one specifically, we use the moving marker plugin, which is available on GitHub here.

because there are limitations to what Leaflet for R can do out of the box. So when we're putting this together, we were looking around for ways that we could extend that, and we found a way that we can use these JavaScript plugins, we can add those onto our Leaflet for R maps, so that we can actually access that functionality.

So that's the plugin that we're using for that, that moving marker, and so that's built for Leaflet JavaScript, and so we need to register that on our Leaflet for R map, so that we can then use it in our application. So we're doing that, we're creating kind of a dependency in global.R, and then we have a function there so that we can register that plugin to our map. And so when we're actually creating the map the first time is where we bind the plugin to the map, and then we do kind of an extra step in the onRender of when we're creating that map to help set up the the marker for the first time. So actually setting up the car.

So back into the code we go, and so starting off with actually registering the plugin. So we have up here, so we have this little utility function that we created called registerPlugin, which takes the arguments for a map and the plugin that we want to register, and it's just adding it to the dependencies of the map and then returning the map. So the reason that we have that set up like so, is so that we can hook it into over here, so we can put that into that kind of pipe. So as we're creating the map we can then pass the map into this register plugin function here alongside the plugin that we've created, which we also do over here in global. So we have this object, this MovingMarkerPlugin, which is an HTML dependency, and so we're just sourcing the javascript. So we have that, we kind of downloaded a copy of the, of the MovingMarkerPlugin, and we just put that into our resources down here, so in our javascript folder. So we have a copy of that plugin sitting here, and so we're creating this HTML dependency, which is just going to source that, that code from our, from our file system here, and then allow us to attach it to the map. So that's where over here, so when we actually call registerPlugin, and so we're passing in that global HTML dependency object, and so that will then attach it to the map, so that when we access the map later on, we can have access to all the functionality that we need.

That also comes into this extra step that we have down here, so there's onRender, so we're saying that when the, when, when, when the map draws the first time, so we want to set up, we want to run this, this function here, and so we're, basically we're creating an object in javascript, which is the map that we've just finished making, and so, so that we can then access that later on from our other javascript code, which we're going to use, and then after that, we're also running this jsString as a part of that function, which if you remember up here, is this, it's a call to a javascript function, which, which we had set up earlier using, you know, our initial position, and our speed, and things like that. So in this onRender, so we're creating, we're making a reference to the map, so we can access it later, and then we're also running this, this javascript function to actually set up the marker for the first time, so that we can use it.

Creating and moving the car marker

Which then leads into the next point, which is you're creating and moving the marker. So there's kind of two stages to this, and there's a, there's a javascript function, which we're going to keep coming back to for a lot of this stuff, which is that update car position. So the two stages here, which are initialization, so when we're making it the first time around, and then movement, which is, you know, it's already, it's already been created, it exists on the map, and we just want to move to the next place. So for the initialization, so we create an icon, and we assign it to a new moving marker, and we set up kind of the, the start and the end behavior for that marker, so when it starts moving, and when it stops moving, what should it do, and then we put it onto our map in that initial position. Whereas for the movement, so if the marker is already there, and it's already set up, then we update the direction, so we're using gifs to handle the direction of the car, so we update that image if we need to, and then we move the marker to the new position, and we also move the map to the new position.

And how that looks in the code, so we have our main.js file here, and then we have these kind of two stages of it, so we have this if init, which is coming in from here, so this is our kind of initial setup phase here, and so in this stage, we're creating an icon, and we're using, to start off, we use the carFacingLeft gif, and we give it a size, and we put the anchor in the middle of that, so that it appears in the right place, and then we create a moving marker using the coordinates which are passed in to this function, we set the icon for this marker to the icon that we created here, we give it, we give the moving marker a much higher offset than, if you remember, we set the offset for the locations, we set that to zero, as we set this to 1000, probably doesn't need to be that high, but the point is to set it higher so that when the car is on the map, it always appears in front of the location markers, and then as the last thing that we do for setting that up, we set interactive equal to false, so that you can't click and interact with the car on the map.

Then we set up the kind of the start and end behavior, so as I said, that's when the car starts moving or when it stops moving, and so we link that up to do some things with our controls, so you may notice in the application when the car starts moving, when it starts moving, these controls get disabled, and then when it stops moving, they get re-enabled, so we set that up in these on start and on end points here.

So that's kind of the initial setup of the car, and then for the movement, basically because we have these parameters, so location, speed, direction, and so for that, we're updating the image that we're using, we're creating some new coordinates, we're moving the car to those coordinates, and then we're also moving the map to those coordinates as well, so that's essentially how the car is functioning in the application.

Reactivity and staged reactives

Which moves us on to the next point, which is to do with reactivity, and so for this app, we're tracking a lot of our important map details as reactives and reactive valves, so we have our current location index as a reactive valve, we have our first and last location, so kind of a little calculation to figure out if we're at the start or the end, we have those as reactives, we have our location data and our current location data as reactives as well, and then we also have kind of some UI parts as reactives too, so like the current postcard and the current description.

We try to keep the static UI as minimal as we can, as we've seen so far, and we do that by defining these UI elements in our server, so we use these render UI and UI outputs, and then that allows us to use reactives and reactivity to update our UI. So back into the code, and in the map page server, so we have our reactives up the top here, so we have our current location index, and we start off from whatever this global variable happens to be, which most of the time is one, yeah we can change that for testing, but most of the time we start off at the start, and then we have our first location and last location reactives, which just tells us if we're at the start or the end, our location data, which takes in our locations which were loaded in global, and then we just do a little bit of formatting to them and sourcing, and then our current location data, which is filtering this reactive here to just our current location, and then the postcard and description, which is pulling the image path and the description from the location data specifically.

So these ones in particular are quite handy because we can, you know, that allows us to kind of, we can build our UI using those elements specifically. So if we look into say postcards, and then postcards has some multiple kind of nested stages, so we have postcard front and postcard back, postcard front here, which we can just use the current postcard, so that's that reactive which we have, which holds the the path to the image, and so that means that whenever that reactive updates, the the UI will update, you know, on its own, on account of, you know, the process of reactivity, and similar thing in postcard back here, where we're using the current description, so anytime our location changes, the description changes, and then the UI changes, so it all kind of happens on its own.

One thing that we like to look at sometimes with that is the react log, so you may or may not be familiar with this, but it's kind of a neat tool for examining the reactive chain of your application. So I can quickly run that here, and we can see kind of what that looks like. So if I go, so is it react log enable, and so that kind of sets it up, and it's running, and it's waiting, and then I just run the application, this is a local version that we'll have here, and then I'll just click through a couple of points here, and in the background the react log is, you know, it's recording, it's watching what's happening here, doesn't really matter what I do too much, but if I bring up, so I come back into here, and then I say shiny react log show, and so that brings up a react log for this application specifically, for that session that I just did, and so from this we can see, yeah, we can see how the different reactives, and reactive elements link together. So you can see, you know, this first here, we have the current location which feeds into these reactives here, so first and last location, which feeds into these observe events, and it kind of goes from there, so you can kind of get an idea of what relies, what elements of your reactivity are relying on the other elements, and if you wanted to get, you know, really specific, you can click on certain elements, and then you can see, yeah, everything that, say, the current location data is linked to, so you can focus in on specific parts of your application as well, and so you can then step through the different stages, and you can watch how your reactive chain essentially operates as you run the app. So that's quite a, you know, quite a handy one for us as well.

User experience improvements

So I think with the reactivity, and then with the, just quickly look at the observe events that we have set up, so this is watching these start and back buttons, and reset buttons, things like that, and so that's kind of just handling like our UI elements, things like that, for the back button, that's up there, and then updating the car position, so we're putting together, kind of preparing these different parameters here, and then we have this function update static car position, which will then make a call to our JavaScript as well, so this is kind of all happening mostly in these observe events here, so how we actually link up those buttons and your user inputs to the car.

Which kind of ties into the last few points here, which is to do with the user experience, so these are the little things that we do along the way to improve the overall feel of the application, so things like animating the car, changing the direction, making the map follow the car, turning off the map interactivity, showing, hiding, disabling controls based on the state of the map, even like animating the background, which we do with just kind of CSS animations.

So for the car, so we already talked about how we animate the car, so what comes to mind is that the simplest solution is often the best solution, and we tried a lot of other more complicated things, like inverting the image CSS transformations, all kind of things like that, and then realize, you know, why don't we just use multiple different images, so we have one image for the car facing left, and one image for the car facing right, and so we just swap between those depending on what direction the car should be going, because we don't need it to be more complicated than that, and we just assign that icon to the marker, you know, as we saw in that, in the JavaScript function here.

what comes to mind is that the simplest solution is often the best solution, and we tried a lot of other more complicated things, like inverting the image CSS transformations, all kind of things like that, and then realize, you know, why don't we just use multiple different images, so we have one image for the car facing left, and one image for the car facing right, and so we just swap between those depending on what direction the car should be going.

For the map then, and the map interactivity, we already looked at the, the leaflet options, so the minimum maximum zoom, and disabling dragging, so that you don't get lost. When we make the marker, we talked about setting the interact, so disabling the interactivity for the marker, so we're trying to kind of make it, yeah, because the overall look and feel of the application is kind of themed around this road trip, and it's these postcards, so we kind of, it's, it's more of like a look, don't touch kind of thing set up there, I mean you can still zoom in and out a bit, but there's not really anything to be gained by interacting with the car, so we just disable that to make it a bit cleaner.

Having the map position following the car movements, so we're sending it to the, so we're sending the camera, I guess you could call it, to the same position as the car, but it, at least it feels like it, the camera kind of arrives a little bit faster than the car does, so that's happening in this step here, so with this move to, and we give it a certain speed, and then the map pan to, so that's being given the same speed, but it feels like the camera arrives there slightly faster, and that's good because, you know, if, if the car arrives before the camera, then you would be able to queue up more movements while the camera is still moving, and then you'd end up with some kind of unexpected camera behavior, which we want to avoid, so easiest way to do that is to just make the camera arrive a little bit first.

For the controls, so we disable the controls while the car is moving, so that also allows us to prevent these unexpected movements, so going off track, you know, just rushing through all of, all of the movements in half of a second, and so we do that again in that, in that JavaScript function here, so in these start and end functions here, so we're finding all of those links, finding all of those links, and then disabling them when the, when the car starts moving, and then, again, when it stops moving, we're removing that disabled class from it.

Actually, the other thing that we're doing in here, which is useful for mobile, which is, you know, if, so we have a scroll locator, so just like a little invisible element attached to our postcards, so that if you're on mobile and you're not looking at the postcards, when the car arrives at the location, it will scroll into view so that you can actually read the text on the postcards.

And then showing and hiding the controls based on the map state that we are doing kind of in the, in the server parts, so we're using remove UI and insert UI for some of it, and we're also using kind of run.js to handle some of it as well, so at the first position where we hide the back button, and then at the last position where we take away that forward button and we replace it with a restart button, and so where we're actually doing that in here in the map page server, so we have down here, so we have is first location, and if it is, then we are hiding the back button, so using run.js, so basically we're adding that hide class to it so that it won't be visible, and then at the last location we're removing the next button and we are inserting a restart button instead, so that kind of allows us to customize the the UI on the fly depending on what stages people are at.

Summary and wrap-up

So that about covers most of the aspects of the application in a bit of a lightning fashion. Quick summary, so we try to minimize our code in UI and server, we like to have kind of a modularized code structure, and we prefer to keep things in the server and use render UI rather than having your static UI that we can't change as easily later. Using the Leaflet JavaScript plugins in Shiny, which allows us to kind of extend Leaflet beyond what would normally be capable out of the box for Leaflet for R, using reactivity, having lots of different staged reactives makes it easier for us to set up the different functionality and also updating the UI, and taking advantage of the different UX features to really just polish up the overall what goes back to whoever's using your application.

So that's about all we have for that. We do, as early mentioned, this we are planning on putting this on on our GitHub. We do have some other projects already available on GitHub, so ipinteractive.github.io, so we have several kind of little self-contained examples of things that you can do with R and Shiny available on there, so feel free to take a look at that. Otherwise, I think that's about all we have, so thanks for coming along.

Thanks, Nick, and yeah, so we put up the code, so give us a bit of time and maybe check in in a week or a couple of weeks time, and I believe, Rachel, we can also share in the recording of the session, because you might want to use some of the methods we showed, and I guess it's a fun little tool, but you can maybe also see it's when you think about storytelling with data or so, so you can use that probably in another context where you sort of sync up certain explanation or outputs with a map and show actually context as you move along.

So I hope you find that useful. I mean, feel free to connect with us on LinkedIn or Twitter, and so we are quite active there, and so whenever we have something available, you would get that in your feed, and I saw that at least I saw one person from New Zealand, so we are hosting an event 27th of May here in Wellington. That's the R Exchange, so we bring a local community, our community together, and yeah, should be a fun event, so welcome for those of you who are local to come along. Otherwise, I think we have a bit of time to take questions, so if you want to ask us something.

Yeah, thank you so much, and I always feel like we need to use these clapping emojis because you can't hear us clapping when it's virtual, but thank you so much for a great presentation. I want to remind everyone, if you want to ask questions, you can raise your hand here on Zoom or feel free to use the Slido link too if you want to ask anonymously.

There actually was an anonymous question, which is what I wanted to ask you too, so thank you for this question as well. It was what would you do differently when you start this project, like if you were to start this project over again?

That is a good question. Yeah, because there's always things in hindsight that you think, oh, I would definitely change that. I think for me, the thing that comes to mind is probably a little bit more following the DRY principle, so don't repeat yourself. So there were certain aspects in this code base where we're kind of replicating the same calculations over and over in different places, so if I was to do it over again, one of the things that I would definitely try and do better this time would be to more use of these utility functions and splitting things out into these functions so that we can just write the logic once and then just reuse that rather than having to run through it and rewrite it multiple times. I think there could also be a case for going a little bit deeper into modularization, so having a separate module for the map or something to that effect for next time potentially.

I think there was also a question about JavaScript, and for those of you guys who don't know about JavaScript, because it's a little bit of a separate thing probably to R, and the question was, do you have any recommendation for those of us that don't know JavaScript to start learning enough to do things, to interact with leaflets or maybe a little bit what's available out of the box to interact with maps?

So with JavaScript, it is definitely a little bit of a separate thing, but because it does tie in quite nicely to Shiny, so I think we find that as you kind of progress with Shiny, you kind of pick up little bits of JavaScript along the way, just because it can be quite a handy kind of workaround to certain aspects. In terms of what's a resource for getting that understanding, I'm not 100% sure off the top of my head. I'm quite fond of things like Codecademy. I know they have quite good courses on things like that, but yeah, I think a lot of it for Shiny specifically is kind of just, it came up along the way, and we kind of just add that to the list of things that we can do, you know?

There's another question that was, how long did it take to complete the entire project? It was a relatively quick turnaround on account of it being, so it's kind of our end of year project, and so we would like to send that out to people that we work with throughout the year, so we needed to have that ready before everyone's gone on their Christmas holiday. So I think, because there was also kind of a design phase to it, would I be right in saying probably about a month overall, Uli?

Yeah, probably. And yeah, so there was a bit of a design part up front. We like to put a bit of thought in it beforehand, before you really start coding. And so, I mean, we're glad to have the Shiny UX and UI designer on board, and we like to use Adobe XD quite a bit. So that's a design program, and you can, specifically for web interfaces, where we can draw out the interface. So that typically speeds up the development process quite a bit, because it's clear where certain elements sit, so you don't need to go backwards and forwards a bit. So we, I think we had to adjust things a little bit, like with the car movements or so. So we didn't quite know what was possible with relatively, let's say, a relatively low effort, because it was a side project of us. And, but then maybe development time, maybe a week design and think about it, and then three weeks or so to develop it. Probably not full time, but a bit on and off, yeah. So yeah, relatively confined project.

That's one of the other good things about these, yeah, our Christmas tool tradition, is it kind of gives us the opportunity to experiment with things that maybe we wouldn't normally get to try. So it's quite a fun one, always, when it comes around.

Awesome. I see, Will, you have a question? Yeah. Can you guys hear me all right?

I had a question for Nick on the UI, where you said to keep it in the server function, and then I think you passed it to the, keep it in the server module, pass it to the UI module via render UI. That's so that you don't have to be passing data between those modules, so that it's all just in that server function. Was that correct?

Yeah. So that we can use the reactives that we have. And so with the UI outputs and render UI, so that is, it's a valid reactive context. So the main reason why we do that is so that we can use those reactives to either decide on what parts of the UI we're going to show, so we can conditionally show certain parts of the UI, or in this case, where we have them kind of directly going into parts of the UI. So we're pulling that text out of the location data and putting it directly into the UI. So if we were to do that in the UI part of the application, so that's kind of static, we would have to be updating that manually. But yeah, so why we push it always to the server, or we prefer to push it to the server, is so that we can have access to, and it's not just the reactives as well, we can do, we can use, so we can do regular R functions, calculations, things like that, that we can then tie into it. So it's kind of just expanding our options by doing that.

There are things to watch out for, not so much in this one, but generally, so things like if you have, so like inputs, so like drop downs or sliders or things like that, if you're creating those in your server, then you might need to do things like making sure that those things have actually been created before you use them. So there are, there are trade-offs to it, but overall, that is kind of the approach we favor.

Great, thank you. I was curious, do you use some of these apps to show customers what's possible? Or I think a lot of times people, like on the data science hangout, will ask questions around if they're interviewing for a role and they want to be able to show apps that they built, it's great to have toy examples available as well. So just curious if you use these with clients.