Skip to main content Skip to footer

New Stock Portfolio App Built on OpenFin Platform API

Wijmo Stock Portfolio is a financial sample that demonstrates the usage of Wijmo Components in an OpenFin application.

The previous version of app represents multiple OpenFin applications each of them is loaded in a separate window allowing the user to organize the desired workspace.

The OpenFin Platform API provides the ability to organize windows & views into logical workspaces out-of-the-box. The new Stock Portfolio App uses OpenFin Platform API. Hence it does not need to run multiple OpenFin applications anymore. The main challenge was to migrate Stock Portfolio App to a single OpenFin applcation. This article is about how it was accomplished as well as is about the new opportunities which opens OpenFin Platform API.

If compare the visual appearance of app with the previous version, the new version is not changed much, and now looks as follows:

 

Running the Financial App

You can try the app quickly just downloading the distributable and running the app on a Windows machine.

If you are interested how to build the app, please follow these steps:

  1. First install the application from GitHub:

git clone https://github.com/GrapeCity/wijmo-openfin-platform-api.git

cd wijmo-openfin-platform-api && npm install

  1. Next, build and run the application in development mode:

npm start

Running the App as a Non-Developer

If you aren’t a developer and still want to try this application, we published an installer.

Install the app and launch it on a Windows machine. Zero technical expertise required!

OpenFin Platforms Overview

OpenFin Platforms introduces the new abstraction Views. It made possible to separate content from windows. Content (a web application) is loaded into an OpenFin View which is then attached to a window. Views have no windowing functionality of their own. They must be attached to a window, and given bounds relative to that window, in order to display their content. Views are possible to be configured in different arrangements: columns/rows, tabs and grid.

As stated in OpenFin documentation, OpenFin Platforms application has the following architecture:

  • A Platform Controller that exposes functionality for coordinating views and windows.
  • One or more child windows of the controller, which may or may not have a layout of views. A collection of windows is referred to as a snapshot.
  • One or more views, which provide content. They reside as part of a window's layout.

Migrating to a Single OpenFin App

The main concern was to move to the single app manifest. The fragment below describes the default snapshot used to define pre-configured workspace in the new Stock Portfolio App:

"snapshot": {         
        "windows": [ 
            { 
                "layout": { 
                    "content": [ 
                        { 
                            "type": "column", 
                            "content": [ 
                                { 
                                    "type": "row", 
                                    "content": [ 
                                        { 
                                            "type": "component", 
                                            "componentName": "view", 
                                            "componentState": { 
                                                "name": "component_stock_portfolio", 
                                                "url": "http://localhost:4200" 
                                            } 
                                        }, 
                                        { 
                                            "type": "component", 
                                            "componentName": "view", 
                                            "componentState": { 
                                                "name": "component_stock_changes_chart", 
                                                "url": "http://localhost:4300/#/changes" 
                                            } 
                                        } 
                                    ] 
                                }, 
                                { 
                                    "type": "row", 
                                    "content": [ 
                                        { 
                                            "type": "component", 
                                            "componentName": "view", 
                                            "componentState": { 
                                                "name": "component_stock_trading", 
                                                "url": "http://localhost:3300" 
                                            } 
                                        } 
                                    ] 
                                } 
                            ] 
                        }                         
                    ] 
                } 
            }, 
            { 
                "layout": { 
                    "content": [ 
                        { 
                            "type": "column", 
                            "content": [ 
                                { 
                                    "type": "component", 
                                    "componentName": "view", 
                                    "componentState": { 
                                        "name": "component_stock_hloc_chart", 
                                        "url": "http://localhost:3100" 
                                    } 
                                }, 
                                { 
                                    "type": "component", 
                                    "componentName": "view", 
                                    "componentState": { 
                                        "name": "component_stock_trendline_chart", 
                                        "url": "http://localhost:3100" 
                                    } 
                                } 
                            ] 
                        }                         
                    ] 
                } 
            } 
        ] 

As shown above, the default pre-configured workspace consists of two windows. These windows load web applications from the URLs provided in view configuration sections.

Customizing Window

OpenFin Platforms comes pre-packaged with OpenFin’s Standard Window, which has standard window controls (close, minimize, maximize) and some style customization.

As the name suggests, the Standard Window is used as the default window you get if you don’t specify the window’s URL upon creation.

The concern was to retain Window styles from preview version as much as possible. OpenFin Platform supports two options to customize window:

  1. By providing URL to the styles of OpenFin’s Standard Window

  2. By providing URL to the custom window different than Standard OpenFin

It was decided that the second option is most appropriate.

This task consists of two steps. First, it is needed to define the HTML file that represents the custom window. The HTML file must contain a div HTML element with the ID layout-container where the layout will be rendered. In our case the HTML file is rather simple and represents the frameless window.

You can the find sources here:

packages\stock-ui\src\platform-window.

Then the URL to the HTML file should be specified in app manifest:

"platform": { 
        ... 
        "defaultWindowOptions": { 
            "url": "http://localhost:3000/platform-window/index.html", 
            ... 
        } 
    } 

Customizing Platform Behavior

OpenFin Platform allows to overwrite or extend default Platform behavior by providing a custom Provider. The Platform Provider is the communication hub that coordinates between all windows in a Platform. This Provider runs in a hidden window which is represented by the HTML file.

Similar the window customization, the behavior customization also occurs in the HTML file. Custom HTML file must call fin.Platform.init to initialize the platform and open the manifest-defined snapshot. fin.Platform.init takes an options argument which may contain an overrideCallback property. The class that implements default Platform behavior is provided as an argument to this callback, and OpenFin uses the callback's return value to handle Platform functionality.

Using overrideCallback allows to override default functionality in order to customize Platform behavior.

The code below shows how to override getSnapshot behavior:

const overrideCallback = (Provider) => { 
    class MyOverride extends Provider { 
        async getSnapshot() { 
            // Custom code here 
        } 
    } 
    return new MyOverride(); 
}; 
fin.Platform.init({ overrideCallback }); 

The new Stock Portfolio App uses this mechanism to save app layout when app quits and to restore app layout when app launches. It makes possible to persist user workspace between app launches.

As in the previous section, the URL to custom HTML file is also specified in app manifest. In our case it looks as follows:

"platform": { 
        ... 
        "providerUrl": "http://localhost:3000/platform-provider/index.html", 
        ... 
    } 

Both custom HTML file and Provider can be found here:

packages\stock-ui\src\platform-provider.

Built on top of Google’s Chromium and GitHub’s Electron, OpenFin allows you to leverage the latest HTML5/JavaScript features. In addition, OpenFin has built-in support for workspace management and cross-application interoperability. Leveraging enterprise JavaScript Components like Wijmo will allow you to develop your applications even faster.

Konstantin Dmitriev

Software Developer
comments powered by Disqus