Target configuration

HUB Client

Target structure

HUB Client Target should have the following structure, which can vary depending on complexity.

Project settings

Project settings can be set in the root index.yml file. The values for these settings can be individually set for any particular environment. (Environment-specific entry points)

List of available parameters

Application URL settings

Example configuration

Here's an example of various settings in index.yml:

Page settings

The entire application consists of pages. Each view that is presentable to a user must be implemented as page. There are two predefined user positions, the index page and the error page. The index must be inside index property in pages. In root of your yaml (typically index.yml), you can specify the value of the property errorPage. This property is name of page to which the user will be redirected when an error occurs (such as a network failure).

List of available parameters

Example configuration

Error page

The error page can be specified as an errorPage parameter in application configuration.

If an error page is not specified, the auth cookie will be deleted and application will be reloaded.

You can create more dynamic error page that provides useful features, such as a button to continue or reattempt the previous action (flowContinue). This button will automaticaly fetch the last stored data from the server and redirect user to correct screen.

Another useful error management feature is to provide a button that reloads the flow. If the problem is not easily resolved, have the user click a button to redirect to start of the flow in case with the form action flowReload.

If you are on error page, there are also available page parameters that contain the reason for the error. For example, query the value of page.params.error to get the raw output from the error catch.

Analytics

You are able to initialize different analytics providers when application starts and call specific action when certain event occurs.

List of currently available providers:

  • ga — Google Analytics
  • gtm — Google Tag Manager
  • hotjar — HotJar ID
  • mixpanel — MixPanel ID

Example integration

User identification

To identify current user for different analytics providers analytics.authorizationToken configuration key can be used, e.g.:

In order to identify user not on initial page load, but by some event, analytics.authorization action from Expression context can be used:

Events management

Analytics events can be dispatched manually or using analytics event management.

By defining analytics in page configuration built-in analytics event management will be involved, some UI components are dispatching basic default events, e.g. form fields have click, change, blur, focus, etc.

Analytics page configuration

Analytics configuration structure is coresponding to an event you want to handle and can be placed on every page.

There are 3 ways you can set event configuration: "string", "object" or "function" annotation:

You can also define this event configuration inside of parent structure, for example this function will be triggered on any field change:

Existing events

Form fields events:

File upload events:

Path for these events is in this format fields.{FieldName}.{EventName}.

Application lifecycle events

Path for these events is in this format {Path}.{EventName}.

Analytics storage

Expression context has support for dispatching analytics events and for storing some values.

Analytics storage is a simple key/value storage, that can contain any value. It has some utils to make its usage simpler: for numeric values there are increment and get. increment will augment value by 1, if value does not exist, it will set it to 1.

Example:

This will sends event with name Click with parameter count: 1 for first call, 2 for second call, etc.

This will sends event with name Click with parameter count with value from storage. If this value does not exist, count will be set to 0 (default value).

Global analytics params

There is a way to set global analytics params which will be sent with every single event. This injection works only when input params in event call is an object or was not provided. Global params has lower priority, so if you redefine same field in event params, it will overwrite it.

Example:

Dispatch events manually

To manually fire analytics event, use analytics.event method from expression context

Formats settings

Global formats should be defined under formats parameter. Later all formats are available as helpers in global application state (expression context)

Example configuration

Global application state and methods

Expressions

Expressions are a simple way to access data from the app runtime, or the response from server. Data is accessed through an object that is internally known as Core context or Expression context. If expression fails, it will return undefined. If you specify the default parameter, it will be returned when expression fails.

Examples of expressions:

Functions

A function is another type of expression. It's useful to add some callbacks, such as a button onClick event.

Extending Expression context

To extend expression context with custom values or methods, globals or utils configuration keys can be used:

Then in page configuration:

Expression context

Expression context is a global object, which is accessible from YAML expression only.

  • analytics - functions for trigger analytics events
  • api - information about API
  • app - information about app

Example usage of wrapByLoading

  • configuration - complete configuration of your target in json. This is an output from target-builder module, which parses all files inside target folder and produces large JSON that contains all settings, configurations, pages structures, etc.
  • constants - list of constants, the most important ones are: COUNTRIES_FULL, COUNTRIES, COUNTRY_CODES, LANGUAGES
  • cookie - methods exported from js-cookie module (cookie.get, cookie.set, cookie.remove)
  • cx - method exported from classnames module
  • device - information about device
  • flow - data from server about flow and flow/route functions from server
  • form - data about form, including states of fields
  • format - global formats used in application
  • globals - custom constants/variables, see more on how to extend expression context
  • helper - Helper functions and 3rd party libraries
  • locals - local page variables and functions
  • page - parameters of page, which may be an error. This data is set only from the local application, not the server
  • translates - function to translate a string of text, change current locale
  • url - information about locations, query params, etc.
  • utils - custom methods, see more on how to extend expression context

Localization

HUB Client has built-in support for multiple locales and an easy way to manage translations.

All translation keys are being stored in src/translates folder under appropriate YAML files: {LANG}.yml and should be described in index.yml project configuration file:

Translations can be stored under nested keys, e.g.

In order to use translation key with some parameter, the following notation can be used:

There are two ways to use translations in YAML:

  • Use the !t function. It can value for any property in any object.
  • Use !expression and call the function t.

To change locale, use the action changeLocale, in which the first parameter is target locale name.

Examples:

Markdown and HTML content in translations

Translation key value can have string, HTML or Markdown as a value:

In order to use Markdown/HTML you need to use !te tag instead of !t:

Built in components

Using components in YAML page configuration

Each component must have an "as" parameter that specifies the component element name. You can use the provided component name, or the standard HTML DOM element.

Each component has also $reference property, which can create a named reference to DOM element. This reference is accessible through a $reference object inside appDataContext.

Examples of $reference:

UI components

List of UI components can be viewed in Zenoo Storybook.

Logical components

Fragment

Fragment wrapper - this is a dummy component without any effect on the rendering. You can wrap a set of components into it to create a single component with children.

VisibilityWrapper

Wrapper for hiding and showing elements. Elements (items) inside it will be shown only if property visible is set to true, or property invisible is set to false.

Properties:

Trigger

This component permits you to track changes on some value and retrieve that value with an expression. On loading (mounting) of this component, the load callback will be called with current value. If this value was changed, the change callback will be called with old and new values. Value variables are accessible in scope. For load function there is value, that referes to current value of the trigger. In a change callback, there is an oldValue and newValue-which contain the values before and after the change, respectively.

Example

Properties

Script

A script component that runs a script, which is defined by the onEnter and onLeave property (use a !function expression). The onEnter script will be run immediately if the trigger property is not defined—or the value of the trigger property changes from false to true. The onLeave script will be run when a component unmounts (in case trigger has not been set), or when trigger changes from true to false.

You can also specify runOnUpdate and the script will run whenever trigger changes. If runOnUpdate is false or not set, both the onEnter and onLeave scripts will be run only once. You can also provide a URL to an external script.

Properties

EJS partials

It is possible to extend initial HTML content of application. By creating/filling the following files in /ejs folder in target source you can extend content of head element and add HTML code at the beginning/end of body tag:

  • head.ejs — head element content
  • index.ejs — beginning of body element content
  • body.ejs — end of body element content

Remote application start

In order to "pause" application initialization prior to perform some asynchorous task, the following approach can be used with the help of EJS partials:

head.ejs