UNPKG

cv-dialog-sdk

Version:

Catavolt Dialog Javascript API

438 lines (437 loc) 14.2 kB
import { Dialog, Form, PropertyFormatter, RedirectionUtil, TypeNames } from '../models'; import { DialogProxy } from '../proxy/DialogProxy'; import { CvLocale } from '../util/CvLocale'; import { Log } from '../util/Log'; import { ObjUtil } from '../util/ObjUtil'; import { SessionTimer } from "../util/SessionTimer"; import { DialogService } from './DialogService'; /** * Top-level entry point into the Catavolt API */ export class CatavoltApiImpl { /** * Construct an CatavoltApiImpl * This should not be called directly, instead use the 'singleton' method * @private */ constructor(serverUrl, serverVersion) { this.DEFAULT_LOCALE = new CvLocale('en'); this.dataLastChangedTime = new Date(); this._locale = null; this._sessionTimer = null; this._onSessionExpiration = null; if (CatavoltApiImpl._singleton) { throw new Error('Singleton instance already created'); } this._devicePropsStatic = {}; this._devicePropsDynamic = {}; this._sessionTimer = new SessionTimer(() => this.remainingSessionTime, CatavoltApiImpl.CHECK_SESSION_INTERVAL_MILLIS, () => { this.logout().then(() => { this._onSessionExpiration && this._onSessionExpiration(); }); }); this.initDialogApi(serverUrl, serverVersion); CatavoltApiImpl._singleton = this; } /* ******************** Statics *********************** */ /** * Get the default session time * @returns {number} */ static get defaultTTLInMillis() { return CatavoltApiImpl.ONE_HOUR_IN_MILLIS; } /** * Get the singleton instance of the CatavoltApiImpl * @returns {CatavoltApiImpl} */ static get singleton() { if (!CatavoltApiImpl._singleton) { CatavoltApiImpl._singleton = new CatavoltApiImpl(CatavoltApiImpl.SERVER_URL, CatavoltApiImpl.SERVER_VERSION); } return CatavoltApiImpl._singleton; } /* ***************** Public Ops ******************* */ /** * Add or replace a dynamic device property (func) * @param propName * @param propFn */ addDynamicDeviceProp(propName, propFn) { this._devicePropsDynamic[propName] = propFn; } /** * Add or replace a static device property * * @param propName * @param propValue */ addStaticDeviceProp(propName, propValue) { this._devicePropsStatic[propName] = propValue; } /** * * @param {ClientListener} clientListener */ addClientListener(clientListener) { this._dialogApi.addClientListener(clientListener, this.locale); } /** * Get the preferred locale * @returns {CvLocale} */ get locale() { if (!this._locale) { const defaultLocale = this.session.tenantProperties.browserLocale; if (defaultLocale) { try { const localeJson = JSON.parse(defaultLocale); if (localeJson.language) { this._locale = new CvLocale(localeJson.language, localeJson.country); } } catch (err) { this._locale = this.DEFAULT_LOCALE; } } } if (!this._locale) { this._locale = this.DEFAULT_LOCALE; } return this._locale; } set locale(locale) { this._locale = locale; } /*@TODO*/ changePasswordAndLogin(tenantId, clientType, userId, existingPassword, newPassword) { return Promise.reject(new Error('Not Yet Implemented')); } /** * Get the number of millis that the client will remain active between calls * to the server. * @returns {number} */ get clientTimeoutMillis() { const mins = this.session.tenantProperties.clientTimeoutMinutes; return mins ? Number(mins) * 60 * 1000 : CatavoltApiImpl.defaultTTLInMillis; } /** * Get the currency symbol override if defined from the server. * @returns {string} */ get currencySymbol() { const currencySymbol = this.session.tenantProperties.currencySymbol; return currencySymbol ? currencySymbol : null; } /** * Get the device props * @returns {{[p: string]: string}} */ get deviceProps() { const newProps = ObjUtil.addAllProps(this._devicePropsStatic, {}); for (const attr in this._devicePropsDynamic) { if (this._devicePropsDynamic.hasOwnProperty(attr)) { newProps[attr] = this._devicePropsDynamic[attr](); } } return newProps; } /** * Get the DialogApi instance * @returns {DialogApi} */ get dialogApi() { return this._dialogApi; } /** * Initialize a dialog service implementation for use by this CatavoltApiImpl * * @param serverVersion * @param serverUrl */ initDialogApi(serverUrl, serverVersion = CatavoltApiImpl.SERVER_VERSION) { this._dialogApi = new DialogService(new DialogProxy(), serverUrl, serverVersion); } /** * Check for the availability of the given featureSet * @see FeatureSet * @param featureSet * @returns {boolean} */ isFeatureSetAvailable(featureSet) { try { const currentVersion = AppVersion.getAppVersion(this.session.serverVersion); const featureMinimumVersion = FeatureVersionMap[featureSet]; return featureMinimumVersion.isLessThanOrEqualTo(currentVersion); } catch (error) { Log.error('Failed to compare appVersions for feature ' + featureSet); Log.error(error); return false; } } /** * Checked logged in status * @returns {boolean} */ get isLoggedIn() { return !!this._session; } /** * Check offline status * * @param tenantId */ isAnyUserInBriefcaseMode(tenantId) { return this.dialogApi.isAnyUserInBriefcaseMode(tenantId); } /** * Check offline status * * @param userInfo * @returns {Promise<boolean>} */ isUserInBriefcaseMode(userInfo) { return this.dialogApi.isUserInBriefcaseMode(userInfo); } /** * Log in and retrieve the Session * * @param tenantId * @param clientType * @param userId * @param password * * @returns {Promise<Session | Redirection>} */ login(tenantId, clientType, userId, password) { if (this.isLoggedIn) { return this.logout().then(result => this.processLogin(tenantId, clientType, userId, password)); } else { return this.processLogin(tenantId, clientType, userId, password); } } loginWithToken(tenantId, clientType, permissionToken, proofKey) { if (this.isLoggedIn) { return this.logout().then(result => this.processLogin(tenantId, clientType, null, null, permissionToken, proofKey)); } else { return this.processLogin(tenantId, clientType, null, null, permissionToken, proofKey); } } /** * Logout and destroy the session * @returns {{sessionId:string}} */ logout() { if (this.isLoggedIn) { const sessionId = this.session.id; return this.dialogApi .deleteSession(this.session.tenantId, this.session.id) .then(result => { this._session = null; this._sessionTimer.stopSessionTimer(); return result; }) .catch(error => { Log.error(`Error logging out ${error}`); this._session = null; this._sessionTimer.stopSessionTimer(); return { sessionId }; }); } else { return Promise.resolve({ sessionId: null }); } } openDialogWithId(dialogId) { return this.dialogApi.getDialog(this.session.tenantId, this.session.id, dialogId).then((dialog) => { dialog.initialize(this); if (dialog.view instanceof Form) { return dialog; } else { throw new Error(`Unexpected top-level dialog view type: ${dialog.view.type}`); } }); } openDialog(redirection) { return this.openDialogWithId(redirection.dialogId); } /** * Not yet implemented * @param {string} url * @returns {Promise<StreamProducer>} */ openStream(url) { // return this.dialogApi.streamUrl(null, null, url); throw Error('not yet implemented'); } toDialogOrRedirection(resultPr) { return resultPr.then((actionResult) => { if (RedirectionUtil.isDialogRedirection(actionResult)) { return this.openDialog(actionResult); } else if (RedirectionUtil.isRedirection(actionResult)) { return Promise.resolve(actionResult); } else { // @TODO - this shouldn't be a null redirection - what should it be? return Promise.resolve(actionResult); } }); } getRedirection(redirectionId) { return this.dialogApi.getRedirection(this.session.tenantId, this.session.id, redirectionId); } /** * Open a {@link WorkbenchAction} * @param workbenchAction * @returns {Promise<{actionId:string} | Redirection>} */ performWorkbenchAction(workbenchAction) { return this.performWorkbenchActionForId(workbenchAction.workbenchId, workbenchAction.id); } /** * Open a {@link WorkbenchWorkbenchAction} * @param workbenchId * @param workbenchActionId * @returns {Promise<{actionId:string} | Redirection>} */ performWorkbenchActionForId(workbenchId, workbenchActionId) { if (!this.isLoggedIn) { return Promise.reject(new Error('User is not logged in')); } return this.dialogApi.performWorkbenchAction(this.session.tenantId, this.session.id, workbenchId, workbenchActionId); } /** * Refresh the CatavoltApiImpl * * @returns {Promise<Session>} */ refreshSession(tenantId, sessionId) { return this.dialogApi.getSession(tenantId, sessionId).then(session => { this._session = session; return session; }); } /** * Time remaining before this session is expired by the server * @returns {number} */ get remainingSessionTime() { return this.clientTimeoutMillis - (new Date().getTime() - this.dialogApi.lastServiceActivity.getTime()); } /** * * @param {ClientListener} clientListener */ removeClientListener(clientListener) { this._dialogApi.removeClientListener(clientListener); } /** * Get the Session * @returns {Session} */ get session() { return this._session; } /** * Return whether or not the session has expired * @returns {boolean} */ get sessionHasExpired() { return this.remainingSessionTime < 0; } /** * Function that will be notified when the session expires * @param {() => void} onSessionExpiration */ set onSessionExpiration(onSessionExpiration) { this._onSessionExpiration = onSessionExpiration; } /** * * @param {string} contentId * @param {StreamConsumer} streamConsumer * @returns {Promise<LargeProperty>} */ streamContent(contentId, streamConsumer) { return Dialog.loadLargeProperty((params) => { return this.dialogApi.getContent(this.session.tenantId, this.session.id, contentId, params); }, streamConsumer); } processLogin(tenantId, clientType, userId, password, permissionToken, proofKey) { const login = { userId, password, permissionToken, proofKey, clientType, deviceProperties: this.deviceProps, type: TypeNames.LoginTypeName }; return this.dialogApi.createSession(tenantId, login).then((result) => { if (result.type === TypeNames.SessionTypeName) { this._session = result; this._sessionTimer.resetSessionTimer(); return result; } else { return result; } }); } } CatavoltApiImpl.ONE_HOUR_IN_MILLIS = 60 * 60 * 1000; CatavoltApiImpl.CHECK_SESSION_INTERVAL_MILLIS = 30 * 1000; // defaults CatavoltApiImpl.SERVER_URL = 'https://dialog.hxgn-api.net'; CatavoltApiImpl.SERVER_VERSION = 'v0'; class AppVersion { constructor(major, minor, patch) { this.major = major; this.minor = minor; this.patch = patch; } static getAppVersion(versionString) { const [major, minor, patch] = versionString.split('.'); return new AppVersion(Number(major || 0), Number(minor || 0), Number(patch || 0)); } /** * Is 'this' version less than or equal to the supplied version? * @param anotherVersion - the version to compare to 'this' version * @returns {boolean} */ isLessThanOrEqualTo(anotherVersion) { if (anotherVersion.major > this.major) { return true; } else if (anotherVersion.major === this.major) { if (anotherVersion.minor > this.minor) { return true; } else if (anotherVersion.minor === this.minor) { return anotherVersion.patch >= this.patch; } else { return false; } } else { return false; } } } const FeatureVersionMap = { View_Support: AppVersion.getAppVersion('1.3.447'), Unified_Search: AppVersion.getAppVersion('1.3.463') }; export const Catavolt = CatavoltApiImpl.singleton; export const propertyFormatter = PropertyFormatter.singleton(Catavolt);