@zohodesk/platform-middleware
Version:
Generalized Contract for the events from Marketplace App, In-App widgets, CRM-Plus and EFC
373 lines (323 loc) • 12.2 kB
JavaScript
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
};
}