Browser Integrations: Notifications, local storage and reCAPTCHA
rowser Integrations: Notifications, local storage and reCAPTCHA
Okay, this year we are in number 26. So we are at a good clip here doing almost every two weeks for the whole year and a mix of topics. Last week we did some best practices. We kind of mix it up between best practices and how to’s and also announcements because also supports professional services team and the R&D team are releasing extensions and components and new features continuously so just keeping you guys up to date with that is a job in and of itself and that is one of the goals of this webinar series. So today I am excited because we have yet more things to announce that our brand new and they are in the form of web package updates in browser integrations. So, as is the tradition with the tech webinar series, we like to demo first and explain later, but just real quickly, the agenda. We’re going to do three separate demos, three new things to release, native browser notifications, HTML5, local web storage, and Google’s recapture integration and servoit. And if you don’t know what those are, you will at the end of this webinar. So, let’s jump into the demo here. Let’s start off in at the demo.surboy.com sample gallery, and we’re going to start with native web notifications. Native web notifications take advantage of your browser’s existing notification feature. And so, the first thing that you need to do is to request permission. If I try to show a notification without permission, you see that I get this message here, I should allow, I should ask the user to allow notifications on the on the browser. So, I attempted it didn’t work because I don’t yet have permission. The browser needs to give me that access. So, I’m going to request permission, and this little dialogue here you may recognize from other websites is asking to show notifications. If I do nothing, I still can’t show the notification. I get the same thing. But, I think that marks it as blocked. But that’s something that we want to show. So, let me show you how to clear your settings in your browser. I think that is this one here, demo.surboy.com. Maybe I should just restart this tab, because I think I’ve screwed things up already. All right, let’s come back in. If you’ve never been here, you can go to demo.surboy.com and try this yourself. So, we go to browser integrations. Native web notifications. It is supported by this browser. I haven’t yet granted permission. I’m going to request permission, and it is not showing. This is interesting. And, it was just showing a minute. It’s not coming up here. Under my notifications. Well, I’m going to proceed without that. So, the way that this works though is once you click allow, then you can show the notification, and it will pop up in the corner just like, I don’t know if you have Gmail or Google inbox or something. And the real benefit is that those notifications show regardless of if the browser tab has focus or if the browser window has focus. So, these are ideal for notifications that are generated from outside the user’s action. So, if you’re actually pushing notifications to running clients. So, go to demo.surboy.com after the webinar, you can try it yourself. The other example that we wanted to show is the source code real quick for this. I can show you that. So, I clicked up here to show the source code involved with this sample. You can do that on your own as well. So, we request the user permission. And that’s what shows that little native dialogue that all the browsers that support this have. And what we have to do is pass it a callback and you can see inside here is where we get the callback. Once they’ve clicked to allow, then we know that that will return true. So, we know that we can proceed. And then you can just call show notification through the plugin. So, the next demo would be the local storage. I’ll show you something in the online demo as a small sample. So, local storage allows you to actually store stuff in HTML5 local storage database and persist it between browser sessions. If I wanted to say enter a search term, and then the next time I come back, I want that search term to be remembered. I’m going to save it here. I’m going to clear it. It’s now stored in my browser and if I restore it, you can see that it brings it back. Perhaps a more visual example is a button style. I’m going to clear this and get the save button style and you can see it goes back to default. Maybe I’ll make a green one and save that to local storage. Even if I change this, say back to default, once I get the save button style, you can see it comes back. And that persists between, I’m showing this right now within one session and it probably doesn’t look that impressive, but that actually persists between sessions. I have a bit more detailed example of that because to show you perhaps a better use case. If I go into an application that I have running just from Servoy developer, I want to persist between session, say some UI settings. Let’s say for example that I have some grids and the user maybe is going to reorder the grids. Let’s say they bring the order date over here and they make order date more narrow. And they make last name of the sales rep more narrow and they put it to the end. So now I’ve reordered some of the columns, re-sized them and let’s say at the same time we’re going to do some searching. So let’s say I look for orders that were in Germany or I’m looking for something where the sales rep was leveralling. You can see that as I start to, maybe I want to do both Germany and leveralling. And as I start to add items, that one didn’t go in, I’m putting them in a value list here of like recent search terms. But what I want to do is have that all those changes persist. So the column adjustments I made in the search terms. So what I can do is I can click persist and then exit and it’s going to save all that stuff out or I can also do it on solution close, persist on exit. I could do it on form height. You could trigger it whenever you want. What I thought would be interesting is if we actually look, you can inspect the local storage. If you go to your, if you’re in Chrome, it’s settings, I’m not sorry, not settings. More tools, developer tools. And you can see that I have the local storage down here and the storage is per domain. So you can see that local host ADAD is one domain and everything is stored in a separate instance there. So now as I persist those changes, I’m just going to click the persist button. You can see a bunch of keys here and a bunch of values. And so that stuff that I’ve chosen to persist in the browsers local storage. So now if I exit and this is going to like close the application and relaunch it, you can see that the grid should come back with the same column widths and orders as I had before. If I come in here to do the search, I get the same value list. So even though I’ve exited, and I really did close the solution and reopen it there, I could even close it from here, say, and go to Servoy developer and relaunch it. And I really do get the same configuration here, the same value list. And you can always follow along whenever you open up the developer tools. And you can see, if I clear storage, it goes away. If I persisted, it comes back. And you can look at that on a key by key basis. Perhaps it’s worth looking at the source code for that as well. Jump back into Servoy developer. So we have a few forms here. Let’s take a look at the outermost form, which, oh, there was one more thing I didn’t show you, which was the split panel location. So if I want to say adjust the split panel location, make it a bit bigger, and persist that and exit, you can see that it’ll come back also now a bit bigger. And if I look at the storage, there should be the entry here for the split panel location. So if I look at something that I’ve written in the persist method, I just wrote this method on three of the forms, persist form state. And if I jump in there, it’s really just you generate a key. Your key should be pretty namespacey. If you know what I mean, it’s because you may have a large, this is, you know, possible to do store all kinds of stuff because you get a lot more storage and local storage than you do, say, with cookies. So you may have lots of keys and they’re really just key value pairs. So you want your keys to maybe be namespaceed. Probably you want to store those in some constants somewhere. But at the end of the day, it’s just a string that has to be unique for that instance. And then you can give it a value. So I’m just capturing the divider location in this case. And I’m doing that when I click that persist button. Also, if I talk with that checkbox and just exit, it does it on solution close. And really the magic happens when we call the plugins web local storage set item and the key value pair. So then when the forms loading, I call the load form state, which reads it back out of the browser storage. And again, it just gets the value. It parses it into a number because it’s stored as a string in this case. And sets it back so that it’s just resetting that as the form’s loading. A more complex example was the grid view. And I believe that is. This one, the orders grid persist form state. And so what I did here is for one, I was capturing those search terms. But let’s look at the grid first. I made this little subroutine called persist element infos. And what this is doing is iterating over all the elements on the form. It’s skipping the search one. And it’s just pushing some information into this array. And down here’s where I do the key value pair. And in this case, we want to do some JSON. So we stringify some object in this case, the array of element information, which is just the name and the dimensions. And we push it into local storage. On the flip side, when we’re loading the form, we read that out. And we look for that value, which is just a string. We deserialize it from JSON using JSON.parse. And we just, we look for the element with the name that was in there. And we set the size and the location. And on the table view form, that actually is the, you know, the order of the columns is based on the X coordinate and it does track the width even though we have anchoring set. So it actually grows some of them. So that’s the source code for the local storage. You can imagine that you could take form inheritance and really take this to another level. So if you had a large ERP application and you really wanted to persist all of the little UI settings, it wouldn’t be that much work to do something generic like this in a base form and say, okay, now all my grids can persist this way. Now all of my lookup fields or search boxes can can persist that way. Hey, Sean, can I ask you a quick answer on this? So saying that the only type of value that can be stored in this is a string and that if you want to store other value types, you’d have to convert them and then parse them. I mean, I know the local storage you could do other stuff. I think then then strings. I think the plug-in might be returning strings when you read it in though. I have to, I haven’t spent too much time with this. This just got released a few days ago. And so that’s probably something that we should follow up on in the form post. But I think that it’s for now, you probably want to, anyway, for complex objects, string is the way they go because you want to use JSON. And so you would just deserialize it. And then you really, when you call JSON parse, you get everything that you had serialized before. So in this case, I didn’t have to, for the X and Y coordinates, those are integers, but I didn’t have to parse in on those. It was just a single key value. The value is a string. But if you do a complex object, then you can do non-string items within there. And the JSON parse will handle all the data typing. OK, thanks. Yeah. Well, that’s, I think, all we want to really show from that example, the, if you go back to the demo site too, you can look at the source code there as well. So if you just go there yourself to demo.seroid.com, you can see how some of this stuff is, is handled. For the third demo, we could do the, the Google recapcha. Probably you guys have seen this at some point in your browsing history. You get to a website or an application, and you got to enter some stuff into a form, but in order to submit the form, you have to verify that you are not a bot of some kind. So if I try to verify, it says, please verify you’re not a robot. Clicking here sends it to Google, Google, and their infinite artificial intelligence figures out that you are not a robot. And now has returned a response back to the application saying that, that it’s cool, this person’s a human. And now if you choose to verify the site information, it’s valid. And that of course is just a little canned example. The reality is probably it would be on some, some form or you’re submitting a bunch of information and then, you know, and then you submit. We can jump into developer and take a look at what this looks like. I have it set up here in this little demo solution, but it’s basically the same thing. If you wanted to look at what this looks like at design time, we close all these tabs. And open this one in the form editor. So really what you do is you, you add this, any of these, you can add through the web, the web package manager. So I, I added the, the Google recaptia from the web package manager. You drag it onto the form. The first thing you probably want to do is bind it to a handler. So whenever they successfully validate, you get, you get a callback. And then it passes in also a response, which you could say, the response is a big string, which is kind of the unique identifier for that verification. But basically just handling that method, lets you know that it was valid. There’s also on, on expire because they can expire. And then it’s no longer, it’s no longer valid. But this is the one that you want to handle. In this case, there’s not much to do. I was just printing out success, but it would be something like you’d store in a form variable, you know, has valid, you know, has validated something like that. And then you’re checking that variable before they can proceed, right? So if we, if we look at the other things we have to do, we have to set up the site key and tell it to render. I’m doing this on load. You may want to tell it to render on every show. The site key is something you get because you have to register your, your domain with Google and say you want a site key for validating that site. And then you get, you get this big long site key and you plug that in probably to a constant. And then when you call validate, you basically want to do want to, before you proceed, you want to, you want to call validate one more time to make sure that the caption is still valid because you could, you could validate it and then sit on that form, you know, for two hours and then come back and, and now it’s no longer valid, right? So you want to call this right before you move to the next level. And then you have to pass in your secret key. So that, that site key, like the public key and then private key, are generated when you register with Google. And that’s pretty much all there is to it. Most of the work is done just by dragging this thing on your form. And then, and then checking it to see if, if it’s still valid, you almost don’t really need this on successful. If you’re just checking if it’s valid anyway. So if you, if you wanted to, let’s see if I had this up on another page, I thought I did. Maybe I must have closed it. May open recent tabs. Nope, never mind. There is a place to go. Nope, I thought I had it open for the, to register, you probably just go to Google. ReCAPTCHA. And there’s, there, get reCAPTCHA, oops. And this is where you go. you give it, you know, my site. And then you pick your, your version. This is the one that we have the reCAPTCHA version to and then you register. And then you’ll get your, your public and private key that you need to plug in. And then you’ll keep that for that domain. Yep, put your domains in here. So, you can register local host for testing. I think it works. I think it ignores local host anyway or just works on local host anyway. Because it seemed to work for me and I don’t know if we had local host registered. But it’s pretty easy to set, set that up. Okay, let’s do a quick overview so that we can end this on time. So the first thing we saw were the notifications and we didn’t really see the notification window popping up. Sorry for that. Something wasn’t quite right. With the demo. But basically the use cases for this are that you’re pushing notifications from sort of system generated events. So different from if you’re familiar with the toaster service where, you know, let’s say you save a record and you pop with little dialogue and say the save was successful. That’s a bit different because that event was generated in the application sort of resulting from the user action. In this case, it’s like the user may be doing something else and you want to get their attention again. Maybe another user posted a comment on a thread that they’re following or, you know, they got a new message or something like that. So even if the browser tab or window is hidden, you’ll still get that notification. Just keep in mind that it’s not fully supported in IE and it also doesn’t really work in mobile, most mobile browsers because mobile has gone the route of like push the mobile push API. So that’s a bit different. But this will work on desktop, most desktop browsers like Chrome and Firefox. The way how it works is sort of three steps. You want to get the permission. You want to check the permission and then show the notification. And those are just three methods that are available through the plugin. When you request permission, you get a callback and it passes in the result through a fall. So if the user allowed it, you get you get that. There’s also a has permission. So if it’s stored in the browser settings, which I was trying to recover there, you saw. So if you already have permissions, I think there’s one more method for has position, has permission, but the very first step you’re requesting the permission. Oh, is this one down here that is permitted? And then finally, you call show notification. Typically, it’s just a title, a body. You can have some images. You can also have a click callback. So it may be something like, hey, a new order came in. And then you click on it and it takes you directly to the order record. So maybe in the future, we’ll provide a better example where you can really see how you would you would use that click to navigate because it could be a pretty powerful feature. If you were monitoring tasks or orders or something like that, HTML5 web storage. So the use cases for this are that you want to persist stuff between sessions. So once you log out and log back in on the same device, you get the same settings. So again, this is this is ideal for device specific stuff. Really good for just recreating some things about the UI, split panel locations, forms sorting, recent searches. That gives the user an enhanced experience because if they set up a form the way they like it and then they come back, it just works. And that’s pretty easy to do. It’s not for cross-device settings. So keep in mind that what you do in one, if you’re on your laptop and then you go to your office and you’re on a desktop, you’ll get whatever we’re set for that device later. It’s not, if you want something like a bookmarking records and you want wherever that user logs in, they have their favorite orders or something, that would be something you would store server-side in a database or something. There is a bit of, there’s two ways to do this really in any application but also in Servoythrough APIs, cookies and web storage. So ever since Servoyhas had a browser offering, we’ve offered the ability to set cookies. And you can do the same thing with cookies. So and in fact, many people have been doing this for years. So you can persist all that stuff with cookies but there are limitations that are overcome with the web storage stuff. So for example, cookies are always sent with every request. So that occupies some bandwidth and cookies are limited in how big they can be. So if you imagine that you want to store every little niggly, wiggly setting for a huge ERP application, you may have quite a bit of storage and if you’re sending that with a cookie with every request, it’s not very scalable. And the fact that they’re sent with every request, cookies are inherently a little bit less secure. Not that the actual storage of the cookie is less secure. Both, I should point out that both cookie storage and local web storage are both inherently insecure, meaning they’re just there, they’re visible in the browser. Anyone with an inspector can look at them. So if you are putting sensitive data, you want to encrypt that server side before you push it down and decrypt it when you read it in. An example of that is sometimes a remember me stuff. If you put some sensitive information about a user into local storage, you still need to encrypt it. I’m just saying it’s more secure because you’re only sending that up to the server when you read it through this plugin, not like a cookie where it’s going every HTTP request. It’s pretty easy. It’s set item and get item with key value pairs. And those key value pairs build up on a per domain setting. So every in web storage, every domain that you hit has a space available for setting these key value pairs. You can clear everything for a domain with one method call. You can also, I didn’t show it here, but you can also remove an individual item, which is the same as setting it to null, so that it’s no longer there. Keep in mind that for complex objects, like what we did with the column settings on the grid that you really want to use JSON. So you just JSON dot stringify when you’re writing it in JSON dot parse when you’re reading it in. And that gives you the power to really nest things and get a complex structure. The last thing we saw was the reCAPTCHA. Again, this validates that you’re not a robot. And the ideal use cases for this are anywhere really where you have unprotected content. You don’t really need something like this if you’re logging into the application anyway. So no need to put this on a login screen. But you may want to put it on the screen where you’re actually registering. So if you have some automated provisioning going on where the user can, you know, sign up for their product and then, you know, click register and get an account, you don’t want robots creating a thousand accounts on your system and bringing it down. So good place to put it is there. Anything where you don’t have to authenticate first. So password recovery, you don’t want a robot trying to run an algorithm on your password recovery system. Any open Servoys that you might send. So, you know, things that you don’t necessarily require a login for, you still don’t want that to be hacked. It’s really easy. You just put it on the form and then you can basically validate that it’s been, it’s been authenticated or confirmed. You just have to get those public private key pairs. I showed you where to do that on the Google website. You create your site. You register your domains. You get those public private key pairs. And then a way you go. I’m sure that we have some questions to see. So while we take some questions, we’ll leave up the useful links here. Yeah, we have one question. Does the web local storage stay in the browser if the user deletes their history or has set to close to delete history on close? Right. I don’t believe it’s associated with history. It’s a bit different history is like where you’ve gone, what sites you’ve visited it. So if you are doing that, then it will, it should remain. I’m not sure how this works in incognito mode on browsers. I think that anything where you’re setting local storage will clear an incognito mode. So cookies and local storage. So it’s, but the browsing history itself is a bit separate. So you should be able to, you clear that separately. You can clear browsing data. It’s called or clear, clear application data on a domain domain domain by domain basis. Okay. Another question, do native web notifications work with Safari? Yeah, so I checked support for that. And and it’s definitely Firefox and Chrome are supported Safari and Opera are supported recently. So if you have a recent version of those, it should work. One that’s definitely not working is Internet Explorer and the other one is mobile browsers because they go for the push API instead. Okay. One other question is the web store? Steve, I think the audio cut out, but I can see questions too. The question was, well, I don’t cut out for just me or the whole thing, I’ll repeat it just in case is the web storage session specific. It’s not session specific. It’s domain specific. So even if you, if you do multiple sessions over time for a single domain, it’s still going all to the same place. So if you, if you want to, for example, if the same multiple users go on your same device or multiple applications run at your same domain, this is quite common, right? So let’s say they log into the CRM or they also log into, you know, the sales analysis, right? Yeah, something like that. And those are both hosted at the same domain. Then you start putting keys in there that might collide, or let’s say different users could log into the same domain from the same device. Then that’s why I was giving those long namespace. So you really might maybe want to prefix everything first with your application, you know, like, you know, my CRM dot, you know, and then down into drill down into the individual settings, you did see that I did like forms dot my form dot. So, so if I have a thousand forms and they can all have a split panel on them, then, you know, it’s, it’s namespace. So you really just tackle that with the namespace strategy. All right, I think that was all the questions. Okay, thanks everyone for your attendance. Again, this will be recorded and posted to our website. We will post the slides for this and the link to the recording on the forum. We have a running forum thread just for this webinar. And you can find that there at form dot Servoy.com. We’ll be back in two weeks. The topic is yet to be determined as we usually, these are all on the camera. Yeah, planning these things on the fly. We always appreciate feedback, questions, comments, abuse and ideas for new topics. So please send those to my email or better, put them on the forum on that same link. Thanks everyone. All right, thank you. Take care. See you in two weeks. Bye bye.