@turbonomic/turbo-ui-manager v1.4.0
A lightweight frontend library with simple API to integrate and embed the © Turbonomic, Inc UI within a parent application UI.
Features
- Promise-based API.
- Bi-directional communication between parent and Turbonomic child application.
- Subscribe for notification about certain events.
Changes/History
- see: Changelog here
Installing
turbo-ui-manager
can be installed with npm or yarn.
Yarn
$ yarn add @turbonomic/turbo-ui-manager # Install via Yarn
NPM
$ npm i @turbonomic/turbo-ui-manager --save # Install via NPM
Import
The library is built to UMD format with library namespace TurboUIManager
;
ES6 Imports
import {TurboUI} from '@turbonomic/turbo-ui-manager';
HTML script include
<script src="./dist/turbo-ui-manager.js"></script>
...
<script>
// self executing function here
window.onload = function() {
TurboUIManager.TurboUI.createUIComponent(...);
};
</script>
require
const TurboUIManager = require('turbo-ui-manager');
...
TurboUIManager.TurboUI.createUIComponent(...);
Usage Overview
The
Parent Application
requests theturbo-ui-manager
to create a new instance of the Turbonomic UI at a given URL attached to a given DOM node and returns an object with interface methods and properties.The
turbo-ui-manaager
asynchronously establishes a handshake with the Turbonomic UI and notifies theParent Application
when this has completed or fails for any reason.The
Parent Application
can subscribe for notification about certain events such as navigation view changes from within the Turbonomic UI instance, Errors, etc.The
Parent Application
can command the Turbonomic UI to navigate to internal views using exposed methods on the interface.The
Parent Application
can call the exposeddestroy
method to cleanup and remove the instance if/when it is no longer needed.
Example
Parent
.append-turbonomic-container {
height: 900px;
width: 100%;
}
import { TurboUI } from '@turbonomic/turbo-ui-manager';
const opts: TurboUI.ITurboUIManagerSettings = {
url: 'http://example.com/turbonomic/app',
handshakeTimeout: 1000 * 60,
};
const turboUIManager = TurboUI.createUIComponent(document.getElementById('append-turbonomic-container') as HTMLElement, opts);
// suggest to show some loading animation while waiting for onReady or onSessionStart
turboUIManager.on(TurboUIEvent.LOGIN_READY, onReady);
turboUIManager.on(TurboUIEvent.SESSION_START, onSessionStart);
turboUIManager.on(TurboUIEvent.ERROR, onError);
// immediate call to navigate to plans will be queued and processed after handshake establishes connection
turboUIManager.navigateToPlans();
// navigate to a supported view by view-name
turboUIManager.navigateToViewByName(TurboUI.TurboUIManagerView.SEARCH);
API
Methods
TurboUI.createUIComponent
const turboUIManager: TurboUI.ITurboUIManager = TurboUI.createUIComponent(domElement, options);
This is the exposed function to initialize everything and return a reference with the public interface. It returns synchronously while the internal initialization happens asynchronously. It is possible to invoke calls with the returned interface before initialization has completed - such as subscribing for notification of events like the APP_READY event - these will simply be queued and handled afterwards.
Name | Type | Description | Required | Default |
---|---|---|---|---|
domElement | HTMLElement | Passed in HTML element where the Turbonomic UI instance will be appended to in the DOM | true | |
options | ITurboUIManagerSettings | Options object with some config details for the connection to the Turbonomic UI | true |
ITurboUIManager.navigateTo___()
There are a number of ways to command navigation of the UI:
Navigate using exposed hooks for specific views
Command the Turbonomic UI to transition to the given top-level view. Each of these corresponds to aTurboUIManagerView
turboUIManager.navigateToHome();
turboUIManager.navigateToSearch();
turboUIManager.navigateToPlans();
turboUIManager.navigateToReports();
turboUIManager.navigateToPlacement();
turboUIManager.navigateToDashboards();
turboUIManager.navigateToSettings();
Navigate to view by view-name argument: ITurboUIManager.navigateToViewByName(viewName: TurboUIManagerView)
Command the Turbonomic UI to transition to the given top-level view by supplying an enumerated view-name argument
turboUIManager.navigateToViewByName(TurboUIManagerView.PLANS);
turboUIManager.navigateToViewByName(TurboUIManagerView.DASHBOARDS);
Navigate to view by url-encoded viewKey: ITurboUIManager.navigateToViewByKey(viewKey: base64-string)
Command the Turbonomic UI to transition to a hashed-view "viewKey" which is a base64 url encoded view path. Ordinarily the intent is to instantiate the UI during create with a viewKey populated from the url query params in order to handle stateful page refreshes or url sharing/bookmarking.
turboUIManager.navigateToViewByKey(new URLSearchParams(window.location.search).get('viewKey'));
Navigate to view by scopeID: ITurboUIManager.navigateToScopeByID(scopeID: uuid-string)
Command the Turbonomic UI to show scoped dashboard overview for a specific entity identified by its UUID (received from API)
turboUIManager.navigateToScopeByID('1839473243894');
Navigate to view by view-options: ITurboUIManager.navigateToViewByOptions(viewOptions: TurboUI.ITurboUIManagerViewSettings)
Encompasses a combination of all of the above options but follows a hard-coded priority order using the options as follows:
scopeID
is checked and followed if it existsviewKey
is checked and followed if it existsview
enumerated view-name is checked and followed if it existsdefault
fallback is to navigate to the home view if no other condition is met.
turboUIManager.navigateToViewByOptions({
scopeID: '01234567891011',
viewKey: 'Iy92aWV3L21haW4vaG9tZS9NYXJrZXQvaHlicmlk',
view: TurboUIManagerView.HOME,
});
ITurboUIManager.viewNotifications()
turboUIManager.viewNotifications();
Open the notifications slideout.
ITurboUIManager.on()
turboUIManager.on(eventName, callbackFunction);
register a subscriber function for a given
TurboUIEvent
. It returns a handle function that can be invoked to remove the specific subscriber. Multiple subscribers can be bound to a given event name topic. To remove all subscribers for an event useoff
Name | Type | Description | Required | Default |
---|---|---|---|---|
eventName | TurboUIEvent | One-of TurboUIEvent values from exported enum | true | |
callbackFunction | TurboEventListener | a callback function accepting 0-N number of arguments | true |
ITurboUIManager.off()
turboUIManager.off(eventName);
Deregister and removes all subscriber functions associated with specific
TurboUIEvent
Name | Type | Description | Required | Default |
---|---|---|---|---|
eventName | TurboUIEvent | One-of TurboUIEvent values from exported enum to unsubscribe from | true |
ITurboUIManager.clearAllSubscribers()
turboUIManager.clearAllSubscribers();
Deregister and removes all subscriber functions for all events. Use this is dismounting/hiding the TurboUI element with the anticipation that you may resume showing it again as this will prevent potential detatched event listeners representing a memory-leak. You will need to re-register the subscribers for handling events upon resuming/showing the TurboUI once again.
ITurboUIManager.hide()
turboUIManager.hide(element);
Hides/minimizes the turbo-ui instance attached to the provided element. Is Promise-based: Tries to Query-select the turbo-ui from the provided element and sets height to
'0px'
explicitly. IFF the query-selection cannot locate the underlying Turbo-UI, the promise will be rejected. This is useful because it provides a way to be aware that a new call to create and instantiate the UI may be required (or indicates the root DOM element provided no longer contains the Turbo-UI as a child node).
Name | Type | Description | Required | Default |
---|---|---|---|---|
element | HTMLElement | _The root HTML DOM element provided to create and mount the turboUI instance initially |
ITurboUIManager.show()
turboUIManager.show(element);
Show/maximizes the turbo-ui instance attached to the provided element. Is Promise-based: Tries to Query-select the turbo-ui from the provided element and sets height to
'inherit'
explicitly. IFF the query-selection cannot locate the underlying Turbo-UI, the promise will be rejected. This is useful because it indicates either something went wrong with the root DOM node provided not being correct and/or that a new call to initialize/create the Turbo-UI instance is required.
Name | Type | Description | Required | Default |
---|---|---|---|---|
element | HTMLElement | _The root HTML DOM element provided to create and mount the turboUI instance initially |
ITurboUIManager.getEnabledViews()
const enabledViews: TurboUI.TurboUIManagerView[] = turboUIManager.getEnabledViews();
A method returning the list of enabled TurboUI.TurboUIManagerView items.
Note: this is also notified as an argument to subscribers of the event
TurboUIManagerEvent.SESSION_START
.ITurboUIManager.getCurrentView()
const currentView: TurboUI.TurboUIManagerView = turboUIManager.getCurrentView();
Call method returning the
currentView
property of the underlying Turbonomic UI.ITurboUIManager.getCurrentViewState()
const currentView: TurboUI.TurboUIManagerView = turboUIManager.getCurrentViewState();
Call method returning an
IViewTransition
interface object describing the current state of the underlying Turbonomic UI. The object can contain the following properties:viewName
,viewUrl
andviewKey
Note: it is also possible (and probably better) to subscribe forTurboUIManagerEvent.VIEW_CHANGE
events with a callback function that will receive this every time the value changes.
ITurboUIManager.isSessionStarted()
const isSessionStarted: boolean = turboUIManager.isSessionStarted();
Check whether an authenticated session has been started within the TurboUI. Note: Typically you will subscribe for
TurboUIManagerEvent.SESSION_START
event to receive a callback when the session starts. However, if you are re-connecting to an existing TurboUI container, the session may already (still) be active so this enables to check the truthiness of that state.
ITurboUIManager.getUrlFromViewKey(viewKey: base64-encoded-string)
const urlPath: string = turboUIManager.getUrlFromViewKey('Iy92aWV3L21haW4vaG9tZS9NYXJrZXQvaHlicmlk'); console.log(urlPath); // ----> '#/view/main/home/Market/hybrid'
Returns the decoded url-path of the view from the supplied view-key. The viewKey is a url-safe base64 encoded string. This is useful for logging or debugging purposes but is not necessary for navigation purposes normally. This path is also provided along with the top-level
TurboUIManagerView
name and the encodedviewKey
to theTurboUIManagerEvent.VIEW_CHANGE
subscribers
Interfaces & Enums
TurboUI.ITurboUIManagerSettings
const options: TurboUI.ITurboUIManagerConnectionSettings = {
url: 'https://example.com/turbonomic/app',
handshakeTimeout: 5000,
scopeID?: string|null,
viewKey?: string|null,
view?: TurboUIManagerView,
}
This is the configuration object for connecting with the underlying Turbonomic UI instance. It is required to provide a fully-qualified URL to the instance.
Note the URL for the Turbonomic UI must be on the same domain as the parent application, else the handshake will fail.
Name | Type | Description | Required | Default |
---|---|---|---|---|
url | string | Fully Qualified URL pointing to the root of the Turbonomic instance to be embedded | true | |
handshakeTimeout | number | Maximum time in milliseconds to wait for the handshake to be established with child Turbonomic UI instance | false | 10000 |
scopeID | string (uuid) | (priority 1) Initialize the Turbo-UI connection to display the scoped dashboard overview for a specific entity identify by its uuid (as scopeID) | false | HOME |
viewKey | string (base64) | (priority 2) Initialize the Turbo-UI connection to display the specified view identified by the base-64 url encoded hash | false | HOME |
view | TurboUIManagerView | (priority 3) A specific Top-Level TurboUI View to display upon initializing the connection | false | HOME |
TurboUI.TurboUIManagerView
Enum of top-level views within the Turbonomic UI. These ordinarily would exist in the Left-hand Navbar. Any number of these can be restricted for various reasons.
Values |
---|
HOME ,SEARCH ,PLANS ,PLACEMENT ,DASHBOARDS , REPORTS ,SETTINGS ,NOTIFICATIONS |
TurboUI.TurboUIManagerEvent
turboUIManager.on(TurboUIEvent.ERROR, onError); turboUIManager.on(TurboUIEvent.LOGIN_READY, onReady); turboUIManager.on(TurboUIEvent.VIEW_CHANGE, onViewChange); turboUIManager.on(TurboUIEvent.SESSION_START, onSessionStart);
private onReady = () => { // Turbonomic UI Login Form is loaded. May want to display some loading animation graphic until this is called. // IF configured for SSO integration, this event will not be emitted };
private onSessionStart = (viewTransition: TurboUI.IViewTransition) => { // User session is logged-in and started; IViewTransition viewState information is returned // If using SSO for authentication, this is probably the first event that will be received to indicate the UI is ready // to be displayed. Recommend displaying some loading animation graphic until this is called. };
private onError = (e: TurboUI.ITurboUIManagerError) => { // Some error has occurred. Read from property 'type' which is one-of TurboUI.TurboUIManagerErrorType in order to // handle different types of errors accordingly (see error-types below) };
#### onViewChange(TurboUI.TurboUIManagerEvent.
```typescript
TurboUI.on(TurboUI.VIEW_CHANGE, onViewChange);
private onViewChange = (viewTransition: TurboUI.IViewTransition) => {
// Turbonomic UI View has changed (e.g. user has navigated from within the child application directly)
const { viewName, viewKey, viewUrl } = viewTransition;
console.log(viewName); // ----> 'HOME'
console.log(viewKey); // ----> 'Iy92aWV3L21haW4vaG9tZS9NYXJrZXQvaHlicmlk'
console.log(viewUrl); // ----> '#/view/main/home/Market/hybrid'
};
Some notes about workflows with VIEW_CHANGE transitions:
- Use-Case: Instantiate a new instance of IWO UI to a given View-State. (The view transition info will come through the SESSION_START event in this case NOT the VIEW_CHANGE for the first transition)
- View: e.g. "HOME"
- ScopeID: Directly link to a scoped overview
ViewKey: browser refresh, bookmark, or link-sharing
- Navigating back to existing Turbonomic UI instance from an external/parent UI view:
- User went to Turbonomic View e.g. "HOME", then to some External/Parent View (non Turbonomic), and back to the SAME Turbonomic view as before e.g. "HOME" again.
- Same as above but the second time going into Turbonomic they went to a different view (e.g. (Turbonomic) HOME -> (parent app) -> (Turbonomic) Plans ).
A subscriber for View Transition events will receive an object conforming to
IViewTransition
interface. This object received identifies:
Name | Type | Description | Always-Included | Default |
---|---|---|---|---|
view | TurboUI.TurboUIManagerView | Top-Level enumerated TurboUI Manager View (useful to indicate corresponding navigation/breadcrumbs | true | |
viewKey | string | Base64, URL-safe encoding of the underlying TurboUI embedded view. Useful to push onto url-query string params to track for stateful reloads and url sharing/bookmarking | true | |
viewUrl | string | Non-Encoded (not query-param safe) url path segment of the underlying TurboUI embedded view. Useful for human-readable logging and debugging | true |
TurboUI.ITurboUIManagerError
TurboUI.TurboUIManagerErrorType
turboUIManager.on(TurboUIEvent.ERROR, this.onError);
private onError = (error: TurboUI.TurboUIManagerError) => {
const errorType: TurboUI.TurboUIManagerErrorType = error.type;
switch(errorType) {
case TurboUIManagerErrorType.HANDSHAKE_FAILURE:
console.warn('Failed to establish handshake with TurboUI within 10000 ms. time limit');
case TurboUIManagerErrorType.INITIALIZATION_ERROR:
console.warn('Some error occurred within the Turbonomic UI instance while initializing as embedded application');
case TurboUIManagerErrorType.RESTRICTED_VIEW:
console.warn(`View Transition Failed. ${view} is currently restricted`);
default:
console.error('Some unexpected error occurred');
}
}
A subscriber for Error events will receive an object conforming to
ITurboUIManagerError
. Within this object is atype
field which is one ofITurboUIManagerErrorType
which allows parent code to handle different error cases.
Name | Type | Description | Required | Default |
---|---|---|---|---|
url | string | Fully Qualified URL pointing to the root of the Turbonomic instance to be embedded | true | |
handshakeTimeout | number | Maximum time in milliseconds to wait for the handshake to be established with child Turbonomic UI instance | false | 10000 |
License
Apache-2.0