Servoy v2020.12 release webinar
Servoy v2020.12 release webinar
Today, I’ll do the 2020.12 release overview. Mostly going over what’s new in the release notes. Of course, the servoicor always fixes and small enhancements. We’ll cover some of those. NG desktop updates. We’ll talk about that if not everybody is using NG desktop but I’ll explain that when we get to that point. There are many packages that are updated on our GitHub sites for extensions. And I’ve picked out a few of those extensions to demo. We do ship a sample application that shows best practices on how to incorporate some of those extensions into your applications. That was just updated recently and I will be demoing from that sample solution as well. So everything that I show is available for you to check out. In terms of what we’re going to do in those demos, there is a kind of, I call it our rock star component. The pop up filter because it does so much without writing really any code or very little code. We’ve done some enhancements on that on how to programmatically add and remove or edit filters. And also some support for custom query conditions which really open up possibilities for you to do interesting things, especially if you have calculations or aggregates, non database columns in your grids and you want to filter on those in interesting ways. We added support for that and I’ll explain how that works. I’ll show and explain how it works. The SVY Utils package is a very generic low level utility API extension. We added a validation helper scope. In the last release webinar back toward the end of last year, I showed some validation. We updated the core to support kind of best practices for centralizing business logic around validation. Since then we added a helper scope to the API extensions to be able to interact with the UI a bit better from that and I’ll sort of show how that hooks together. Another one of our most popular extensions, the SVY search API. This is for those of you that don’t know, it’s been around for one of our oldest extensions, but it’s still actively maintained and it’s used, I think, by almost all projects, text-based searching against databases. We continue to enhance that to make it operate more like an internet search engine and one of my colleagues added some alternate date formats to do some interesting things when you’re searching on date columns and I’ll give a brief demo of that. Afterwards, I’ll go through some of the more minor release notes and talk about what those mean and give you guys a chance to ask questions about that. But as is the tradition of the tech webinar series, let’s jump right into some demos. I’m going to switch over to the example solution. Please let me know if this doesn’t show up clearly. I can scale up the browser a bit, but it fits nicer the way it’s set up right now. This, again, is the sample solution that is available for you at you can test-drive it at sample.servoy.com and it’s also available to download and install via the package manager in the IDE. So I’m going to be using that to demo a few of the items I put on the agenda. Let’s go over the pop-up filters first. I have a grid here showing order records from the example database and the search and the filter toolbar at the top. The extension that we’re going to be going over. I’m only going over the new features. We have done at least two webinars, I think, featuring this extension. So if you want to know more about it, please check our archives on the pop-up filter extension. What I’m going to be showing first is the use case for adding and editing filters programmatically. I’m going to start off by explaining a bit of a problem. So by default, this extension allows you to search on any item or any column in the grid. It also allows you to potentially filter on any column in the grid depending on how you’ve configured it. One thing that’s really nice about the search is that it can search across databases. So in this case, the orders table is showing the customer, which is of course a foreign table. And if I want to search on a bit of a string fragment, you can see that I get orders for a matching customer. That’s quite nice and productive. However, if I’m going to also want to filter on that, we have a bit of a problem because the, the filter would be nice to use the, like a valueless so I could actually see individual customers. But if I just put on the related data provider onto my grid, in this case, it’s the, you know, order to customer.company name data provider. Then when I go to filter on the customer, I won’t get that nice list of, of, of customers. So what I’ve done is I’ve, I’ve programmatically kind of intercepted that filter and, and added the valueless to it. So I can both search on, on customer and filter on it with, with kind of discrete values from the valueless. So I can pick those instead. I forgot to hit return after I clear the search. So now it’s, it’s showing only those, those items that were filtered. This before was, it’s a small thing, but it’s, yeah, I think it comes up a lot because you show a lot of related data. You, you expect to be able to search and filter and it behaves the same, but you want to use those valueless. This is how you can do it. Another problem that happens is, is similar. We have, say, ship country and ship city, which also worked nice for searching. I can, I can search those with string fragments or tokens. However, if I do want to filter on those, I get the same problem. In that case, I will also want to use a valueless. So now what I’m able to do is apply the valueless to bring up country here. And now I, I get the valueless and I could take off some values or search for values and take them off. Again, a full demonstration of this component is in other webinars. So that’s programmatically adding, editing, removing valueless. I’m going to jump into Servoy IDE, a Servoy developer and show you that. I think I have to do a new share here for that. And please, if you have any questions about what I’m showing you, because I’m assuming some prior knowledge of what we’re talking about in terms of search and filter, go ahead and pop those in the Q&A panel and we’ll pick them up as we go or toward the end. So the one example I showed here, the, the customer column on here, you can see that I’ve used the related data provider orders to customers.companyname. And again, that will then not allow me to use a valueless which gets picked up in the filter. So what I’ve done, same, same goes for, for city and country. You can see that I don’t specify a valueless here so that when I search, I can search on string fragments directly in the search box. What I’ve done is, is on the first show of this form in the on show event of this form, I’m adding, I’m adding some filters here. Oh, this is, you can ignore this first one. This is an example of, you could just add a filter to make something filterable, which is not on the grid. When we jump back to the client, I’ll show that. So I’ve added to the postcode as well, which doesn’t appear on the grid, but you might want to be able to filter on it. So there’s support for that for adding filters, which are not on the grid. And if I forget, you can remind me to show that when we switch back to the client. But here’s, here’s the examples that, that I just showed in the client. Let’s start with the company name for the customer. In this case, I’m getting the filter, which is already defined because it’s, it’s set up in the grid. And I’m, I’m attaching the valueless to it and switching the data provider to customer ID. It would have been on the related data provider. This doesn’t change the search because the search is bound earlier in the setup. But it’s just nice to know that you can get in between when stuff is happening and, and really customize things because at the end of the day, these are kind of low level APIs with UX patterns built on top of them. So they can be nearly no code, but, you know, the Servoy way is always that if you need to, you can get under, underneath, and really make it your own. The same is true for the city in the country. In this case, I just grabbed the filter and I set the valueless so that, that it’s available. If I didn’t do that, you wouldn’t have that nice pick list in the filter. Okay, I’m going to switch back to the client and show another example about custom, custom conditions in the filter. By the way, here’s the, the filter on, on Postcode. It’s not showing in the grid, but it’s available here. I could do, I think. There’s a Postcode starting with 5.1. Yeah. That’s an example of dynamically adding. But for my next example, I want to talk about something which I think is a bit more, kind of clever and advanced and, and will come up in real applications. And that is that some of these columns on here are not database columns. They are calculations, aggregates, that sort of thing. And I’ll start with the, the order status. In this case, the order status is a calculation. It’s based on some comparison of the, the dates on the order. The required date and the shift date and the order date. If it doesn’t have an order date, it’s new. If it has a require an order date, I think, but no shift date and its plan. And if it has a shift date, it’s completed, something like that. So this, this column here is placed on the grid as, as a calculation. So what happens if I just try to pick this off and, and put it in the filter, it doesn’t know how to send a filter to the back end database. We have to interpret it for that. So what we want to do is intercept that, that event when you’re sort of applying that filter and send it to the database. So what I’m going to do is grab the order status here as my filter. And now I can say I want to just see new orders. You can see it selects only new orders or plan orders. Now, Servoy always works well against even very large backend databases. So I want to emphasize that the data is not the same. But I want to emphasize that this filtering is not a simple filtering of what’s cached in the grid, where this to be a table with, I think it only has like 800 records. But if it had 800,000 records, this would work just the same. Because it’s, it’s really running this back through the database, even though this is dynamic. The same could be true for the order total here. In this case, an order total is, you know, quantity times uniprice for all of the lines on the order. I think some discount or something is also applied. So this is a calculation done in the application at runtime. But I want to run it back to the database with some SQL aggregates. So I’m going to select the filter here. And I want to filter on the order total. And this is specified as a numeric filter. So I might want to grab orders that are, let’s say, just bigger than 500. Or we could do a between 100 and 500. And there you can see I’m actually filtering on what would be a calculation. Doesn’t live in the database, but I’m going to grab that at runtime and interpret it onto the query condition. So this is a bit more advanced, a bit more complex, but I think this comes up in a lot of projects. So it’s nice to follow along as I go into Servoy developer and show how it’s done. Sean, somebody is asking how this affects the SQL performance. Okay. Well, that’s, that’s really up to you. So what I’m going to do is show, I’m going to show that the SQL is under your control. And that’s what we’re going to look at right now, so a bit of how it works. So again, we’re back on that grid. And you’ll notice that for status, the data provider here is order status, which if I jump into it, is really just a calculation, right? That looks at those dates and the same is true for the order total, which is up here, which is in memory running over the order lines and then totaling it up. So we couldn’t possibly send those back to the database. So how do we do that? Well, what I’ve done again in that on load or on show method, the first time this form shows is set some things up. So I’ll jump back to that. So we were looking at this earlier. You can see this last line I call on the two of our filter object to set on filter apply query condition. This is one of the new API’s that we’ve added. And what this really does is you’re allowed to pass in a callback method. So at the moment when they set up a filter and they, and they, the user clicks off and it, it applies the filter, it’s first going to run your callback method and give you a chance to inspect all of the filters that are applied. And to, you know, get in between that if you want to. I’m sorry, to inspect the filter object which is being applied at that moment, not all of them. I misspoke. So this is the method here that’s being called the callback on filter query condition. And just follow along it. It’s not as scary as it looks. But just understand that it passes in a query object, a QB select object from the query builder API. If you’re not familiar with that, we’ve done webinars on that a while back. It’s very powerful, nice mature and robust data API. And we did a whole webinar on it so you can go into our archives and find that. But it passes in sort of a query object that’s already like in progress. It’s already been built for whatever’s happening in the grid. It could be, you know, the search and the filters, etc. And you’re just going to get in between that and then put in the condition that you want. It also tells you what data provider’s been filtered on, what the operator was, and what the value or values were. And then it gives you access to that filter object that gets passed in. So the first thing you want to do is, well, if it’s empty, we just kick it out. There’s nothing to do, right? They haven’t really applied anything if they didn’t set any values. But what we want to do is check the data provider because we could be filtering on any, you know, column on that grid. And so let’s go through that first example, supposing that the data provider was that order status calculation. So what we want to do is get into that query and make an OR condition. And we’re going to interpret those values, the new plan and completed into actual SQL. So if it’s new, it’s that required data’s null. And so we put in this query builder fragment here. If it’s planned, it’s a little bit more complicated. If it’s the required data’s not null, and the ship date is null, right? So we don’t yet have a ship date. I guess we do have a required but not a ship date. And then it’s completed when we do have everything basically, the ship date. And so we just sort of put that into the query builder object as we evaluate what value was put in the filter. And then we append that to the where clause of the query. In this case, it’s a bit of an OR. So it’s a little more complicated. But to take part, this is actually pretty easy, even though the example is a bit bigger. Perhaps a bit more complex is that order total because that gets into aggregates. But this is really where the power comes in because your users, if they see a field on a grid and you can filter on everything that they like it. But they don’t care about that it’s a real physical column in the database or some derived aggregate. They just expect to say, yeah, I want to be able to filter on what I see. So they assume that you figure that out. So here’s how we do it. We check that, okay, this data provider is the order total. And then we have to set up a bit of a like a sub query here for the, because if you’re, there’s a bit of a SQL thing. If you’re going to, if you’re going to query on, on an aggregate, you have to use the having, having clause. And it’s a bit of a rule about what you can put into, soundsets filter per amp, which happens after all of this, this goes off. But basically it’s this part right here. So orders to order details. So those are all the line items on the order. And then we multiply unit price. By the quantity over here, right? And then we sum that together. So there’s that SQL aggregate. So we’re doing a bit of a numeric operation and then a SQL aggregate at the end. And this SQL aggregate is what means that we have to put it into having clause. And so it’s a bit trickier there. So then we look at the operator. And if it’s between, then we put in both of those values. Otherwise, and I think this works because we can ignore empty values as well. So that works for greater than and less than as well. Otherwise, we just do that as a strict equals on the first value. So we kind of put a bit of the SQL on what’s going to be there. And then finally, we add it back to the, the where clause. In the, in the results of that, that’s up query. So that’s how you send the SQL now to get back to the question that was asked about how does this impact performance? Again, you’re in control here of the query builder. So yeah, it’s possible that you could do something that, that doesn’t perform well in the database. And when you get into aggregates that, that can be possible, depending on how your database is set up and index and everything. But, but you are in control. So it’s not like we make assumptions and then we do something just because the user clicked on it. It, it doesn’t make any assumptions. So you have to work a bit harder here, but the upside is that you’re in full control. And you can, you can be ready for it to perform well. So that’s, that’s the code behind it. I know that’s a little bit of a bigger example to follow, but I hope that you understand the, the use case, which is now you can filter on things which are not database columns. They could be calculations, aggregates, variables, whatever it might be. So that’s, that’s on a pop of filter. Sure. I got a question. Yeah. Is it, somebody is asking if it’s possible to add two buttons in the filter dialogue. For instance, okay, is confirmed to fill the values and cancel is cancel the filter value. Okay. So let me see if I can bring that up in the UI on, on one of the more simple filters. I think on the text ones we have a checkbox. I think just do all of these now have a, a value list attached to them, I think. Yeah, it’s clicking off applies the filter. I think when it’s the free text, there’s a, there’s a checkbox. I’m not sure. Or clicking off applies the filter. But the question is, can you have a, okay, in cancel? The, the short answer is yes. So what’s nice about the, the setup of this is that it’s built on sort of several layers, API first. So the, the pop up filter API doesn’t assume any, any UX pattern. It’s all just plain API. On top of that is, is a, like a provider form, which provides what does a filter look like? For example, let’s do that, that order, order total again, right? If we allow me to jump back to the developer, because it’s a good question. I want to try to answer this. If we look at the order total in the, the IDE here, you can see that the filter type is number. And this is, I assume I’m assuming a bit of, we covered this component before. So I didn’t show you how everything is set up. But to make these filter bowl, you, you declare what kind of, basically what kind of filter it’s going to be. Text, which is a free text number date value list. In this case, it’s, it’s numeric. And if we jump back to the browser and the client, you can see that when I bring this up, that’s what gives me the equal bigger smaller between. Now the actual UI of this is in sort of like a default implementation form as part of that, that extension. But you can actually go and make your own, your own implementation and theme it with your application. So if you didn’t like the UI of this or you wanted something different, you wanted OK and cancel on it. You can actually do that. So, and a lot of these kinds of UX patterns that we ship are, are like that. They, they sit on top of a more abstract layer that you can, you know, you could, you could build your own. The, the whole, the look up thing when you, when you have the type ahead look up is also another one of those. This is actually built on layers of components and, and APIs. So that’s the long answer. The short answer is yes. OK. All right. I can move on with the next demo, which is the validation. So I, I said there was this new validation scope. Oh, by the way, before I move on. Sorry. The home, the home page for the pop of filter is, this, get help.servoy.com slash, as you I pop up filter, and then you can come into the wiki documentation. You can see we’ve even highlighted those new, those new links for, for the only the new API. And the examples that I, I am showing are actually in here as well. And I think they might be in the latest version of this, the sample solution. I’d have to double check. But you can see exactly how, how those were built. All of these extensions have a home page with wiki documentation and release notes on the latest releases. One of our, our oldest extensions is that validation, or sorry, that the SUI utils, the low level utility, which is actually a whole list of different APIs for things like IO system, networking, etc. And what we added to that was a validation utility scope, which allows you to do some, just do some extra, like shortcuts on, on some of the validation stuff we showed at the end of last year. So if you, if you don’t know what I’m talking about, the new validation APIs, go back and watch the 2020.09 release, the Q3 release. And there, there we demo the, the way validation works, but, but you’ll get it through this coming up demo here. What I’m going to do is double click one of these orders and go into an edit screen. And we showed this in, in a prior webinar where we could, we can specify some central validation logic and see it reflected in the UI with, with very little code. So suppose that country is, is required. And I, I clear that and I try to save it. You can see it highlights it in, in red and it says ship countries required. Suppose that also I put a ship date, which is far in the future, or sorry, far in the past, like before the order date, that would make no sense. So if I try to save the changes, now I have two bad fields and they each have a message. But the, the logic for this and even the error messages are coming from a central validation handling point and not anything to do with the UI. So it allows you to really separate that logic from UI. We covered most of that in a prior webinar. What I want to show is how we added this utility scope to make some things easier. So I’m going to go again under the hood to the IDE. Is the, when I’m switching between the IDE and browser, is it going okay for us, girl? Yeah, yeah, it does. Okay. Yeah. Sometimes that doesn’t display right. So let’s go to the, I think it’s the order info edit, order edit. Yeah. Whenever I’m running zoom the rendering, I’ll always slow its way down. Yeah. So this is, there’s a lot coming from a base form here in this, in this example, because all these forms will then all these sort of of crud forms will work the same. So I haven’t specified anything in the UI that says, yeah, we’re going to validate that ship date field or that country field over here. If we look at the code on the, on the save button. And we go into the, this is now in the base form. So all forms will inherit this, all of those crud forms will inherit this. We call the database manager saved data. And then I just call this new method that I added when I made this example, which is validate UI. And so what this does is it first iterates overall the elements on the form and removes any style class for the invalid field. And then it calls this new scope scope.sey validation utils get record markers for the selected record. So the validation when I, when I tried to save the validation all happened in background on the validation layer in that entity layer. And I’ll jump into that in a minute. And what it does is pass, pass back these validation markers, which is in a ray of, you know, information about the validation state of the record that I asked for. And then I iterate over the markers and then I call again this new validation scope, the utility scope. This one, the get marker element. This is really handy. It’s just a shortcut for finding on the form and I pass in this form. Because this is in a base form. So it could be in, you know, any form that’s running. And then the marker. So basically I’m saying, find me the element that is showing the, you know, the, the, the data provider or the field that could be invalid. And I get back a reference to that, that element on a form. And then there might not be one. So I, I check for that example here that condition here on 199. But then all I do is I add a style class for an invalid field. And I set the tool tip text for the marker message. I just realized that I never cleared the tool tip text either. So if you didn’t catch in the, when I was mousing over even when they were, they were valid, it was still showing that, that tool tip text. So I would add that in to clear it as well. Anyway, it’s as simple as that. Just iterate over those markers and then find the element and, and apply the, that style class. But it’s really these two calls to scy validation utils. And there’s a number of methods there. Of course you always get code complete when you are entering into an API. So you can see all of the, the methods that we added there. And these are, are typically self documenting when you’re selecting them. You’ll see the description parameters, return types, et cetera. Tell you what’s going on. But really, it’s about how they get messages or markers from a particular data source. Because there could be a bunch of, a bunch of validation markers for different entities. And it’s also about how to interact with the UI. So I can get elements for a particular marker and, and change the style of those dynamically. So not a lot of code I had to write here to, and this is again in the base form. So all of those edit forms would work the same. Now, I said that the validation logic is centralized in a entity scope. So where, where do these markers get generated? This goes back to the webinar we did in for the 2020-09 release, which talks about this, but I’ll quickly revisit that. If we look at our orders table. And we look at the events. We added back in an earlier release, this on validate event. And so anytime we’re trying to save an entity, this gets called first, and it can run it through some validation. And it passes in the record objects and the markers, because this could be a running list of markers that different validators, at, you know, in different modules could attach to. And some additional optional state, which is just custom properties that you could pass in. And so what I do is I check if the ship country is null. You know, I, I report the error with a message. This can be I 18N. This last argument is for I 18N parameters do. So if you want to have like kind of a layered I 18N message so we can work in any language, you can. And then basically say for the data provider ship country, it’s this data provider that we find when we, when we say get the, get the elements on the form for the marker that we found the validation marker. And then we, we apply that, that message in the tool tip, which is this. And then we add that style class, which is just coming from the look and feel. So it really lets you centralize validation logic and, and keep that separate from the UI and handle it in sort of just just an implicit way in the UI only working with, you know, what you want to do with those elements. And it’s the same here for the ship date and the order date that they, the ship date can’t be before the order date would make any sense, right. So that’s that’s all happening. This is on the entity itself. So anywhere that I include this is in a module to doesn’t it sits below the UI. So anywhere where I would include this module, I would get my validation logic centralized. We did it this way because a lot of people were, I think, have it’s more of a best practice thing, but it centralizes everything. So there’s a lot of people who are wanting to know what’s the right way to handle this. And so we really believe that centralizing it on the entities the right way to do it. And then now you always have access to it in the UI to just look it up. So that’s the validation example. I expect that there will be some questions about that before I go on. I got a long question coming in. Somebody’s asking if you can get to the old value of a data provider. The old value of a data provider. Okay. Yes, you can. I assume you mean in the validation itself and not the UI, but you could do it in both and I can type that out for you right here. So it passes in the record, which is an object that stores the state. And if you do record dots, get change data. And you can see the documentation here. It actually returns like a little data set of changes on that record. And this is a JSA to set which is like a 2D array, which will have for you the name of the data provider, the old value and the new value. So if you were to get this and then get column as array, you know, at one, that would get you all of the columns that were the had been changed on that record. This would get you all of the old values and this would get you all of the new values. Or if you did get row as array, get each one. And so this would say, okay, the first change and then you would get inside that it would have three values in it. Call them name old value new value. That’s well documented. And that’s been in our API for ages. But it’s on JS record get change data. Good question. So that’s the next. Don’t know if you explained it before, but somebody’s asking. Where do you define the invalid fields? Well, I think they must mean the class. Yeah, I think it’s your way to find that. Yeah, yeah, sure. So let’s go back to the base card. This is the base form where I’m calling remove style class here. I think split question refers to. And then down here I found an invalid marker. I found the element for that marker. And then I add style class field invalid. This is not part of that framework. This is up to you. In this case, you can create a style class. If we look at the. Solution explorer here. And we look at the style sheet for this. I’ve put it in somewhere here right at the top. Also, this is covered in a prior webinar markers can have a severity level errors in frozen warnings. So it could be that you want to put a warning in. Which doesn’t block the safe, but you may want to give feedback to the user. So it could be that even you had an end in the prior webinar in the 2020 or nine release. I actually showed it where it was validating continuously as the user. Tabs through the fields that some of the fields could have warnings where it sort of turned orange and not red and didn’t block the save. You know, so it’s really you’re in control there, but we provide kind of a framework for getting it getting it going. But here’s here’s a simple style class. The foreground color. It gives that the thick. Border at the bottom and the background color. Hope that’s clear. Cool. One other question. Is this looks like it’s it’s working strictly with a database table. What if you wanted to validate from a for a forum. Very, very, very reliable. Right. Yes. So this is this is being called on on a database table. That’s a good question. The on validate and the record markers that whole that whole scheme is geared around entities. It doesn’t necessarily have to be a relational database, but it does have to be a Servoy abstract data source. So so databases are one kind of data source we support. But we also support in memory data sources, which could be backed by files or web services or JSON or something like that. We also support something called a view data source, which could be a complex query that’s simplified into a regular data source. So all of those we could. Well, I don’t know if we can do the validate on on the view because it’s a bit tricky, but the other ones should be supported. So that works the same, but if you have a form variable and you want to run some validation on it, we don’t really consider that an entity. We consider that sort of like application state and you’d have to do that through other means. You certainly can take the same approach with the adding and removing style classes. You can use the on element data change handler, which I’ve disabled all the code here. This was running every time you like to have off the field, right? And running that dynamically. That’s a good way to do it too. So if they put in something in a form variable that you don’t like, you can capture that at a low level on element data change and handle it. Cool. All right. I have one more example to go through. This should be pretty fast. So I got to share my browser again. I’ll spend meeting controls. There we go. Put the country back in. This is still in Val and I’m just going to validate this so we can move on, put this in the future. Still not far enough in the future. There we go. There we go. Next example. And this should be pretty quick. I know we’re running long on time here. This is the last example. The SEY search project, which is an oldie but a goodie. It’s what allows us to type in any sort of string tokens up here and search on all these columns in the grid. And, you know, even if it’s a date or a numeric order or string, it just works. We added something nice to that and I made a separate form here for the date format that can be supported. So let’s look particularly at the order date. We used to support a strict date format to say like for this search provider order date, we’ll accept this date format. And if the user wants to type it in, it has to match it. So it would be like 2021 dash o 7 dash o 4. And that didn’t even work. Hang on. I said o 7 but I typed o 4. So then I get those two records. And that was all you could do. But we wanted to make this work a bit more like an internet search engine and give something users can work with more quickly. So suppose I just want to find orders that are in 2021. You can see order date. Those are all 2021 or 2019. You get the idea, right? Suppose I’m going for just 2019 and in July. It’s part of the date there or suppose I want to go with July 2019. That way. Or I typed the full text July 2019. I could do it with a space. But I have to quote it because the space sees it as another token. So we can support. Suppose I want to do 2020 o 7 with a forward slash. Get July in 2020 that way. Right instead of the dash. So we call this alternate date formats. And it allows you to specify like an array of formats that you will accept on a particular search provider. So that’s just pertaining to order date here. And I’ll show you how that works under the hood. Switching back to Servoy developer. Again, if that whole text based searching thing is new to you, it’s been around for ages. But we did a webinar on one of our earliest tech webinars. Still, it’s still totally valid. That webinar if you want to go watch it. So we’re going to move over to that example search. I lost it here. This one example search date formats. This form I built from scratch. I didn’t use a base form so that I could sort of show you the search API in full. The on action events when the user enters its enter or taps out of this one. Runs this method. And that field is found to this search text form variable to capture the user input. But basically we use this SUI search API. I’m not going to go into the details of that. But just getting down to the new stuff. Basically, I say I want a search object for this entity, this found set. And I’m going to search all available columns. You don’t have to do that. But that makes it quick and easy for me. So this is not related to the grid in this case. And then what I want to do is I want to kick out the required date and shift date. Because I don’t want to have false hits on those. I wasn’t even showing those in the grid. So I set those as implied search, which means you actually have to type in the field name in your search. So I just wanted to eliminate those so I don’t get any false positives. Because what we see is is ordered date on the grid. Then I add in all these alternate date formats. And I said something wrong a couple minutes ago. I said it was on the search provider. It’s actually on the search object. The whole search object. So it applies to all date fields in the search object. So the default is that a year month day and I chose that because I have an international audience and no one can agree on what order to put things in. But I think this one kind of satisfies everyone because it goes from year to month to day. And so you can see that I support the full date now the year and the month or just the year. I also do it with the dashes. I also support some of those. The three character code for the month. So the first three letters of the month. Or the full month, which is the four amps. For those you have to put the year. It’s not supported if you don’t put the year. I didn’t put the forward slash one. I could have added that. Also we support a space but keep in mind that if I go back to the input there. If I put a space in it sees that as two different tokens and you have to quote it. The same if you put in a first name last name and you wanted to match exactly like first name last name on one field. You have to quote it just like a search engine. So that’s it. You have to have those day formats. There are some things that aren’t supported like you can’t just put in a month. It has to be it always have to be in order or specificity like year or month day. You can’t go in more detail and just put a month but not a year. So that’s that example. And then I’m aware of the time here. I want to wrap this up by the end of the hour. I’m going to switch back to the release notes and below through those. And then I see some questions. I want to leave some time for that. All right. My slides are visible. Yes. Small definitely. Okay. So I’ll go through these real quick and then just say what it is. And then if there’s questions we can answer that because these are kind of the low level release notes and those are always available on the Click click just once again. So I’m always available on our wiki as well. So on the core updates, Eclipse is updated. If you’re going to run 2020.12. Java 11 is required and Java 8 is no longer supported. If you’re deploying 2020.12, Java 8 is still supported for now that could change. not supported anymore and 11 is required but we shift the JDK with the install so unless you’re using your own JDK or JRE then you’ll be fine. We do offer better support in the IDE for external Git clients. This has to do with you know suppose you pool from a Git repository and it updates the files but maybe not everything refreshed in the IDE and you have to go in and click refresh. There’s a bit more support for different Git clients and the underlying file system to keep things up to date. NG Desktop. We talked about this in our Wednesday webinar as part of our initiative for supporting hybrid deployments from a single code base so this is related to native desktop access from the NG client. Things like file system hardware software that’s installed and getting access to that. We updated to the latest Electron. Electron is a technology that wraps the NG client that gives us that bridge onto the local desktop. What’s nice is with that update now we can start doing the auto updates for the next time so we can set up so that it stays up to date which is think important for shipping a cloud-enabled desktop application. There’s some API added to that NG desktop UI project. If you’re using NG Desktop you probably know what I’m talking about if you’re not you probably don’t care but you can now add an external browser view so this is like embedding you know a browser. If you were coming from Smart Client you would have used the FX web panel just to show browser content inside your application. Now you can you can create that through this NG desktop UI and interact you can even send JavaScript into it so if you want to scrape it or interact with it you can so that’s pretty powerful and that was added. There’s also a number of export options having to do with how the updates are handled so look at the release notes and look at the export wizard in the IDE for that as well. You’ll notice in the scripting API updates if you update you may get a bunch of new warnings don’t panic these are for missing return tags. Your methods should have a return tag if they are returning something so you’ll get a warning for that. My advice is you go through them and fix them. If you ignore them nothing bad will happen or not I should say nothing bad will happen that wouldn’t happen in the older version but they’re there for a reason so pretty much every update we’re adding new new checks on the build and now we are checking for that return tag for anything that’s actually returning something so go ahead and look at those warnings and fix them. We added some things to the database manager API around looking at what records have edits on them so the database manager get edited records you can now pass in a data source string object it used to just be what are the edited records on a found set or a record object but now you can just say what are all the edited records on orders and it could be in different found sets so that’s a nice little filter and then there’s a parameter for like a custom filter as well so you can get in and so somebody requested probably better filtering for how you fetch edit records and this kind of goes back to the validation stuff that we were showing as well because you can discover edited records and you can also look at each as someone asked each record and determine what was actually changed old value new value. This is an important change if you are publishing REST web services from your Servoy application. We updated the REST plugin to support large files and I’ll explain what this is as quickly as I can. It used to be that if you want to accept a file through a put or a post or return a file from from a get request that that was first going through a byte array. What that means is that the entire contents of the file would go through memory and so supporting large files was problematic. We’ve updated that so that it actually now goes to a file handle instead of a byte array so that even if you had a very large file it would just stream it so you suppose you were uploading it it would stream it into a file and then return when it’s done a handle to that template and vice versa. If you want to return you don’t have to first read into a byte array and then return it out of your method you can just return the file handle and the plugin will stream it for you. So that’s really nice because that fixes a problem with support for large files however it could be potentially breaking if you’re already doing that byte array setup. So my recommendation is you go in and you switch from returning or accepting byte array to a file handle however if you want to be the least invasive way to do it and just make it compatible without changing your code we snuck in a little hidden setting into the properties file where you can you know specify that it’s this this JF upload is default to true you just put it back to false and then it it goes back to the byte array so if it is breaking for you we always give a property to escape it without forcing you to do a code change so that’s nice. For War X forts I think this is the last one there’s an option now to to we remove the parameters for what you can kind of dynamically stick into the context XML file now there’s an option to just grab a file when you’re exporting for the full context.xml file so now you can do whatever you want to that you would normally do this is for Tomcat configuration it’s not required that you do anything special but for those of you that want to do some special things in Tomcat configuration in the context that is supported the example I put here is if you want to embed your ng client application in another domain you need to you know set this seems like cookies parameter and you know stuff like that you now have more control there. All right I know we have some questions and we’re also coming up on the end of the hour and I’m running out of breath so uh retaker let me have it. Yeah I think there’s one or two open questions by the way I see a lot of positive feedback coming in about you to be demo so I appreciate that. That’s why I mean I think there’s one open question about your first demo that somebody’s asking if you can query on multiple columns. For instance country is Germany plus status is planned. Yeah yeah I’m not sure the context of the question in the search that you can actually just type in in the free search you could type in fragments of strings for either country or city and it will it will narrow it down. If you’re talking about the query builder yeah you can you can eject whatever you want into the query so I hope that that answers it. Then there is an open question about your second demo somebody says it’s asking does remove style class reginstates any non-default style classes that have been set. Does it remove style class reginstate non default happens? That’s a good question it depends a bit on the CSS right. So when you when you add a style class you may be overriding something and then when you remove it the override would go away because CSS the order of application also depends right so we change the background color of something because it’s overwriting obviously like probably several style classes that are saying what the background color should be when we remove it it should revert back to the way it was so I don’t think there’s a problem with that I’ve never seen a problem with remove style class. Last but not least yeah you lost them all. Month was in capitals and and they days were presenting lowercase is there a special reason behind that? Yeah there’s a wiki documentation on date formats so if you look at our wiki documentation you can see all the different formats strings so you could also have time in there and and lowercase m is minutes and uppercase m is months and that’s why there’s a difference. Okay thanks. I don’t see any other questions so I think we can wrap up. Okay I want to say a couple things the the example that I’m using is also an extension or it is available through the package manager not all of the code that I showed you is in there but we update all of these we update all of the best practices into that sample so I encourage you to check that out and we’ll be having more webinars about the sample itself coming up I think this quarter. Okay well Siang I would say thank you also again from from the audience people like the demos keep it up have a nice weekend and see you all soon. Thanks everyone ciao bye bye