UNPKG

@zohodesk/platform-middleware

Version:

Generalized Contract for the events from Marketplace App, In-App widgets, CRM-Plus and EFC

328 lines (289 loc) 12 kB
import selectn from 'selectn'; function clearNonRuntimeWidgetInstances() { var allwidgetsInstance = ZApp.GetAllWidgetInstance(); allwidgetsInstance = Object.keys(allwidgetsInstance); var widgetInstance = null; for (var i = 0; i < allwidgetsInstance.length; i++) { widgetInstance = ZApp.GetWidgetInstance(allwidgetsInstance[i]); if (widgetInstance.getIFrame() === null) { ZApp.DeleteWidgetInstance(allwidgetsInstance[i]) } } } function patchString(string, data) { if (!string || typeof string !== 'string') { throw new Error('Invalid String'); } if (!data || typeof data !== 'object') { throw new Error('Invalid Params object'); } let patchedString = string.replace(/\{\{\w+\}\}?/g, match => { let key = match.replace(/[{{}}]/g, ''); return data[key] || match; }); return patchedString; } function isObject(obj) { return obj.constructor === {}.constructor; } // function getComputedParams(paramsObj) { // return Object.keys(paramsObj.computeParams).reduce((result, param) => { // result[param] = selectn(patchString(paramsObj.computeParams[param], paramsObj.data), paramsObj.data); // return result; // }, {}); // } // function paraseData(dataObj) { // return Object.keys(dataObj.params).reduce((result, param) => { // if (typeof dataObj.params[param] === "object") { // paraseData({ // params: params[param], // data: dataObj.data // }) // } else { // result[param] = selectn(patchString(dataObj.params[param], dataObj.data), dataObj.data); // } // return result; // }, {}); // } // export function constructDataForEvent(dataObj) { // let computedParams = getComputedParams({ computeParams: dataObj.computeParams, data: dataObj.data }); // computedParams = Object.assign({}, computedParams, dataObj.data); // return paraseData({ params: dataObj.params, data: computedParams }); // } // export let zAppBroadcastEvent = (eventObj) => { // if (typeof ZApp !== 'undefined') { // clearNonRuntimeWidgetInstances(); // ZApp.BroadcastEvent(eventObj.name, eventObj.data); // } // PlatformInstance.BroadcastEvent({ name: eventObj.name, data: eventObj.data }) // } function isValidEventObj(eventObj) { return eventObj.eventName && eventObj.responseHandler && typeof eventObj.responseHandler == 'function' ? true : false } function hasWidgetsForEvent(eventName) { return ZApp.GetWidgetsByEvent(eventName).length > 0 ? true : false; } export function isEventNeededToBroadCast(eventObj) { return isValidEventObj(eventObj); } export let zAppBroadcastEvent = (eventObj) => { let { getState, dispatch, action, event, getPrevState } = eventObj; let { responseHandler, eventName } = event; if (typeof eventName == 'function') { eventName = eventName({ action, getState, getPrevState }); } if (Array.isArray(eventName)) { eventName.map((name) => { responseHandler(action, getState, dispatch, name, getPrevState).then(function (response) { if (typeof ZApp !== 'undefined') { clearNonRuntimeWidgetInstances(); isObject(response) ? ZApp.BroadcastEvent(name, response) : null; } isObject(response) && typeof PlatformInstance != 'undefined' ? PlatformInstance.BroadcastEvent({ name, data: response }) : null; }); }) } else { responseHandler(action, getState, dispatch, eventName, getPrevState).then(function (response) { if (typeof ZApp !== 'undefined') { clearNonRuntimeWidgetInstances(); isObject(response) ? ZApp.BroadcastEvent(eventName, response) : null; } isObject(response) && typeof PlatformInstance != 'undefined' ? PlatformInstance.BroadcastEvent({ name: eventName, data: response }) : null; }); } } export let zAppHookEvent = (eventObj) => { return new Promise((resolve, reject) => { let { getState, dispatch, action, hook } = eventObj; let { responseHandler, eventName } = hook; if (typeof eventName === 'function') { eventName = eventName({ action, getState }); } responseHandler(action, getState, dispatch, eventName).then(hookData => { if (typeof ZApp !== 'undefined') { clearNonRuntimeWidgetInstances(); let isTimeOutCalled = false, failedWidgets = [], eventListeners = ZApp.GetWidgetsByEvent(eventName); if (eventListeners.length > 0) { //TODO: Get the Hook Timing from the application let eventTimeout = setTimeout(() => { isTimeOutCalled = true; resolve(eventObj.action); }, 30000); //Third argument true is set because of Hook Event Promise.all(ZApp.BroadcastEvent(eventName, hookData, true)).then(response => { let content = null; if (!isTimeOutCalled) { clearTimeout(eventTimeout); response.map(widgetsResponse => { let widgetInstance = ZApp.GetWidgetInstance(widgetsResponse.widgetID); let widgetName = widgetInstance.getProp('title') || widgetInstance.getProp('name'); let responseObj = widgetsResponse.response && widgetsResponse.response[0] || {}; if (!responseObj.isSuccess) { let widgetResult = responseObj.response || {}; let rejectTitle = widgetResult.title || ''; let shouldNotify = widgetResult.hasOwnProperty('shouldNotify') ? widgetResult.shouldNotify : true; if(shouldNotify){ let rejectMessage = widgetResult.msg || widgetResult.message || ''; if (rejectMessage && typeof rejectMessage === 'string') { content = rejectMessage.trim(); } else { content = `This widget has stopped the ${eventName} operation`; } } failedWidgets.push({ title: rejectTitle || widgetName, content: content }); } else { widgetsResponse.response[0].response == false ? failedWidgets.push({ title: widgetName, content: `This widget has stopped the ${eventName} operation` }) : null; } }); if (failedWidgets.length) { failedWidgets.forEach(widget => { if(widget.content){ eventObj.notifyHandler({ title: widget.title, content: widget.content }); } let hookRejectCallback = action.hookRejectCallback; if (hookRejectCallback && typeof hookRejectCallback === 'function') { hookRejectCallback(); } }); } else { resolve(eventObj.action) } } }).catch(err => { if (!isTimeOutCalled) { clearTimeout(eventTimeout); eventObj.notifyHandler({ title: 'Hook Event Failed', content: `Some widget has stopped the ${eventName} hook event` }); let hookRejectCallback = action.hookRejectCallback; if (hookRejectCallback && typeof hookRejectCallback === 'function') { hookRejectCallback(); } } }) } else { resolve(eventObj.action) } } }).catch(err => { let hookRejectCallback = action.hookRejectCallback; if (hookRejectCallback && typeof hookRejectCallback === 'function') { hookRejectCallback(err); } reject(err); }); }); } function constructEventAndResponseObject(eventObj) { var info = {}; if (eventObj.event.EVENT_FROM == 'PRODUCT') { info = { type: eventObj.event.type, value: eventObj.event.payload, property: eventObj.event.property } } else { info = { type: eventObj.event.data.type, value: eventObj.event.data.value, property: eventObj.event.data.property || null, iframe: eventObj.event.iframe } } function sendResponse(eventPromise, eventResponseObj) { let data = eventResponseObj.data; if (eventResponseObj.hasOwnProperty('status')) { eventResponseObj.status ? eventPromise.resolve(data) : eventPromise.reject({ errMsg: data }); } } return { info: info, sendResponse: sendResponse.bind(null, eventObj.event.promise) } } function constructWidgetObject(widgetId, extension_id) { let widgetInstance = ZApp.GetWidgetInstance(widgetId); return { id: widgetInstance.getProp('widgetId'), clientId: widgetId, title: widgetInstance.getProp('title') || widgetInstance.getProp('name'), extensionId: extension_id, location: widgetInstance.getLocation() }; } export function handleEvent(eventObj) { let { widgetID, extension_id } = eventObj.event; let constructedEventObject = { store: { getState: eventObj.getState, dispatch: eventObj.dispatch }, patchString }; if (widgetID && extension_id) { constructedEventObject.widget = constructWidgetObject(widgetID, extension_id); } constructedEventObject.event = constructEventAndResponseObject(eventObj); return constructedEventObject; } export function validateConfig(config) { let errorMsg = null; if (config.featureFlags.isMarketplaceNeeded) { if (!config.hasOwnProperty('marketplace')) { errorMsg = 'marketplace object is missing'; } else { if (!(config.marketplace.hasOwnProperty('renderHandler') && typeof config.marketplace.renderHandler === 'function')) { errorMsg = 'marketplace object should have renderHandler key with function as value' } if (!(config.marketplace.hasOwnProperty('postAssestsFetch') && typeof config.marketplace.postAssestsFetch === 'function')) { errorMsg = 'marketplace object should have postAssestsFetch key with function as value' } if (!(config.marketplace.hasOwnProperty('isDevMode') && typeof config.marketplace.isDevMode === 'function')) { errorMsg = 'marketplace object should have isDevMode key with function as value' } if (!(config.marketplace.hasOwnProperty('requestHandler') && typeof config.marketplace.requestHandler === 'function')) { errorMsg = 'marketplace object should have requestHandler key with function as value' } if (!(config.marketplace.hasOwnProperty('notifyHandler') && typeof config.marketplace.notifyHandler === 'function')) { errorMsg = 'marketplace object should have notifyHandler key with function as value' } } } if (!(config.hasOwnProperty('globalNameSpace') && typeof config.globalNameSpace === 'string')) { errorMsg = 'globalNameSpace key with string as value is missing' } if (!(config.hasOwnProperty('postProductSDKAssetsFetch') && typeof config.postProductSDKAssetsFetch === 'function')) { errorMsg = 'postProductSDKAssetsFetch key with function as value is missing' } if (!(config.hasOwnProperty('isPromiseBasedAction') && typeof config.isPromiseBasedAction === 'boolean')) { errorMsg = 'isPromiseBasedAction key with true/false as value is missing' } if (!(config.hasOwnProperty('locale') && typeof config.locale === 'string')) { errorMsg = 'locale key with string as value is missing' } if (!config.hasOwnProperty('eventListeners')) { errorMsg = 'eventListeners object is missing'; } else { Object.keys(config.eventListeners).forEach(key => { if (!(typeof config.eventListeners[key] === 'function')) { errorMsg = 'every keys in eventListeners object should have function as value' return } }); } return { isConfigValid: errorMsg ? false : true, errorMsg }; }