Your familiar HotSpot Image comes to the TMS FNC UI Pack v3.3

We have a new major release of the TMS FNC UI Pack, next to some fixes and new features, we have added the TTTMSFNCHotSpotImage to the already extensive set of powerful and feature-rich UI controls that can be used cross framework and cross platform with just one code base.

TMS FNC Controls can be simultaneously used on these frameworks:

  • VCL
  • WEB
  • FMX
  • LCL

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

  •           

TMS FNC Controls can be simultaneously used on these IDE’s:

  •    

 

TTMSFNCHotSpotImage

This component is already known to VCL and FMX users and for the TMS WEB Core users who don’t know the component, you can compare it with the idea of an Image Map.

The TTMSFNCHotSpotImage (further referred to as ‘hotspotimage’) gives you the ability to choose one image and then add different areas (hotspots) with which you can interact and each of them can have their own appearance.

TTMSFNCHotSpotImageEditor

Our team considers the convenience of visually creating and configuring your components, that is why an editor was created to help you design your hotspots. This can be done in designtime by a double click or right-click on the hotspotimage. To give you full control over your hotspotimage, the editor is also available in runtime.

Hotspotimage Demo

To let you get more familiar with the component, we have created a demo application that you can find here.

This topic describes the steps we have taken to create such a demo application. It is a simple example of a selection game that shows a lot of features.
You’ll need to find the correct country for a given capital.

The TTMSFNCHotSpotImageEditor (further referred to as ‘hotspotimage editor’) can be used to create the hotspots of the different countries. All of the following can be done in the code as well. But to give an example of the possibilities, we will explain how to this visually.

The image can be added in the editor or with the Bitmap property.

On the top of the editor there is a toolbar that can be used to create or manipulate the poylgons.

Because there is a high contrast and the edgy shape of the different countries, the Magic Wand was the perfect tool to create the polygons.

In the panel on the right, you have the buttons ‘Hover’, ‘Selected’ and ‘Down’. With these buttons you can change the appearance for the different states.
If none of the hotspots are selected in the listbox, then you are able to change the default appearance used on newly created hotspots in the different pages.
On the other hand, if you select a hotspot, you can change the appearance for the specific hotspot.
This way, I’ve changed the Fill kind of the polygon to a texture with an image of the flag. You can also change the stroke and font used by the hotspot.

To change the name of the different hotspots, select the hotspot in the listbox, edit the text in the edit box and click on the ‘Change Name’ button.

Now let’s have a look at the code that is used. Besides the code used to change the settings between game mode and normal selection mode, only two specific events are needed.

The event OnSelectedHotSpotChange where the check is added to see if the selection is allowed.
As it would not be helpful to unselect a hotspot while playing the game.

procedure TForm2.TMSFNCHotSpotImage1SelectedHotSpotChange(Sender: TObject; AIndex: Integer; var Allow: Boolean);
begin
  if (AIndex >= 0) and not TMSFNCHotSpotImage1.HotSpots[AIndex].Selected then
    Allow := True
  else
    Allow := False;
end;

If it is allowed, then we can catch the change of the index with the event OnSelectedHotSpotChanged.

In this event we check if the name of the selected hotspot is the same as the one we were looking for.
if that is the case we add a point to our score and pick a new random country. If not, then the selected index is set back to false and if the answer was wrong for the second time, then we retrieve the hotspot by its name and and fill that one with a red color.

procedure TForm2.TMSFNCHotSpotImage1SelectedHotSpotChanged(Sender: TObject; AIndex: Integer);
var
  hsIdx: Integer;
begin
  if (length(countries) > 0) and Start then
  begin
    if TMSFNCHotSpotImage1.HotSpots[AIndex].Name = countries[idx] then
    begin
      Label2.Text := cities[idx] + ' is the capital of ' + countries[idx] + ' ('+ Point.ToString+')';
      Score := Score + Point;
      Label3.Text := Score.ToString + '/10';

      Delete(cities, idx, 1);
      Delete(countries, idx, 1);
      NextCapital;
    end
    else
    begin
      TMSFNCHotSpotImage1.HotSpots[AIndex].Selected := False;
      Point := Point - 0.5;

      if Point = 0 then
      begin
        hsIdx := TMSFNCHotSpotImage1.GetHotSpotIndexByName(countries[idx]);
        if hsIdx > -1 then
        begin
          TMSFNCHotSpotImage1.HotSpots[hsIdx].Appearance.SelectedFill.Color := gcTomato;
          TMSFNCHotSpotImage1.HotSpots[hsIdx].Selected := True;
        end;

        Label2.Text := cities[idx] + ' is not the capital of ' + TMSFNCHotSpotImage1.HotSpots[AIndex].Name + ' but ' + countries[idx] + ' (Next question)';

        Delete(cities, idx, 1);
        Delete(countries, idx, 1);

        NextCapital;
      end
      else
        Label2.Text := cities[idx] + ' is not the capital of ' + TMSFNCHotSpotImage1.HotSpots[AIndex].Name + ' ('+Point.ToString+')';
    end;
  end;
end;

The rest of the code can be found in the demo folder of the TMS FNC UI Pack.

This video of Gjalt’s 101 gives you a quick example on how the ‘Hover Bitmap’ property is used:


Read More

Read More

FireMonkey 3D – Sun, Earth and Moon

Following up on an earlier post, Simple FireMonkey 3D, I'm going to make a simplified model of the solar system to explore multiple 3D objects interacting with each other in a scene. I'll also play around a little with light sources. Source code for the project is available here and is compatible with the Delphi Community Edition. The project starts off like most of my 3D projects; A
Read More

Melbourne Meeting – March 2021

Monday 15 March at 6 for 6:15pm start. ONLINE MEETING – WE WILL NOT BE MEETING IN PERSON We will meet online, instead of meeting at the Shed. At this meeting, Grahame Grieve from Health Intersections will present his experiences converting from a FMX application to an LCL application that runs on Windows, Linux and OSX using Lazarus and discuss what bits have worked well, and what hasn’t.… Continue reading ›
Read More

Introducing FNC Grid Excel Bridge components

In the last weeks, we’ve been working on a component to allow you to import and export FNC Grids to the xlsx file format. We’ve also used the opportunity to rename the existing “Grid Filters” and “FMX Grid Filters” to “VCL Grid Excel Bridge” and “FNC Grid Excel Bridge” because the word “Filter” has a different meaning in a grid. We hope the new “Bridge” naming proves less ambiguous.

Same as the “Filters” before, the new Bridge components are free, but they require to have both TMS FNC UI Pack and TMS FlexCel licenses.

You can get the components here:

And the documentation is available here:

So what is the state now if you want to export or import a grid to/from Excel?  We have the following choices:

  1. (VCL Only) You can use StringGrid.SaveToXLS and StringGrid.LoadFromXLS. Those methods will use OLE Automation under the hood, and so they require that Excel is installed in the machine. Because they need Excel, they can only work on Windows.
  2. You can use TAdvGridExcelIO (VCL), TTMSFMXGridExcelIO (FMX) and TTMSFNCGridExcelIO (FNC). Those components use an older trimmed-down FlexCel 3 to do their job. Because they use FlexCel 3, which predates the XLSX file format, they can only work with XLS files, not XLSX.
  3. You can use the “TMS Grid Excel Bridge” components. Those components use an existing  FlexCel 7 to do the work, and so they can export to xls and xlsx, but also HTML and PDF.  Because they require a FlexCel license, they can access the full FlexCel behind it, to do extra customization. Just as an an example: You could add conditional formats to the generated files, as shown in the example here: https://doc.tmssoftware.com/grid-excel-bridge/fnc/guides/user-guide.html#customizing-the-export.



Note: FNCGrid already supports exporting to PDF and HTML natively, you don’t need the bridge components for that. But if you are customizing the xlsx output, you might want to have a PDF or HTML exported with those customizations, and that’s where the Bridge’s exporting to HTML and PDF can be useful.

Up to now, the “Bridges” had support for VCL Grids and FMX Grids. With the release of FNC Bridge, we are extending the first-class Excel exporting and importing to FNC.

Note that in FNC, we only support VCL and FMX at the moment (all platforms). We can’t support Lazarus or WebCore because FlexCel doesn’t support them yet.

So to finish this small post, I’d like to show how it works. We’ll try adding export support for the FNC Grid in the “ClientDataset” demo. This is the grid:

We dropped a TTMSFNCGridExcelExportComponent, and wrote the code:

TMSFNCGridExcelExport1.Export('r:\test.xlsx');

And we got this result:

The checkboxes work in Excel, they are not images. But they will be exported as images to HTML and PDF.

Next, we tried with HTML:

  TMSFNCGridExcelExport1.ExportHtml('r:\test.html', THtmlExportMode.SingleSheet);

And we got:

Finally we went for the PDF export. We could also have tried the one-liner, but in this case it would end up with 2 pages. The grid is too wide and the right part of it goes to the second page. But here is where the power of having full access to the FlexCel engine can help. We could export this file to xlsx, then set the print options in the xlsx file to fit to one page, and only then export to PDF:

    
  var xls := TXlsFile.Create(1, true);
  try
    TMSFNCGridExcelExport1.Export(xls);
    var Pdf := TFlexCelPdfExport.Create(xls, true);
    try
      xls.PrintToFit := true;
      xls.PrintNumberOfHorizontalPages := 1;
      xls.PageHeader := '&L FNC Grid Excel Export Demo&RPage &P of &N';
      Pdf.ExportAllVisibleSheets('r:\test.pdf', false, '');
    finally
      Pdf.Free;
    end;
  finally
    FreeAndNil(xls);
  end;

Just for fun, we also added a page header, and we could have customized the result a lot more. Like for example setting the PDF author or signing the PDF file.

Here is the PDF we got:

Read More

Read More

High performance tree list in FMX

Intro

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 TTMSFNCTreeView component, a component with high performance virtual and collection-based modes able to deal with millions of nodes.

Features

Below is a list of the most important features the TTMSFNCTreeView 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 a hierarchical tree list in FireMonkey.

  • Multi-line HTML formatted text
  • Various built-in column editors
  • Multi-column support
  • Fixed and variable node height
  • High performance virtual and collection-based modes
  • Multiple events for custom drawing and customization of default drawing
  • Multiple events for all kinds of interactions such as editing, expand / collapse and selection
  • Auto-sizing and stretching of columns
  • Mouse and keyboard interaction
  • Nodes with checkbox, radiobutton, image, disabled nodes
  • Nodes extending over multiple columns
  • Sorting, Filtering
  • Clipboard support
  • Keyboard lookup
  • Reordering
  • Drag & Drop

Learn More!

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

Download & Explore!

The TTMSFNCTreeView 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 TTMSFNCTreeView component.

Coming up

The TTMSFNCTreeView is the third 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 TTMSFNCRichEditor and the TTMSFNCPlanner. Next up will be the TTMSFNCKanbanBoard component, a highly configurable workflow visualization component.

Read More

Read More

Real-world Delphi projects out of this world…

How much of our daily life here on planet Earth is impacted by running Delphi code is beyond imagination. Whether it is controlling trains on the French railway system, contact tracing in the COVID19 pandemic in Poland, salary calculation and reporting in Germany, tax invoice approvals in Brazil,… the list is endless. But Delphi’s impact already reached out beyond planet Earth with several projects of the NASA and this week we stumbled on the social media post from Dave Akerman mentioning it was Delphi based software where several TMS components were involved, that was used to produce the sophisticated coating for the Perseverance parachute that was instrumental in its highly critical but eventually successful and safe landing on Mars on Feb 18:

As we chatted, I found out that David had a similar educational background as me in electronic engineering, also loves car racing, worked together with a very good friend of mine having a company Theys Industrial producing electronic PCB’s 2km away from here and I learned that the fabrics for the Perseverance parachute were produced by the company Picanol that is like 20km driving from where the TMS headquarters are. Talking about coincidences…
Well, that was enough a reason to get in touch with David and have a chat about our passion we all share: software development with Delphi! Our colleague Holger Flick produced this video interview with David, where David tells exciting stories of how he got into software development, how he used Delphi for controlling machines precisely mixing chemicals, how he also uses Delphi for his hobby of tracking weather measurement balloons (where TMS WEB Core plays a role in), how he uses the FireMonkey framework for writing software for a Sony watch and so much more…

I’m sure you will enjoy this video interview between two passionate Delphi software developers and be inspired to also do cool things with Delphi!

Read More

Read More

Real-world Delphi projects out of this world…

How much of our daily life here on planet Earth is impacted by running Delphi code is beyond imagination. Whether it is controlling trains on the French railway system, contact tracing in the COVID19 pandemic in Poland, salary calculation and reporting in Germany, tax invoice approvals in Brazil,… the list is endless. But Delphi’s impact already reached out beyond planet Earth with several projects of the NASA and this week we stumbled on the social media post from Dave Akerman mentioning it was Delphi based software where several TMS components were involved, that was used to produce the sophisticated coating for the Perseverance parachute that was instrumental in its highly critical but eventually successful and safe landing on Mars on Feb 18:

As we chatted, I found out that David had a similar educational background as me in electronic engineering, also loves car racing, worked together with a very good friend of mine having a company Theys Industrial producing electronic PCB’s 2km away from here and I learned that the fabrics for the Perseverance parachute were produced by the company Picanol that is like 20km driving from where the TMS headquarters are. Talking about coincidences…
Well, that was enough a reason to get in touch with David and have a chat about our passion we all share: software development with Delphi! Our colleague Holger Flick produced this video interview with David, where David tells exciting stories of how he got into software development, how he used Delphi for controlling machines precisely mixing chemicals, how he also uses Delphi for his hobby of tracking weather measurement balloons (where TMS WEB Core plays a role in), how he uses the FireMonkey framework for writing software for a Sony watch and so much more…

I’m sure you will enjoy this video interview between two passionate Delphi software developers and be inspired to also do cool things with Delphi!

Read More

Read More

Firemonkey Particles

We see images with connected points used a lot in diagrams, illustrations, advertising and just cool abstract art. They visually represent networks of related things and ideas or connectivity. The web, for example. It's effective and visually appealing and when the effect is animated, it's mesmerising. And popular. There are any number of animated backgrounds and JavaScript libraries to add
Read More

GraphQL, workflow engine, multitenancy and more: what you will do with Delphi in 2021

Here at TMS, we are working on so much new exciting frameworks and features that I decided to share with you what we expect to bring to you in 2021!


Photo by Rhett Wesley on Unsplash

First, a disclaimer: this is not an official commitment. Some of the things listed here might be delayed or not be released at all. But of course, that’s not our intention, since we are listing it here. We want to (and probably will) release all of this in 2021. But, since unexpected things might happen, we can never guarantee what will happen in future. One second thing: thislist only covers what is coming around TMS Business line of products. There is much more to come from TMS in 2021!

I was going to title this post as “TMS Business Roadmap for 2021”. But I thought that the current title brings more attention and curiosity. And it looks like it worked, thanks for coming! ??

Ok, jokes aside, another reason is that we still don’t know if all of the libraries, features and technologies listed here will be part of the TMS Business bundle, and the original title could be misleading.

But regardless, everything listed here will for sure be smoothly integrated with TMS Business – either using ORM (TMS Aurelius) or REST/JSON framework (TMS XData), or any other core product, what is for sure is that everything listed here makes up a huge ecosystem around TMS Business technologies.

An exciting year is coming ahead! So, without further ado, this is what we expect to bring to Delphi world this year, with TMS Business.

GraphQL

TMS is bringing GraphQL to Delphi! We have it already in a beta state, the core is complete, all is going fine. We still need to document everything, and add a few more features here and there, but it’s in a very advanced stage.

This teaser video shows GraphQL server in action, written in Delphi! The frontend is GraphQL Playground JS framework, but still being served via a Delphi server.

The relevant parts of the code used to build the server in the video are the following. First, the GraphQL schema is built:

SchemaDocument := TGraphQLDocumentParser.ParseSchema(
    'type Query { hello(name: String!): String }');
  Schema := TGraphQLSchemaBuilder.Build(SchemaDocument);

  Schema.SetResolver('Query', 'hello', function(Args: TFieldResolverArgs): TValue
    begin
      Result := 'Hello, ' + Args.GetArgument('name').AsString;
    end
  );

Then, the endpoints for the GraphQL API and the GraphQL Playground are created:

  ADispatcher.AddModule(
    TGraphQLServerModule.Create('http://+:2001/tms/graphql', FSchema));

  ADispatcher.AddModule(
    TGraphQLPlaygroundModule.Create('http://+:2001/tms/playground', '/tms/graphql'));

And that’s it for the “Hello, world” demo!

TMS Auth

A complete framework for adding authentication to your application, with user, roles and permissions management and providing features like login, registration, e-mail confirmation and more.

Relying on Aurelius ORM and XData REST framework, with a few lines of code you will get all your database setup and have an authentication API server running, with lots of features.

Well, it’s said one picture is worth a thousand words, so here is an example of the available API out of box:

And these are screenshots of an existing app built with TMS Web Core which is already using TMS Auth for user registration and login:

It will never been as easy to add user and permissions management and login system to your Delphi application and server!

BPM Workflow

A full workflow engine is coming. You might ask what is the difference between this new library and TMS Workflow Studio.

It’s a night and day difference. TMS Workflow Studio is nice product, but it was made 13 years ago with a different goal in mind – desktop VCL applications – and when lots of technologies didn’t even exist, and even several TMS products. Cross-platform, REST servers, ORM, cloud applications.

This new project is a workflow engine written from scratch, with all modern technologies and paradigms in mind. It will have a REST API, it will be cross-database, thread-safe, scalable, and of course will have lots of new features.

The following workflow, for example:

Can be built from code this way:

RenewalProcess := TProcessBuilder.CreateProcess
    .Variable('process_id')
    .StartEvent
    .Condition(GroupedCondition([
      TRenewalAllowedCondition.Create,
      SubscriptionNotInAnyProcess
    ]))
    .Activity(SetProcessStatus(TProcessStatus.processing))
    .Activity(IssueInvoice)
    .ExclusiveGateway.Id('gateway1')
      .Condition(THasErrorCondition.Create)
      .Activity(TRenewalFailureActivity.Create).Id('renewal_failure')
      .Activity(SetProcessStatus(TProcessStatus.failed))
      .EndEvent
    .GotoElement('gateway1')
      .Condition(InvoiceIsPaid)
      .Activity(RenewSubscription).Id('renew_subscription')
      .ExclusiveGateway.Id('gateway4')
        .Condition(THasErrorCondition.Create)
        .LinkTo('renewal_failure')
      .GotoElement('gateway4')
        .Activity(TRenewalSuccessActivity).Id('renewal_success')
        .Activity(SetProcessStatus(TProcessStatus.succeeded))
        .EndEvent
    .GotoElement('gateway1')
      .Condition(InvoiceIsOpen)
      .Activity(ChargePayment).Id('charge_payment')
      .Activity(GetPaymentStatus).Id('get_payment_status')
      .ExclusiveGateway.Id('gateway2')
        .Condition(THasErrorCondition.Create)
        .LinkTo('renewal_failure')
      .GotoElement('gateway2')
        .Condition(GroupedCondition(
          TConditionOperator._or, [PaymentIsCanceled, PaymentIsFailed]))
        .LinkTo('renewal_failure')
      .GotoElement('gateway2')
        .Condition(PaymentIsSucceeded)
        .ExclusiveGateway.Id('gateway3')
          .Condition(InvoiceIsPaid)
          .LinkTo('renew_subscription')
        .GotoElement('gateway3')
          .Condition(InvoiceIsOpen)
          .LinkTo('charge_payment')
    .Done;
end;

And can be executed in a thread queue, can be instantiated using a REST API, and many more to come. Actually, you can follow what is being developed so far in its GitHub repository. We are still working on it of course, in both features and licensing terms.

REST Server Authorization

TMS XData, our amazing library for building REST APIs and multitier applications, will have an authorization mechanism that will be very easy to use.

Developers will be able to just add authorization attributes to methods (service operations) or entities (automatic CRUD endpoints) and everything will be applied accordingly. Fine-tuning the protection of your REST API will never be as simple.

  [Authorize]
  IDocumentService = interface(IInvokable)
    procedure Insert(Value: TDoc);

    [AuthorizeScopes('user, editor')]
    procedure Modify(Value: TDoc);

    [AuthorizeScopes('admin')]
    procedure Delete(DocId: string);

    [AuthorizeClaims('email')]
    procedure Approve(DocId: string);
  end;

In the example above, all methods (endpoints) require authentication, because the interface has an Authorize attribute that propagates to all methods. So, to invoke Insert, user must be authenticated. Still, to invoke Modify, the user must be authenticated and have either user or editor scope in its credentials. He must be admin to invoke Delete, and finally to approve a document, user must have an email in its claims.

It’s also worth noting that the same strategy applies to entities that generate automatic CRUD endpoints:

  [Entity, Automapping]
  [EntityAuthorize]
  [EntityAuthorizeScopes('editor', [TEntitySetPermission.Modify, TEntitySetPermission.Insert])]
  [EntityAuthorizeScopes('admin', [TEntitySetPermission.Delete])]
  TCustomer = class
  {...}
  public
    property Id: Integer read FId write FId;
    property Name: string read FName write FName;
  end;

To access customer endpoints, user must be authenticated. But he must have editor privileges to modify and insert (PUT and POST) and must be admin to invoke DELETE. Easy and straightforward.

Development for the web: even easier

TMS XData is smoothly integrated with TMS Web Core, the TMS framework to build web applications. It provides easy-to-use, high-level client classes to access XData servers from Web Core applications. With the amazing release of TMS Web Core 1.6, several language features were introduced, like generics, async/await, attributes, among others.

This will make TMS XData client objects easier than ever to be used in web applications. The experience will be pretty similar to VCL/FMX applications, like retrieving entity objects from the server without having to deal with JSON directly and invoking endpoints using interfaces without having to worry about HTTP methods or URL endpoints.

And even more, async/await can be used. As an example, invoking a XData REST API endpoint asynchronously will be as easy as doing this:

PendingOrders := await(XClient.List<TOrder>('$filter=Status eq pending'));
if PendingOrders.Count = 0 then
  Exit; // no pending orders to process

The single line above will build the HTTP request with proper URL endpoint and HTTP method, invoke it, deserialize the returned JSON into a list of TOrder objects, and all asynchronously! The await function will guarantee that the next line will be executed only after the async execution is executed. Can’t get easier than that.

Global filters and multitenancy

Our state-of-art ORM for Delphi, TMS Aurelius, will have amazing additions this year. One of them is the global filter mechanism. Users will be able to define filters globally, including parameters, and choose which entities will have it applied.

While global filters can obviously be used for any purpose, using it to build multitenant applications is the first one that comes to mind. Consider the following entity class mapped with filtering attributes:

  [Entity, Automapping]
  [Filter('Multitenant')]
  [FilterDef('Multitenant', '{TenantId} = :tenantId')]
  [FilterDefParam('Multitenant', 'tenantId', TypeInfo(string))]
  TProduct = class
  private
    FId: Integer;
    FName: string;
    FTenantId: string;
  public
    property Id: Integer read FId write FId;
    property Name: string read FName write FName;
    property TenantId: string read FTenantId write FTenantId;
  end;

You can use the class normally, without any filter. But you can also enable the “Multitenant” filter like this:

  Manager.EnableFilter('Multitenant')
    .SetParam('tenantId', 'acme');
  Products := Manager.Find<TProduct>.OrderBy('Name').List;

After you’ve enabled the “Multitenant” filter passing the proper id, you can use the Aurelius object manager as usual. But any request you do, like in the example, asking a list of products, will add the tenant filter.

Aurelius will not only allow global filters for queries, but also will allow you to enforce the filter in INSERT, UPDATE and DELETE operations:

  FEnforcer := TFilterEnforcer.Create('Multitenant', 'TenantId', 'FTenantId');
  FEnforcer.AutoComplyOnInsert := True;
  FEnforcer.AutoComplyOnUpdate := True;
  FEnforcer.Activate(TMappingExplorer.Get('Samples'));

Thus, you can simply create or modify a product as you would usually do in single tenant application, but the filter enforcer will make sure to set data to the proper tenant id (or raise an error if the tenant is wrong, depending on your configuration).

Building single-database multitenant applications with TMS Aurelius is already possible, of course. But it will be really easy with the upcoming features. And not only that: building multi-database multitenant applications will also be easy with the new TMultiTenantConnectionPool:

  FMultiPool := TMultiTenantConnectionPool.Create(
    TXDataHttpHeaderTenantResolver.Create('tenant-id'),
    TDBConnectionPoolFactory.Create
    );

The pool will automatically choose the correct database based on the HTTP header tenant-id – or any other criteria you might choose. All transparently.

In summary: you will be able to build your app as if you are coding for single tenant applications, and let Aurelius do everything under the hood to make it multitenant, with minimum effort and in a robust and reliable way.

Data validation

Another great feature coming is data validation. Again, you can already do it using events, but soon it will be orders of magnitude easier. You will be able to add validators to your entities in several ways, attributes being the most common (irrelevant parts of the following class declaration removed for clarity):

  TCustomer = class
  private
    [Required]
    FName: string;
    
    [EmailAddress]
    FEmail: string;
  
    [DisplayName('class rate')]
    [Range(1, 10, 'Values must be %1:d up to %2:d for field %0:s')]
    FInternal_Rate: Integer;

All fields will be proper validated according to the validation attributes applied. Name will be required, Email must be a valid address and FInternal_Rate value must be between 1 and 10. With a few lines you will guarantee that the entity will be persisted with a valid state.

Validation will also help you with your API and GUI. Note how you can provide readable display names and error messages. When using validation in your API build with XData, the API responses will be detailed and informative, and all automatically:

And, of course, you can benefit from such information to easily build nice user interfaces informing the user about the validation results. The following screenshot is the same one used for the TMS Auth example above, but displaying results for password validation:

Attribute-based event handlers

Events are an important feature of any framework, and with Aurelius is not different. It provides several events you can use to add custom business logic. You can add specific code just before an entity is being saved, after an entity is deleted, when an SQL is being executed, among others.

The interesting feature coming is that you will now be able to add event handlers directly in your classes, using attributes. This will make your code even more organized, will improve readability and allow you to better follow the single-responsibility principle. It will be as simple as this:

TCustomer = class
  [OnInserting]
  procedure DoSomethingBeforeSave;

  [OnDelete]
  procedure DoSomethingAfterDelete;

Whenever a customer entity is about to be persisted, OnInserting method will be called and you can add any relevant code in that method. You can receive arguments in OnInserting, or you can even use with without them, like in the example above, making you class really independent of 3rd party custom types.

And more events are coming as well, for example, the new data validation mechanism mentioned above will also offer you an OnValidate event, which you can easily use like this:

TCustomer = 
  [OnValidate]
  function CheckBirthday: IValidationResult;

{...}  

  function TCustomer.CheckBirthday: IValidationResult;
  begin
    Result := TValidationResult.Create;

    if YearOf(Birthday) < 1899 then
      Result.Errors.Add(TValidationError
        .Create('A person born in the XIX century is not accepted'));

    if (MonthOf(Birthday) = 8) and (DayOf(Birthday) = 13) then
      Result.Errors.Add(TValidationError
        .Create('A person born on August, 13th is not accepted'));
  end;

That’s all…?

I hope you have followed me until here, and I hope you are as excited as us with the upcoming features and and libraries. Yes, that’s a lot of things to expect for Delphi and TMS Business in 2021! But I’d like to stress that what’s coming is not necessarily limited to what we put here. There might be even more! (Things we cannot disclose right now).

Did you like the news? Please comment below, let us know what you think and what are your opinions and expectations on this. And don’t forget to subscribe to our news channels to be informed when things are released and for many other exciting news from TMS: subscribe to our e-mail newsletter, follow our Facebook page and subscribe to our YouTube channel!

Update: Want to see these listed features in action? Register for the free webinar “What is coming in TMS BIZ in 2021”, to happen on Tuesday, February 23, 2021 3:00:00 PM UTC at the TMS Web Academy!

Read More

Read More

GraphQL, workflow engine, multitenancy and more: what you will do with Delphi in 2021

Here at TMS, we are working on so much new exciting frameworks and features that I decided to share with you what we expect to bring to you in 2021!


Photo by Rhett Wesley on Unsplash

First, a disclaimer: this is not an official commitment. Some of the things listed here might be delayed or not be released at all. But of course, that’s not our intention, since we are listing it here. We want to (and probably will) release all of this in 2021. But, since unexpected things might happen, we can never guarantee what will happen in future. One second thing: thislist only covers what is coming around TMS Business line of products. There is much more to come from TMS in 2021!

I was going to title this post as “TMS Business Roadmap for 2021”. But I thought that the current title brings more attention and curiosity. And it looks like it worked, thanks for coming! ??

Ok, jokes aside, another reason is that we still don’t know if all of the libraries, features and technologies listed here will be part of the TMS Business bundle, and the original title could be misleading.

But regardless, everything listed here will for sure be smoothly integrated with TMS Business – either using ORM (TMS Aurelius) or REST/JSON framework (TMS XData), or any other core product, what is for sure is that everything listed here makes up a huge ecosystem around TMS Business technologies.

An exciting year is coming ahead! So, without further ado, this is what we expect to bring to Delphi world this year, with TMS Business.

GraphQL

TMS is bringing GraphQL to Delphi! We have it already in a beta state, the core is complete, all is going fine. We still need to document everything, and add a few more features here and there, but it’s in a very advanced stage.

This teaser video shows GraphQL server in action, written in Delphi! The frontend is GraphQL Playground JS framework, but still being served via a Delphi server.

The relevant parts of the code used to build the server in the video are the following. First, the GraphQL schema is built:

SchemaDocument := TGraphQLDocumentParser.ParseSchema(
    'type Query { hello(name: String!): String }');
  Schema := TGraphQLSchemaBuilder.Build(SchemaDocument);

  Schema.SetResolver('Query', 'hello', function(Args: TFieldResolverArgs): TValue
    begin
      Result := 'Hello, ' + Args.GetArgument('name').AsString;
    end
  );

Then, the endpoints for the GraphQL API and the GraphQL Playground are created:

  ADispatcher.AddModule(
    TGraphQLServerModule.Create('http://+:2001/tms/graphql', FSchema));

  ADispatcher.AddModule(
    TGraphQLPlaygroundModule.Create('http://+:2001/tms/playground', '/tms/graphql'));

And that’s it for the “Hello, world” demo!

TMS Auth

A complete framework for adding authentication to your application, with user, roles and permissions management and providing features like login, registration, e-mail confirmation and more.

Relying on Aurelius ORM and XData REST framework, with a few lines of code you will get all your database setup and have an authentication API server running, with lots of features.

Well, it’s said one picture is worth a thousand words, so here is an example of the available API out of box:

And these are screenshots of an existing app built with TMS Web Core which is already using TMS Auth for user registration and login:

It will never been as easy to add user and permissions management and login system to your Delphi application and server!

BPM Workflow

A full workflow engine is coming. You might ask what is the difference between this new library and TMS Workflow Studio.

It’s a night and day difference. TMS Workflow Studio is nice product, but it was made 13 years ago with a different goal in mind – desktop VCL applications – and when lots of technologies didn’t even exist, and even several TMS products. Cross-platform, REST servers, ORM, cloud applications.

This new project is a workflow engine written from scratch, with all modern technologies and paradigms in mind. It will have a REST API, it will be cross-database, thread-safe, scalable, and of course will have lots of new features.

The following workflow, for example:

Can be built from code this way:

RenewalProcess := TProcessBuilder.CreateProcess
    .Variable('process_id')
    .StartEvent
    .Condition(GroupedCondition([
      TRenewalAllowedCondition.Create,
      SubscriptionNotInAnyProcess
    ]))
    .Activity(SetProcessStatus(TProcessStatus.processing))
    .Activity(IssueInvoice)
    .ExclusiveGateway.Id('gateway1')
      .Condition(THasErrorCondition.Create)
      .Activity(TRenewalFailureActivity.Create).Id('renewal_failure')
      .Activity(SetProcessStatus(TProcessStatus.failed))
      .EndEvent
    .GotoElement('gateway1')
      .Condition(InvoiceIsPaid)
      .Activity(RenewSubscription).Id('renew_subscription')
      .ExclusiveGateway.Id('gateway4')
        .Condition(THasErrorCondition.Create)
        .LinkTo('renewal_failure')
      .GotoElement('gateway4')
        .Activity(TRenewalSuccessActivity).Id('renewal_success')
        .Activity(SetProcessStatus(TProcessStatus.succeeded))
        .EndEvent
    .GotoElement('gateway1')
      .Condition(InvoiceIsOpen)
      .Activity(ChargePayment).Id('charge_payment')
      .Activity(GetPaymentStatus).Id('get_payment_status')
      .ExclusiveGateway.Id('gateway2')
        .Condition(THasErrorCondition.Create)
        .LinkTo('renewal_failure')
      .GotoElement('gateway2')
        .Condition(GroupedCondition(
          TConditionOperator._or, [PaymentIsCanceled, PaymentIsFailed]))
        .LinkTo('renewal_failure')
      .GotoElement('gateway2')
        .Condition(PaymentIsSucceeded)
        .ExclusiveGateway.Id('gateway3')
          .Condition(InvoiceIsPaid)
          .LinkTo('renew_subscription')
        .GotoElement('gateway3')
          .Condition(InvoiceIsOpen)
          .LinkTo('charge_payment')
    .Done;
end;

And can be executed in a thread queue, can be instantiated using a REST API, and many more to come. Actually, you can follow what is being developed so far in its GitHub repository. We are still working on it of course, in both features and licensing terms.

REST Server Authorization

TMS XData, our amazing library for building REST APIs and multitier applications, will have an authorization mechanism that will be very easy to use.

Developers will be able to just add authorization attributes to methods (service operations) or entities (automatic CRUD endpoints) and everything will be applied accordingly. Fine-tuning the protection of your REST API will never be as simple.

  [Authorize]
  IDocumentService = interface(IInvokable)
    procedure Insert(Value: TDoc);

    [AuthorizeScopes('user, editor')]
    procedure Modify(Value: TDoc);

    [AuthorizeScopes('admin')]
    procedure Delete(DocId: string);

    [AuthorizeClaims('email')]
    procedure Approve(DocId: string);
  end;

In the example above, all methods (endpoints) require authentication, because the interface has an Authorize attribute that propagates to all methods. So, to invoke Insert, user must be authenticated. Still, to invoke Modify, the user must be authenticated and have either user or editor scope in its credentials. He must be admin to invoke Delete, and finally to approve a document, user must have an email in its claims.

It’s also worth noting that the same strategy applies to entities that generate automatic CRUD endpoints:

  [Entity, Automapping]
  [EntityAuthorize]
  [EntityAuthorizeScopes('editor', [TEntitySetPermission.Modify, TEntitySetPermission.Insert])]
  [EntityAuthorizeScopes('admin', [TEntitySetPermission.Delete])]
  TCustomer = class
  {...}
  public
    property Id: Integer read FId write FId;
    property Name: string read FName write FName;
  end;

To access customer endpoints, user must be authenticated. But he must have editor privileges to modify and insert (PUT and POST) and must be admin to invoke DELETE. Easy and straightforward.

Development for the web: even easier

TMS XData is smoothly integrated with TMS Web Core, the TMS framework to build web applications. It provides easy-to-use, high-level client classes to access XData servers from Web Core applications. With the amazing release of TMS Web Core 1.6, several language features were introduced, like generics, async/await, attributes, among others.

This will make TMS XData client objects easier than ever to be used in web applications. The experience will be pretty similar to VCL/FMX applications, like retrieving entity objects from the server without having to deal with JSON directly and invoking endpoints using interfaces without having to worry about HTTP methods or URL endpoints.

And even more, async/await can be used. As an example, invoking a XData REST API endpoint asynchronously will be as easy as doing this:

PendingOrders := await(XClient.List<TOrder>('$filter=Status eq pending'));
if PendingOrders.Count = 0 then
  Exit; // no pending orders to process

The single line above will build the HTTP request with proper URL endpoint and HTTP method, invoke it, deserialize the returned JSON into a list of TOrder objects, and all asynchronously! The await function will guarantee that the next line will be executed only after the async execution is executed. Can’t get easier than that.

Global filters and multitenancy

Our state-of-art ORM for Delphi, TMS Aurelius, will have amazing additions this year. One of them is the global filter mechanism. Users will be able to define filters globally, including parameters, and choose which entities will have it applied.

While global filters can obviously be used for any purpose, using it to build multitenant applications is the first one that comes to mind. Consider the following entity class mapped with filtering attributes:

  [Entity, Automapping]
  [Filter('Multitenant')]
  [FilterDef('Multitenant', '{TenantId} = :tenantId')]
  [FilterDefParam('Multitenant', 'tenantId', TypeInfo(string))]
  TProduct = class
  private
    FId: Integer;
    FName: string;
    FTenantId: string;
  public
    property Id: Integer read FId write FId;
    property Name: string read FName write FName;
    property TenantId: string read FTenantId write FTenantId;
  end;

You can use the class normally, without any filter. But you can also enable the “Multitenant” filter like this:

  Manager.EnableFilter('Multitenant')
    .SetParam('tenantId', 'acme');
  Products := Manager.Find<TProduct>.OrderBy('Name').List;

After you’ve enabled the “Multitenant” filter passing the proper id, you can use the Aurelius object manager as usual. But any request you do, like in the example, asking a list of products, will add the tenant filter.

Aurelius will not only allow global filters for queries, but also will allow you to enforce the filter in INSERT, UPDATE and DELETE operations:

  FEnforcer := TFilterEnforcer.Create('Multitenant', 'TenantId', 'FTenantId');
  FEnforcer.AutoComplyOnInsert := True;
  FEnforcer.AutoComplyOnUpdate := True;
  FEnforcer.Activate(TMappingExplorer.Get('Samples'));

Thus, you can simply create or modify a product as you would usually do in single tenant application, but the filter enforcer will make sure to set data to the proper tenant id (or raise an error if the tenant is wrong, depending on your configuration).

Building single-database multitenant applications with TMS Aurelius is already possible, of course. But it will be really easy with the upcoming features. And not only that: building multi-database multitenant applications will also be easy with the new TMultiTenantConnectionPool:

  FMultiPool := TMultiTenantConnectionPool.Create(
    TXDataHttpHeaderTenantResolver.Create('tenant-id'),
    TDBConnectionPoolFactory.Create
    );

The pool will automatically choose the correct database based on the HTTP header tenant-id – or any other criteria you might choose. All transparently.

In summary: you will be able to build your app as if you are coding for single tenant applications, and let Aurelius do everything under the hood to make it multitenant, with minimum effort and in a robust and reliable way.

Data validation

Another great feature coming is data validation. Again, you can already do it using events, but soon it will be orders of magnitude easier. You will be able to add validators to your entities in several ways, attributes being the most common (irrelevant parts of the following class declaration removed for clarity):

  TCustomer = class
  private
    [Required]
    FName: string;
    
    [EmailAddress]
    FEmail: string;
  
    [DisplayName('class rate')]
    [Range(1, 10, 'Values must be %1:d up to %2:d for field %0:s')]
    FInternal_Rate: Integer;

All fields will be proper validated according to the validation attributes applied. Name will be required, Email must be a valid address and FInternal_Rate value must be between 1 and 10. With a few lines you will guarantee that the entity will be persisted with a valid state.

Validation will also help you with your API and GUI. Note how you can provide readable display names and error messages. When using validation in your API build with XData, the API responses will be detailed and informative, and all automatically:

And, of course, you can benefit from such information to easily build nice user interfaces informing the user about the validation results. The following screenshot is the same one used for the TMS Auth example above, but displaying results for password validation:

Attribute-based event handlers

Events are an important feature of any framework, and with Aurelius is not different. It provides several events you can use to add custom business logic. You can add specific code just before an entity is being saved, after an entity is deleted, when an SQL is being executed, among others.

The interesting feature coming is that you will now be able to add event handlers directly in your classes, using attributes. This will make your code even more organized, will improve readability and allow you to better follow the single-responsibility principle. It will be as simple as this:

TCustomer = class
  [OnInserting]
  procedure DoSomethingBeforeSave;

  [OnDelete]
  procedure DoSomethingAfterDelete;

Whenever a customer entity is about to be persisted, OnInserting method will be called and you can add any relevant code in that method. You can receive arguments in OnInserting, or you can even use with without them, like in the example above, making you class really independent of 3rd party custom types.

And more events are coming as well, for example, the new data validation mechanism mentioned above will also offer you an OnValidate event, which you can easily use like this:

TCustomer = 
  [OnValidate]
  function CheckBirthday: IValidationResult;

{...}  

  function TCustomer.CheckBirthday: IValidationResult;
  begin
    Result := TValidationResult.Create;

    if YearOf(Birthday) < 1899 then
      Result.Errors.Add(TValidationError
        .Create('A person born in the XIX century is not accepted'));

    if (MonthOf(Birthday) = 8) and (DayOf(Birthday) = 13) then
      Result.Errors.Add(TValidationError
        .Create('A person born on August, 13th is not accepted'));
  end;

That’s all…?

I hope you have followed me until here, and I hope you are as excited as us with the upcoming features and and libraries. Yes, that’s a lot of things to expect for Delphi and TMS Business in 2021! But I’d like to stress that what’s coming is not necessarily limited to what we put here. There might be even more! (Things we cannot disclose right now).

Did you like the news? Please comment below, let us know what you think and what are your opinions and expectations on this. And don’t forget to subscribe to our news channels to be informed when things are released and for many other exciting news from TMS: subscribe to our e-mail newsletter, follow our Facebook page and subscribe to our YouTube channel!

Update: Want to see these listed features in action? Register for the free webinar “What is coming in TMS BIZ in 2021”, to happen on Tuesday, February 23, 2021 3:00:00 PM UTC at the TMS Web Academy!

Read More

Read More

Planning / Scheduling in FMX

Intro

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 TTMSFNCPlanner component, a highly configurable planning/scheduling component.

Features

Below is a list of the most important features the TTMSNCPlanner 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 view and edit appointments / tasks in FireMonkey.

  • Built-in and customizable inplace and dialog editing
  • Moveable and sizeable items with HTML formatted text and hyperlink detection
  • High performance virtual mode
  • Various display modes: day, month, day period, half day period, multi day, multi month, multi day resource, multi resource day and custom displays
  • Multiple events for all kinds of interactions such as editing, item inserting, updating, moving and sizing
  • Multiple events for custom drawing and customization of default drawing
  • Item hints and time indication helpers
  • Optional overlapping items
  • Touch scrolling and selection
  • Optimized for mobile devices
  • Recurrency support
  • Databinding support via the TTMSFNCPlannerDatabaseAdapter
  • Separate ToolBar Popup
  • PDF Export capabilities

Learn More!

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

Download & Explore!

The TTMSFNCPlanner 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 TTMSFNCPlanner component.

Coming up

The TTMSFNCPlanner is the second 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 TTMSFNCRichEditor. Next up will be the TTMSFNCTreeView component, a highly configurable, high performance tree view with virtual and collection-based modes able to deal with millions of nodes so stay tuned for more!.

Read More

Read More