 Andra check there's another link as well. So go ahead and switch over to that one. But now we will talk a little bit about how to use the DHS to API from your platform web application. We have built a library called we call app runtime, which makes it easy and a little bit more robust to access that API from particularly from react applications. So I will be covering that in the next 20 or 30 minutes. I'm going to share my screen again. So you should see my screen here now. Yes. Great. So this is going to be just an introduction to app runtime. Some of you may be familiar with it already. But it is, yeah, it'll be a refresher for those that are familiar already. And app runtime is a collection of different utilities that are used at runtime by DHS to applications. So I'm going to focus on what we call the data service or the data engine here today. And so that's using queries and mutations to interact with the DHS to API. But there are, it's important to note that there are some other things that you can do with the runtime as well and there will be more things, more functionality added to the runtime in the future as well. But I won't cover that too much. I'll tease it a little bit today, but I won't cover it too much. So this is one thing you can do. This actually isn't related to the API, but this is one of those other other functionalities that is available in the app runtime. And basically this is what's called a react hook. If you're not familiar with react hooks, there's lots of good documentation for it on the react website, and some of the links that Deborah sent out as well. So the hook that exposes base URL API version and server version for a particular DHS to instance so your application doesn't necessarily know what the base URL is what the API version is or what the server version is when you build that application, because you can then it might be installed in a different DHS to instance that has a different version or different URL or those types of things. So in order to get those, those variables or the that information from any component in your application you can use the use config hook. The server version is particularly interesting because you can turn on and off different parts of your application if you want based on the server version that you're talking to so if there's a feature in DHS to 235 that it doesn't exist in DHS to 234 that you want to support both in the same application. So you can use this server version which has minor and patch version numbers within it parses it automatically and to determine which which version you're talking to, and then you can do different things in your application based on what's what the version of the server is so that's something that is quite interesting. And you can also use this if you need to, to manually do API requests but I wouldn't recommend it because there's a lot of things that the app runtime gives gives you out of the box that you would have to do yourself like error handling, like authentication, some other things as well parsing. So, let again I'm not going to go into use config too much it's fairly simple, but I will also say that if you want to learn more about any of the things that I'm talking about today. You can go to developers.dhs2.org. And then in the docs section under reference. You can find the app runtime link. Click on the app runtime link, and we have this this documentation site that talks about everything that that I'm going to talk about today. So it'll tell you how to add the app runtime how to use it. I'm going to talk about the provider today but there is a provider which gives you this base URL and API version for the rest of the application to use, but you don't need to use this can this provider. So you are using the app platform, it's it's done for you, it's provided for you. So, don't worry about the provider if you're using the platform which you should be for for everything in this workshop in this Academy. There are also the the hooks that are available from the app runtime. And so we just talked about the config hook. This tells you there's no input variables or arguments for this function call. You just call use config, and it gives you some output base URL API version server version, etc. Next we're going to talk about use data query as well. So let's look at the use data query. I'm going to actually come back to this slide after I introduced queries and mutations and declarative data fetching. But this is another hook that is exposed by the app runtime. And it basically gives you a way to say for this component in my application, I need the, let's say the list of 10 indicators with their display display name and ID, which is what is shown on the in this code sample here. And then react and the app runtime know that you need that information. So they'll go and request it from the server for you. It will also re render your component every time the state of that request changes so when it first starts, it will return loading equals true, and you can render something in your component that says, I'm loading and waiting for this response to come back. When that response comes back, if it's an error, it will give you the error. If it's successful, it will give you the data that was returned from that API call. And so this is a way to do declarative data fetching within a component, and it lets the the component can say exactly what data it needs. The runtime is responsible for combining all of the needs of all the different components that are on a page, requesting that information from the server, and then re rendering all of those components when they're when they're available. So we're going to use data mutation, which we'll cover a little bit today but we're going to focus more more on queries, and use data mutation is just a way to mutate or change information through the DHS to web API. Usually you would use posts, put or delete requests to do that through the API itself. This is a way to do it in a declarative way similar to the query from within a react component. I'll talk more about that in a minute. And then this is one that will cover more in the workshop in May. It's called use alert. Basically, this is a standardized way to show alerts to the user that the little snack bar that pops up at the bottom of your screen. And this is again a declarative way to do that so you can declare the the alert that will be shown by a particular component of your application, and then you can call the show function when when you're ready to show that alert. We'll talk more about alerts and what those look like and how to how to use them effectively in the design system in the May workshop. I've mentioned declarative data fetching here a couple times. If you've seen me present this before maybe you are familiar with the example I'm about to give but if you haven't. Or even if you have hopefully it's a good refresher on what declarative means. And declarative is the opposite of imperative. So imperative means I'm giving a command to do something very specific. It's also a grammar a term from grammar to say like the the command version of a verb when you're when you're telling somebody to do something. And declarative, on the other hand, is just announcing what you want rather than telling someone to do something. So we'll talk a little bit about the difference there and why it's important in software engineering and in web application development in particular for DHS two applications. So a destination is declarative. I can tell you where I want to go, where I want to be, rather than how I want to get there. So if I say that my destination is this particular Boulangerie in Paris, or my destination is the Jinja Uganda, where the source of the Nile River, for instance, and that's a destination but I'm in I'm in France it would take me out there were a lot of steps to get me to Uganda from here. And that's just an example. Any destination would would work for that. But I'm not telling you how how I'm going to get from Paris to Jinja in Uganda. That would be imperative so directions for how to get from my my apartment to the Boulangerie in Paris, or from my apartment to Jinja Uganda is imperative so there are a number of very specific steps that I could say could could tell you in how to do that so I could say that I would need to take the train to the airport fly to Kampala take the a bus to Jinja something like that to get to the that that destination. But there are other ways that you could do the same thing right so maybe there's a you take a motorcycle instead of a bus, or you take the different train to get to the airport. There are a lot of different ways to go about that and it might, depending on the situation it might be better to take a different train or to take a car or a motorcycle rather than a bus in in a certain situation for for this metaphor example. And by by giving you instead of these turn by turn directions specific directions by giving you just a destination it gives the person that is for the system that's responsible for for figuring out how to how to get to that destination. It gives them some freedom to choose the best option in the moment. And so what is this what does this mean for software engineering and for fetching data from an API. And basically it means that if I tell you that I want the the the information about the current user. I want the name of the current user and that's all I really want. There are a number of different ways that I could get that I could tell you that you need to go to HTTPS colon slash slash the name of the server slash API slash 32 slash me. The question mark format equals JSON and fields equals name. And then you would send an eight and I would tell you send an HTTP request with this authentication header to that URL, get back the response and parse the response in a certain way, and then I would have the name. Maybe someone else already got on the same page as as my component already fetched the name of the current user. So in that case there's no need to go across the network to get the name of the current user because I already have it in the browser. So the runtime allows us to do so all the different components can declare what they want, and the runtime can figure out what requests it needs to send across the network what it needs to fetch from its local cash potentially, and do do a bunch of things to to make that more efficient maybe it combines multiple requests into one. It's a black box you don't need to know what's inside of it. So by moving to this declarative model where the application sends a query to the app shell or the app runtime. That app runtime maybe makes a request to the server, maybe it makes a request to the local or offline cash. Cashing and offline support are coming very soon as I mentioned earlier so that you won't necessarily see cash hits today, but in the very in the near future you will. The important thing is that when you declare your your data dependencies in this way. The application doesn't need to change in order to automatically get the responses the correct responses back from the cash. So when the cash is added or when there's additional time to combine different requests into one in the runtime that will be automatically available and used by every application that uses that runtime without any changes to the code. So that's an important thing to think about. Let's talk a little bit more about what a data query is I've said that word a couple times. It's a specific term for the way we make declarative data requests in DHS to and particularly in DHS to web applications using the app runtime. So it's a declarative data request for data that will come from the DHS to API at some point, whether that is some point in the past or at the moment the request is made is up to the runtime. So that's the whole query here. So I'm going to go ahead and present so you can make this a little bit bigger. And this is a simple rest API request, and it has it's going to the URL that we are using for our Academy instance, and it's fetching the me endpoint so the information about the current user, and it's getting the name field. So as the example I just just was talking about. But this is the imperative way to get that information so you were actually saying to send an HP request to this specific destination with a particular header or those types of things. The same exact request can be made with the data query using this object down here. The resource is me. So that's what I want. And specifically what I want is the name field for this resource. Everything else is is is more instructions and directions than destination to make that even a little bit more clear. We've broken down the URL the API request into different sections and talking about what those actually mean so we have the base URL which is the URL of the instance that we're talking to. We also have the path of the API version that we're that we're requesting from, we have the name of the resource that we actually want. We have the format of the response that we want in this case it's JSON, it might be XML or something else. And we have the parameters which say what, in this case we're specifying fields, I talked about a lot of other parameters that you can also pass to a rest API endpoint in the CSS to API, but in this case we're talking about fields so we're requesting the parameters with fields name so we just want the name field. And these things tell you how to fetch from the API, because their base URL the API version the transit format is all instructions. We don't actually need those when we're using the app runtime. Because the only things that are actually telling you what you want to fetch are me, which is the name of the resource that we're requesting and fields equals name, which is just a way to kind of specify exactly what you want from that me resource. So those two things are the only things that are present in this declarative data query that we can use to request that information from the app runtime, and then that would turn into potentially this API request potentially a different API request potentially something or request to the local cache. This is a good example or a good moment to introduce the data query playground. This is a simple data query on the left here I have the query itself which is me with the fields name, the one that we just talked about. And then on the right I have the response. And so I'm going to go out of this and go back to my runtime documentation. Again, you can I'm going to get get there again so if you go to developers that Jesus to work, you can click on docs reference overview, click on app runtime. This will open here. And you'll see that there's a big blue button on the left that says query playground. So let's go ahead and click on that. This is an application it's actually a DHS to application built with the app platform that is running on the DHS or on the runtime documentation website. So I've already filled this out of this in and it remembers what what URL you previously connected to. And I could also do HTTP local host 8080 if I had a server running on my local machine, but I don't so I'm going to use the Academy instance, and then we put in our username and password, and we sign it. And remember that if you're you doing this with a custom DHS to instance or a production DSS DSS to instance or something like that. You need to make sure that runtime dot DHS to dot and you. The DHS is in the cores whitelist as Deborah mentioned yesterday. So what does this application do it's it's just a handy way to test different queries and mutations and and to see what the results are. So the default query is just here. Again, it's to the me resource so the current information about the current user. We have ID name, email and introduction. Let's go ahead and execute that query. And it actually made a request to our DHS to instance, which fetched the information about the current user with the fields name ID email and introduction which is exactly what we requested. This is the query and I didn't need to specify any information about the other stuff that the runtime already knows which is listed up here on the right side. And so we can actually say we can we can change this and just experiment so let's go ahead and get rid of that let's do the exactly the query that we had here in the previous. So we just wanted the name, for instance, let's get indicators instead, which we talked about earlier. Note that this is JSON. So the keys need to have double quotes around them. If you did just like this which you can do in JavaScript, that doesn't work and it shows you that the, this is bad, bad JSON. Let's just click execute. Now we have, again, we have the list of indicators and we have the name of each of those indicators and our page size is 50. Under params we can pass the other parameters that we also could pass in the query string of our DHS to rest API. So we can say page size is 10 comma. We have nine pages. We've got 10 indicators with the name only. Let's try organization units. So let's get. Again, I wouldn't recommend using all. So you can use all here. We will actually see, let's look, let's look at the request that's made under the hood here. So if we use the all resource. It will show me all of the available. Yeah, all of the available fields for this organization, these organization units. And it actually makes this request, which is the same one that we might have typed manually into our browser. So you can actually see the requests that are made if we change this to just be, let's say, so here in organization units, we have a set a bunch of data sets, let's say data sets. And then we want the ID and the name, let's say display name for that data set. Let's do page size. Actually, let's get an ID as well. So you'll see that fields is an array. So you can have multiple different fields specified as arrays, but if you're using the field expansion, it needs to be in one string. So data sets, open parentheses ID, comma display name. So now if I execute this, we get the ID of this particular organization unit. There are 1300 organization units, which is quite a few. And I'm only interested in this particular one. So I'm actually going to add ID here to my resource. Sorry, that's not the right ID. This is the ID. This is my ID. So we didn't talk about this quite yet, but you have resource, which is useful for specifying what your, what type of object you're trying to request in this case organization units. And then you can also pass ID, which is the specific organization unit that you care about. So we make that request. It goes to, if we see in this URL here slash organization units slash that ID, and then it passes the page size, the fields, etc. So now we see that we have a list of a bunch of data sets that are affiliated with this with this organization unit. And actually let's change this name. So you see this name here is me, we can actually change that to whatever we want. So my results or something like that. This is just to identify this particular query in this query set. Now we have so we can get some other information about this data set let's change ID and names to star for the moment just to explore and see what we get. And it's quite a lot of information. So if you see that this this request for fields equals ID and data sets star. We actually got 112 kilobytes over the network after G zipping so it's actually 600 kilobytes of data. That was downloaded. That's a lot. So if I if I changed this to a slow 3G connection and I tried to make that same request. It takes a long time. And if we don't actually need all of that information for every single data set. That's a lot of wasted time and wasted network that we don't want to do. So let's look at what fields we have available here let's say we want let's say display name ID ID display name. Let's try. Let's just get another one. Period type. Instead of when we when we reduced that from every field in data sets to just the ID display name and period type. We're still getting a list of all the data sets that are associated with this particular org unit. But instead of 112 kilobytes across the network it's one kilobyte. So that can be a huge savings when you when you actually specify the the correct fields that you want. And in the latest version of the app runtime, it will actually show you a warning if you specify all or star as the field name here because that is can be quite dangerous. I'll also give you a warning, if you say paging false, which would only work in this case. But if I said paging false, I'm going to turn. I'm still on slow 3G. I'm going to turn off page size but I say paging false. Let's even just get the ID. Actually, let's get star. So if we if we did this which is bad, you don't want to do a request like this. This means that we're not going to page the org units, and we're going to get everything about that or unit. Remember we have more than 1000 org units in this system, and some have 10,000 or more. So this is going to be quite a big request here. This is 500 kilobytes across the network, more than two and a half three megabytes of download. So it was actually 500 kilobytes across the network 3.4 megabytes of data when we used paging false and star so don't do that. So this is again something that will show a warning when you when you do it in the latest app runtime, but it will also at the sometime in the future we will restrict that ability to do to do something that could be harmful in that way. So that is the the runtime playground I'm sorry I'm running a little bit over time here but hopefully that's alright Deborah let me know if I should. This is a that that is a good way to test out simple data queries and mutations as well. We're not going to get into this too much either but you notice that I had the my results here in this response here, you can also. Let's make this something reasonable ID. Page size 10. Let's say this is my oh you results so that's going to give you the organization units for 10, the top 10 organization units and their IDs, but I can also have two requests that will run at the same time. So I have my oh you results here and let's also get information about the current user for instance so let's say we want we also want the current users name, which we did before as well. So resource is going to be me rams is going to be fields to do that. We got 10 organization units you'll see we have two different things here we have my oh you results and me and they're both in this object and actually if we looked at the network graph, which I think we can see. It's a little hard to see, but I showed it in this slide a little bit better. So we actually did made two different requests across the network here we had the me request and the organization units request, but we specified it in a single data query here. And those would actually be requested at the same time, so that they run in parallel, which is, it's a nice kind of advantage here as well. So we have now the result of the organization units query and the result of the me query. If we look at this, you can see in the waterfall here in this little pull out that all three of the requests in this query run at exactly the same time. If you ran one and then the other and then the other it would take three times as long so it's, it's important to do this in this way. I'll cover very briefly data mutations, and then I think we'll do some exercise an exercise on data queries. So data mutations have basically queries are for reading information mutations are for writing or changing that information. So three different kinds create update and delete. There's also partial update mutation, but that is not supported by all endpoints so I would caution against using it unless you know what you're doing. So create mutation. Again, you can test this out in the app runtime playground, and you can specify basically a resource in this case we're talking about indicators we're going to create a new indicator, and we pass it some data. So we have the params we have data here, and we specify some information that will be in the, the new indicator that is created in this case. We can also do an update mutations in this case I'm going to update the introduction of the current user. I'm going to specify it as hello world, my type here is update, and they get that response. And finally, we can do delete. So if we created this indicator here and we get this you ID in the response, we can then delete that same indicator later using a delete request, or a mutation of type delete. So that was a very, very quick introduction to mutations. I'll talk a little bit more about them in a little bit but first I think I'll turn it over to Deborah to do the, to facilitate our first exercise unless there are any questions. Were there any questions that came up with that I know it's a lot of information. So, don't worry if you have questions. I'm sure other people do too.