This is an old revision of the document!


ECE Finesse Headless Gadget

/**
 * Test Gadget GOR
 *
 * Logs Cisco Finesse dialog events for voice calls and for ECE chats, so you
 * can see exactly when a chat starts, changes and ends.
 *
 * Based on the Cisco DevNet samples: github.com/CiscoDEVNet/finesse-Test-code
 *
 * Event sources:
 *   - user.getDialogs()       -> voice dialogs only
 *   - new Media({id: 5000}) -> the ECE chat media, loaded directly by id
 *     media.getMediaDialogs() -> ECE chat dialogs (new and already active)
 *
 * Note: onCollectionAdd only fires for dialogs created AFTER a collection has
 * loaded. Dialogs that already exist (e.g. after a browser refresh) are found
 * in the onLoad handlers.
 */
 
var finesse = finesse || {};
finesse.gadget = finesse.gadget || {};
finesse.container = finesse.container || {};
finesse.modules = finesse.modules || {};
 
finesse.modules.TestGadgetGOR = (function ($) {
    "use strict";
 
    // ------------------------------------------------------------------
    // Constants
    // ------------------------------------------------------------------
    var GADGET_ID = "TestGadgetGOR";
    var ECE_MEDIA_ID = "5000";   // Media Routing Domain id used by ECE chat
 
    // ------------------------------------------------------------------
    // Module state
    // ------------------------------------------------------------------
    var _logger;                 // finesse.cslogger.ClientLogger (set in init)
    var _user;                   // finesse.restservices.User
    var _dialogs;                // voice dialogs collection
    var _eceMedia;               // finesse.restservices.Media for the ECE chat media
    var _currentDialog = null;   // voice dialog where this agent is ACTIVE
 
    // ------------------------------------------------------------------
    // Helpers
    // ------------------------------------------------------------------
 
    /** Log through the Finesse client logger, prefixed with the calling function. */
    function _log(source, message) {
        if (_logger) {
            _logger.log(source + "(): " + message);
        }
    }
 
    /** Turn a failed REST response into a readable string. */
    function _errText(rsp) {
        return rsp ? (rsp.status + " " + rsp.content) : "no response";
    }
 
    /** Log the commonly useful properties of a dialog. */
    function _logDialogDetails(source, dialog) {
        var callVars = dialog.getMediaProperties() || {};
 
        _log(source, "dialog id: " + dialog.getId());
        _log(source, "MediaType: " + dialog.getMediaType());
        _log(source, "State: " + dialog.getState());
        _log(source, "callType: " + (callVars.callType || ""));
        _log(source, "from (ani): " + dialog.getFromAddress());
        _log(source, "to: " + dialog.getToAddress());
    }
 
    /**
     * Find this agent's participant entry in a dialog (matched by extension).
     * @returns the participant object, or null if the agent isn't in the dialog
     */
    function _getParticipant(dialog) {
        var participants = dialog.getParticipants();
        var extension = _user.getExtension();
 
        for (var key in participants) {
            if (participants.hasOwnProperty(key) &&
                participants[key].mediaAddress === extension) {
                return participants[key];
            }
        }
        return null;
    }
 
    // ------------------------------------------------------------------
    // Voice dialogs (user.getDialogs)
    // ------------------------------------------------------------------
 
    /** A voice dialog was added (or already existed when the gadget loaded). */
    function _handleNewDialog(dialog) {
        _log("_handleNewDialog", "--------");
        _logDialogDetails("_handleNewDialog", dialog);
 
        var participant = _getParticipant(dialog);
        _log("_handleNewDialog", "participant state: " + (participant ? participant.state : "none"));
 
        // Call variables may not have arrived yet, so keep listening for changes.
        dialog.addHandler("change", _updateDialog);
    }
 
    /** A voice dialog changed (call variables, participant state, etc.). */
    function _updateDialog(dialog) {
        _log("_updateDialog", "--------");
        _logDialogDetails("_updateDialog", dialog);
 
        var participant = _getParticipant(dialog);
        _log("_updateDialog", "participant state: " + (participant ? participant.state : "none"));
 
        // Remember the dialog the agent is actively on.
        if (participant && participant.state === "ACTIVE") {
            _currentDialog = dialog;
        }
    }
 
    /** A voice dialog ended. */
    function _handleEndDialog(dialog) {
        _log("_handleEndDialog", "--------");
        _logDialogDetails("_handleEndDialog", dialog);
 
        if (_currentDialog && _currentDialog.getId() === dialog.getId()) {
            _currentDialog = null;
        }
    }
 
    /** The voice dialog collection has loaded: process any existing dialogs. */
    function _handleDialogsLoaded() {
        _log("_handleDialogsLoaded", "--------");
 
        var collection = _dialogs.getCollection();
        for (var id in collection) {
            if (collection.hasOwnProperty(id)) {
                _handleNewDialog(collection[id]);
            }
        }
    }
 
    // ------------------------------------------------------------------
    // ECE chat dialogs (media 5000)
    // ------------------------------------------------------------------
 
    /** A chat dialog was added (or already existed when the gadget loaded). */
    function _handleNewMediaDialog(dialog) {
        _log("_handleNewMediaDialog", "--------");
        _log("_handleNewMediaDialog", "dialog id: " + dialog.getId());
        _log("_handleNewMediaDialog", "MediaType: " + dialog.getMediaType());
        _log("_handleNewMediaDialog", "State: " + dialog.getState());
 
        dialog.addHandler("change", _updateMediaDialog);
    }
 
    /** A chat dialog changed. */
    function _updateMediaDialog(dialog) {
        _log("_updateMediaDialog", "--------");
        _log("_updateMediaDialog", "dialog id: " + dialog.getId());
        _log("_updateMediaDialog", "MediaType: " + dialog.getMediaType());
        _log("_updateMediaDialog", "State: " + dialog.getState());
    }
 
    /** A chat dialog ended. */
    function _handleEndMediaDialog(dialog) {
        _log("_handleEndMediaDialog", "dialog id: " + dialog.getId());
    }
 
    /** The chat dialogs have loaded: process any that are already active. */
    function _handleMediaDialogsLoaded(mediaDialogs) {
        var collection = mediaDialogs.getCollection();
        var count = 0;
 
        for (var id in collection) {
            if (collection.hasOwnProperty(id)) {
                count++;
                _handleNewMediaDialog(collection[id]);
            }
        }
        _log("_handleMediaDialogsLoaded", "existing chat dialogs: " + count);
    }
 
    /** The ECE media object has loaded: subscribe to its chat dialogs. */
    function _handleEceMediaLoaded(media) {
        _log("_handleEceMediaLoaded", "media id: " + ECE_MEDIA_ID + ", name: " + media.getName());
 
        // getMediaDialogs() throws unless the media is loaded, which is why
        // it is called from the media's onLoad handler.
        media.getMediaDialogs({
            onCollectionAdd: _handleNewMediaDialog,
            onCollectionDelete: _handleEndMediaDialog,
            onLoad: _handleMediaDialogsLoaded,
            onError: function (rsp) {
                _log("_handleEceMediaLoaded", "dialogs ERROR: " + _errText(rsp));
            }
        });
    }
 
    // ------------------------------------------------------------------
    // User events
    // ------------------------------------------------------------------
 
    /** The user object has loaded: start listening for dialogs. */
    function _handleUserLoad() {
        _log("_handleUserLoad", "agent state: " + _user.getState());
 
        // 1. Voice dialogs
        _dialogs = _user.getDialogs({
            onCollectionAdd: _handleNewDialog,
            onCollectionDelete: _handleEndDialog,
            onLoad: _handleDialogsLoaded
        });
 
        // 2. ECE chat dialogs. Load the ECE media directly by id; its parent
        //    is the user, so the REST path is .../User/<id>/Media/5000
        _eceMedia = new finesse.restservices.Media({
            id: ECE_MEDIA_ID,
            parentObj: _user,
            onLoad: _handleEceMediaLoaded,
            onError: function (rsp) {
                _log("_handleUserLoad", "ECE media ERROR: " + _errText(rsp));
            }
        });
    }
 
    /** Any change to the user (e.g. agent state). */
    function _handleUserChange() {
        _log("_handleUserChange", "agent state: " + _user.getState());
    }
 
    // ------------------------------------------------------------------
    // Public API
    // ------------------------------------------------------------------
    return {
        /** Performs all initialization for this gadget. */
        init: function () {
            var config = finesse.gadget.Config;
 
            // Set up the Finesse client logger. The gadget id is included in each message.
            _logger = finesse.cslogger.ClientLogger;
            _logger.init(gadgets.Hub, GADGET_ID, config);
            _log("init", "Initializing...");
 
            // Initialise ClientServices with the current config, then load the user.
            finesse.clientservices.ClientServices.init(config, false);
 
            _user = new finesse.restservices.User({
                id: config.id,
                onLoad: _handleUserLoad,
                onChange: _handleUserChange
            });
 
            // When this gadget's tab becomes visible, re-adjust the height.
            // adjustHeight only works on a visible tab, so without this the
            // gadget is the wrong size on load until the page is refreshed.
            var containerServices = finesse.containerservices.ContainerServices.init();
            containerServices.addHandler(
                finesse.containerservices.ContainerServices.Topics.ACTIVE_TAB,
                function () {
                    _log("init", "Gadget is now visible");
                    gadgets.window.adjustHeight();
                }
            );
            containerServices.makeActiveTabReq();
 
            _log("init", "Initialization finished.");
        }
    };
}(jQuery));
  • vendors/cisco/uc/ece/finesse-headless-gadget.1791296557.txt.gz
  • Last modified: 2026/10/06 15:22
  • by gerardorourke