Quantcast
Viewing all 1006 articles
Browse latest View live

Customer Case Study: Viasoft Korp

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

Wagner Landgraf, TMS Business Product Manager, has recently published a post in his landgraf.dev blog, with a transcription of a nice interview he has made with Alexandre Henzen, Technical Director at Viasoft Korp, a big software company in Brazil that provides ERP software for industry and belongs to Viasoft group, which also has software for other segments like agribusiness, retail stores, among others.

The interview was in Portuguese but the the English transcription of the main parts of it is provided by the blog.

It's really great to see how TMS Software and Delphi made an important role in the company history. The company now has more than 70 employees, being part of the group that has more than 500 employees.

According to Alexandre himself:

All the architecture of our software written in Delphi is built around TMS Business.

He uses TMS Scripter, TMS Workflow Studio, TMS Aurelius, TMS RemoteDB and TMS XData, among other products belonging to the TMS Business line of products.

Some of their customers are as big as having 500 simultaneous users, with thousands of operations every day. TMS Business products are handling it hands down.

He also mentioned his experience after upgrading to Delphi 10.4.2 Sydney. In his own words:

Sydney 10.4.2 is the most stable release that I’ve seen since XE2. Compilation time was 58 minutes, it dropped to less than a half of it just by upgrading to it.

It's a very interesting interview when they also talk about other topics, including the role Alexandre had in TMS Aurelius development. Visit landgraf.dev interview post to see the full text and let us know in your comments what did you think about it!




Introduction to using Firestore and new Firestore features in TMS WEB Core v1.7

This article is the first in a 4 part series that will explore the new features available in the TWebFirestoreClientDataSet component in TMS Web Core v1.7.


A quick summary of the basic features in the previous version of Firestore ClientDataSet component

 Here's a quick introduction for those developers who have not had a chance to use the component so far.

 TWebFirestoreClientDataSet was introduced in TMS Web Core v1.3 to enable the developers to use Google Firestore as a cloud-hosted, NoSQL database for their web apps. By using this component, you can use a Google Firestore collection as a dataset and get a full CRUD functionality to update it. As you make changes to the dataset, the component updates the Firestore collection behind the scenes. What is more, since the component is a ClientDataSet, you can bind the component to various DB-aware TMS WEB Core UI controls via a TWebDataSource.

 

Here are the steps to use a Firestore collection as a dataset:

  1. In order to connect to a Firestore collection, all you have to do is drop a TWebFirestoreClientDataSet component on a form and set a few Firebase properties and CollectionName in it. Then define the dataset fields either in design view or in code and make the component Active.
  2. Additionally, you can bind the component to various DB-aware TMS WEB Core UI controls via a TWebDataSource. What you get is a basic App with a CRUD functionality out-of-the-box. A Firestore collection is created automatically as soon as you insert the first record. Any dataset updates you make in code or via the DB-aware controls are automatically sent to Firestore collection by the component.
  3. Further, the basic authentication of a Google Sign-In is also available in the component so that you can force the user to Sign-In with Google before the data in the Firestore collection can be accessed. This requires a simple Authentication rule to be set up in the Firestore dashboard. Then all you need to do in the component is switch ON its property SignInIsRequired. It takes care of presenting a Google Sign-In popup as soon as you make the dataset active.


Complete details for the above steps are given in the TMSWeb Core Firestore documentation.

You will also find a TodoList Demo in the folder "Demo\DBBackend\Firestore" that demonstrates the above features. Please follow the instructions in the TMS Web Core Firestore documentation to set up and run this Demo.

 

Here is a screenshot of the demo:

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

What you will see in action is a web app that displays the Task records from a Firestore collection called "Tasks" and provides the features to edit the data by means of various DB-aware controls bound to the data source. It also prompts for a Google Sign-In if the user is not signed in.

Although the basic demo does a good job of showing the CRUD features, it has some problems in the way its start up logic is coded and there is a reason for it as explained below.

  • The demo expects the end user to enter the API Key and other Firebase parameters
  • The values for these parameters are used to set Firebase properties in the Firestore ClientDataSet after the Open button is clicked
  • The values are remembered in the local storage to be used in the next session

 

The reason the basic demo is coded this way is for the convenience of you as a developer when setting up Firebase for the first time. The API Key or some other parameter may not work as you learn the process of set up. Hence, it gives entry boxes for you to experiment till you get them right and remembers the parameters for the next session.

 

But this is not the way a real Web App will work!

Please do not follow the above model for your own web app that uses Firestore ClientDataSet.

 

Here is an attempt to explain why the above approach in the basic demo is wrong and should not be taken as sample code for your own web app:

  • In reality, a web app should never prompt for the Firebase parameters from the user. Setting them belongs in the code or in the object inspector. For the same reason, the Firebase parameters are not remembered in the local storage as they are not prompted for.
  • The App should subscribe to Firebase sign-in events as soon as it starts in order to know whether a user is already signed-in. This is to give a good start up experience to the user. And the Subscribe method needs the Firebase parameters to be set so they can not be postponed to be set later on a button click as the basic demo does.


If you see the new Multi-Tenant Demo described later, it follows the correct approach of setting up these parameters in the code and getting the status of the signed-in user to open the dataset automatically. Also it remembers the Email address of the user in local storage which is convenient for the user.

 

New Sign-In features in the Firestore ClientDataSet component

In this part 1 of the series, we take a look at the new Sign-In related features. There are plenty of them.

 

Sign-In by Email/Password is now supported

The earlier version of the Firestore ClientDataSet Component only supported Google Sign-In method. Many users do not want to sign up for web apps with their Google Sign-In. They prefer to sign up with a custom email address and password for privacy reasons. Hence, the Email/Password method of Firebase Sign-In is popular with web apps as it gives them a complete control over authentication right up to the reset password feature often needed by users.

Your TMS Web Core App can support the Email/Password Sign-In method of Firebase by using the following features of the TWebFirestoreClientDataSet component.

 

Enable Email/Password Sign-In method in Firebase Console first

  •  First of all, you need to enable the Email/Password Sign-In method in the authentication section of the Firebase console.

 

Let the user Sign-Up

  •  Use your own interface in the web app to collect the sign-up email address and password from the user
  • Call the method SignInAsync with the given email and password. Pass a True value for the IsSignUp flag.

 

The suffix "Async" of the method name "SignInAsync" means that you can get the success or failure result of the call by passing an anonynous response procedure to the method. Here is the sample code.

 

    fireStoreClientDataSet.SignInAsync(
        aUserEmail, 
        aPassword,
        True, // IsSignup flag
 
        procedure(success: Boolean; errorName, errorMsg: String)
        begin
            // do something on success or failure
        end
    ); 

 

Let the user Sign-In

  •  Use your own interface to collect the sign-in email address and password from the user
  • Call the same method SignInAsync with the given email, password and a False value for the IsSignUp flag.

 

Let the user Reset Password

  •  To provide this functionality in the App, call the method SendPasswordResetEmail. This tells Firebase to send an Email to the user with a special link to reset the password. You can customize the contents of this email in the Firebase console.

 

fireStoreClientDataSet.SendPasswordResetEmail(

         aUserEmail,

         procedure(success: Boolean; errorName,

            errorMsg: String)

       begin

         if not success then

         begin

           showmessage(errorMsg);

           exit;

         end;

         ... Success actions like

         ... asking the user to check email

         ... and follow the instructions

       end

    );

 

It's good to know that the Firebase Console also helps manage the users

  • In addition to the above features given by the component, you get the features to manage the users in the Firebase console too. There, you can see the list of Users in the Authentication section from where you can disable a user, delete a user or even initiate a reset password for the user.

 

Getting the Signed-In status and acting on it is now easier

 

The features to get the Signed-In status are needed in order to present a better interface to the user who may want to remain signed in.

 

Better example of using SubscribeToSignInEvents

The previous version of TWebFirestoreClientDataSet component already had a method SubscribeToSignInEvents that allows you to get a Sign-In event whenever a user signed in or signed out of your web app. This method enables the web app to change the user interface according to the Signed-In status. But as already explained earlier, the basic TodoList demo does not use this feature properly because it prompts for the Firebase parameters and calls SubscribeToSignInEvents only after a successful Sign In.

In reality, a web app will not prompt for firebase parameters and would rather set them during the initialization of the App. Also the App would then immediately call the SubscribeToSignInEvents method to let a common OnSignInChange event change the interface accordingly.

For example, an App may hide the Sign-In panel and display the Signed-In user's identity. This way the App can change its user interface to show a Signed-In state. The new Firestore Multi-Tenant Demo (folder Demo\Services\Firestore) has the proper sample code that demonstrates this approach.

 

The Sign-In panel in the new Multi-Tenant Demo

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

 

In this demo, the Sign-In panel appears only if the user is not signed in.

 

![alt SignIn Panel in the Multi-Tenant Demo](./SigninPanel.png "SignIn Panel in the Multi-Tenant Demo")

 

How the interface changes after Sign In is described in the next section along with a screenshot.

To see the exact implementation, please see the code and comments in the Firestore Multi-Tenant Demo (folder Demo\Services\Firestore). Please note that this is just an example. It's up to you how you prompt for Sign-In credentials. You can even design your own Modal popup to ask for that.

 

GetSignedInUserAsync Method to take one-time actions

If you have used the Sign-In event feature in the previous version, you may have realized that a Sign-In event may occur multiple times for a web app whenever a user signs in and out of web app. Hence, it does not give you a clean way to do something only once if the user is already signed in. 

For example, assume that a user Email is remembered from the last session in local storage. On startup, the App finds that the same user is already logged in to Firebase. In this case, it can open the dataset automatically to give the user a nice start up experience. 

For this purpose, you can use the method GetSignedInUserAsync that gives you the user information of the signed-in user through the anonymous procedure that you pass to it. 

Here is the sample code from the new Firestore Multi-Tenant Demo (folder Demo\Services\Firestore). It automatically opens the dataset if the same user who intends to sign-in is already signed in.

 

  fireStoreClientDataSet.GetSignedInUserAsync(

      procedure(isSignIn: Boolean; UserName: String; UserEmail: String)

      begin

        if isSignIn then

        begin

          if (edEmail.Text <> '') and SameText(edEmail.Text, UserEmail) then

            openDatabase;

        end;

      end

    );


The Multi-Tenant Demo after the user Signs In

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

Once the Sign-In occurs or if the user is already found Signed In by the App at start up, the following screen appears where the Sign-In panel is hidden and another control panel appears. Notice how the Signed-In user's email is shown and a Sign-Out button is provided. User may or may not Sign Out when closing the browser. Next time when the user starts the App, it is smart enough to detect a signed in status and open the dataset automatically.

![alt User has Signed In](./SignedInStatus.png "User has Signed In")

 

To see how this approach is implemented, please see the code and comments in the Firestore Multi-Tenant Demo folder Demo\Services\Firestore).

 

Letting the user Sign-Out

To Sign Out of Firebase, you need to call the SignOut method of the component. But you need to close the dataset before you do that otherwise it will generate a usage error. SignOut does not do a close automatically. It depends on the App to close prior to sign-out because only the App knows its proper state whether it is safe to close.

 

Summary of what we learned in this article

  • First, we had a brief look at the basic features of Firestore ClientDataSet component for those of you who haven't had a chance to use it.
  • Next we described the new Sign-In related features of the component that give you the popular Email/Password authentication of Firebase out-of-the-box by the use of a simple flag.
  • We also discussed the proper approach to detect a signed-in user in order to provide a nice user experience.
  • Then we looked at the new Multi-Tenant Demo that uses these new sign-in features in the recommended way.


In the next part 2 of this series, we are going to take a look at the Multi-Tenant capability of the Firestore ClientDataSet component that allows to keep the data of each signed-in user separate and safe.




TMS WEB Core v1.7 Ancona is released

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


We're happy to announce the major release of TMS WEB Core v1.7 Ancona.

The main new features are:

  • Miletus framework : desktop application development with web technology
  • Introduction of async methods in many areas
  • USB device access
  • Firestore filtering, multi-tenant, async functionality added
  • Local file access
  • TWebStringGrid, TWebDBGrid enhancements
  • Popup menu component
  • Enhanced TWebForm


The full list of new features & improvements can be found on the product page and previous blog post.


TMS WEB Core for Visual Studio Code v1.3

The new version v1.3 of TMS WEB Core for Visual Studio Code is also around the corner. The major new feature of v1.3 will be extensibility via 3rd party components with a package system and with this, the whole portfolio of TMS FNC components will also become usable at design-time in Visual Studio Code. The TMS WEB Core framework will be at the same level as TMS WEB Core v1.7 for Delphi & Lazarus. The only feature that will not yet be included in TMS WEB Core for Visual Studio Code v1.3 is Miletus support. That is reserved for v1.4 and with this, it is expected to already bring Miletus for Windows, macOS, and Linux.


More content



Feedback

We are curious to hear what you like the most about TMS WEB Core v1.7 Ancona or what you wish to see in future versions of TMS WEB Core! We look forward to discussing all these great milestones with you!



Multi-tenant TMS WEB Core client applications with Firestore

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

This is the 2nd article in a series of 4 about Firestore features in TMS WEB Core v1.7. Firestore is a cloud based solution from Google allowing to create modern web client backend databases in the Google cloud. So, there is zero config or server setup, all is managed by Google. This article series explores how components in TMS WEB Core facilitate the use of a Google Cloud Firestore backend in your web client applications.

Previous Firestore ClientDataSet component

Before TMS WEB Core v1.7, the built-in dataset component only supported a shared usage of a Firestore collection as a dataset. This means a collection is shared between different users who can sign-in and can access all the records in the collection through the dataset and are able to modify them. 

This kind of shared usage is still supported and may be desirable for certain collections depending on the requirements of the web app. 

But consider the case where you want to develop a web client application where each signed-in user can only see and change his own data. Such a feature is called Multi-tenancy

If you were to develop this kind of Multi-tenant App directly in JavaScript that uses the Firestore API, you will need to devise your own scheme to keep each user's data separate. A common approach is based on an internal-user-id of the signed-in user that is available from the API. But how your design uses that user-id is entirely up to you.

There are many alternate designs possible to support this kind of Multi-tenancy. One design may use the relational approach of keeping a user-id field with each row or data object (called document in Firestore). Another design may create a nested collection whose name is based on the internal-user-id. 

The new version of TWebFirestoreClientDataSet makes it simple for you by taking care of this internally as described next.

New Multi-tenancy feature in TWebFirestoreClientDataSet 

The new Firestore  specific TWebFirestoreClientDataSet component makes it easy for you to keep the data separate for each signed-in user. You tell it to do so by using the following property:

property UserIdFilter


The new version of the component has an internal implementation of the relational approach described above whereby it can automatically attach the internal-user-id of the signed-in user as an additional field to keep the data separate for the user. 

To get this feature, all you need to do is set the property UserIdFilter as active.
 
fireStoreClientDataSet.UserIdFilter := ufActive;

Once you do that, the component adds a new field named 'uid' to each new object (called document in Firestore) to identify the documents belonging to the signed-in user. Similarly when getting the initial list of objects on opening, it filters the collection on the 'uid' field. However, this automatic adding of 'uid' field happens only when creating new objects or documents. Hence, you may use this feature on a new collection only unless an existing collection already has the data separated by the same scheme--a field containing the internal-user-id. This is described next.

property UserIdFieldName


Suppose you want to connect to a pre-existing collection made by another app with the same scheme where the difference is that the user id field is not named 'uid' but is 'userid'. To connect to such a collection with the feature to view and maintain separate user data, what you need to do is additionally specify a field name to use instead of 'uid' by using the property UserIdFieldName.


  fireStoreClientDataSet.UserIdFieldName := 'userid'; 

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
Security Note: But all this happens at the client. How can we protect the data on Firestore itself?
As already described above, the component implements the above internal-user-id based logic by using a filter to view the data for the current user id and to update the data with a user id field forced in it. But that also means that all the code to do this is on the client side. That poses a security risk because a malicious signed-in user can use the same Firestore API code to get a list of other users' data by using a filter without the user id condition or by using the internal-user-id of another user in the condition.

How do you prevent that? Firestore does give a solution for this problem at the server end. You can modify the authentication rule in the Firebase console. Here is a sample rule to do that:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow create: if request.auth != null;
      allow read, write: if request.auth != null && request.auth.uid == resource.data.uid;
    }
  }
}

Once you have this rule active, no signed-in user can access another user's data even by faking the user id. It will generate a permission error.

Important
If you are using another field name by way of property UserIdFieldName, for instance "userid" to store the internal-user-id, please modify the above rule to replace resource.data.uid with resource.data.userid.

How does it work?
The new allow statement for read/write protects any data in which the uid property of a data object does not match the uid of the Signed-In user. This check is not needed for a new record and hence the allow for create operation only checks for a Signed-In user access.

New Multi-Tenant Demo demonstrates the "user specific data" feature

You will find the new Firestore Multi-tenant Demo in the folder "Demo\Services\Firestore Multitenant." To run the Demo and see the above features in action, you need to perform the following steps:

  1. Enable the Email/Password Sign-In method in the authentication section of the Firebase console.

  2. Open the Multi-Tenant Demo and customize the Firebase parameter constants at the top of the Form unit. See details on how to get the parameters by referring to the Firestore documentation in the TMS Web Core developer's guide. They are basically the same parameters that you may have used to run the Basic TodoList Demo.

  3. Put the following Rule in Firestore console. This is not really needed to run the Demo. But it is required for better security as described earlier.

    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /{document=**} {
          allow create: if request.auth != null;
          allow read, write: if request.auth != null && request.auth.uid == resource.data.uid;
        }
      }
    }

  4. Now build and run the Demo. Create a new user account by entering an email and password. Add a few tasks. Then sign out and create another new user, adding another set of tasks for that user. Now sign out and sign in as either of the users. You will see that only the tasks belonging to the signed-in user appear in the data grid.

Note that the Multi-tenant demo creates a new collection by the name "UserTasks" in Firestore. You can change the collection name in the form unit code that sets the CollectionName property.

Here is a screenshot of Multi-tenant demo in action where a user john@doe.com has signed-in and the data grid shows the tasks belonging to this user.

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
Multi-Tenant Demo showing tasks for the signed-in user


Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
 Summary of what we learned in this article

  • First, we had a brief look at what it means to have Multi-tenancy wherein each signed-in user can only view and modify his own data.
  • Next, we saw the Multi-tenancy feature provided in the new version of the Firestore ClientDataSet component.
  • We also discussed the security aspects and how to implement the security for Multi-tenancy at the Firestore end.
  • Then we looked at the new Multi-Tenant Demo that demonstrates the "user specific data" features.

In the next part of this series, we are going to take a look at the new Filtering features of the Firestore ClientDataSet component that would allow us to limit the data coming in and paginate it as needed.


TMS WEB Core for Visual Studio Code v1.3 beta is available

We're pleased to inform that we have released the beta for TMS WEB Core for Visual Studio Code v1.3 to our TMS ALL-ACCESS customers and customers of TMS WEB Core for Visual Studio Code.

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
 What is on the table

This is a very exciting new version as it brings:

  1. Support for packages
    Yes, from now on, it is easy to create your own custom components and compile & install these for use at design-time. The package system is similar to how you can use packages to install components in the Delphi IDE or Lazarus

  2. Support for workspaces
    With workspaces, now you can have multiple projects in a folder and activate and select which project to compile/run/debug.

  3. Support for using the entire FNC component suite
    As our entire set of FNC components is ready for use in web client applications, the new package support in TMS WEB Core for Visual Studio Code enables to install all TMS FNC components in the TMS WEB Core for Visual Studio Code IDE. The latest FNC registered version updates released last week contain all the required packages for this.

  4. Brings the framework up-to-date with latest version as available in TMS WEB Core for Delphi/Lazarus v1.7
    The TMS WEB Core framework that comes with TMS WEB Core for Visual Studio Code is now in sync and up-to-date with the latest release of TMS WEB Core for Delphi. This means that all new components and component improvements are now also available for Visual Studio Code users. This includes the new USB components, local file access components, new Firestore dataset capabilities, extensions to grids, web socket connection improvements and much more...  One important note though, the Miletus application type is not yet in our release for Visual Studio Code release but scheduled for the next release.


Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
 Start learning

Developing your own custom components is for sure a very powerful way to fully apply a RAD component based and in a sense also low-code approach to become productive at developing web client applications with TMS WEB Core.
Our chief architect José Leon Serna explains in this video how you can use packages and start writing your own components.

We held a webinar (on our TMS Web Academy platform that was by the way developed entirely with TMS WEB Core for Visual Studio Code) with a sneak preview of TMS WEB Core for Visual Studio Code v1.3 earlier this week, so you can see the replay and see the package support, FNC components in the IDE and learn from the discussion and Q&A with attendees.


Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
 Start developing

TMS ALL-ACCESS customers and customers of TMS WEB Core for Visual Studio Code, login on our website and under Account / My Products, you will find the beta download of TMS WEB Core for Visual Studio Code v1.3. Enter your credentials to activate the product. If you also have the full FNC component suite, open the FNC web specific packages from the FNC product folder opened in Visual Studio Code and activate and install these packages.
From here, you'll have the full power of TMS WEB Core + custom packages + well over 200 FNC components to start developing exciting web client applications!

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
 Your feedback

We are now testing, polishing, fine-tuning till we can officially release TMS WEB Core for Visual Studio Code v1.3.
Your feedback is crucial to achieve the highest possible quality for the release as well as for steering all future developments. Our team is eager to learn about your experiences and work on it! Contact us via regular email or the support center!




Firestore server-side filtering in TMS WEB Core v1.7

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


To create a high performance web client application, a lot of things need to be taken in account. But foremost, when you create a modern SPA (single-page-application) architecture web client application, you will want to look at optimizing the communication of the application to your database back-end. In case you use the Google cloud based infrastructure as your database back-end, you will want to perform as little as possible requests and ensure that the data involved in these requests is as compact as possible. The server-side filtering capabilities of Google Firestore allow you to easily achieve this, especially with the new built-in support for it in the TWebFirestoreClientDataSet in TMS WEB Core.

Recalling loading and filtering features of TClientDataSet in classic VCL


If you have used a TClientDataSet in Delphi VCL, you already know that the component provides an in-memory table that can be manipulated easily and efficiently. But if there are a large number of records in a database, loading all of them in the TClientDataSet needs to be avoided. With traditional Delphi TClientDataSet, if the records are loaded through a DataSetProvider that supports queries then you can change those queries to load limited records based on a criteria. This approach greatly reduces the memory overhead of the TClientDataSet, since fewer records need to be stored in memory. 

Compare this with another option of local filters, also from standard Delphi VCL, where the number of records visible in the dataset can be reduced by using local filtering options. But that does not reduce the number of records in memory. It only restricts access to the records filtered out.

In Web Core, we give a solution similar to  DataSetProvider where certain filtering criteria can be applied at the Firestore to reduce the number of records fetched on opening the dataset.

New server-side filtering features in TWebFirestoreClientDataSet


The new server-side filtering features purpose is to limit the number of records fetched from a Firestore collection. Consider the problem when the Firestore collection has a large number of records. Loading all of them at once is not a good idea due to the memory overhead of an in-memory table in the TClientDataSet. 

In the new release of TMS WEB Core, the Firestore ClientDataSet component provides new features to apply filters to the data obtained at the Firestore end.

Important background information

Before we look at the details of each filtering method, it is necessary to understand some core principles.

1) Method names begin with "AddService"


There are several Firestore related filtering methods available in the Firestore ClientDataSet component.  They are named starting with "AddService" indicating that they are applied at the Firestore Service level. This is to differentiate them from any local filtering methods already available in the standard ClientDataSet.

2) Firestore filters are not as flexible as SQL queries 


The primary purpose of the Firestore filter methods is to limit the number of records fetched on opening the dataset in order to reduce the memory overhead. 

Don't expect the Firestore filters to be as flexible as an SQL query for your data processing requirements. There are many restrictions and limitations as you will discover later. For an exanple, please see "Limitations and Gotchas" under AddServiceFilterCondition method later in this article. 

If you have advanced filtering requirements then in addition to the Firestore filters, you should use the local filtering features of the ClientDataSet for the advanced filtering needs.

3) Understand their mapping to the Firestore Filter API


It's necessary to understand that each of the methods descibed in this article maps to a particular kind of query on the Firestore side, for example AddServiceFilterCondition maps to a "where" query on Firestore. 

The mappings are important to keep in mind so that you can refer to the proper Firestore documentation to look for more details on what works and what doesn't. We can not possibly describe/repeat all the Firestore specific gotchas in the TMS WEB Core documentation.

For example, the description of the method AddServiceFilterCount in this article mentions the following mapping:


The "maps to" means that internally the component uses "Firestore limit query." So if you are a curious type and want complete details on "Firestore limit queries," please go to the Firestore documentation on that keyword.


4) Many Filters depend on the current Sort order that you need to set up before calling the filter


For some of the Firestore filters, you need to sort on the field being used. This can be done by using the calls ClearSortFieldDefs and AddSortFieldDef. Note that this sorting happens at the Firestore end.

Here is an example of setting up a sort on the age field.

fireStoreCDS.ClearSortFieldDefs;
fireStoreCDS.AddSortFieldDef(
                   'age', // field name
                   true); // is ascending


5) The Filtering Methods

AddServiceFilterCount method (Maps to: Firestore "limit" query)

You can limit the number of records obtained by this method on an Open. You need to set it before calling Open.

Example:
The following filter when set up will fetch only 100 records on open.

fireStoreCDS.AddServiceFilterCount(100);
Usage notes:
  • If you have set up a sort order, they will be first 100 records in that sort order.
  • How do you get the next 100 records? Use the method AddServiceFilterContinueAfterLast described next.

AddServiceFilterContinueAfterLast method for pagination (Maps to: Firestore pagination)

This is the method that sets up the pagination to get the next set of records. You need to call Refresh after this. Then you can call Refresh again and again to get the next set of records or pages.

For example, if you call it after the above example of AddServiceFilterCount and call Refresh, it will fetch the next 100 records. Subsequently, just call Refresh to get the next set and so on till you get an empty dataset.

Usage notes:
AddServiceFilterContinueAfterLast can also be used after the AddServiceFilterRange method described later. But it also requires to clear filters and set a new range. Please see the Filters demo for the actual code. 


AddServiceFilterCondition method  (Maps to: Firestore "where" query)

Use this method to specify a where condition filter. Setting the filter activates it on the next Open or Refresh. 

Requirement:
If you are using a Sort Order by using a AddSortFieldDef call, it must be on the same field that you are using in this filter.

Examples:

1. Get records where field "status" has the value "New"

fireStoreCDS.AddServiceFilterCondition('status', '==', 'New');

2. Use more than once to specify multiple conditions ANDed but for the same field. 

fireStoreCDS.AddServiceFilterCondition('age', '>', 18);
fireStoreCDS.AddServiceFilterCondition('age', '<', 65);

3. For an OR condition, use the "in" operator. For example, to get records where field "status" has the value "New" or "Pending"

fireStoreCDS.AddServiceFilterCondition('status', 'in', TJSArray.New('New', 'Pending'));

Limitations and gotchas:
  • Date/Time fields require special code. This is described in Web Core documentation of Firestore.
  • This filter maps to Firestore "where" that is much limited as compared to SQL's "where." For example, one of the rules says, you can add more than one where filters, provided they are on the same field and if a Sort Order is being used, the Sort Order must be on the same field. To give you another example, the example 2 above works as AND. But if you want to use a similar OR condition, it's not easily possible. People have written articles on such problems that you can find on the Internet by searching for Firestore where query problems with proper keywords.
  • It's not possible to describe all possible rules and usage of Firestore "where" filter in this article or even in the Web Core documentation. For more details, please refer to the Firestore document "Querying and filtering data" (search Google on this) and refer to the section on "where" queries. 

AddServiceFilterRange method (Maps to: Firestore filters startAt, startAfter, endAt, endBefore)

Use this method to specify a Firestore "start" and/or "end" condition on a value that refers to the current sort field set by AddSortFieldDef call. Setting the range filter activates it on next Refresh or Open call. 

Requirement:
The value passed works on the current sort field. So you must have defined a sort order by AddSortFieldDef call.

Example:
Suppose you have defined the sort on the "age" field by AddSortFieldDef

fireStoreCDS.ClearSortFieldDefs;
fireStoreCDS.AddSortFieldDef("age", true);
Now you want to start at age 18 and end at age 65. You will use 2 filters.

fireStoreCDS.AddServiceFilterCondition(frStartAt, 18);
fireStoreCDS.AddServiceFilterCondition(frEndAt, 65);

Limitations and gotchas:
  • Date/Time fields require special code. This is described in TMS WEB Core documentation of Firestore.

ClearServiceFilters

Clears all the Firestore filters set up so that all the records are obtained on the next open or refresh.


New Firestore Filtering Demo


A demo is available that shows use of the above filtering methods. You will find this demo under Demo\Services\Firestore.

There are 2 parts to this demo, an import utility that imports 500 JSON objects to a Firestore collection as a prerequisite for the demo and then the Demo itself that filters the collection when obtaining data.

Preparing for the Filter Demo: Build and Run the Import Utility

In the Firestore Filters Demo folder under "Demo\Services," you will find a project ImportTestData. 

Please follow these steps:

  1. Open the project TMSWeb_ImportTestData
  2. Build and Run the project
  3. Enter values for API Key, AuthDomain and ProjectID if they are not automatically filled by your previous usage of any Firestore demo. 
  4. Click on Import Test Data.

This should import 500 objects from the JSON file in a new collection called SalesData. You can verify that the data is imported to such a collection in the Firestore Console. Also, in case you want to recreate this collection due to any problems, you can delete the colleciton in Firestore console and import again.

Running the Filters Demo

Please follow these steps:

  1. Open the project TMSWeb_FirestoreFilters.
  2. If you didn't change the Collection name when importing, just Build the project. Otherwise, please search for CUSTOMIZE comment and use the same collection name here in which you imported the data above.
  3. Now run the project.
  4. Click on the Filters items one by one and see how they work.
  5. To look at how the actual filters are used in code, please see the procedure setupExampleFilter.
Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Summary

  • First, we recalled the Loading and Filtering features of TClientDataSet from Delphi VCL. This was necessary to understand the memory limitations of TClientDataSet.
  • Next, the article stressed on some background information that is necessary to understand before going into the Firestore filtering methods.
  • This was followed with the actual description of the Firestore filtering methods along with examples, usage notes and limitations.
  • Then we looked at the Firestore Filtering Demo that uses the filtering methods of the component.


Of course, everything you learned here applies to TMS WEB Core for Delphi or Lazarus as well as TMS WEB Core for Visual Studio Code.


What's next

In the next part 4 of this series, we are going to take a look at the new Async methods to perform database operations in code. In particular, we show you how to wait for the result of the previous operation before performing the next operation in a world of async Firestore updates.



3 upcoming free webinars!

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


We especially ramped up organizing webinars this year to give your more opportunities than ever to learn about what is available to empower you as Delphi developers to deliver great solutions to your customers. In the coming 3 weeks, there are 3 upcoming free webinars. So, don't tell us we didn't inform you Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


FNC Cloud components webinar : Apr 29, 14h UTC

Embarcadero Germany organizes on April 29 a free webinar about using FNC cloud components to consume cloud services in  a service agnostic way. The webinar will be held in German language. The official title of the webinar is:
"Plattformübergreifend Webdienste einfach nutzen mit TMS FNC Cloud Pack" and is presented by Matthias Eißing and Holger Flick. See the full webinar info and register here
Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


First steps into using an ORM with Delphi : May 5, 15h UTC

If you are completely new to using an ORM (Object Relational Mapping), this webinar is for you. Our product manager and architect of the BIZ product line, Wagner Landgraf will introduce you to the concepts of ORM, why you can benefit from using it and how it will change your developer life forever when you abstract the database you use via an ORM.
This webinar centers around the flagship Delphi ORM: TMS Aurelius and is even more interesting as TMS Aurelius was recently added to our academic program. This means that students and teachers can register for their fully free and fully functional version.
Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
 
We offer this free webinar via our own TMS Web Academy webinar platform. Register now for your free seat!


First steps into creating web apps with Delphi : May 12, 15h UTC

While since the introduction of TMS WEB Core a lot of Delphi developers picked up this tool to produce web client applications with the familiar RAD component based Delphi development approach, for many Delphi developers it is still a big step to enter the world of web application development. This webinar is especially focused at Delphi developers with no prior experience with web application development and we will introduce the concepts and approaches to create these web client applications with TMS WEB Core step by step. After this webinar, you'll be comfortable to set your first steps into a new and exciting platform to deliver applications to your customers. This webinar is hosted by Bruno Fierens, CTO of tmssoftware.com and architect of the TMS WEB Core framework.
Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
 
We offer this free webinar via our own TMS Web Academy webinar platform, that was by the way entirely developed using TMS WEB Core! Register now for your free seat!


More webinars?

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
 
If you have ideas, let us know what you want to see covered in upcoming webinars! We are eager to learn where we can add value with content offered via a webinar. Or, if you created a great application or have an original or creative use case for any of our products and you feel like presenting this to your fellow Delphi developers, don't hesitate to reach out and you could be next offering a webinar on our TMS Web Academy.
Or meanwhile you can have a look at the previous webinars we offered and for which the recorded sessions are available.





Firestore async dataset methods in TMS WEB Core v1.7

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

In this last blog article of 4 blog posts, we introduce a last major new feature in the Google Firestore dataset, i.e. new async features. Before providing details about these new features, let's first look at the classic VCL TClientDataSet, how it can work how it works and what the implications are of inherently asynchronous implementations for use with a REST API based communication between a client dataset and the Google Firestore backend.

Classic VCL TClientDataSet operations

The editing and navigation interface for a TClientDataSet is best provided by using data-aware controls such as TDBGrid, TDBNavigator and more. Still, many times you need to process some records in code according to specific business logic. When it comes to populating and modifying a TClientDataSet in classic VCL code, you would use code similar to the following code snippets.

Inserting a record in the dataset

ClientDataSet1.Insert;
ClientDataSet1.FieldByName('Description').AsString := 'Call up a meeting with Sales group.';
ClientDataSet1.FieldByName('Status').AsString := 'New';
ClientDataSet1.Post;

Modifying a record in the dataset

ClientDataSet1.Edit; 
ClientDataSet1.FieldByName('Status').AsString := 'Done';
ClientDataSet1.Post;

Deleting a record in the dataset

ClientDataSet1.Delete;

 Processing all the records in the dataset

ClientDataSet1.First;
while not ClientDataSet1.EOF do
begin
  //do some processing based on one or more fields of the record

  ClientDataSet1.Next;
end;

Equivalents with Firestore?

Question is, will the above code work in Firestore ClientDataSet too? Yes the above code will work as standalone. But the code that follows the above code will fail if it depends on the success of the database operation in the previous code. This is important to understand so let's look at 2 examples of how the code that follows can fail in Firestore TClientDataSet.

Failing code example 1
Consider the following variation of the last example:

if not ClientDataSet1.Active 
  then ClientDataSet1.Open;
ClientDataSet1.First;
while not ClientDataSet1.EOF do
begin
  // do some processing based on one or more fields of the record ..

  ClientDataSet1.Next;
end;

This will fail on TClientDataSet1.First. Why? Because an open is an asynchronous operation that takes time to open the cloud database. There is no guarantee that the open will be complete by the time you reach the next statement. What will happen is unpredictable. In fact, this is true of all the ClientDataSets in TMS Web Core dealing with cloud databases.

Failing code example 2

Consider another example where we want to first insert a record in a Firestore collection, then get the record's id that Firestore generates and stuff it as a foreign key value in another dataset's new record.


// adding a new customer's record
Customers.Insert;
Customers.FieldByName('FirstName').AsString := 'John';
... more data for the customer record as needed ...
Customers.Post;

// getting the generated id from Firestore
newid := Customers.FieldByName('id').AsString; 

// adding the invoice for the customer
Invoices.Insert;
... more data for the invoice record as needed ...

// setting the foreign key value as the id generated earlier
Invoices.FieldByName('customer_id').AsString := newid;
Invoices.Post;
Do you see what will cause a problem here? Customers.Post is an async operation as it will add a new record in the Firestore collection. There is no guarantee that it will finish by the time you reacth the next statement that remembers the generated id in newid. 

To rescue with async

Fortunately, we have a solution for the above coding problems in the new version of TWebFirestoreClientDataSet. They consist of the following methods that allow you to wait for the outcome of the previous async operation before proceeding with code that depends on the outcome.

OpenAsync and SignInAsync

As shown in the following code sample, the OpenAsync method accepts an anonymous procedure as a parameter to which it returns a success or failure result after the open completes.

fireStoreClientDataSet.OpenAsync(
    procedure(success: Boolean; errorName, errorMsg: String)
    begin
      if not success then
      begin
        .. handle error case by using errorMsg ..
      end
      else
      begin
        .. further processing on success ..
        .. First, Insert, Edit, etc ..
      end;
    end);

The method SignInAsync discussed in Part 1 of this article is another async method to use when you also need to login with the Email and Password of the end user.

    fireStoreClientDataSet.SignInAsync(
        aUserEmail,  
        aPassword, 
        False, // IsSignup flag

        procedure(success: Boolean; errorName, errorMsg: String)
        begin
          .. do something on success or failure ..
        end
    );

PostAsync after Insert

Similarly, if you were to do an Insert and obtain the generated ID for the record in the Firestore collection, you will use this kind of code.

fireStoreClientDataSet.Insert;
fireStoreClientDataSet.FieldByName('FirstName').AsString := 'John';

.. set other field values as required in the new record ..

fireStoreClientDataSet.PostAsync(
    procedure(success: Boolean; data: JSValue; errorName, errorMsg: String)
    begin
      if not success then
      begin
        .. handle error case ..
      end
      else
      begin
        .. data parameter coming above is the id generated by Firestore for the new record ..
        .. do something with the id if required ..
        .. further processing on success ..
      end;
    end);


PostAsync after Edit

Here is an example of modifying a record and waiting for the outcome.

fireStoreClientDataSet.Edit;

fireStoreClientDataSet.FieldByName('FirstName').AsString := 'John';

.. set other field values as required in the new record ..

fireStoreClientDataSet.PostAsync(
    procedure(success: Boolean; data: JSValue; errorName, errorMsg: String)
    begin
      if not success then
      begin
        .. handle error case ..
      end
      else
      begin
        .. data parameter is the JSON data object of the record that was updated ..
      end;
    end);

The data parameter is not useful in this example. But it can be useful to identify which update finished when the response procedure is a common object method of the form that receives response for many update operations.

DeleteAsync and CloseAsync

Similarly, there are DeleteAsync and CloseAsync methods that return a success or failure to the passed response procedure with a signature similar to OpenAsync.

Processing Loops

It might be tricky to make processing loops this way that process all the records till EOF using Next but it's certainly possible. Several designs can be made by either using anonymous response functions with recursion or by using an object method instead of an anonymous response procedure. 

Batch Inserts with AddServiceObjects

If you need to insert a large number of records in the Firestore collection, you could write a processing loop as described above. But that is complicated and would be slow if you waited for previous insert to finish before inserting the next record. On the other hand, if you decided to fire many inserts at once, the speed might improve but there are complications of finding when they finish and whether there were any errors.

To deal with such use cases, we have added a Class Method AddServiceObjects that you can use to insert upto 500 records from a JSON Array at once, directly to the Firestore collection. This is also an async method by its very nature that sends the result to a response procedure passed to it.

Since this is a class method, you are supposed to use it by prefixing with the class name TFirestoreClientDataset. You don't need to open any dataset locally as it directly inserts at the server end.

For an advanced code sample on how this method is used, please see the ImportTestData project of the Firestore Filters Demo.

Summary

  • First, we discussed some issues with the classic VCL code used to process the records of a Firestore ClientDataSet in code. This is due to the async nature of the cloud database operations.
  • Next, we showed how the new async methods help you wait for the outcome of previous database operation before proceeding with code that depends on it.

We hope that you have enjoyed discovering the new features in the Firestore ClientDataSet component in this 4 part series.
If you have missed the previous articles, here are the links:

We will look forward to any additional ideas and feedback from you!




Announcing beta support for FMXLinux!

Intro

We have been working on this for quite some time now and today we can proudly announce beta support for FMXLinux in ALL FNC products. Download the latest update today to get started! Below is a list of FNC products that have been tested in FMXLinux.

With FMXLinux, we add a new platform to the wide variety of already supported platforms in FNC.

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

TMS FNC Components can be used simultaneously on these frameworks


TMS FNC Components can be used simultaneously on these operating systems/browsers


TMS FNC Controls can be used simultaneously on these IDEs


Getting Started

Beta support means that the components have been tested and deployed on a Linux environment (Ubuntu 20.04) after properly setting up FMXLinux and other dependencies required for various parts of FNC. Support for FMXLinux is limited to RAD Studio 10.4 Sydney and the path to the source files has to be manually configured in the library path (the automated installer currently does not pick up FMXLinux). Please follow the instructions below to add FMXLinux support to RAD Studio. Please note that adding the SDK is an essential part of the configuration process and it is important to add the SDK to RAD Studio when all the necessary libraries are added to your Linux environment.


After following the above instructions, please execute the following commands

sudo apt install joe wget p7zip-full curl openssh-server build-essential zlib1g-dev libcurl4-gnutls-dev libncurses5
sudo apt-get install zlib1g-dev
sudo apt install libgl1-mesa-glx libglu1-mesa libgtk-3-common libgstreamer1.0-0 libgstreamer-plugins-base1.0-0
sudo apt install libwebkit2gtk-4.0-dev

Add each path that contains FNC source files of the products you have installed to the Linux 64 bit library path.

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Start a new multi-device FMX project and select the Linux 64 bit profile.

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

When the PAServer is running correctly, you can connect to Linux environment and start deploying your application. 

Preview

We have created a short video to give you an idea on what you can expect when deploying new or existing FNC applications.


Feedback!

With this beta support for FMXLinux announcement we start a journey on a new and exciting road. Feedback during the beta period is highly appreciated. After a couple of updates, we'll announce full support and further fine-tune the installation process as well as provide more videos, documentation and demos.





High performance multi-feature grid

Intro

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
The multi-device, true native app platform The FireMonkey® framework is the app development and runtime platform behind RAD Studio, Delphi and C++Builder. FireMonkey is designed for teams building multi-device, true native apps for Windows, OS X, Android and iOS, and getting them to app stores and enterprises fast.
source: https://www.embarcadero.com/products/rad-studio/fm-application-platform

FMX (FireMonkey) released in 2011 and shortly after we delivered a first set of components. Today, we want to show you the TTMSFNCGrid component, a high performance multi-feature grid

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Features

Below is a list of the most important features the TTMSFNCGrid has to offer. The features are not limited to this list, but this will give you a quick insight on what we offer to be able to create an application that visualizes your data in a grid structure in FireMonkey.

  • Column Persistence
  • Fixed cell single and range selection
  • Autosizing columns / rows on double-click
  • Highly configurable and flexible grid
  • Various cell types available and built-in as well as support for custom cell types
  • Fixed columns left and/or right, fixed rows at top and/or bottom.
  • Column & row freezing
  • High performance virtual mode
  • Several selection modes: single & multi cell, column, row, distinct cell, row, column
  • Cells with support for HTML formatted text, hyperlinks
  • Editing with range of built-in editor types and capability of using custom cell inplace editors
  • Cell merging and splitting
  • Grouping support with summary rows, and group calculations such as average, sum, min, max, custom calculation...
  • Filtering with optional auto filtering via dropdown
  • Different cell layouts for different cell states
  • Read-only and/or fixed state per cell configurable
  • Single column sorting, indexed column sorting, grouped column & indexed column sorting
  • Pixel and cell scrolling modes
  • Keyboard and Mouse handling customization: tab, enter, insert, delete key handling
  • Column and row dragging and sizing
  • Cell controls such as checkbox, radiobutton, button, bitmap, progressbar etc...
  • Configurable touch scrolling optimized for iOS / Android
  • Banding
  • Clipboard support
  • HTML Export
  • PDF Export
  • Excel Import / Export via the TTMSFNCGridExcelIO
  • Find and replace functionality
  • Separate ToolBar Popup


Learn More!

Want to learn more about what the TTMSFNCGrid can do? Here is a video that highlights some of the above features through a demo application.




Download & Explore!

The TTMSFNCGrid component is part of the TMS FNC UI Pack, which, on top of FMX, also offers the ability to write your code once and target other frameworks (VCL, LCL and WEB). You can download a full featured trial version of the TMS FNC UI Pack and start exploring the capabilities of the TTMSFNCGrid component.

Stay tuned!

The TTMSFNCGrid is the fifth and last component of a series of components that is covered to empower your FMX (FireMonkey) developments. We started the series with a general overview of the most important components that we have to offer, followed by the TTMSFNCRichEditorTTMSFNCPlannerTTMSFNCTreeView and the TTMSFNCKanbanBoard. Keep an eye on our blog post for more exciting news coming up for the FMX framework and FNC in the form of a whole new platform!



Customer use case: bringing an FMX app to the web with TMS WEB Core

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

Introduction

In this blog article, we want to present you the story of Howard Sanderson from the company Star Analyzer. Howard converted in the past couple of months his cross-platform FireMonkey app to a TMS WEB Core powered web application and hereby eases the life of his customers tremendously.

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
 

Why and How I converted my Delphi FMX App to TMS WEB Core

After years of marketing a Delphi Windows/macOS version of my Star Analyzer program, I found that many clients wanted a web-based program which would run on any device, especially a tablet. They also wanted their data stored in the cloud so that several people could use the program at the same time. The macOS version produced by Delphi was often plagued with macOS incompatibilities, and neither version would run on a tablet. So I decided to take the leap to the web.

Should I use Delphi and TMS WEB Core or learn another programming language?

I looked at most of the current web programming languages, and took a short course on several of them. But because I’ve been using Delphi for 25 years I find that my brain is rather hooked on Delphi. In fact, I think that JavaScript and other web languages are totally incompatible with my brain. 

Another deciding factor was the library of 85 Object Pascal code files that I developed over the years for use with all my programs. I definitely did not want to rewrite my library from scratch. I am rather fond of it. My Star Analyzer program included another 100 Object Pascal code files which all use my library files.

Given the above conditions, I decided it would make sense to use TMS WEB Core to write my new web-based program in Object Pascal rather than to start from scratch in some other language. While there was a bit of a learning curve, the final program is  quite lovely I think. You can see Star Analyzer by going to my website, www.StarAnalyzer.com, scrolling down the page a bit, and clicking the "Run The Program" link.

Eight reasons I decided to use Delphi and TMS WEB Core

       Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

  1. I do not have to learn a new programming language. JavaScript and my brain are incompatible.
  2. I can reuse hundreds of library routines in Delphi.
  3. The new program can also look and act like a familiar Windows program for my customers.
  4. It runs on any web browser and almost any device.
  5. If you change the program, users have immediate access to the new code. You don’t have to send them emails or guide users through new install procedures.
  6. They do not have to fight anti-virus programs when installing program updates.
  7. They can run the program on multiple devices at the same time.
  8. Customer data is stored securely in the cloud and not lost when their computer dies.

Converting my existing code to TMS WEB Core

So far I have not needed to write a single line of JavaScript or HTML code, and about 80% my existing Delphi code works nicely with the WEB Core components. Some of 20% of new code I had to write was relatively straight forward, and some was a bit tricky. I’ll talk about the tricky parts a bit later in in this Blog.

Converting my existing FMX forms to TMS WEB Core

As we all know, the components on the forms talk to your code through their event handlers. Theoretically then all I would have to do is create new forms, drop FNC and WEB Core components on the new forms, and use hook them up to most of my existing code.  Not too much work, or so I thought, but it turns out it was not quite that simple.

If you look at Star Analyzer for the web you’ll see that it is built around tab controls. Click Data Entry and Data Analysis button and you’ll find there are 15 tab controls on the main form and 18 tab controls on the tabs on the main form. The original program was built around one large and complicated main form that held all the components for all 33 tabs, but the program worked nicely, and was easy to code and trouble shoot.

In converting my program to WEB Core, I first duplicated this tab structure using the TTMSFNCPageControl. The new layout looked just like the old layout, and was easy to work with in programming, but it would not compile. It turns out that you can’t compile a program with thousands of components and 33 tabs on one main form. It chokes the compiler.

Using Hosted Forms to reduce the complexity of browser pages

The solution was to use a TTMSFNCTabSet (which has no pages, just tabs) and to use a hosted form as shown in the TMSDemos\Web\Basics\Formhosting demo provide by TMS. The text and number of tabs on the main TabSet are changed in code, and the controls that used to be on the tabs are now on a Hosted Form.

In the image below the area outside the red box is the main form, while the area inside the red box shows one of the 23 different Hosted Forms. The advantage of Hosted Forms is that each web browser page has a small number of components and on it. 

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


This Case statement below shows how the hosted forms are called and created by the program.
  case SubFm of  // there are 23 hosted forms that I think of as SubForms
    sfProp     : MF.MainSubFm := TmfPropSubForm.CreateNew(MF.pnlMainHost.ElementID, @AfterSubFmCreate);
    sfFinBuy  : MF.MainSubFm := TmfFinBuySubForm.CreateNew(MF.pnlMainHost.ElementID, @AfterSubFmCreate);
    sfFinSell  : MF.MainSubFm := TmfFinSellSubForm.CreateNew(MF.pnlMainHost.ElementID, @AfterSubFmCreate);
   end;

Creating Pop-up Forms

In addition to the Hosted Forms mentioned above, every program needs pop-up forms as shown below. Forgive my wife and my cat in the images. This is just a demo after all. You can import photos and even take photos on your iPad with the TMS components. See the TMSDemos\Web\Basics\Multiform demo for details on creating pop-up forms. 

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Why I chose Google Firestore as my online database

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


My original Star Analyzer program used a local SQL database and the FMS FNC Cloud Pack to allow users to backup and restore their data to Dropbox so that they could use multiple computers, one at a time, with their data. This confused a lot of users. Not a good solution.

After spending many days looking at all the cloud databases available, and after playing with various TMS cloud data storage solutions, I ended up choosing the Google Firestore and the TMS WebFirestoreClientDataset as my cloud data storage solution. 

Without the TMS Firestore components I never would have chosen Firestore. If you go to https://firebase.google.com/
and begin reading the hundreds of pages of Firestore documents you may find it overwhelming as I did. Or perhaps not. But I wanted a relatively simple solution, and did not want to learn another programming language. I know that you can write Java Script routines that work with Firestore, but as I said, Java Script is incompatible with my mind.

Beyond ease of use, I was looking for an inexpensive cloud database solution. Look at https://firebase.google.com/pricing
you’ll see that Firestore is free at first, and then inexpensive as your needs increase. You can write 20,000 documents and read 50,000 documents per day for no charge, and after that it is only $0.06 per 100,000 reads. Given my customer database, and the fact that each customer will never have more than 100 documents in their database, I’ll probably never have to spend a penny on cloud storage.

Learning to use the TMS TWebFirestoreClientDataset

It is probably best to start by reading the TMS WEB Core PDF help file, which is well written and fairly comprehensive. Next you should look at the TMS Blog entries on Firestore. And finally, you can look at the Demos\Web\DBBackend\Firestore as a simple example to learn the basics. 

At first you may find the lack of SQL query capability in Firestore to be a bit disturbing, but you’ll find that there are ways around most of the limitations. One limitation of Firestore is that the maximum document size is 1 Meg, so if you are storing photographs you’ll need to shrink them a bit. And that brings me to my next topic, hints and tricks in using WEB Core.

TMS WEB Core Hints and Tips

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

As you work with TMS WEB Core you’ll find little tricks that are not emphasized in the documentation. Here are a couple that I’ve found useful.

Tip 1: Selecting and Resizing Images

There are two images controls that I use with WEB Core, the TTMSFNCImage and the WebImageControl. The TTMSFNCImage can show images in their proper Height and Width Ratio (which I like), while in the TWebImageControl the image always takes the shape of the control on the form (which I don’t like). 

However I can resize images with the TWebImageControl and not with the TTMSFNCImage. Since the Firestore database can’t handle images larger than 1 Meg, you must resize all images larger than that. The best way to see this is in a demo program, which you can download from www.StarAnalyzer.com/TMS/ImageSel.zip and you can view the demo from https://www.StarAnalyzer.com/TMS/ImageSelDemo.

If you click the button or the image on the main form, a pop-up Image Select Form is shown. See the TMSDemos\Web\Basics\Multiform demo for more information on pop-up forms.

On the image select form, you can select a JPG if you are on a computer, and you can even take a photo if you are in an iPad. The image select form uses both an FNCImage (to see the image in actual height/width ratio) and an TWebImageControl to allow me to shrink JPG’s that are larger than 1 Meg. The image resizing is done during the TWebImage OnLoaded event. 

Curiously, the length of the resized images depends on the physical size of the TWebImageControl on the page. See the code in the zip file for details. I spent days trying to find a useable image resizing routine that did not distort the height/width ratio, but finally gave up and resorted to the TWebImageControl resizing. If anyone has a nice resizing routine, I would appreciate a copy.

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Tip 2: Handling asynchronous behavior

I started writing the Star Analyzer for the web before the many async/await functions were introduced in TMS WEB Core and I'm eager to investigate and start using these. But well, when writing applications running applications in the browser, one cannot change the fact there are many asynchronous processes happening in the browser all for the sake of keeping the application at all times responsive. This is also the case in Star Analyzer when opening databases. Some delays occur when reading and writing to Firestore databases. In Star Analyzer we have to open three databases when the program starts up: Agents, Images, and Properties. This takes around seven seconds. This is how I handle the startup.

  1. Show the WaitMessage
  2. Call OpenServiceFilter for each database
  3. Start the WebTimer
  4. Wait for the WebTimer OnTimer event
  5. Check to see if all databases are open
  6. Keep looping with the timer until all are open
  7. Stop the WebTimer

The code will look something like this:

{----------------------------------------------}
procedure TMF.EnableWaitMsgAndStartupTimer;
{----------------------------------------------}
  procedure dbOpenDBSvcFilterStr(CDS: TWebFirestoreClientDataset;
                                 const FldName, Condition, Data: string);
  begin
    dbClose(CDS);
    CDS.ClearSortFieldDefs;
    CDS.ClearServiceFilters;
    CDS.AddServiceFilterCondition(FldName, Condition, Data);
    dbOpen(CDS);
  end; {dbOpenDBSvcFilterStr}

{--- EnableWaitMsgAndStartupTimer ---}
begin
  WaitMsg.Show;

  {--- agent ---}
  dbOpenDBSvcFilterStrEq(FAgent.CDS, xagAgentIDStr, cfv.SelectedAgentIDStr);

  {--- agent photo and logo ---}
  dbOpenDBSvcFilterStrEq(DM.imCDS, ximAgentIDStr, cfv.SelectedAgentIDStr);

  {--- agent properties ---}
  dbOpenDBSvcFilterStrEq(FProp.CDS, xprAgentIDStr, cfv.SelectedAgentIDStr);

  StartupTimer.Enabled := true;
end; 

We now loop while waiting for the three databases to all be open. Once all are open, we stop the timer, hide the wait message, and continue with the program.

{----------------------------------------------}
procedure TMF.mfStartupTimerUp(Sender: TObject);
begin
  //Note: DM.IsOpen uses the CDSAfterOpen event to set values true

  if not DM.IsOpen(Agents.CDS) then exit;
  if not DM.IsOpen(Images.CDS)   then exit;
  if not DM.IsOpen(Properties.CDS)  then exit;

  {--- stop timer and hide wait message ---}
  StartupTimer.Enabled := false;
  WaitMsg.Hide;

  //All datasets are open. Proceed with code
end; 

Conclusion

Well, that’s probably enough for now. Bottom line, my Star Analyzer program now runs perfectly in any web browser on most any device, my users don’t need to download and install program updates and fight antivirus programs, and their data is available from any computer they or their assistants wish to use. I’m happy. They are happy.

Feel free to contact me at Howard@StarAnalyzer.com if you have questions that I can answer, or hints to share with me about programming with TMS WEB Core. Or more, I'm also available for remote development services for your projects and can apply my expertise with TMS WEB Core for your developments. And again, it has been fun working with you! Thanks for all the time you’ve given me.

Your story here?

Did you develop equally exciting projects meanwhile with TMS WEB Core? Your fellow Delphi developers for sure will want to hear & learn from it! Be in touch and we can work on bringing your success story here.


Upcoming Miletus cross platform support

About 3 weeks ago we released TMS WEB Core v1.7 Ancona. One of the new features was Miletus, our new framework to create desktop applications with TMS WEB Core. It was exciting to see that many of you showed interest in Miletus, so we'll take a look at what you can expect in the future.

What's coming in TMS WEB Core 1.8

We launched Miletus with Windows 32-bit and 64-bit support, but our goal was already set from the beginning: a cross platform alternative that is based on TMS WEB Core. To make this possible, research work has already started before the TMS WEB Core v1.7 release. We are happy to share that as of today here in the labs, we can already target MacOS and Linux!

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Starting from TMS WEB Core 1.8 you'll be able to select the MacOS and Linux target. This will mean that you can create MacOS and Linux applications on Windows without an additional connection to the target systems! After the proper setup, you'll only need to copy your created application to the operating system of your choice. Keep in mind that for distribution it's recommended to sign your application and that can only be done on the target operating systems.

Why choose Miletus?

Miletus is not meant to be an Electron replacement, but rather something to co-exists next to our current Electron support as an alternative to those who want:
  • No NodeJS dependency
  • Smaller executable sizes
  • Less deployed files
  • More broad local database support
You can take full advantage of web technologies combined with native operating system level operations:

There's a lot of native functionality exposed already. Access to the local file system, operating system menus and notifications, drag and drop functionality, global shortcuts just to name a few. We are always looking to extend the native support based on your feedback! 

You don't necessarily need a DB backend running, you can easily connect to a local DB file or a cloud DB service just like in a VCL or FMX application! For cross platform targets, the following databases will be supported: SQLite, MSSQL, PostgreSQL, mySQL. This if of course only the beginning, we already have plans to expand the supported DB list!

The power of HTML5 and CSS3 is at your disposal. There are a huge amount of libraries and templates available for web applications that you can not only reuse in your Miletus application but with their help you can also create visually more pleasing user interfaces! 

And did you know? It's easy to migrate your existing TMS WEB Core application to Miletus. Watch this hands-on video from our colleague Dr. Holger Flick, who explains the process in detail:



After the TMS WEB Core v1.8 release the next step will be to bring Miletus to TMS WEB Core VSC too. We already did some further research in this area, and our results are promising to bring a truly cross platform experience!
But that's not the only long-term goal: based on the feedback we got, we'll also look to add more DB support! 

As mentioned earlier, we have full control over this technology which means we can extend the palette of components and functionalities without depending on 3rd party solutions while maintaining the advantages listed above. We are eager to learn what you'd like to see in future versions!


#WEBWONDERS : The browser console is your friend

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

When writing web client applications with TMS WEB Core, chances are you will be spending quite some time in the browser developer tools. This is the place where you can debug your web client applications and can inspect every detail of your web application: the DOM, source, network, performance, local storage, ... in a nutshell a wealth of useful information

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


One of the capabilities of the browser developer tools is the console and from your application you can add logging statements to output these in the browser console.

The closest comparison with the Windows desktop application development world is the OutputDebugString() command that sends text to a debugger. The direct equivalent is using console.log("Hello world") that will do exactly the same but to the browser console. But all similarities end here.

The console object that is fully available as Pascal class in a TMS WEB Core web client application has many more options. This object is described here: https://www.w3schools.com/jsref/obj_console.asp

Timing functions to measure performance


A first convenience of the console object is the ability to time certain parts of your code. You can do this by calling console.time('identifier') to start a browser timer and when the part of the code was executed, call console.timeEnd('identifier') and the browser will output the time difference in the browser console.

This example demonstrates the timing of a bubble sort algorithm (for the sake of having some code that takes some time to execute)

function BubbleSort( list: TStringList ): TStringList;
var
  i, j: Integer;
  temp: string;
begin
  // bubble sort
  for i := 0 to list.Count - 1 do begin
    for j := 0 to ( list.Count - 1 ) - i do begin
      if ( j + 1 = list.Count ) then
        continue;
      if ( list.Strings[j] > list.Strings[j+1] ) then begin
        temp              := list.Strings[j];
        list.Strings[j]   := list.Strings[j+1];
        list.Strings[j+1] := temp;
      end;
    end;
  end;
  Result := list;
end;

function GenerateRandomWord(CONST Len: Integer=16; StartWithVowel: Boolean= FALSE): string;
const
  sVowels: string = 'AEIOUY';
  sConson: string = 'BCDFGHJKLMNPQRSTVWXZ';
var
  i: Integer;
  B: Boolean;
begin
  B := StartWithVowel;
  SetLength(Result, Len);
  for i := 1 to len DO
   begin
    if B then
      Result[i] := sVowels[Random(Length(sVowels)) + 1]
    else
      Result[i] := sConson[Random(Length(sConson)) + 1];
    B:= not B;
   end;
end;

procedure TForm1.MeasureTime;
var
  sl: TStringList;
  i: integer;
  d: dword;
  mr: TMyRec;

begin
  console.time('bubble');
  sl := TStringList.Create;

  for i := 0 to 2000 do
  begin
    sl.Add(generaterandomword(8,false));
  end;

  BubbleSort(sl);

  console.timeEnd('bubble');

  sl.Free;
end;

The result in the browser console looks like:

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

Inspecting values of variables, records, objects

The console.log() call can have a variable number of arguments of different types. You can call for example:

console.log('Date today',DateToStr(Now));
and this will output today's date in the console.

But also objects or records will be shown with all their details in the console, as this example for a record demonstrates:

type
  TMyRec = record
    Name: string;
    Age: integer;
    Member: boolean;
  end;
var
  mr: TMyRec;

begin
  mr.Name := 'Delphi';
  mr.Age := 25;
  mr.Member := true;

  console.log(mr);
end;

Or take this example, where the details of a HTML element are displayed in the console, in this example the HTML element used for a TWebEdit: 

  console.log(WebEdit1.ElementHandle);

All these statements combined outputted in the browser console:

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Formatting output

If you thought the browser could only output dull fixed text, you are wrong! On top of that, the console.log() command allows you to use CSS specifiers to format text. By specifiying %c in the text parameter of a console.log() call, it will take the next parameter as a CSS style to apply to the text following the %c specifier.

This example should make this clear:

console.log('%cTMS %c WEB %c Core%c rocks!','color:red','background-color:green;color:white;font-weight:bold', 'font-weight: bold','""');
with the corresponding output in the browser console:
Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

Summary

The browser developer tools and in particular the console are tremendously helpful tools to assist in the development process. With TMS WEB Core (and also TMS WEB Core for Visual Studio Code) you can take fully advantage of it. Get started with developing web applications today, a wide range of helpful tools is more than ready for you!





What's new in TMS FNC Maps 1.5

We are back with another substantial update for TMS FNC Maps. 4 new components are introduced in TMS FNC Maps v1.5:

TTMSFNCStaticMap, TTMSFNCMapsImage, TTMSFNCTollCost and TTMSFNCTimeZone.


1. Static Maps & Map Image

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


The new TTMSFNCStaticMap component lets you request a static map image for a specific location. The static image can be customized by setting the map type (roads, satellite …), zoom level and an optional marker at the center point. The resulting image can be displayed by using the TTMSFNCMapsImage component.

The following mapping services are supported: Azure, Bing, Google, Here, MapBox, TomTom

Only a single line of code is needed to request and display a static map image:

TMSFNCMapsImage1.URL := TMSFNCStaticMap1.GetStaticMap(CenterCoordinate, 
    TMSFNCMapsImage1.Width, TMSFNCMapsImage1.Height, ZoomLevel, ShowMarkerBoolean, MapType);
   

2. Toll Cost calculation

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Using the TTMSFNCTollCost component the toll route costs between an origin and destination location can be calculated. Toll cost information is returned for each toll segment along the route together with turn by turn directions.

The following mapping services are supported: Here, PTV xServer

The toll cost calculation can be requested with just one line of code:

TMSFNCTollCost1.GetTollCost(OriginCoordinate, DestinationCoordinate);


3. TimeZone information


Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

The TTMSFNCTimeZone component can be used to request time zone information for a specified location.

The following mapping services are supported: Azure, Bing, Google, Here

Again a minimum of code is needed to request and display time zone information:


procedure TForm1.TMSFNCMaps1MapClick(Sender: TObject;
  AEventData: TTMSFNCMapsEventData);
begin
  TMSFNCTimeZone1.GetTimeZone(AEventData.Coordinate.toRec)
end;
procedure TForm1.TMSFNCTimeZone1GetTimeZone(Sender: TObject;
  const ARequest: TTMSFNCTimeZoneRequest;
  const ARequestResult: TTMSFNCCloudBaseRequestResult);
var
  it: TTMSFNCTimeZoneItem;
begin
  it := ARequest.Items[0];
  memo.Lines.Clear;
  memo.Lines.Add('TimeZone: ' + it.TimeZone);
  meTimeZone.Lines.Add(it.Description);
  meTimeZone.Lines.Add('Offset: ' + it.Offset);
  meTimeZone.Lines.Add('DST: ' + it.DSTOffset);
end;


4. Minor improvements

Apart from all the new components, some improvements are also included with this update.
One of the noteworthy improvements is the possibility to retrieve the index of the waypoints in the optimized order for TTMSFNCDirections.

The following mapping services are supported: Azure, Google Maps, TomTom

That's it for this TMS FNC Maps v1.5 update. I hope you'll enjoy all these exciting new features!


What's new in TMS FNC UI Pack 3.4

There are a lot of great new features available in our FNC components and this blog will highlight the new additions to the TMS FNC UI Pack. If you want to check the improvements on TMS FNC Maps, click here.

For the list of fixes and improvements, you can check the version history, but two new components were added to the product as well.

TTMSFNCPassLock

TTMSFNCPassLock is an updated version of the FMX passlock in the TMS FMX UI Pack.
This component gives you the ability to add password protection to your application. It's not only possible to further customize the buttons and pattern, but also the ability to not show the length of your password. Next to that you have the similar workings of the numpad and pattern layout and the learn mode to set a new password.
Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

TTMSFNCControlPicker

The TTMSFNCControlPicker helps you to create a dropdown variant of your control.

This can be done with the ITMSFNCControlPicker interface and is implemented by default in the TTMSFNCTreeView, TTMSFNCTableView, TTMSFNCListBox and TTMSFNCListEditor.

It is possible to implement the interface in your own control, for more information regarding the necessary procedures and functions to implement, please check the documentation.
Some additional events are available, to mimic the basic mechanics of the interface without implementing it and to make the control even more customizable.

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

This is an example of the base implementation to retrieve the content that should be shown in the dropdown edit. It shows the number of times the button was clicked.

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

First create a new extended button class:

type
  TButtonEx = class(TButton, ITMSFNCControlPickerBase)
  private
    FCount: Integer;
    function PickerGetContent: String;
  protected
    procedure Click; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;
 
{ ButtonEx }

procedure TButtonEx.Click;
begin
  inherited;
  Inc(FCount);

  if Assigned(Parent) and (Parent is TTMSFNCCustomSelector) and Assigned(Parent.Owner) and (Parent.Owner is TTMSFNCControlPicker)then
  begin
    //Update ControlPicker if assigned as control
    (Parent.Owner as TTMSFNCControlPicker).UpdateDropDown;
  end;
end;

constructor TButtonEx.Create(AOwner: TComponent);
begin
  inherited;
  FCount := 0;
  Text := 'Click this';
end;

function TButtonEx.PickerGetContent: String;
begin
  Result := IntToStr(FCount) + ' Clicks';
end;
The only thing left to do is creating the button and assiging it to a TTMSFNCControlPicker:

procedure TForm1.FormCreate(Sender: TObject);
begin
  b := TButtonEx.Create(Self);
  b.Parent := self;

  TMSFNCControlPicker.Control := b;
end;




Announcing support for FMXLinux!

Intro

A couple of weeks ago we announced beta support for FMXLinux and today we announce stable support. The beta period is finished and we now fully support FMXLinux in the latest version of all of our FNC products. Download the latest update today to get started! Below is a list of FNC products that have been tested in FMXLinux.

With FMXLinux, we add a new platform to the wide variety of already supported platforms in FNC.

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

TMS FNC Components can be used simultaneously on these frameworks


TMS FNC Components can be used simultaneously on these operating systems/browsers


TMS FNC Controls can be used simultaneously on these IDEs


Getting Started

The components have been tested and deployed on a Linux environment (Ubuntu 20.04) after properly setting up FMXLinux and other dependencies required for various parts of FNC. Support for FMXLinux is limited to RAD Studio 10.4 Sydney and the path to the source files has to be manually configured in the library path (the automated installer currently does not pick up FMXLinux). Please follow the instructions below to add FMXLinux support to RAD Studio. Please note that adding the SDK is an essential part of the configuration process and it is important to add the SDK to RAD Studio when all the necessary libraries are added to your Linux environment.


After following the above instructions, please execute the following commands

sudo apt install joe wget p7zip-full curl openssh-server build-essential zlib1g-dev libcurl4-gnutls-dev libncurses5
sudo apt-get install zlib1g-dev
sudo apt install libgl1-mesa-glx libglu1-mesa libgtk-3-common libgstreamer1.0-0 libgstreamer-plugins-base1.0-0
sudo apt install libwebkit2gtk-4.0-dev

Add each path that contains FNC source files of the products you have installed to the Linux 64 bit library path.

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Start a new multi-device FMX project and select the Linux 64 bit profile.

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

When the PAServer is running correctly, you can connect to Linux environment and start deploying your application. 

Video

The above instructions along with a showcase of some FNC components are demonstrated in the video below.



Stay tuned!

With FMXLinux support we add yet another major and exciting feature to the already huge amount of features and components FNC has to offer. Yesterday we also announced exciting new features and improvements in TMS FNC Maps 1.5 and TMS FNC UI Pack 3.4. Read the linked blog posts to find out more. Stay tuned for more FNC improvements and features coming up in the near future!.




Freebie Friday: TMS FNC Maps helper functions

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

We are back with another freebie friday!

TMS FNC Maps comes with a lot of great functionality as well as a (lesser visible) unit bundling helper functions to empower your developments. The unit is called (FMX.)TMSFNCMapsCommonTypes.pas. The prefix FMX., can be replaced with VCL., WEBLib. or LCL depending on the framework. Below are a couple of helper functions explained to help you in write your code more efficiently or add more complex functionality to your application.


Plus Codes

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Plus Codes are like street addresses for people or places that don’t have one. Instead of addresses with street names and numbers, Plus Codes are based on latitude and longitude, and displayed as numbers and letters. With a Plus Code, people can receive deliveries, access emergency and social services, or just help other people find them.
source: https://maps.google.com/pluscodes/

TMS FNC Maps supports Plus Codes encoding & decoding with the TTMSFNCMapsPlusCode class. To get started, and convert an existing coordinate to a Plus Code, use the following code:

procedure TForm1.EncodeCoordinate;
var
  p: string;
begin
  p := TTMSFNCMapsPlusCode.Encode(CreateCoordinate(40.689188, -74.044562));
  //p = '87G7MXQ4+M5'
end;
To decode a Plus Code to a coordinate bounds, which defines the area corresponding to the code, the Decode function can be used:

procedure TForm1.DecodePlusCode;
var
  c: TTMSFNCMapsBoundsRec;
begin
  c := TTMSFNCMapsPlusCode.Decode('87G7MXQ4+M5'); 
end; 


Measuring distance between 2 coordinates

Another great utility function is to measure the distance (in meters) between 2 coordinates. The distance measured is based on the average earth radius (6371000 meters). The sample below demonstrates how to measure the distance between 2 coordinates, but also how to create bounds, create a circle, calculate a new coordinate based on the bearing and many more.

procedure TForm1.AddCircle;
var
  b: TTMSFNCMapsBoundsRec;
  d, br: Double;
  c: TTMSFNCMapsCoordinateRec;
  I: Integer;
begin
  b := CreateBounds(40.76437, -73.94928, 40.76799, -73.98235);
  d := MeasureDistance(b.NorthEast, b.SouthWest);
  c := CalculateCoordinate(b.NorthEast, CalculateBearing(b.NorthEast, b.SouthWest), d);

  TMSFNCMaps1.BeginUpdate;

  with TMSFNCMaps1.AddCircle(b.NorthEast, Round(MeasureDistance(b.NorthEast, b.SouthWest) / 2)) do
  begin
    FillColor := gcRed;
    FillOpacity := 0.5;
    StrokeWidth := 10;
    StrokeColor := gcPink;
  end;

  TMSFNCMaps1.EndUpdate;
end;


Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components



#WEBINARS #WEBINARS #WEBINARS

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

Ever since we introduced our TMS WEB Academy platform (entirely built using our own TMS WEB Core product by the way) in February this year, it has been popular and much appreciated. Accelerated by the COVID19 pandemic, it is here to stay as a (free) way to learn about software development and directly communicate and interact with our experts during focused webinars. 

So, today, we announce 3 new free webinars coming up in June!


Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

Introduction to TMS WEB Core for Visual Studio Code

June 3, 15h00 UTC
You want to use your favorite Object Pascal language. You want to develop web client applications. You want to use an IDE directly on Windows or macOS or a Linux machine. You want to use RAD component based development methodology. Then we have this webinar for you where we introduce TMS WEB Core for Visual Studio Code. No prior knowledge or experience required, we will take you through the steps to create your first web client applications with this hugely popular free IDE and TMS WEB Core.

Sign up for the webinar here Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

Miletus : Using web technology to create cross-platform desktop applications

June 10, 15h00 UTC
You have customers who prefer a web application? You have customers who prefer a desktop application? You want to take advantage of web technology to create stunning user interfaces? You want an easy way to use local databases? With Miletus coming with TMS WEB Core, you can do it all. In this webinar, we show you what Miletus is, what you can use it for, how you can use it. Learn in just one hour webinar how to build a database powered, cross-platform desktop app with a good looking web front-end running on Windows, macOS or Linux.   

Sign up for the webinar here Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

What is FNC : Introduction to the growing family of FNC technology based components

June 17, 15h00 UTC
You heard about this yet another TLA (Three-Letter-Acronym) FNC but are unsure what it stands for and why and how you can benefit from it? In this webinar, we explain the basics of what FNC is, how it is created, what FNC components and products exist meanwhile. Whether you are a Delphi VCL classic Windows application developer, a Delphi FMX cross-platform developer, a developer wanting to create web applications or a developer preferring free IDEs like Lazarus or Visual Studio Code, FNC will empower you in any scenario. Learn all about this in this webinar and never forget anymore what the TLA FNC stands for.

Sign up for the webinar here Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

More webinars?

If you have ideas, let us know what you want to see covered in upcoming webinars! We are eager to learn where we can add value with content offered via a webinar. Or, if you created a great application or have an original or creative use case for any of our products and you feel like presenting this to your fellow Delphi developers, don't hesitate to reach out and you could be next offering a webinar on our TMS Web Academy.
Or meanwhile you can have a look at the previous webinars we offered and for which the recorded sessions are available.


TMS WEB Core for Visual Studio Code v1.3 released

Today is an exciting day as we reached yet another milestone, this time the release of TMS WEB Core for Visual Studio Code v1.3.

You are an Object Pascal expert, your customers look out to access your applications everywhere via the web and without any install hassle, you love the RAD component based development methodology, you can do this software development from the operating system you love ... then having a look at TMS WEB Core for Visual Studio Code v1.3 will open a whole new world!

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
 What brings TMS WEB Core for Visual Studio Code


  • Fully Object Pascal based web development
  • RAD component methodology driven fast & productive development 
  • Hosted in a free hugely popular IDE for web developers
  • Running on Windows, macOS and Linux
  • Using a WYSIWYG form designer
  • A framework that has a similarities with the familiar VCL framework where possible

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
 What is on the table in v1.3


This major update is packed with significant new features:

Support for packages
Yes, from now on, it is easy to create your own custom components and compile & install these for use at design-time. The package system is similar to how you can use packages to install components in the Delphi IDE or Lazarus

Support for workspaces
With workspaces, now you can have multiple projects in a folder and activate and select which project to compile/run/debug.

Support for using the entire FNC component suite
As our entire set of FNC components is ready for use in web client applications, the new package support in TMS WEB Core for Visual Studio Code enables to install all TMS FNC components in the TMS WEB Core for Visual Studio Code IDE. The latest FNC registered version updates released last week contain all the required packages for this.

Brings the framework up-to-date with latest version as available in TMS WEB Core for Delphi/Lazarus v1.7
The TMS WEB Core framework that comes with TMS WEB Core for Visual Studio Code is now in sync and up-to-date with the latest release of TMS WEB Core for Delphi. This means that all new components and component improvements are now also available for Visual Studio Code users. This includes the new USB components, local file access components, new Firestore dataset capabilities, extensions to grids, web socket connection improvements and much more...  One important note though, the Miletus application type is not yet in our release for Visual Studio Code release but scheduled for the next release.


Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
 Get started!


There are several ways to get started with TMS WEB Core for Visual Studio Code

  • TMS ALL-ACCESS users have immediate & free access to TMS WEB Core for Visual Studio Code
  • TMS WEB Core for Visual Studio Code registered users will find the new release now on your "My Products" page
  • A fully functional trial version for Windows, macOS or Linux is available
  • We have a webinar coming up that will guide you around the IDE, the framework, the possibilities
  • Check more details about FNC and using FNC components from Visual Studio code in this blog

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
 Learn how to use packages, write your own components or use FNC components

We have already two videos for you and more are coming.

Chief architect José Leon Serna explains how to start using packages:


José Leon Serna and Bruno Fierens host a webinar giving a sneak preview of v1.3


Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components
Get in touch

We have our Support Center to help you getting started, contact our sales team to assist in any licensing queries, our let us know what you think about TMS WEB Core for Visual Studio Code and in what direction you wish to see things being developed further! We are eager to hear your feedback and further shape the product to your needs & wishes!





Custom control development with TMS WEB Core for Visual Studio Code, an intern reports

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components

At tmssoftware.com we love to have interns. I believe it is a fantastic experience to learn young aspiring software developers about Delphi, its eco-system, its amazing productivity and at the same time, absorb a lot of energy, get new fresh ideas and get to know what drives and motivates the next generation of software developers.
So, also this school year, we had 2 interns learning all about Delphi, TMS WEB Core, Object Pascal, components and much more here at tmssoftware.com.
Today, we want to give the word to our intern, and very soon colleague, Bradley who did a lot of stunning work this school year and tells in his first blog post about building his first custom control for TMS WEB Core. Nothing but an amazing and exciting story! So, with pleasure, I give the word to Bradley:

A first custom web control

Having only one year experience using Delphi and TMS WEB Core, I was assigned the (at first sight) daunting task of developing my first ever custom web control, namely a chat box control. I had only been developing web applications since I joined tmssoftware.com as an intern, so clearly writing a component was something completely new. Using the available documentation and the experience of my mentor Bruno I quickly obtained the necessary skills for developing a TMS WEB Core custom control, the TWebChatBox control.
Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


First steps

To gain some experience, I first developed another very small control, a custom toggle button control to switch a web application between full-screen and normal mode. I went for developing the custom control directly from TMS WEB Core for Visual Studio Code because I just feel more comfortable for web projects to use this IDE. I had the "privilege" to use first the alpha and then the beta version of TMS WEB Core for Visual Studio Code v1.3 (released yesterday btw) as this introduced component package support. Using the new package support for installing custom controls made it very easy to test the control, also at design-time. The development of this first small control allowed me to get used to the concept of custom controls as well as the steps involved to get it installed in the IDE.

Starting the chatbox implementation

After I was comfortable enough with the principle of custom controls. I’ve started building the chat box component. As there were a ton of features on the requirements list, I had actually no idea where to start. I’ve focused first of all on a working way of sending/receiving messages. When I had that going, I started focusing on adding a basic design, followed up by adding the necessary properties for manipulating said chat box. 
I think implementing collections as a way of managing messages was the only thing I really struggled with. Having never implemented anything like this, figuring out how to implement the chat message bubbles at collection item level was a challenge. If you add a message to your collection, a chat message bubble will be generated and displayed in the chat control. The collection item will also keep a reference of the chat message bubble so that you can manipulate it later on.
A chat bubble contains several HTML elements. We have a SPAN for the message. For the user avatar there is an IMG element. And both the sender name and time are in P elements. The other elements are mostly used for positioning all the elements. The IMG element will not be shown when you choose to disable user images.

FChatMessage := TJSHTMLElement(document.createElement('SPAN'));
FMessageInfo := TJSHTMLElement(document.createElement('DIV'));
FTimeStamp := TJSHTMLElement(document.createElement('P'));
FChatSender := TJSHTMLElement(document.createElement('P'));
FImageArea := TJSHTMLElement(document.createElement('DIV'));
FMessageArea := TJSHTMLElement(document.createElement('DIV'));
FImage := TJSHTMLElement(document.createElement('IMG'));
These chat bubbles are, after being made, displayed on the chat display which is nothing more than a flexbox DIV. 
Underneath the chat display we have our input area. This area contains several elements like an input for the message, a send button and an emoji picker.
FArea := TJSHTMLElement(document.createElement('DIV'));
FInputDisplay := TJSHTMLElement(document.createElement('DIV'));
FInputTextBox := TJSHtmlElement(document.createElement('TEXTAREA'));
FSendButton := TJSHTMLElement(document.createElement('BUTTON'));
FInputDisplay.appendChild(FInputTextBox);
FArea.appendChild(FInputDisplay);
FArea.appendChild(FSendButton);
ElementHandle.appendChild(FArea);
FSendButton.addEventListener('click', @HandleSendMessageButtonClick);
FInputTextBox.addEventListener('keyup', @HandleSendMessageInputEnter);
There are 2 event listeners. You can press the send button for sending messages. But pressing enter will also send your message. When sending/receiving messages the chat box will auto scroll with all messages except if you scroll up.
Another feature that the chat box has, is an auto scroll. when you send a message the chat box will automatically scroll down as long as the user hasn’t scrolled up. To check if a user has scrolled up is nothing more than using this function:
function TChatBox.isScrolledToBottom: Boolean;
begin
  Result := (FChatDisplay.scrollHeight – 
FChatDisplay.clientHeight <= FChatDisplay.scrollTop + 1);
end;
To effectively scroll down you use this procedure:
procedure TChatBox.scrollToBottom;
begin
  FChatDisplay.scrollTop := FChatDisplay.scrollHeight;
end;
The Emoji Picker is an external JavaScript library. The emoji picker is added by instantiating the EmojiPicker class and then use the generateElements function and giving the input textbox as a parameter.    
 asm 
   (()=> {
     var picker = new EmojiPicker();
     picker.generateElements(element);
   })();
 end;
This library will add a dropdown button linked to your input textbox and will allow you to choose an emoji.

Image may be NSFW.
Clik here to view.
TMS Software Delphi  Components


Typing some of the mostly used emoji shortcuts in the textbox will also change to an emoji when sending the message. The same applies for hyperlinks that are converted into clickable links in the chat bubble.

Conclusion

While web custom controls appear like complex magic black boxes at first sight, after some effort to learn their architecture and how to build them mapping to HTML elements, it turns out to be actually relatively straight-forward and doable. The advantage of TMS WEB Core certainly is that the built-in controls all come with full source code, so this is also a great resource to learn from. Using the Visual Studio Code IDE made it easy to immediately see the result on the form designer. Overall, I’m happy with the result. The chatbox will be integrated in the TMS WEB Academy application and will also become standard part of TMS WEB Core. I look forward to develop many more exciting web custom controls for TMS WEB Core! 


Thank you

Thank you Bradley for a great collaboration during the internship. We look forward to go to the next level as a colleague in the tms family in July! The year went by fast and let's see who will take on the challenge to become an intern at tmssoftware.com in the next school year!  



Viewing all 1006 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>