var finesse = finesse || {};
finesse.gadget = finesse.gadget || {};
finesse.container = finesse.container || {};
clientLogs = finesse.cslogger.ClientLogger || {}; // for logging
/** @namespace */
finesse.modules = finesse.modules || {};
finesse.modules.SampleGadget = (function ($) {
var user, dialogs, currentDialog,
defaultHtml = "This Gadget will populate once call arrives --\
Left side manual entry -- Right side click to update the Call Data",
/**
* Make a REST API request and send the response to the success or error
* handler depending on the HTTP status code
*
* @param {String} url
* The unencoded URL to which the request is sent (will be encoded)
* @param {Object} options
* An object containing additional options for the request.
*
* {String} options.method
* The type of request (e.g. GET, PUT, POST, DELETE)
* {String} options.authorization
* [Optional] The authorization string for the request
* {String} options.contentType
* [Optional] The Content-Type of the request (e.g. application/json,
* application/xml)
* {String} options.content
* A string to send in the content body of the request.
* @param {Object} handlers
* An object containing the success and error handlers.
*
* {Function} handlers.success(response)
* A callback function to be invoked for a successful request.
* {Function} handlers.error(response)
* A callback function to be invoked for an unsuccessful request.
*/
makeRequest = function (url, options, handlers) {
var params, uuid;
clientLogs.log("makeRequest()");
// Protect against null dereferencing of options & handlers allowing its (nonexistant) keys to be read as undefined
params = {};
options = options || {};
handlers.success = _util.validateHandler(handlers.success);
handlers.error = _util.validateHandler(handlers.error);
// Request Headers
params[gadgets.io.RequestParameters.HEADERS] = {};
// HTTP method is a passthrough to gadgets.io.makeRequest
params[gadgets.io.RequestParameters.METHOD] = options.method;
if (options.method === "GET") {
// Disable caching for GETs
if (url.indexOf("?") > -1) {
url += "&";
} else {
url += "?";
}
url += "nocache=" + _util.currentTimeMillis();
} else {
// Generate a requestID and add it to the headers
uuid = _util.generateUUID();
params[gadgets.io.RequestParameters.HEADERS].requestId = uuid;
params[gadgets.io.RequestParameters.GET_FULL_HEADERS] = "true";
}
// Add authorization to the request header if provided
if(options.authorization) {
params[gadgets.io.RequestParameters.HEADERS].Authorization = options.authorization;
}
// Add content type & body if content body is provided
if (options.content) {
// Content Type
params[gadgets.io.RequestParameters.HEADERS]["Content-Type"] = options.contentType;
// Content
params[gadgets.io.RequestParameters.POST_DATA] = options.content;
}
// Call the gadgets.io.makereqest function with the encoded url
clientLogs.log("makeRequest(): Making a REST API request to: " + url);
gadgets.io.makeRequest(encodeURI(url), handleResponse(handlers), params);
},
/**
* Handler for the response of the REST API request. This function determines if
* the success or error handler should be called based on HTTP status code.
*
* @param {Object} handlers
* An object containing the success and error handlers.
*
* {Function} handlers.success(response)
* A callback function to be invoked for a successful request.
* {Function} handlers.error(response)
* A callback function to be invoked for an unsuccessful request.
*/
handleResponse = function(handlers) {
return function (response) {
clientLogs.log("handleResponse(): The response status code is: " + response.rc);
// Send the response to the success handler if the http status
// code is 200 or 202. Send the response to the error handler
// otherwise.
if ((response.rc === 200 || response.rc === 202) && handlers.success) {
clientLogs.log("handleResponse(): Got a successful response.");
handlers.success(response);
} else if (handlers.error) {
clientLogs.log("handleResponse(): Got a failure response.");
handlers.error(response);
} else {
clientLogs.log("handleResponse(): Missing the success and/or error handler.");
}
};
},
/**
* Handler for when the REST API response has a HTTP status code >= 200 and < 300.
*
* @param {Object} response
* An object containing the HTTP response.
*/
handleResponseSuccess = function(response) {
clientLogs.log("handleResponseSuccess():");
},
/**
* Handler for when the REST API response has a HTTP status code < 200 and >= 300.
*
* @param {Object} response
* An object containing the HTTP response.
*/
handleResponseError = function(response) {
clientLogs.log("handleResponseError():");
},
/**
* Get the logged in user's participant object
* from the dialog object.
*
* @param {Object} dialog
* An object containing the dialog
* @returns {Object} participant
* The participant object representing the
* logged in user for the given dialog
*/
getParticipant = function (dialog) {
clientLogs.log("getParticipant(): Getting the participant.");
var participants = dialog.getParticipants();
for (var num in participants) {
var participant = participants[num];
// Found the user
if (participant.mediaAddress === user.getExtension()) {
return participant;
}
}
return null;
},
/**
* Determine if UPDATE_CALL_DATA is an allowable action
* for the currently logged in user.
*
* @param {Object} dialog
* An object containing the dialog
* @returns {boolean}
* true if UPDATE_CALL_DATA is allowed
* false otherwise
*/
isUCDAllowableAction = function (dialog) {
clientLogs.log("isUCDAllowableAction(): Checking to see if UPDATE_CALL_DATA is an allowable action.");
var participant = getParticipant(dialog);
if (participant != null) {
// Check the allowable actions
var allowableActions = participant.actions.action;
if (typeof allowableActions === 'string') {
// Make it an array
allowableActions = [allowableActions];
}
if (allowableActions.indexOf(finesse.restservices.Dialog.Actions.UPDATE_CALL_DATA) !== -1) {
clientLogs.log("isUCDAllowableAction(): UPDATE_CALL_DATA is an allowable action.");
return true;
}
}
clientLogs.log("isUCDAllowableAction(): UPDATE_CALL_DATA is not an allowable action.");
return false;
},
/**
* Build the default HTML to display when there isn't a call
* where call variables can be updated.
*/
displayDefaultHtml = function () {
currentDialog = null;
$('#callVariablesDiv').html(defaultHtml);
gadgets.window.adjustHeight();
},
/**
* Build the HTML to display the list of callvariables with
* buttons on the gadget.
*
* @param {Object} dialog
* An object containing the dialog
*/
displayCallVariables = function (dialog) {
// Check to see if the user has UPDATE_CALL_DATA as an allowable action
if(isUCDAllowableAction(dialog)) {
// The user has UPDATE_CALL_DATA as an allowable action
// Build the list of call variables that can be updated
var callVariables = dialog.getMediaProperties();
html = "";
var i = 1;
for (var callVariableName in callVariables) {
clientLogs.log("displayCallVariables(): key is: " + callVariableName);
var callVarMap = { 'userContact_Info' : 'Contact Info' ,
'callVariable3' : 'Contact ID' ,
'userContactName' : 'Contact Name' ,
'userCID' : 'Customer ID' ,
'callVariable2' : 'Customer Name' ,
'userPartnerName' : 'Partner Name' ,
'callVariable4' : 'Priority' ,
'callVariable7' : 'Request Type' ,
'callVariable8' : 'Severity' ,
'callVariable9' : 'Summary of Issue' ,
'callVariable10' : 'Ticket ID' ,
'userVIPType' : 'VIP' } ;
var callVarDisplayName = callVarMap[callVariableName];
if (callVariableName in callVarMap) {
var inputId = "callVariable" + i;
html += "";
html += "";
html += " ";
i++;
}
}
$('#callVariablesDiv').html(html);
gadgets.window.adjustHeight();
} else {
displayDefaultHtml();
}
},
/**
* Handler for when the dialog object changes.
*
* @param {Object} dialog
* The dialog object that has changed
*/
_processCall = function (dialog) {
clientLogs.log("_processCall():");
// See if this dialog is the current active call
var participant = getParticipant(dialog);
if ((participant != null) && (participant.state == 'ACTIVE')) {
currentDialog = dialog;
}
if (currentDialog.getId() === dialog.getId()) {
displayCallVariables(currentDialog);
}
},
/**
* Handler for additions to the Dialogs collection object. This will occur when a new
* Dialog is created on the Finesse server for this user.
*/
handleNewDialog = function (dialog) {
if(isUCDAllowableAction(dialog)) {
currentDialog = dialog;
displayCallVariables(currentDialog);
}
// add a dialog change handler in case the callvars didn't arrive yet
dialog.addHandler('change', _processCall);
},
/**
* Handler for deletions to the Dialogs collection object. This will occur when a
* Dialog is removed from the Finesse server for this user.
*/
handleEndDialog = function (dialog) {
var numDialogs = dialogs.getDialogCount(true);
if (numDialogs == 2) {
dialogCollection = dialogs.getCollection();
for (var dialogId in dialogCollection) {
if (dialogId !== dialog.getId()) {
currentDialog = dialogCollection[dialogId];
displayCallVariables(currentDialog);
}
}
} else {
displayDefaultHtml();
}
},
/**
* Handler for the onLoad of a User object. This occurs when the User object is initially read
* from the Finesse server. Any once only initialization should be done within this function.
*/
_handleUserLoad = function (userevent) {
// Get an instance of the dialogs collection and register handlers for dialog additions and
// removals
dialogs = user.getDialogs( {
onCollectionAdd : handleNewDialog,
onCollectionDelete : handleEndDialog
});
},
/**
* Handler for all User updates
*/
_handleUserChange = function(userevent) { },
/**
* Update the given call variable via the Update Call Data API.
*
* @param {String} name
* The name of the call variable
* {String} value
* The value to set the call variable to
*/
updateCallVariable = function(name, value) {
if (currentDialog) {
clientLogs.log("updateCallVariable(): Updating " + name + " to " + value + " for dialog with id: " + currentDialog.getId());
// Call the Dialog — Update Call Variable Data REST API
var config = finesse.gadget.Config;
var url = config.scheme + "://" + config.host + ":" + config.hostPort + currentDialog.getRestUrl();
clientLogs.log("updateCallVariable(): URL is: " + url);
// Build the content body
var contentBody = {
"Dialog" : {
"requestedAction": finesse.restservices.Dialog.Actions.UPDATE_CALL_DATA,
"mediaProperties": {
"callvariables": {
"CallVariable": {
"name": name,
"value": value
}
}
}
}
};
makeRequest(url, {
method: 'PUT',
authorization: _util.getAuthHeaderString(finesse.gadget.Config),
contentType: 'application/xml',
content: _util.json2xml(contentBody),
}, {
success: handleResponseSuccess,
error: handleResponseError
});
} else {
clientLogs.log("updateCallVariable(): There are currently no active dialogs");
}
};
/** @scope finesse.modules.SampleGadget */
return {
/**
* Update the call variable.
*/
updateCallVariable : function (name, value) {
updateCallVariable(name, value);
},
/**
* Performs all initialization for this gadget
*/
init : function () {
var cfg = finesse.gadget.Config;
_util = finesse.utilities.Utilities;
clientLogs.init(gadgets.Hub, "UpdateCallVariableDataSampleGadget", finesse.gadget.Config); //this gadget id will be logged as a part of the message
// Initiate the ClientServices and the logger and then load the user object. ClientServices are
// initialized with a reference to the current configuration.
finesse.clientservices.ClientServices.init(finesse.gadget.Config);
user = new finesse.restservices.User({
id: cfg.id,
onLoad : _handleUserLoad,
onChange : _handleUserChange
});
displayDefaultHtml();
containerServices = finesse.containerservices.ContainerServices.init();
clientLogs.log("Adding Tab Visible Handler...");
containerServices.addHandler(finesse.containerservices.ContainerServices.Topics.ACTIVE_TAB, function() {
clientLogs.log("Gadget is now visible"); // log to Finesse logger
// automatically adjust the height of the gadget to show the html
gadgets.window.adjustHeight();
});
containerServices.makeActiveTabReq();
}
};
}(jQuery));