From: Andrea Bianco Date: Mon, 6 Apr 2020 10:33:16 +0000 (+0200) Subject: Built motion from commit (unavailable).|2.4.13 X-Git-Url: http://repos.xcallymotion.com/base/%22https:/wiki.xcallymotion.com/display/XMV//%22?a=commitdiff_plain;h=52c4901c90a2d744c90b8d57ae5a78edf7f48ae2;p=motion2.git Built motion from commit (unavailable).|2.4.13 --- diff --git a/apidoc/api_project.js b/apidoc/api_project.js index 8fba0f3..ac9439c 100644 --- a/apidoc/api_project.js +++ b/apidoc/api_project.js @@ -17,7 +17,7 @@ define({ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2020-04-06T08:16:03.852Z", + "time": "2020-04-06T10:20:59.269Z", "url": "http://apidocjs.com", "version": "0.20.1" } diff --git a/apidoc/api_project.json b/apidoc/api_project.json index c008b26..ae7bb18 100644 --- a/apidoc/api_project.json +++ b/apidoc/api_project.json @@ -17,7 +17,7 @@ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2020-04-06T08:16:03.852Z", + "time": "2020-04-06T10:20:59.269Z", "url": "http://apidocjs.com", "version": "0.20.1" } diff --git a/public/app/main/apps/dashboards/i18n/en.json b/public/app/main/apps/dashboards/i18n/en.json index b7855aa..441f2f7 100644 --- a/public/app/main/apps/dashboards/i18n/en.json +++ b/public/app/main/apps/dashboards/i18n/en.json @@ -511,6 +511,35 @@ "TO": "To", "INVOICEEMITED": "Issued", "INVOICEPAYED": "Payed", - "INVOICETOTAL": "Total" + "INVOICETOTAL": "Total", + "ADVANCED_SEARCH": "Advanced Search", + "NEW_CONDITION": "New Condition", + "SELECT_FIELD": "Select field", + "SELECT_OPERATOR": "Select operator", + "VALUE": "Value", + "VALUES": "Values", + "APPLY": "Apply", + "MEET_ALL_CONDITIONS": "Meet all conditions", + "MEET_ANY_CONDITIONS": "Meet at least one condition", + "EQUALS": "Equals", + "IS_NOT_EQUAL": "Does not equal", + "IS_AMONG": "Is among", + "IS_NOT_AMONG": "Is not among", + "IS_GREATER_THAN": "Is greater than", + "IS_GREATER_THAN_OR_EQUAL_TO": "Is greater than or equal to", + "IS_LESS_THAN": "Is less than", + "IS_LESS_THAN_OR_EQUAL_TO": "Is less than or equal to", + "IS_BETWEEN": "Is between", + "CONTAINS": "Contains", + "STARTS_WITH": "Starts with", + "ENDS_WITH": "Ends with", + "STARTING_DATE": "Starting date", + "ENDING_DATE": "Ending date", + "STARTING_VALUE": "Starting value", + "ENDING_VALUE": "Ending value", + "VALUE_RANGE_CHECK": "Value must be greater than", + "AND": "And", + "ENABLED": "Enabled", + "DISABLED": "Disabled" } -} \ No newline at end of file +} diff --git a/public/app/main/apps/dashboards/i18n/it.json b/public/app/main/apps/dashboards/i18n/it.json index bf3d80b..a993a63 100644 --- a/public/app/main/apps/dashboards/i18n/it.json +++ b/public/app/main/apps/dashboards/i18n/it.json @@ -124,6 +124,7 @@ "RATING": "Valutazione", "FEEDBACK": "Feedback", "SUBJECT": "Oggetto", + "CUSTOMER_IP": "IP Cliente", "REFERER": "Referer", "WEBSITE": "Sito Web", "AGENT": "Agente", @@ -196,8 +197,8 @@ "DROP_RATE": "Il tasso di chiamate in coda non andate a buon fine", "ORIGINATEDLIMITED": "Chiamate generate dalle campagne", "EXACT_MATCH_FILTER": "Cerca una corrispondenza esatta", - "LIKE_FILTER": "Cerca il modello specificato", - "MANDATORY_DISPOSITION_ENABLED": "Disposizione obbligatoria abilitata per questo account" + "LIKE_FILTER": "Cerca il modello specificato", + "MANDATORY_DISPOSITION_ENABLED": "Disposizione obbligatoria abilitata per questo account" }, "NO_AVAILABLE_INFO": "Nessuna informazione disponibile", "WELCOME_TO_MOTION": "Benvenuto in Motion", @@ -320,25 +321,27 @@ "TRANSFER_NUMBER": "Trasferisci", "CALL_SAVED": "Chiamata salvata correttamente", "CALL_DISPOSED": "Chiamata disposta correttamente", + "CUSTOMER_PORT": "Porta di origine del cliente", "AGENTS": "Agents", "INTERACTION_CLOSED": "Interazione chiusa correttamente", "INTERACTION_DISPOSED": "Interazione disposta correttamente", "INTERACTION_CLOSED_DISPOSED": "Interazione chiusa e disposta correttamente", "SELECT_ALL": "Seleziona tutti", - "ASSIGNED_TO_OTHERS": "Assegnate ad altri", - "CHAT_INTERACTIONS": "Interazioni Chat", - "FAX_INTERACTIONS": "Interazioni Fax", - "MAIL_INTERACTIONS": "Interazioni Email", - "OPENCHANNEL_INTERACTIONS": "Interazioni Open Channel", - "SMS_INTERACTIONS": "Interazioni SMS", - "DRAFT": "Bozza", - "DRAFT_SAVE_WARNING_TITLE": "Sovrascrivere bozza esistente?", - "DRAFT_SAVE_WARNING_MESSAGE": "C'è già una bozza salvata per questa interazione. Sei sicuro di volerla sovrascrivere?", - "OVERWRITE": "Sovrascrivi", - "CANCEL": "Annulla", - "UNTITLED": "Senza nome", - "SAVE_AS_DRAFT": "Salva come bozza", + "ASSIGNED_TO_OTHERS": "Assegnate ad altri", + "CHAT_INTERACTIONS": "Interazioni Chat", + "FAX_INTERACTIONS": "Interazioni Fax", + "MAIL_INTERACTIONS": "Interazioni Email", + "OPENCHANNEL_INTERACTIONS": "Interazioni Open Channel", + "SMS_INTERACTIONS": "Interazioni SMS", + "DRAFT": "Bozza", + "DRAFT_SAVE_WARNING_TITLE": "Sovrascrivere bozza esistente?", + "DRAFT_SAVE_WARNING_MESSAGE": "C'è già una bozza salvata per questa interazione. Sei sicuro di volerla sovrascrivere?", + "OVERWRITE": "Sovrascrivi", + "CANCEL": "Annulla", + "UNTITLED": "Senza nome", + "SAVE_AS_DRAFT": "Salva come bozza", "UPDATE_DRAFT": "Aggiorna bozza", + "NO_AVAILABLE_INTERACTION" : "Nessuna interazione disponibile", "DOSSIERS": "Pratiche", "DOSSIER": "Pratica", "DOSSIER_INFO": "Informazioni", @@ -509,8 +512,34 @@ "INVOICEEMITED": "Emesse", "INVOICEPAYED": "Pagate", "INVOICETOTAL": "Totale", - "NO_AVAILABLE_INTERACTION": "Nessuna interazione disponibile", - "CUSTOMER_IP": "Indirizzo IP di origine", - "CUSTOMER_PORT": "Porta TCP di origine" + "ADVANCED_SEARCH": "Ricerca Avanzata", + "NEW_CONDITION": "Nuova Condizione", + "SELECT_FIELD": "Seleziona campo", + "SELECT_OPERATOR": "Seleziona operatore", + "VALUE": "Valore", + "VALUES": "Valori", + "APPLY": "Applica", + "MEET_ALL_CONDITIONS": "Soddisfa tutte le condizioni", + "MEET_ANY_CONDITIONS": "Soddisfa almeno una condizione", + "EQUALS": "È uguale a", + "IS_NOT_EQUAL": "È diverso da", + "IS_AMONG": "È compreso tra", + "IS_NOT_AMONG": "Non è compreso tra", + "IS_GREATER_THAN": "È maggiore di", + "IS_GREATER_THAN_OR_EQUAL_TO": "È maggiore o uguale di", + "IS_LESS_THAN": "È minore di", + "IS_LESS_THAN_OR_EQUAL_TO": "È minore o uguale di", + "IS_BETWEEN": "È compreso tra", + "CONTAINS": "Contiene", + "STARTS_WITH": "Inizia con", + "ENDS_WITH": "Finisce con", + "STARTING_DATE": "Data inizio", + "ENDING_DATE": "Data fine", + "STARTING_VALUE": "Valore iniziale", + "ENDING_VALUE": "Valore finale", + "VALUE_RANGE_CHECK": "Il valore deve essere maggiore di", + "AND": "E", + "ENABLED": "Abilitato", + "DISABLED": "Disabilitato" } -} \ No newline at end of file +} diff --git a/public/app/toolbar/i18n/en.json b/public/app/toolbar/i18n/en.json index 864237d..5df0521 100644 --- a/public/app/toolbar/i18n/en.json +++ b/public/app/toolbar/i18n/en.json @@ -94,9 +94,6 @@ }, "BRAZILIAN": "Brazilian", "ESTONIAN": "Estonian", - "CZECH": "Czech", - "WEBRTC_MICROPHONE_NOT_AVAILABLE": "No microphone available", - "WEBRTC_SPEAKER_NOT_AVAILABLE": "No speaker available", - "WEBRTC_AUDIO_DEVICES_NOT_AVAILABLE": "No audio devices available" + "CZECH": "Czech" } } \ No newline at end of file diff --git a/public/assets/plugins/jabra/jabra.browser.integration-2.0.js b/public/assets/plugins/jabra/jabra.browser.integration-2.0.js index 45454c7..de1c77d 100644 --- a/public/assets/plugins/jabra/jabra.browser.integration-2.0.js +++ b/public/assets/plugins/jabra/jabra.browser.integration-2.0.js @@ -25,1176 +25,1432 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + /** * The global jabra object is your entry for the jabra browser SDK. */ + +function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } + +function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } + +function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } + +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } + +function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } + +function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } + +function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } + +function _instanceof(left, right) { if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); } + +function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } + +function _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } + +function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + var jabra; + (function (jabra) { - /** - * Version of this javascript api (should match version number in file apart from possible alfa/beta designator). - */ - jabra.apiVersion = "2.0.1"; - /** - * Is the current version a beta ? - */ - const isBeta = jabra.apiVersion.includes("beta"); - /** - * Id of proper (production) release of browser plugin. - */ - const prodExtensionId = "okpeabepajdgiepelmhkfhkjlhhmofma"; - /** - * Id of beta release of browser plugin. - */ - const betaExtensionId = "igcbbdnhomedfadljgcmcfpdcoonihfe"; - ; - ; - ; - /** - * Names of command response events. - */ - const commandEventsList = [ - "devices", - "activedevice", - "getinstallinfo", - "Version", - "setmmifocus", - "setactivedevice2", - "setbusylight", - "setremotemmilightaction" - ]; - /** - * All possible device events as internal array. - */ - let eventNamesList = ["mute", "unmute", "device attached", "device detached", "acceptcall", - "endcall", "reject", "flash", "online", "offline", "linebusy", "lineidle", - "redial", "key0", "key1", "key2", "key3", "key4", "key5", - "key6", "key7", "key8", "key9", "keyStar", "keyPound", - "keyClear", "Online", "speedDial", "voiceMail", "LineBusy", - "outOfRange", "intoRange", "pseudoAcceptcall", "pseudoEndcall", - "button1", "button2", "button3", "volumeUp", "volumeDown", "fireAlarm", - "jackConnection", "jackDisConnection", "qdConnection", "qdDisconnection", - "headsetConnection", "headsetDisConnection", "devlog", "busylight", - "hearThrough", "batteryStatus", "gnpButton", "mmi", "error"]; - /** - * Error status codes returned by SDK. Same as Jabra_ErrorStatus in native SDK. - */ - let ErrorCodes; - (function (ErrorCodes) { - ErrorCodes[ErrorCodes["NoError"] = 0] = "NoError"; - ErrorCodes[ErrorCodes["SSLError"] = 1] = "SSLError"; - ErrorCodes[ErrorCodes["CertError"] = 2] = "CertError"; - ErrorCodes[ErrorCodes["NetworkError"] = 3] = "NetworkError"; - ErrorCodes[ErrorCodes["DownloadError"] = 4] = "DownloadError"; - ErrorCodes[ErrorCodes["ParseError"] = 5] = "ParseError"; - ErrorCodes[ErrorCodes["OtherError"] = 6] = "OtherError"; - ErrorCodes[ErrorCodes["DeviceInfoError"] = 7] = "DeviceInfoError"; - ErrorCodes[ErrorCodes["FileNotAccessible"] = 8] = "FileNotAccessible"; - ErrorCodes[ErrorCodes["FileNotCompatible"] = 9] = "FileNotCompatible"; - ErrorCodes[ErrorCodes["Device_NotFound"] = 10] = "Device_NotFound"; - ErrorCodes[ErrorCodes["Parameter_fail"] = 11] = "Parameter_fail"; - ErrorCodes[ErrorCodes["Authorization_failed"] = 12] = "Authorization_failed"; - ErrorCodes[ErrorCodes["FileNotAvailable"] = 13] = "FileNotAvailable"; - ErrorCodes[ErrorCodes["ConfigParseError"] = 14] = "ConfigParseError"; - ErrorCodes[ErrorCodes["SetSettings_Fail"] = 15] = "SetSettings_Fail"; - ErrorCodes[ErrorCodes["Device_Reboot"] = 16] = "Device_Reboot"; - ErrorCodes[ErrorCodes["Device_ReadFail"] = 17] = "Device_ReadFail"; - ErrorCodes[ErrorCodes["Device_NotReady"] = 18] = "Device_NotReady"; - ErrorCodes[ErrorCodes["FilePartiallyCompatible"] = 19] = "FilePartiallyCompatible"; - })(ErrorCodes = jabra.ErrorCodes || (jabra.ErrorCodes = {})); - ; - /** - * Error return codes. Same as Jabra_ReturnCode in native SDK. - */ - let ErrorReturnCodes; - (function (ErrorReturnCodes) { - ErrorReturnCodes[ErrorReturnCodes["Return_Ok"] = 0] = "Return_Ok"; - ErrorReturnCodes[ErrorReturnCodes["Device_Unknown"] = 1] = "Device_Unknown"; - ErrorReturnCodes[ErrorReturnCodes["Device_Invalid"] = 2] = "Device_Invalid"; - ErrorReturnCodes[ErrorReturnCodes["Not_Supported"] = 3] = "Not_Supported"; - ErrorReturnCodes[ErrorReturnCodes["Return_ParameterFail"] = 4] = "Return_ParameterFail"; - ErrorReturnCodes[ErrorReturnCodes["ProtectedSetting_Write"] = 5] = "ProtectedSetting_Write"; - ErrorReturnCodes[ErrorReturnCodes["No_Information"] = 6] = "No_Information"; - ErrorReturnCodes[ErrorReturnCodes["NetworkRequest_Fail"] = 7] = "NetworkRequest_Fail"; - ErrorReturnCodes[ErrorReturnCodes["Device_WriteFail"] = 8] = "Device_WriteFail"; - ErrorReturnCodes[ErrorReturnCodes["Device_ReadFails"] = 9] = "Device_ReadFails"; - ErrorReturnCodes[ErrorReturnCodes["No_FactorySupported"] = 10] = "No_FactorySupported"; - ErrorReturnCodes[ErrorReturnCodes["System_Error"] = 11] = "System_Error"; - ErrorReturnCodes[ErrorReturnCodes["Device_BadState"] = 12] = "Device_BadState"; - ErrorReturnCodes[ErrorReturnCodes["FileWrite_Fail"] = 13] = "FileWrite_Fail"; - ErrorReturnCodes[ErrorReturnCodes["File_AlreadyExists"] = 14] = "File_AlreadyExists"; - ErrorReturnCodes[ErrorReturnCodes["File_Not_Accessible"] = 15] = "File_Not_Accessible"; - ErrorReturnCodes[ErrorReturnCodes["Firmware_UpToDate"] = 16] = "Firmware_UpToDate"; - ErrorReturnCodes[ErrorReturnCodes["Firmware_Available"] = 17] = "Firmware_Available"; - ErrorReturnCodes[ErrorReturnCodes["Return_Async"] = 18] = "Return_Async"; - ErrorReturnCodes[ErrorReturnCodes["Invalid_Authorization"] = 19] = "Invalid_Authorization"; - ErrorReturnCodes[ErrorReturnCodes["FWU_Application_Not_Available"] = 20] = "FWU_Application_Not_Available"; - ErrorReturnCodes[ErrorReturnCodes["Device_AlreadyConnected"] = 21] = "Device_AlreadyConnected"; - ErrorReturnCodes[ErrorReturnCodes["Device_NotConnected"] = 22] = "Device_NotConnected"; - ErrorReturnCodes[ErrorReturnCodes["CannotClear_DeviceConnected"] = 23] = "CannotClear_DeviceConnected"; - ErrorReturnCodes[ErrorReturnCodes["Device_Rebooted"] = 24] = "Device_Rebooted"; - ErrorReturnCodes[ErrorReturnCodes["Upload_AlreadyInProgress"] = 25] = "Upload_AlreadyInProgress"; - ErrorReturnCodes[ErrorReturnCodes["Download_AlreadyInProgress"] = 26] = "Download_AlreadyInProgress"; - })(ErrorReturnCodes = jabra.ErrorReturnCodes || (jabra.ErrorReturnCodes = {})); - ; - /** - * Custom error returned by commands expecting results when failing. - */ - class CommandError extends Error { - constructor(command, errmessage, data) { - super("Command " + command + " failed with error message " + errmessage + " and details: " + JSON.stringify(data || {})); - this.command = command; - this.errmessage = errmessage; - this.data = data; - this.name = 'CommandError'; - } + /** + * Version of this javascript api (should match version number in file apart from possible alfa/beta designator). + */ + jabra.apiVersion = "2.0.1"; + /** + * Is the current version a beta ? + */ + + var isBeta = jabra.apiVersion.includes("beta"); + /** + * Id of proper (production) release of browser plugin. + */ + + var prodExtensionId = "okpeabepajdgiepelmhkfhkjlhhmofma"; + /** + * Id of beta release of browser plugin. + */ + + var betaExtensionId = "igcbbdnhomedfadljgcmcfpdcoonihfe"; + ; + ; + ; + /** + * Names of command response events. + */ + + var commandEventsList = ["devices", "activedevice", "getinstallinfo", "Version", "setmmifocus", "setactivedevice2", "setbusylight", "setremotemmilightaction"]; + /** + * All possible device events as internal array. + */ + + var eventNamesList = ["mute", "unmute", "device attached", "device detached", "acceptcall", "endcall", "reject", "flash", "online", "offline", "linebusy", "lineidle", "redial", "key0", "key1", "key2", "key3", "key4", "key5", "key6", "key7", "key8", "key9", "keyStar", "keyPound", "keyClear", "Online", "speedDial", "voiceMail", "LineBusy", "outOfRange", "intoRange", "pseudoAcceptcall", "pseudoEndcall", "button1", "button2", "button3", "volumeUp", "volumeDown", "fireAlarm", "jackConnection", "jackDisConnection", "qdConnection", "qdDisconnection", "headsetConnection", "headsetDisConnection", "devlog", "busylight", "hearThrough", "batteryStatus", "gnpButton", "mmi", "error"]; + /** + * Error status codes returned by SDK. Same as Jabra_ErrorStatus in native SDK. + */ + + var ErrorCodes; + + (function (ErrorCodes) { + ErrorCodes[ErrorCodes["NoError"] = 0] = "NoError"; + ErrorCodes[ErrorCodes["SSLError"] = 1] = "SSLError"; + ErrorCodes[ErrorCodes["CertError"] = 2] = "CertError"; + ErrorCodes[ErrorCodes["NetworkError"] = 3] = "NetworkError"; + ErrorCodes[ErrorCodes["DownloadError"] = 4] = "DownloadError"; + ErrorCodes[ErrorCodes["ParseError"] = 5] = "ParseError"; + ErrorCodes[ErrorCodes["OtherError"] = 6] = "OtherError"; + ErrorCodes[ErrorCodes["DeviceInfoError"] = 7] = "DeviceInfoError"; + ErrorCodes[ErrorCodes["FileNotAccessible"] = 8] = "FileNotAccessible"; + ErrorCodes[ErrorCodes["FileNotCompatible"] = 9] = "FileNotCompatible"; + ErrorCodes[ErrorCodes["Device_NotFound"] = 10] = "Device_NotFound"; + ErrorCodes[ErrorCodes["Parameter_fail"] = 11] = "Parameter_fail"; + ErrorCodes[ErrorCodes["Authorization_failed"] = 12] = "Authorization_failed"; + ErrorCodes[ErrorCodes["FileNotAvailable"] = 13] = "FileNotAvailable"; + ErrorCodes[ErrorCodes["ConfigParseError"] = 14] = "ConfigParseError"; + ErrorCodes[ErrorCodes["SetSettings_Fail"] = 15] = "SetSettings_Fail"; + ErrorCodes[ErrorCodes["Device_Reboot"] = 16] = "Device_Reboot"; + ErrorCodes[ErrorCodes["Device_ReadFail"] = 17] = "Device_ReadFail"; + ErrorCodes[ErrorCodes["Device_NotReady"] = 18] = "Device_NotReady"; + ErrorCodes[ErrorCodes["FilePartiallyCompatible"] = 19] = "FilePartiallyCompatible"; + })(ErrorCodes = jabra.ErrorCodes || (jabra.ErrorCodes = {})); + + ; + /** + * Error return codes. Same as Jabra_ReturnCode in native SDK. + */ + + var ErrorReturnCodes; + + (function (ErrorReturnCodes) { + ErrorReturnCodes[ErrorReturnCodes["Return_Ok"] = 0] = "Return_Ok"; + ErrorReturnCodes[ErrorReturnCodes["Device_Unknown"] = 1] = "Device_Unknown"; + ErrorReturnCodes[ErrorReturnCodes["Device_Invalid"] = 2] = "Device_Invalid"; + ErrorReturnCodes[ErrorReturnCodes["Not_Supported"] = 3] = "Not_Supported"; + ErrorReturnCodes[ErrorReturnCodes["Return_ParameterFail"] = 4] = "Return_ParameterFail"; + ErrorReturnCodes[ErrorReturnCodes["ProtectedSetting_Write"] = 5] = "ProtectedSetting_Write"; + ErrorReturnCodes[ErrorReturnCodes["No_Information"] = 6] = "No_Information"; + ErrorReturnCodes[ErrorReturnCodes["NetworkRequest_Fail"] = 7] = "NetworkRequest_Fail"; + ErrorReturnCodes[ErrorReturnCodes["Device_WriteFail"] = 8] = "Device_WriteFail"; + ErrorReturnCodes[ErrorReturnCodes["Device_ReadFails"] = 9] = "Device_ReadFails"; + ErrorReturnCodes[ErrorReturnCodes["No_FactorySupported"] = 10] = "No_FactorySupported"; + ErrorReturnCodes[ErrorReturnCodes["System_Error"] = 11] = "System_Error"; + ErrorReturnCodes[ErrorReturnCodes["Device_BadState"] = 12] = "Device_BadState"; + ErrorReturnCodes[ErrorReturnCodes["FileWrite_Fail"] = 13] = "FileWrite_Fail"; + ErrorReturnCodes[ErrorReturnCodes["File_AlreadyExists"] = 14] = "File_AlreadyExists"; + ErrorReturnCodes[ErrorReturnCodes["File_Not_Accessible"] = 15] = "File_Not_Accessible"; + ErrorReturnCodes[ErrorReturnCodes["Firmware_UpToDate"] = 16] = "Firmware_UpToDate"; + ErrorReturnCodes[ErrorReturnCodes["Firmware_Available"] = 17] = "Firmware_Available"; + ErrorReturnCodes[ErrorReturnCodes["Return_Async"] = 18] = "Return_Async"; + ErrorReturnCodes[ErrorReturnCodes["Invalid_Authorization"] = 19] = "Invalid_Authorization"; + ErrorReturnCodes[ErrorReturnCodes["FWU_Application_Not_Available"] = 20] = "FWU_Application_Not_Available"; + ErrorReturnCodes[ErrorReturnCodes["Device_AlreadyConnected"] = 21] = "Device_AlreadyConnected"; + ErrorReturnCodes[ErrorReturnCodes["Device_NotConnected"] = 22] = "Device_NotConnected"; + ErrorReturnCodes[ErrorReturnCodes["CannotClear_DeviceConnected"] = 23] = "CannotClear_DeviceConnected"; + ErrorReturnCodes[ErrorReturnCodes["Device_Rebooted"] = 24] = "Device_Rebooted"; + ErrorReturnCodes[ErrorReturnCodes["Upload_AlreadyInProgress"] = 25] = "Upload_AlreadyInProgress"; + ErrorReturnCodes[ErrorReturnCodes["Download_AlreadyInProgress"] = 26] = "Download_AlreadyInProgress"; + })(ErrorReturnCodes = jabra.ErrorReturnCodes || (jabra.ErrorReturnCodes = {})); + + ; + /** + * Custom error returned by commands expecting results when failing. + */ + + var CommandError = + /*#__PURE__*/ + function (_Error) { + _inherits(CommandError, _Error); + + function CommandError(command, errmessage, data) { + var _this; + + _classCallCheck(this, CommandError); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(CommandError).call(this, "Command " + command + " failed with error message " + errmessage + " and details: " + JSON.stringify(data || {}))); + _this.command = command; + _this.errmessage = errmessage; + _this.data = data; + _this.name = 'CommandError'; + return _this; } - jabra.CommandError = CommandError; - ; - ; - /** - * Internal mapping from all known events to array of registered callbacks. All possible events are setup - * initially. Callbacks values are configured at runtime. - */ - const eventListeners = new Map(); - eventNamesList.forEach((event) => eventListeners.set(event, [])); - /** - * Device feature codes. - */ - let DeviceFeature; - (function (DeviceFeature) { - DeviceFeature[DeviceFeature["BusyLight"] = 1000] = "BusyLight"; - DeviceFeature[DeviceFeature["FactoryReset"] = 1001] = "FactoryReset"; - DeviceFeature[DeviceFeature["PairingList"] = 1002] = "PairingList"; - DeviceFeature[DeviceFeature["RemoteMMI"] = 1003] = "RemoteMMI"; - DeviceFeature[DeviceFeature["MusicEqualizer"] = 1004] = "MusicEqualizer"; - DeviceFeature[DeviceFeature["EarbudInterconnectionStatus"] = 1005] = "EarbudInterconnectionStatus"; - DeviceFeature[DeviceFeature["StepRate"] = 1006] = "StepRate"; - DeviceFeature[DeviceFeature["HeartRate"] = 1007] = "HeartRate"; - DeviceFeature[DeviceFeature["RRInterval"] = 1008] = "RRInterval"; - DeviceFeature[DeviceFeature["RingtoneUpload"] = 1009] = "RingtoneUpload"; - DeviceFeature[DeviceFeature["ImageUpload"] = 1010] = "ImageUpload"; - DeviceFeature[DeviceFeature["NeedsExplicitRebootAfterOta"] = 1011] = "NeedsExplicitRebootAfterOta"; - DeviceFeature[DeviceFeature["NeedsToBePutIncCradleToCompleteFwu"] = 1012] = "NeedsToBePutIncCradleToCompleteFwu"; - DeviceFeature[DeviceFeature["RemoteMMIv2"] = 1013] = "RemoteMMIv2"; - DeviceFeature[DeviceFeature["Logging"] = 1014] = "Logging"; - DeviceFeature[DeviceFeature["PreferredSoftphoneListInDevice"] = 1015] = "PreferredSoftphoneListInDevice"; - DeviceFeature[DeviceFeature["VoiceAssistant"] = 1016] = "VoiceAssistant"; - DeviceFeature[DeviceFeature["PlayRingtone"] = 1017] = "PlayRingtone"; - })(DeviceFeature = jabra.DeviceFeature || (jabra.DeviceFeature = {})); - ; - /** - * A specification of a button for MMI capturing. - */ - let RemoteMmiType; - (function (RemoteMmiType) { - RemoteMmiType[RemoteMmiType["MMI_TYPE_MFB"] = 0] = "MMI_TYPE_MFB"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_VOLUP"] = 1] = "MMI_TYPE_VOLUP"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_VOLDOWN"] = 2] = "MMI_TYPE_VOLDOWN"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_VCB"] = 3] = "MMI_TYPE_VCB"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_APP"] = 4] = "MMI_TYPE_APP"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_TR_FORW"] = 5] = "MMI_TYPE_TR_FORW"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_TR_BACK"] = 6] = "MMI_TYPE_TR_BACK"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_PLAY"] = 7] = "MMI_TYPE_PLAY"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_MUTE"] = 8] = "MMI_TYPE_MUTE"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_HOOK_OFF"] = 9] = "MMI_TYPE_HOOK_OFF"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_HOOK_ON"] = 10] = "MMI_TYPE_HOOK_ON"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_BLUETOOTH"] = 11] = "MMI_TYPE_BLUETOOTH"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_JABRA"] = 12] = "MMI_TYPE_JABRA"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_BATTERY"] = 13] = "MMI_TYPE_BATTERY"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_PROG"] = 14] = "MMI_TYPE_PROG"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_LINK"] = 15] = "MMI_TYPE_LINK"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_ANC"] = 16] = "MMI_TYPE_ANC"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_LISTEN_IN"] = 17] = "MMI_TYPE_LISTEN_IN"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_DOT3"] = 18] = "MMI_TYPE_DOT3"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_DOT4"] = 19] = "MMI_TYPE_DOT4"; - RemoteMmiType[RemoteMmiType["MMI_TYPE_ALL"] = 255] = "MMI_TYPE_ALL"; - })(RemoteMmiType = jabra.RemoteMmiType || (jabra.RemoteMmiType = {})); - ; - /** - * A MMI effect specification for light on, off or blinking in different tempo. - */ - let RemoteMmiSequence; - (function (RemoteMmiSequence) { - RemoteMmiSequence[RemoteMmiSequence["MMI_LED_SEQUENCE_OFF"] = 0] = "MMI_LED_SEQUENCE_OFF"; - RemoteMmiSequence[RemoteMmiSequence["MMI_LED_SEQUENCE_ON"] = 1] = "MMI_LED_SEQUENCE_ON"; - RemoteMmiSequence[RemoteMmiSequence["MMI_LED_SEQUENCE_SLOW"] = 2] = "MMI_LED_SEQUENCE_SLOW"; - RemoteMmiSequence[RemoteMmiSequence["MMI_LED_SEQUENCE_FAST"] = 3] = "MMI_LED_SEQUENCE_FAST"; - })(RemoteMmiSequence = jabra.RemoteMmiSequence || (jabra.RemoteMmiSequence = {})); - ; - /** - * MMI button actions reported when button has focus. - */ - let RemoteMmiActionInput; - (function (RemoteMmiActionInput) { - RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_UP"] = 1] = "MMI_ACTION_UP"; - RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_DOWN"] = 2] = "MMI_ACTION_DOWN"; - RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_TAP"] = 4] = "MMI_ACTION_TAP"; - RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_DOUBLE_TAP"] = 8] = "MMI_ACTION_DOUBLE_TAP"; - RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_PRESS"] = 16] = "MMI_ACTION_PRESS"; - RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_LONG_PRESS"] = 32] = "MMI_ACTION_LONG_PRESS"; - RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_X_LONG_PRESS"] = 64] = "MMI_ACTION_X_LONG_PRESS"; - })(RemoteMmiActionInput = jabra.RemoteMmiActionInput || (jabra.RemoteMmiActionInput = {})); - ; - /** - * The log level currently used internally in this api facade. Initially this is set to show errors and - * warnings until a logEvent (>=0.5) changes this when initializing the extension or when the user - * changes the log level. Available in the API for testing only - do not use this in normal applications. - */ - jabra.logLevel = 2; - /** - * An internal logger helper. - */ - const logger = new class { - trace(msg) { - if (jabra.logLevel >= 4) { - console.log(msg); - } + + return CommandError; + }(_wrapNativeSuper(Error)); + + jabra.CommandError = CommandError; + ; + ; + /** + * Internal mapping from all known events to array of registered callbacks. All possible events are setup + * initially. Callbacks values are configured at runtime. + */ + + var eventListeners = new Map(); + eventNamesList.forEach(function (event) { + return eventListeners.set(event, []); + }); + /** + * Device feature codes. + */ + + var DeviceFeature; + + (function (DeviceFeature) { + DeviceFeature[DeviceFeature["BusyLight"] = 1000] = "BusyLight"; + DeviceFeature[DeviceFeature["FactoryReset"] = 1001] = "FactoryReset"; + DeviceFeature[DeviceFeature["PairingList"] = 1002] = "PairingList"; + DeviceFeature[DeviceFeature["RemoteMMI"] = 1003] = "RemoteMMI"; + DeviceFeature[DeviceFeature["MusicEqualizer"] = 1004] = "MusicEqualizer"; + DeviceFeature[DeviceFeature["EarbudInterconnectionStatus"] = 1005] = "EarbudInterconnectionStatus"; + DeviceFeature[DeviceFeature["StepRate"] = 1006] = "StepRate"; + DeviceFeature[DeviceFeature["HeartRate"] = 1007] = "HeartRate"; + DeviceFeature[DeviceFeature["RRInterval"] = 1008] = "RRInterval"; + DeviceFeature[DeviceFeature["RingtoneUpload"] = 1009] = "RingtoneUpload"; + DeviceFeature[DeviceFeature["ImageUpload"] = 1010] = "ImageUpload"; + DeviceFeature[DeviceFeature["NeedsExplicitRebootAfterOta"] = 1011] = "NeedsExplicitRebootAfterOta"; + DeviceFeature[DeviceFeature["NeedsToBePutIncCradleToCompleteFwu"] = 1012] = "NeedsToBePutIncCradleToCompleteFwu"; + DeviceFeature[DeviceFeature["RemoteMMIv2"] = 1013] = "RemoteMMIv2"; + DeviceFeature[DeviceFeature["Logging"] = 1014] = "Logging"; + DeviceFeature[DeviceFeature["PreferredSoftphoneListInDevice"] = 1015] = "PreferredSoftphoneListInDevice"; + DeviceFeature[DeviceFeature["VoiceAssistant"] = 1016] = "VoiceAssistant"; + DeviceFeature[DeviceFeature["PlayRingtone"] = 1017] = "PlayRingtone"; + })(DeviceFeature = jabra.DeviceFeature || (jabra.DeviceFeature = {})); + + ; + /** + * A specification of a button for MMI capturing. + */ + + var RemoteMmiType; + + (function (RemoteMmiType) { + RemoteMmiType[RemoteMmiType["MMI_TYPE_MFB"] = 0] = "MMI_TYPE_MFB"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_VOLUP"] = 1] = "MMI_TYPE_VOLUP"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_VOLDOWN"] = 2] = "MMI_TYPE_VOLDOWN"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_VCB"] = 3] = "MMI_TYPE_VCB"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_APP"] = 4] = "MMI_TYPE_APP"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_TR_FORW"] = 5] = "MMI_TYPE_TR_FORW"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_TR_BACK"] = 6] = "MMI_TYPE_TR_BACK"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_PLAY"] = 7] = "MMI_TYPE_PLAY"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_MUTE"] = 8] = "MMI_TYPE_MUTE"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_HOOK_OFF"] = 9] = "MMI_TYPE_HOOK_OFF"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_HOOK_ON"] = 10] = "MMI_TYPE_HOOK_ON"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_BLUETOOTH"] = 11] = "MMI_TYPE_BLUETOOTH"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_JABRA"] = 12] = "MMI_TYPE_JABRA"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_BATTERY"] = 13] = "MMI_TYPE_BATTERY"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_PROG"] = 14] = "MMI_TYPE_PROG"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_LINK"] = 15] = "MMI_TYPE_LINK"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_ANC"] = 16] = "MMI_TYPE_ANC"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_LISTEN_IN"] = 17] = "MMI_TYPE_LISTEN_IN"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_DOT3"] = 18] = "MMI_TYPE_DOT3"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_DOT4"] = 19] = "MMI_TYPE_DOT4"; + RemoteMmiType[RemoteMmiType["MMI_TYPE_ALL"] = 255] = "MMI_TYPE_ALL"; + })(RemoteMmiType = jabra.RemoteMmiType || (jabra.RemoteMmiType = {})); + + ; + /** + * A MMI effect specification for light on, off or blinking in different tempo. + */ + + var RemoteMmiSequence; + + (function (RemoteMmiSequence) { + RemoteMmiSequence[RemoteMmiSequence["MMI_LED_SEQUENCE_OFF"] = 0] = "MMI_LED_SEQUENCE_OFF"; + RemoteMmiSequence[RemoteMmiSequence["MMI_LED_SEQUENCE_ON"] = 1] = "MMI_LED_SEQUENCE_ON"; + RemoteMmiSequence[RemoteMmiSequence["MMI_LED_SEQUENCE_SLOW"] = 2] = "MMI_LED_SEQUENCE_SLOW"; + RemoteMmiSequence[RemoteMmiSequence["MMI_LED_SEQUENCE_FAST"] = 3] = "MMI_LED_SEQUENCE_FAST"; + })(RemoteMmiSequence = jabra.RemoteMmiSequence || (jabra.RemoteMmiSequence = {})); + + ; + /** + * MMI button actions reported when button has focus. + */ + + var RemoteMmiActionInput; + + (function (RemoteMmiActionInput) { + RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_UP"] = 1] = "MMI_ACTION_UP"; + RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_DOWN"] = 2] = "MMI_ACTION_DOWN"; + RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_TAP"] = 4] = "MMI_ACTION_TAP"; + RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_DOUBLE_TAP"] = 8] = "MMI_ACTION_DOUBLE_TAP"; + RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_PRESS"] = 16] = "MMI_ACTION_PRESS"; + RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_LONG_PRESS"] = 32] = "MMI_ACTION_LONG_PRESS"; + RemoteMmiActionInput[RemoteMmiActionInput["MMI_ACTION_X_LONG_PRESS"] = 64] = "MMI_ACTION_X_LONG_PRESS"; + })(RemoteMmiActionInput = jabra.RemoteMmiActionInput || (jabra.RemoteMmiActionInput = {})); + + ; + /** + * The log level currently used internally in this api facade. Initially this is set to show errors and + * warnings until a logEvent (>=0.5) changes this when initializing the extension or when the user + * changes the log level. Available in the API for testing only - do not use this in normal applications. + */ + + jabra.logLevel = 2; + /** + * An internal logger helper. + */ + + var logger = new ( + /*#__PURE__*/ + function () { + function _class() { + _classCallCheck(this, _class); + } + + _createClass(_class, [{ + key: "trace", + value: function trace(msg) { + if (jabra.logLevel >= 4) { + console.log(msg); } - ; - info(msg) { - if (jabra.logLevel >= 3) { - console.log(msg); - } + } + }, { + key: "info", + value: function info(msg) { + if (jabra.logLevel >= 3) { + console.log(msg); } - ; - warn(msg) { - if (jabra.logLevel >= 2) { - console.warn(msg); - } + } + }, { + key: "warn", + value: function warn(msg) { + if (jabra.logLevel >= 2) { + console.warn(msg); } - ; - error(msg) { - if (jabra.logLevel >= 1) { - console.error(msg); - } + } + }, { + key: "error", + value: function error(msg) { + if (jabra.logLevel >= 1) { + console.error(msg); } - ; - }; - /** - * A reasonably unique ID for our browser extension client that makes it possible to - * differentiate between different instances of this api in different browser tabs. - */ - const apiClientId = Math.random().toString(36).substr(2, 9); - /** - * A mapping from unique request ids for commands and the promise information needed - * to resolve/reject them by an incomming event. - */ - const sendRequestResultMap = new Map(); - /** - * A counter used to generate unique request ID's used to match commands and returning events. - */ - let requestNumber = 1; - /** - * Contains initialization information used by the init/shutdown methods. - */ - let initState = {}; - /** - * The JavaScript library must be initialized using this function. It returns a promise that - * resolves when initialization is complete. - */ - function init() { - return new Promise((resolve, reject) => { - // Only Chrome is currently supported - let isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor); - if (!isChrome) { - return reject(new Error("Jabra Browser Integration: Only supported by Google Chrome.")); - } - if (initState.initialized || initState.initializing) { - return reject(new Error("Jabra Browser Integration already initialized")); + } + }]); + + return _class; + }())(); + /** + * A reasonably unique ID for our browser extension client that makes it possible to + * differentiate between different instances of this api in different browser tabs. + */ + + var apiClientId = Math.random().toString(36).substr(2, 9); + /** + * A mapping from unique request ids for commands and the promise information needed + * to resolve/reject them by an incomming event. + */ + + var sendRequestResultMap = new Map(); + /** + * A counter used to generate unique request ID's used to match commands and returning events. + */ + + var requestNumber = 1; + /** + * Contains initialization information used by the init/shutdown methods. + */ + + var initState = {}; + /** + * The JavaScript library must be initialized using this function. It returns a promise that + * resolves when initialization is complete. + */ + + function init() { + return new Promise(function (resolve, reject) { + // Only Chrome is currently supported + var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor); + + if (!isChrome) { + return reject(new Error("Jabra Browser Integration: Only supported by Google Chrome.")); + } + + if (initState.initialized || initState.initializing) { + return reject(new Error("Jabra Browser Integration already initialized")); + } + + initState.initializing = true; + sendRequestResultMap.clear(); + var duringInit = true; + + initState.eventCallback = function (event) { + if (event.source === window && event.data.direction && event.data.direction === "jabra-headset-extension-from-content-script") { + var eventApiClientId = event.data.apiClientId || ""; + var requestId = event.data.requestId || ""; // Only accept responses from our own requests or from device. + + if (apiClientId === eventApiClientId || eventApiClientId === "") { + logger.trace("Receiving event from content script: " + JSON.stringify(event.data)); // For backwards compatibility a blank message might be send as "na". + + if (event.data.message === "na") { + delete event.data.message; + } // For backward compatability reinterprent messages starting with error as errors: + + + if (event.data.message && event.data.message.startsWith("Error:")) { + event.data.error = event.data.message; + delete event.data.message; } - initState.initializing = true; - sendRequestResultMap.clear(); - let duringInit = true; - initState.eventCallback = (event) => { - if (event.source === window && - event.data.direction && - event.data.direction === "jabra-headset-extension-from-content-script") { - let eventApiClientId = event.data.apiClientId || ""; - let requestId = event.data.requestId || ""; - // Only accept responses from our own requests or from device. - if (apiClientId === eventApiClientId || eventApiClientId === "") { - logger.trace("Receiving event from content script: " + JSON.stringify(event.data)); - // For backwards compatibility a blank message might be send as "na". - if (event.data.message === "na") { - delete event.data.message; - } - // For backward compatability reinterprent messages starting with error as errors: - if (event.data.message && event.data.message.startsWith("Error:")) { - event.data.error = event.data.message; - delete event.data.message; - } - if (event.data.message) { - logger.trace("Got message: " + JSON.stringify(event.data)); - const normalizedMsg = event.data.message.substring(7); // Strip "Event" prefix; - if (normalizedMsg.startsWith("logLevel")) { - jabra.logLevel = parseInt(event.data.message.substring(16)); - logger.trace("Logger set to level " + jabra.logLevel); - // Loglevels are internal events and not an indication of proper - // initialization so skip rest of handling for log levels. - return; - } - const commandIndex = commandEventsList.findIndex((e) => normalizedMsg.startsWith(e)); - if (commandIndex >= 0) { - // For install info and version command, we need to add api version number. - if (normalizedMsg === "getinstallinfo" || (normalizedMsg.startsWith("Version "))) { - // Old extension/host won't have data so make sure it exists to avoid breakage. - if (!event.data.data) { - event.data.data = {}; - } - event.data.data.version_jsapi = jabra.apiVersion; - } - // For install info also check if the full installation is consistent. - if (normalizedMsg === "getinstallinfo") { - event.data.data.installationOk = isInstallationOk(event.data.data); - } - // Lookup and check that we have identified a (real) command target to pair result with. - let resultTarget = identifyAndCleanupResultTarget(requestId); - if (resultTarget) { - let result; - if (event.data.data) { - result = event.data.data; - } - else { - let dataPosition = commandEventsList[commandIndex].length + 1; - let dataStr = normalizedMsg.substring(dataPosition); - result = {}; - if (dataStr) { - result.legacy_result = dataStr; - } - ; - } - resultTarget.resolve(result); - } - else { - let err = "Result target information missing for message " + event.data.message + ". This is likely due to some software components that have not been updated or a software bug. Please upgrade extension and/or chromehost"; - logger.error(err); - notify("error", { - error: err, - message: event.data.message - }); - } - } - else if (eventListeners.has(normalizedMsg)) { - let clientEvent = JSON.parse(JSON.stringify(event.data)); - delete clientEvent.direction; - delete clientEvent.apiClientId; - delete clientEvent.requestId; - clientEvent.message = normalizedMsg; - notify(normalizedMsg, clientEvent); - } - else { - logger.warn("Unknown message: " + event.data.message); - notify("error", { - error: "Unknown message: ", - message: event.data.message - }); - // Don't let unknown messages complete initialization so stop here. - return; - } - if (duringInit) { - duringInit = false; - return resolve(); - } - } - else if (event.data.error) { - logger.error("Got error: " + event.data.error); - const normalizedError = event.data.error.substring(7); // Strip "Error" prefix; - // Reject target promise if there is one - otherwise send a general error. - let resultTarget = identifyAndCleanupResultTarget(requestId); - if (resultTarget) { - resultTarget.reject(new CommandError(resultTarget.cmd, normalizedError, event.data.data)); - } - else { - let clientError = JSON.parse(JSON.stringify(event.data)); - delete clientError.direction; - delete clientError.apiClientId; - delete clientError.requestId; - clientError.error = normalizedError; - notify("error", clientError); - } - if (duringInit) { - duringInit = false; - return reject(new Error(event.data.error)); - } - } - } - } - }; - window.addEventListener("message", initState.eventCallback); - // Initial getversion and loglevel. - setTimeout(() => { - sendCmdWithResult("getversion", null, false).then((result) => { - let resultStr = (typeof result === 'string' || result instanceof String) ? result : JSON.stringify(result, null, 2); - logger.trace("getversion returned successfully with : " + resultStr); - sendCmd("logLevel", null, false); - }).catch((error) => { - logger.error(error); - }); - }, 1000); - // Check if the web-extension is installed - setTimeout(function () { - if (duringInit === true) { - duringInit = false; - const extensionId = isBeta ? betaExtensionId : prodExtensionId; - reject(new Error("Jabra Browser Integration: You need to use this Extension and then reload this page")); - } - }, 5000); - /** - * Helper that checks if the installation is consistent. - */ - function isInstallationOk(installInfo) { - let browserSdkVersions = [installInfo.version_browserextension, installInfo.version_chromehost, installInfo.version_jsapi]; - // Check that we have install information for all components. - if (browserSdkVersions.some(v => !v) || !installInfo.version_nativesdk) { - return false; - } - // Check that different beta versions are not mixed. - if (!browserSdkVersions.map(v => { - let betaIndex = v.lastIndexOf('beta'); - if (betaIndex >= 0 && v.length > betaIndex + 4) { - return v.substr(betaIndex + 4); - } - else { - return undefined; + + if (event.data.message) { + logger.trace("Got message: " + JSON.stringify(event.data)); + var normalizedMsg = event.data.message.substring(7); // Strip "Event" prefix; + + if (normalizedMsg.startsWith("logLevel")) { + jabra.logLevel = parseInt(event.data.message.substring(16)); + logger.trace("Logger set to level " + jabra.logLevel); // Loglevels are internal events and not an indication of proper + // initialization so skip rest of handling for log levels. + + return; + } + + var commandIndex = commandEventsList.findIndex(function (e) { + return normalizedMsg.startsWith(e); + }); + + if (commandIndex >= 0) { + // For install info and version command, we need to add api version number. + if (normalizedMsg === "getinstallinfo" || normalizedMsg.startsWith("Version ")) { + // Old extension/host won't have data so make sure it exists to avoid breakage. + if (!event.data.data) { + event.data.data = {}; + } + + event.data.data.version_jsapi = jabra.apiVersion; + } // For install info also check if the full installation is consistent. + + + if (normalizedMsg === "getinstallinfo") { + event.data.data.installationOk = isInstallationOk(event.data.data); + } // Lookup and check that we have identified a (real) command target to pair result with. + + + var resultTarget = identifyAndCleanupResultTarget(requestId); + + if (resultTarget) { + var result; + + if (event.data.data) { + result = event.data.data; + } else { + var dataPosition = commandEventsList[commandIndex].length + 1; + var dataStr = normalizedMsg.substring(dataPosition); + result = {}; + + if (dataStr) { + result.legacy_result = dataStr; } - }).filter(v => v).every((v, i, arr) => v === arr[0])) { - return false; - } - return true; - } - /** - * Post event/error to subscribers. - */ - function notify(eventName, eventMsg) { - let callbacks = eventListeners.get(eventName); - if (callbacks) { - callbacks.forEach((callback) => { - callback(eventMsg); - }); - } - else { - // This should not occur unless internal event mappings in this file - // are not configured correctly. - logger.error("Unexpected unknown eventName: " + eventName); - } - } - /** Lookup any previous stored result target information for the request. - * Does cleanup if target found (so it can't be called twice for a request). - * Nb. requestId's are only provided by >= 0.5 extension and chromehost. - */ - function identifyAndCleanupResultTarget(requestId) { - // Lookup any previous stored result target information for the request. - // Nb. requestId's are only provided by >= 0.5 extension and chromehost. - let resultTarget; - if (requestId) { - resultTarget = sendRequestResultMap.get(requestId); - // Remember to cleanup to avoid memory leak! - sendRequestResultMap.delete(requestId); - } - else if (sendRequestResultMap.size === 1) { - // We don't have a requestId but since only one is being executed we - // can assume this is the one. - let value = sendRequestResultMap.entries().next().value; - resultTarget = value[1]; - // Remember to cleanup to avoid memory leak and for future - // requests like this to be resolved. - sendRequestResultMap.delete(value[0]); - } - else { - // No idea what target matches what request - give up. - resultTarget = undefined; - } - // Warn in case of likely memory leak: - const mapSize = sendRequestResultMap.size; - if (mapSize > 10 && mapSize % 10 === 0) { // Limit warnings to every 10 size increases to avoid flooding: - logger.warn("Memory leak found - Request result map is getting too large (size #" + mapSize + ")"); + + ; + } + + resultTarget.resolve(result); + } else { + var err = "Result target information missing for message " + event.data.message + ". This is likely due to some software components that have not been updated or a software bug. Please upgrade extension and/or chromehost"; + logger.error(err); + notify("error", { + error: err, + message: event.data.message + }); } - return resultTarget; + } else if (eventListeners.has(normalizedMsg)) { + var clientEvent = JSON.parse(JSON.stringify(event.data)); + delete clientEvent.direction; + delete clientEvent.apiClientId; + delete clientEvent.requestId; + clientEvent.message = normalizedMsg; + notify(normalizedMsg, clientEvent); + } else { + logger.warn("Unknown message: " + event.data.message); + notify("error", { + error: "Unknown message: ", + message: event.data.message + }); // Don't let unknown messages complete initialization so stop here. + + return; + } + + if (duringInit) { + duringInit = false; + return resolve(); + } + } else if (event.data.error) { + logger.error("Got error: " + event.data.error); + var normalizedError = event.data.error.substring(7); // Strip "Error" prefix; + // Reject target promise if there is one - otherwise send a general error. + + var _resultTarget = identifyAndCleanupResultTarget(requestId); + + if (_resultTarget) { + _resultTarget.reject(new CommandError(_resultTarget.cmd, normalizedError, event.data.data)); + } else { + var clientError = JSON.parse(JSON.stringify(event.data)); + delete clientError.direction; + delete clientError.apiClientId; + delete clientError.requestId; + clientError.error = normalizedError; + notify("error", clientError); + } + + if (duringInit) { + duringInit = false; + return reject(new Error(event.data.error)); + } } - initState.initialized = true; - initState.initializing = false; + } + } + }; + + window.addEventListener("message", initState.eventCallback); // Initial getversion and loglevel. + + setTimeout(function () { + sendCmdWithResult("getversion", null, false).then(function (result) { + var resultStr = typeof result === 'string' || _instanceof(result, String) ? result : JSON.stringify(result, null, 2); + logger.trace("getversion returned successfully with : " + resultStr); + sendCmd("logLevel", null, false); + }).catch(function (error) { + logger.error(error); }); - } - jabra.init = init; - ; - /** - * De-initialize the api after use. Not normally used as api will normally - * stay in use thoughout an application - mostly of interest for testing. - */ - function shutdown() { - if (initState.initialized) { - window.removeEventListener("message", initState.eventCallback); - initState.eventCallback = undefined; - sendRequestResultMap.clear(); - requestNumber = 1; - initState.initialized = false; - // Unsubscribe all. - eventListeners.forEach((value, key) => { - value = []; - }); - return Promise.resolve(); + }, 1000); // Check if the web-extension is installed + + setTimeout(function () { + if (duringInit === true) { + duringInit = false; + var extensionId = isBeta ? betaExtensionId : prodExtensionId; + reject(new Error("Jabra Browser Integration: You need to use this Extension and then reload this page")); } - return Promise.reject(new Error("Browser integration not initialized")); - } - jabra.shutdown = shutdown; - ; - /** - * Internal helper that returns an array of valid event keys that correspond to the event specificator - * and are known to exist in our event listener map. - */ - function getEvents(nameSpec) { - if (Array.isArray(nameSpec)) { - // @ts-ignore: Disable wrong "argument not assignable" error in ts 3.4 - return [...new Set([].concat.apply([], nameSpec.map(a => getEvents(a))))]; + }, 5000); + /** + * Helper that checks if the installation is consistent. + */ + + function isInstallationOk(installInfo) { + var browserSdkVersions = [installInfo.version_browserextension, installInfo.version_chromehost, installInfo.version_jsapi]; // Check that we have install information for all components. + + if (browserSdkVersions.some(function (v) { + return !v; + }) || !installInfo.version_nativesdk) { + return false; + } // Check that different beta versions are not mixed. + + + if (!browserSdkVersions.map(function (v) { + var betaIndex = v.lastIndexOf('beta'); + + if (betaIndex >= 0 && v.length > betaIndex + 4) { + return v.substr(betaIndex + 4); + } else { + return undefined; + } + }).filter(function (v) { + return v; + }).every(function (v, i, arr) { + return v === arr[0]; + })) { + return false; } - else if (nameSpec instanceof RegExp) { - return Array.from(eventListeners.keys()).filter(key => nameSpec.test(key)); + + return true; + } + /** + * Post event/error to subscribers. + */ + + + function notify(eventName, eventMsg) { + var callbacks = eventListeners.get(eventName); + + if (callbacks) { + callbacks.forEach(function (callback) { + callback(eventMsg); + }); + } else { + // This should not occur unless internal event mappings in this file + // are not configured correctly. + logger.error("Unexpected unknown eventName: " + eventName); } - else { // String - if (eventListeners.has(nameSpec)) { - return [nameSpec]; - } - else { - logger.warn("Unknown event " + nameSpec + " ignored when adding/removing eventlistener"); - } + } + /** Lookup any previous stored result target information for the request. + * Does cleanup if target found (so it can't be called twice for a request). + * Nb. requestId's are only provided by >= 0.5 extension and chromehost. + */ + + + function identifyAndCleanupResultTarget(requestId) { + // Lookup any previous stored result target information for the request. + // Nb. requestId's are only provided by >= 0.5 extension and chromehost. + var resultTarget; + + if (requestId) { + resultTarget = sendRequestResultMap.get(requestId); // Remember to cleanup to avoid memory leak! + + sendRequestResultMap.delete(requestId); + } else if (sendRequestResultMap.size === 1) { + // We don't have a requestId but since only one is being executed we + // can assume this is the one. + var value = sendRequestResultMap.entries().next().value; + resultTarget = value[1]; // Remember to cleanup to avoid memory leak and for future + // requests like this to be resolved. + + sendRequestResultMap.delete(value[0]); + } else { + // No idea what target matches what request - give up. + resultTarget = undefined; + } // Warn in case of likely memory leak: + + + var mapSize = sendRequestResultMap.size; + + if (mapSize > 10 && mapSize % 10 === 0) { + // Limit warnings to every 10 size increases to avoid flooding: + logger.warn("Memory leak found - Request result map is getting too large (size #" + mapSize + ")"); } - return []; - } - /** - * Hook up listener call back to specified event(s) as specified by initial name specification argument nameSpec. - * When the nameSpec argument is a string, this correspond to a single named event. When the argument is a regular - * expression all lister subscribes to all matching events. If the argument is an array it recursively subscribes - * to all events specified in the array. - */ - function addEventListener(nameSpec, callback) { - getEvents(nameSpec).map(name => { - let callbacks = eventListeners.get(name); - if (!callbacks.find((c) => c === callback)) { - callbacks.push(callback); - } - }); - } - jabra.addEventListener = addEventListener; - ; - /** - * Remove existing listener to specified event(s). The callback must correspond to the exact callback provided - * to a previous addEventListener. - */ - function removeEventListener(nameSpec, callback) { - getEvents(nameSpec).map(name => { - let callbacks = eventListeners.get(name); - let findIndex = callbacks.findIndex((c) => c === callback); - if (findIndex >= 0) { - callbacks.splice(findIndex, 1); - } - }); - } - jabra.removeEventListener = removeEventListener; - ; - /** - * Activate ringer (if supported) on the Jabra Device - */ - function ring() { - sendCmd("ring"); - } - jabra.ring = ring; - ; - /** - * Change state to in-a-call. - */ - function offHook() { - sendCmd("offhook"); - } - jabra.offHook = offHook; - ; - /** - * Change state to idle (not-in-a-call). - */ - function onHook() { - sendCmd("onhook"); - } - jabra.onHook = onHook; - ; - /** - * Mutes the microphone (if supported). - */ - function mute() { - sendCmd("mute"); + + return resultTarget; + } + + initState.initialized = true; + initState.initializing = false; + }); + } + + jabra.init = init; + ; + /** + * De-initialize the api after use. Not normally used as api will normally + * stay in use thoughout an application - mostly of interest for testing. + */ + + function shutdown() { + if (initState.initialized) { + window.removeEventListener("message", initState.eventCallback); + initState.eventCallback = undefined; + sendRequestResultMap.clear(); + requestNumber = 1; + initState.initialized = false; // Unsubscribe all. + + eventListeners.forEach(function (value, key) { + value = []; + }); + return Promise.resolve(); } - jabra.mute = mute; - ; - /** - * Unmutes the microphone (if supported). - */ - function unmute() { - sendCmd("unmute"); + + return Promise.reject(new Error("Browser integration not initialized")); + } + + jabra.shutdown = shutdown; + ; + /** + * Internal helper that returns an array of valid event keys that correspond to the event specificator + * and are known to exist in our event listener map. + */ + + function getEvents(nameSpec) { + if (Array.isArray(nameSpec)) { + // @ts-ignore: Disable wrong "argument not assignable" error in ts 3.4 + return _toConsumableArray(new Set([].concat.apply([], nameSpec.map(function (a) { + return getEvents(a); + })))); + } else if (_instanceof(nameSpec, RegExp)) { + return Array.from(eventListeners.keys()).filter(function (key) { + return nameSpec.test(key); + }); + } else { + // String + if (eventListeners.has(nameSpec)) { + return [nameSpec]; + } else { + logger.warn("Unknown event " + nameSpec + " ignored when adding/removing eventlistener"); + } } - jabra.unmute = unmute; - ; - /** - * Change state to held (if supported). - */ - function hold() { - sendCmd("hold"); + + return []; + } + /** + * Hook up listener call back to specified event(s) as specified by initial name specification argument nameSpec. + * When the nameSpec argument is a string, this correspond to a single named event. When the argument is a regular + * expression all lister subscribes to all matching events. If the argument is an array it recursively subscribes + * to all events specified in the array. + */ + + + function addEventListener(nameSpec, callback) { + getEvents(nameSpec).map(function (name) { + var callbacks = eventListeners.get(name); + + if (!callbacks.find(function (c) { + return c === callback; + })) { + callbacks.push(callback); + } + }); + } + + jabra.addEventListener = addEventListener; + ; + /** + * Remove existing listener to specified event(s). The callback must correspond to the exact callback provided + * to a previous addEventListener. + */ + + function removeEventListener(nameSpec, callback) { + getEvents(nameSpec).map(function (name) { + var callbacks = eventListeners.get(name); + var findIndex = callbacks.findIndex(function (c) { + return c === callback; + }); + + if (findIndex >= 0) { + callbacks.splice(findIndex, 1); + } + }); + } + + jabra.removeEventListener = removeEventListener; + ; + /** + * Activate ringer (if supported) on the Jabra Device + */ + + function ring() { + sendCmd("ring"); + } + + jabra.ring = ring; + ; + /** + * Change state to in-a-call. + */ + + function offHook() { + sendCmd("offhook"); + } + + jabra.offHook = offHook; + ; + /** + * Change state to idle (not-in-a-call). + */ + + function onHook() { + sendCmd("onhook"); + } + + jabra.onHook = onHook; + ; + /** + * Mutes the microphone (if supported). + */ + + function mute() { + sendCmd("mute"); + } + + jabra.mute = mute; + ; + /** + * Unmutes the microphone (if supported). + */ + + function unmute() { + sendCmd("unmute"); + } + + jabra.unmute = unmute; + ; + /** + * Change state to held (if supported). + */ + + function hold() { + sendCmd("hold"); + } + + jabra.hold = hold; + ; + /** + * Change state from held to OffHook (if supported). + */ + + function resume() { + sendCmd("resume"); + } + + jabra.resume = resume; + ; + /** + * Capture/release buttons for customization (if supported). This turns off default behavior and enables mmi events to + * be received instead. It also allows for mmi actions to be applied like changing lights with setRemoteMmiLightAction. + * + * @param type The button that should be captured/released. + * @param capture True if button should be captured, false if it should be released. + * + * @returns A promise that is resolved once operation completes. + */ + + function setMmiFocus(type, capture) { + var typeVal = numberOrString(type); + var captureVal = booleanOrString(capture); + return sendCmdWithResult("setmmifocus", { + type: typeVal, + capture: captureVal + }); + } + + jabra.setMmiFocus = setMmiFocus; + /** + * Change light/color on a previously captured button. + * Nb. This requires the button to be previously captured though setMMiFocus. + * + * @param type The button that should be captured/released. + * @param color An RGB array of 3x integers or a RGB number (with 0x or # prefix for hex). + * @param effect What effect to apply to the button. + * + * @returns A promise that is resolved once operation completes. + */ + + function setRemoteMmiLightAction(type, color, effect) { + var typeVal = numberOrString(type); + var colorVal = colorOrString(color); + var effectVal = numberOrString(effect); + return sendCmdWithResult("setremotemmilightaction", { + type: typeVal, + color: colorVal, + effect: effectVal + }); + } + + jabra.setRemoteMmiLightAction = setRemoteMmiLightAction; + /** + * Internal helper to get detailed information about the current active Jabra Device + * from SDK, including current status but excluding media device information. + */ + + function _doGetActiveSDKDevice() { + return sendCmdWithResult("getactivedevice"); + } + + ; + /** + * Internal helper to get detailed information about the all attached Jabra Devices + * from SDK, including current status but excluding media device information. + */ + + function _doGetSDKDevices() { + return sendCmdWithResult("getdevices"); + } + + ; + /** + * Get detailed information about the current active Jabra Device, including current status + * and optionally also including related browser media device information. + * + * Note that browser media device information requires mediaDevices.getUserMedia or + * getUserDeviceMediaExt to have been called so permissions are granted. Browser media information + * is useful for setting a device constraint on mediaDevices.getUserMedia for input or for calling + * setSinkId (when supported by the browser) to set output. + */ + + function getActiveDevice() { + var includeBrowserMediaDeviceInfo = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var includeBrowserMediaDeviceInfoVal = booleanOrString(includeBrowserMediaDeviceInfo); + + if (includeBrowserMediaDeviceInfoVal) { + return _doGetActiveSDKDevice_And_BrowserDevice(); + } else { + return _doGetActiveSDKDevice(); } - jabra.hold = hold; - ; - /** - * Change state from held to OffHook (if supported). - */ - function resume() { - sendCmd("resume"); + } + + jabra.getActiveDevice = getActiveDevice; + ; + /** + * List detailed information about all attached Jabra Devices, including current status. + * and optionally also including related browser media device information. + * + * Note that browser media device information requires mediaDevices.getUserMedia or + * getUserDeviceMediaExt to have been called so permissions are granted. Browser media information + * is useful for setting a device constraint on mediaDevices.getUserMedia for input or for calling + * setSinkId (when supported by the browser) to set output. + */ + + function getDevices() { + var includeBrowserMediaDeviceInfo = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var includeBrowserMediaDeviceInfoVal = booleanOrString(includeBrowserMediaDeviceInfo); + + if (includeBrowserMediaDeviceInfoVal) { + return _doGetSDKDevices_And_BrowserDevice(); + } else { + return _doGetSDKDevices(); } - jabra.resume = resume; - ; - /** - * Capture/release buttons for customization (if supported). This turns off default behavior and enables mmi events to - * be received instead. It also allows for mmi actions to be applied like changing lights with setRemoteMmiLightAction. - * - * @param type The button that should be captured/released. - * @param capture True if button should be captured, false if it should be released. - * - * @returns A promise that is resolved once operation completes. - */ - function setMmiFocus(type, capture) { - let typeVal = numberOrString(type); - let captureVal = booleanOrString(capture); - return sendCmdWithResult("setmmifocus", { - type: typeVal, - capture: captureVal - }); + } + + jabra.getDevices = getDevices; + ; + /** + * Internal utility that select a new active device in a backwards compatible way that works with earlier chrome host. + * Used internally by test tool - do not use otherwise. + * + * Note: The active device is a global setting that affects all browser + * instances using the browser SDK. Unless changed specifically, the setting + * persist until browser is restarted or device is unplugged. + * + * @deprecated Use setActiveDeviceId instead. + */ + + function _setActiveDeviceId(id) { + var idVal = numberOrString(id); // Use both new and old way of passing parameters for compatibility with <= v0.5. + + sendCmd("setactivedevice " + id.toString(), { + id: idVal + }); + } + + jabra._setActiveDeviceId = _setActiveDeviceId; + ; + /** + * Select a new active device returning once selection is completed. + * + * Note: The active device is a global setting that affects all browser + * instances using the browser SDK. Unless changed specifically, the setting + * persist until browser is restarted or device is unplugged. + * + * @param id The id number of the new active device. + * @returns A promise that is resolved once selection completes. + * + */ + + function setActiveDeviceId(id) { + var idVal = numberOrString(id); + return sendCmdWithResult("setactivedevice2", { + id: idVal + }); + } + + jabra.setActiveDeviceId = setActiveDeviceId; + ; + /** + * Set busylight on active device (if supported) + * + * @param busy True if busy light should be set, false if it should be cleared. + */ + + function setBusyLight(busy) { + var busyVal = booleanOrString(busy); + return sendCmdWithResult("setbusylight", { + busy: busyVal + }); + } + + jabra.setBusyLight = setBusyLight; + ; + /** + * Get version number information for all components. + */ + + function getInstallInfo() { + return sendCmdWithResult("getinstallinfo"); + } + + jabra.getInstallInfo = getInstallInfo; + ; + /** + * Internal helper that forwards a command to the browser extension + * without expecting a response. + */ + + function sendCmd(cmd) { + var args = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + var requireInitializedCheck = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + + if (!requireInitializedCheck || requireInitializedCheck && initState.initialized) { + var requestId = (requestNumber++).toString(); + var msg = { + direction: "jabra-headset-extension-from-page-script", + message: cmd, + args: args || {}, + requestId: requestId, + apiClientId: apiClientId, + version_jsapi: jabra.apiVersion + }; + logger.trace("Sending command to content script: " + JSON.stringify(msg)); + window.postMessage(msg, "*"); + } else { + throw new Error("Browser integration not initialized"); } - jabra.setMmiFocus = setMmiFocus; - /** - * Change light/color on a previously captured button. - * Nb. This requires the button to be previously captured though setMMiFocus. - * - * @param type The button that should be captured/released. - * @param color An RGB array of 3x integers or a RGB number (with 0x or # prefix for hex). - * @param effect What effect to apply to the button. - * - * @returns A promise that is resolved once operation completes. - */ - function setRemoteMmiLightAction(type, color, effect) { - let typeVal = numberOrString(type); - let colorVal = colorOrString(color); - let effectVal = numberOrString(effect); - return sendCmdWithResult("setremotemmilightaction", { - type: typeVal, - color: colorVal, - effect: effectVal + } + + ; + /** + * Internal helper that forwards a command to the browser extension + * expecting a response (a promise). + */ + + function sendCmdWithResult(cmd) { + var args = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + var requireInitializedCheck = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + + if (!requireInitializedCheck || requireInitializedCheck && initState.initialized) { + var requestId = (requestNumber++).toString(); + return new Promise(function (resolve, reject) { + sendRequestResultMap.set(requestId, { + cmd: cmd, + resolve: resolve, + reject: reject }); + var msg = { + direction: "jabra-headset-extension-from-page-script", + message: cmd, + args: args || {}, + requestId: requestId, + apiClientId: apiClientId, + version_jsapi: jabra.apiVersion + }; + logger.trace("Sending command to content script expecting result: " + JSON.stringify(msg)); + window.postMessage(msg, "*"); + }); + } else { + return Promise.reject(new Error("Browser integration not initialized")); } - jabra.setRemoteMmiLightAction = setRemoteMmiLightAction; - /** - * Internal helper to get detailed information about the current active Jabra Device - * from SDK, including current status but excluding media device information. - */ - function _doGetActiveSDKDevice() { - return sendCmdWithResult("getactivedevice"); - } - ; - /** - * Internal helper to get detailed information about the all attached Jabra Devices - * from SDK, including current status but excluding media device information. - */ - function _doGetSDKDevices() { - return sendCmdWithResult("getdevices"); - } - ; - /** - * Get detailed information about the current active Jabra Device, including current status - * and optionally also including related browser media device information. - * - * Note that browser media device information requires mediaDevices.getUserMedia or - * getUserDeviceMediaExt to have been called so permissions are granted. Browser media information - * is useful for setting a device constraint on mediaDevices.getUserMedia for input or for calling - * setSinkId (when supported by the browser) to set output. - */ - function getActiveDevice(includeBrowserMediaDeviceInfo = false) { - let includeBrowserMediaDeviceInfoVal = booleanOrString(includeBrowserMediaDeviceInfo); - if (includeBrowserMediaDeviceInfoVal) { - return _doGetActiveSDKDevice_And_BrowserDevice(); - } - else { - return _doGetActiveSDKDevice(); - } - } - jabra.getActiveDevice = getActiveDevice; - ; - /** - * List detailed information about all attached Jabra Devices, including current status. - * and optionally also including related browser media device information. - * - * Note that browser media device information requires mediaDevices.getUserMedia or - * getUserDeviceMediaExt to have been called so permissions are granted. Browser media information - * is useful for setting a device constraint on mediaDevices.getUserMedia for input or for calling - * setSinkId (when supported by the browser) to set output. - */ - function getDevices(includeBrowserMediaDeviceInfo = false) { - let includeBrowserMediaDeviceInfoVal = booleanOrString(includeBrowserMediaDeviceInfo); - if (includeBrowserMediaDeviceInfoVal) { - return _doGetSDKDevices_And_BrowserDevice(); - } - else { - return _doGetSDKDevices(); - } - } - jabra.getDevices = getDevices; - ; - /** - * Internal utility that select a new active device in a backwards compatible way that works with earlier chrome host. - * Used internally by test tool - do not use otherwise. - * - * Note: The active device is a global setting that affects all browser - * instances using the browser SDK. Unless changed specifically, the setting - * persist until browser is restarted or device is unplugged. - * - * @deprecated Use setActiveDeviceId instead. - */ - function _setActiveDeviceId(id) { - let idVal = numberOrString(id); - // Use both new and old way of passing parameters for compatibility with <= v0.5. - sendCmd("setactivedevice " + id.toString(), { id: idVal }); - } - jabra._setActiveDeviceId = _setActiveDeviceId; - ; - /** - * Select a new active device returning once selection is completed. - * - * Note: The active device is a global setting that affects all browser - * instances using the browser SDK. Unless changed specifically, the setting - * persist until browser is restarted or device is unplugged. - * - * @param id The id number of the new active device. - * @returns A promise that is resolved once selection completes. - * - */ - function setActiveDeviceId(id) { - let idVal = numberOrString(id); - return sendCmdWithResult("setactivedevice2", { id: idVal }); - } - jabra.setActiveDeviceId = setActiveDeviceId; - ; - /** - * Set busylight on active device (if supported) - * - * @param busy True if busy light should be set, false if it should be cleared. - */ - function setBusyLight(busy) { - let busyVal = booleanOrString(busy); - return sendCmdWithResult("setbusylight", { busy: busyVal }); + } + + ; + /** + * Configure an audio html element on a webpage to use jabra audio device as speaker output. Returns a promise with boolean success status. + * The deviceInfo argument must come from getDeviceInfo or getUserDeviceMediaExt calls. + */ + + function trySetDeviceOutput(audioElement, deviceInfo) { + if (!audioElement || !deviceInfo) { + return Promise.reject(new Error('Call to trySetDeviceOutput has argument(s) missing')); } - jabra.setBusyLight = setBusyLight; - ; - /** - * Get version number information for all components. - */ - function getInstallInfo() { - return sendCmdWithResult("getinstallinfo"); + + if (!(typeof audioElement.setSinkId === "function")) { + return Promise.reject(new Error('Your browser does not support required Audio Output Devices API')); } - jabra.getInstallInfo = getInstallInfo; - ; - /** - * Internal helper that forwards a command to the browser extension - * without expecting a response. - */ - function sendCmd(cmd, args = null, requireInitializedCheck = true) { - if (!requireInitializedCheck || (requireInitializedCheck && initState.initialized)) { - let requestId = (requestNumber++).toString(); - let msg = { - direction: "jabra-headset-extension-from-page-script", - message: cmd, - args: args || {}, - requestId: requestId, - apiClientId: apiClientId, - version_jsapi: jabra.apiVersion - }; - logger.trace("Sending command to content script: " + JSON.stringify(msg)); - window.postMessage(msg, "*"); - } - else { - throw new Error("Browser integration not initialized"); - } + + return audioElement.setSinkId(deviceInfo.browserAudioOutputId).then(function () { + var success = audioElement.sinkId === deviceInfo.browserAudioOutputId; + return success; + }); + } + + jabra.trySetDeviceOutput = trySetDeviceOutput; + ; + /** + * Checks if a Jabra Input device is in fact selected in a media stream. + * The deviceInfo argument must come from getDeviceInfo or getUserDeviceMediaExt calls. + */ + + function isDeviceSelectedForInput(mediaStream, deviceInfo) { + if (!mediaStream || !deviceInfo) { + throw Error('Call to isDeviceSelectedForInput has argument(s) missing'); } - ; - /** - * Internal helper that forwards a command to the browser extension - * expecting a response (a promise). - */ - function sendCmdWithResult(cmd, args = null, requireInitializedCheck = true) { - if (!requireInitializedCheck || (requireInitializedCheck && initState.initialized)) { - let requestId = (requestNumber++).toString(); - return new Promise((resolve, reject) => { - sendRequestResultMap.set(requestId, { cmd, resolve, reject }); - let msg = { - direction: "jabra-headset-extension-from-page-script", - message: cmd, - args: args || {}, - requestId: requestId, - apiClientId: apiClientId, - version_jsapi: jabra.apiVersion - }; - logger.trace("Sending command to content script expecting result: " + JSON.stringify(msg)); - window.postMessage(msg, "*"); - }); - } - else { - return Promise.reject(new Error("Browser integration not initialized")); - } + + var tracks = mediaStream.getAudioTracks(); + + for (var i = 0, len = tracks.length; i < len; i++) { + var track = tracks[i]; + var trackCap = track.getCapabilities(); + + if (trackCap.deviceId !== deviceInfo.browserAudioInputId) { + return false; + } } - ; - /** - * Configure an audio html element on a webpage to use jabra audio device as speaker output. Returns a promise with boolean success status. - * The deviceInfo argument must come from getDeviceInfo or getUserDeviceMediaExt calls. - */ - function trySetDeviceOutput(audioElement, deviceInfo) { - if (!audioElement || !deviceInfo) { - return Promise.reject(new Error('Call to trySetDeviceOutput has argument(s) missing')); - } - if (!(typeof (audioElement.setSinkId) === "function")) { - return Promise.reject(new Error('Your browser does not support required Audio Output Devices API')); - } - return audioElement.setSinkId(deviceInfo.browserAudioOutputId).then(() => { - var success = audioElement.sinkId === deviceInfo.browserAudioOutputId; - return success; - }); + + return true; + } + + jabra.isDeviceSelectedForInput = isDeviceSelectedForInput; + ; + /** + * Replacement for mediaDevices.getUserMedia that makes a best effort to select the active Jabra audio device + * to be used for the microphone. Unlike getUserMedia this method returns a promise that + * resolve to an object containing both a stream and the device info for the selected device. + * + * Optional, additional non-audio constrains (like f.x. video) can be specified as well. + * + * Note: Subsequently, if this method appears to succeed use the isDeviceSelectedForInput function to check + * if the browser did in fact choose a Jabra device for the microphone. + */ + + function getUserDeviceMediaExt(constraints) { + // Good error if using old browser: + if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { + return Promise.reject(new Error('Your browser does not support required media api')); + } // Init completed ? + + + if (!initState.initialized) { + return Promise.reject(new Error("Browser integration not initialized")); + } // Warn of degraded UX experience unless we are running https. + + + if (location.protocol !== 'https:') { + logger.warn("This function needs to run under https for best UX experience (persisted permissions)"); + } // Check input validity: + + + if (constraints !== undefined && constraints !== null && _typeof(constraints) !== 'object') { + return Promise.reject(new Error("Optional constraints parameter must be an object")); } - jabra.trySetDeviceOutput = trySetDeviceOutput; - ; /** - * Checks if a Jabra Input device is in fact selected in a media stream. - * The deviceInfo argument must come from getDeviceInfo or getUserDeviceMediaExt calls. + * Utility method that combines constraints with ours taking precedence (deep). */ - function isDeviceSelectedForInput(mediaStream, deviceInfo) { - if (!mediaStream || !deviceInfo) { - throw Error('Call to isDeviceSelectedForInput has argument(s) missing'); - } - var tracks = mediaStream.getAudioTracks(); - for (var i = 0, len = tracks.length; i < len; i++) { - var track = tracks[i]; - var trackCap = track.getCapabilities(); - if (trackCap.deviceId !== deviceInfo.browserAudioInputId) { - return false; - } - } - return true; - } - jabra.isDeviceSelectedForInput = isDeviceSelectedForInput; - ; - /** - * Replacement for mediaDevices.getUserMedia that makes a best effort to select the active Jabra audio device - * to be used for the microphone. Unlike getUserMedia this method returns a promise that - * resolve to an object containing both a stream and the device info for the selected device. - * - * Optional, additional non-audio constrains (like f.x. video) can be specified as well. - * - * Note: Subsequently, if this method appears to succeed use the isDeviceSelectedForInput function to check - * if the browser did in fact choose a Jabra device for the microphone. - */ - function getUserDeviceMediaExt(constraints) { - // Good error if using old browser: - if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { - return Promise.reject(new Error('Your browser does not support required media api')); - } - // Init completed ? - if (!initState.initialized) { - return Promise.reject(new Error("Browser integration not initialized")); - } - // Warn of degraded UX experience unless we are running https. - if (location.protocol !== 'https:') { - logger.warn("This function needs to run under https for best UX experience (persisted permissions)"); - } - // Check input validity: - if (constraints !== undefined && constraints !== null && typeof constraints !== 'object') { - return Promise.reject(new Error("Optional constraints parameter must be an object")); - } - /** - * Utility method that combines constraints with ours taking precedence (deep). - */ - function mergeConstraints(ours, theirs) { - if (theirs !== null && theirs !== undefined && typeof ours === 'object') { - let result = {}; - for (var attrname in theirs) { - result[attrname] = theirs[attrname]; - } - for (var attrname in ours) { - result[attrname] = mergeConstraints(ours[attrname], theirs[attrname]); - } // Ours takes precedence. - return result; - } - else { - return ours; - } + + + function mergeConstraints(ours, theirs) { + if (theirs !== null && theirs !== undefined && _typeof(ours) === 'object') { + var result = {}; + + for (var attrname in theirs) { + result[attrname] = theirs[attrname]; } - // If we have the input device id already we can do a direct call to getUserMedia, otherwise we have to do - // an initial general call to getUserMedia just get access to looking up the input device and then a second - // call to getUserMedia to make sure the Jabra input device is selected. - return navigator.mediaDevices.getUserMedia(mergeConstraints({ audio: true }, constraints)).then((dummyStream) => { - return _doGetActiveSDKDevice_And_BrowserDevice().then((deviceInfo) => { - // Shutdown initial dummy stream (not sure it is really required but let's be nice). - dummyStream.getTracks().forEach((track) => { - track.stop(); - }); - if (deviceInfo && deviceInfo.browserAudioInputId) { - return navigator.mediaDevices.getUserMedia(mergeConstraints({ audio: { deviceId: deviceInfo.browserAudioInputId } }, constraints)) - .then((stream) => { - return { - stream: stream, - deviceInfo: deviceInfo - }; - }); - } - else { - return Promise.reject(new Error('Could not find a Jabra device with a microphone')); - } - }); + + for (var attrname in ours) { + result[attrname] = mergeConstraints(ours[attrname], theirs[attrname]); + } // Ours takes precedence. + + + return result; + } else { + return ours; + } + } // If we have the input device id already we can do a direct call to getUserMedia, otherwise we have to do + // an initial general call to getUserMedia just get access to looking up the input device and then a second + // call to getUserMedia to make sure the Jabra input device is selected. + + + return navigator.mediaDevices.getUserMedia(mergeConstraints({ + audio: true + }, constraints)).then(function (dummyStream) { + return _doGetActiveSDKDevice_And_BrowserDevice().then(function (deviceInfo) { + // Shutdown initial dummy stream (not sure it is really required but let's be nice). + dummyStream.getTracks().forEach(function (track) { + track.stop(); }); - } - jabra.getUserDeviceMediaExt = getUserDeviceMediaExt; - ; - /** - * Internal helper for add media information properties to existing SDK device information. - */ - function fillInMatchingMediaInfo(deviceInfo, mediaDevices) { - function findBestMatchIndex(sdkDeviceName, mediaDeviceNameCandidates) { - // Edit distance helper adapted from - // https://stackoverflow.com/questions/10473745/compare-strings-javascript-return-of-likely - function editDistance(s1, s2) { - s1 = s1.toLowerCase(); - s2 = s2.toLowerCase(); - var costs = new Array(); - for (var i = 0; i <= s1.length; i++) { - var lastValue = i; - for (var j = 0; j <= s2.length; j++) { - if (i == 0) - costs[j] = j; - else { - if (j > 0) { - var newValue = costs[j - 1]; - if (s1.charAt(i - 1) != s2.charAt(j - 1)) - newValue = Math.min(Math.min(newValue, lastValue), costs[j]) + 1; - costs[j - 1] = lastValue; - lastValue = newValue; - } - } - } - if (i > 0) - costs[s2.length] = lastValue; - } - return costs[s2.length]; - } - // Levenshtein distance helper adapted from - // https://stackoverflow.com/questions/10473745/compare-strings-javascript-return-of-likely - function levenshteinDistance(s1, s2) { - let longer = s1; - let shorter = s2; - if (s1.length < s2.length) { - longer = s2; - shorter = s1; - } - let longerLength = longer.length; - if (longerLength === 0) { - return 1.0; - } - return (longerLength - editDistance(longer, shorter)) / longerLength; - } - if (mediaDeviceNameCandidates.length == 1) { - return 0; - } - else if (mediaDeviceNameCandidates.length > 0) { - let similarities = mediaDeviceNameCandidates.map(candidate => { - if (candidate.includes("(" + sdkDeviceName + ")")) { - return 1.0; - } - else { - // Remove Standard/Default prefix from label in Chrome when comparing - let prefixEnd = candidate.indexOf(' - '); - let cleanedCandidate = (prefixEnd >= 0) ? candidate.substring(prefixEnd + 3) : candidate; - return levenshteinDistance(sdkDeviceName, cleanedCandidate); - } - }); - let bestMatchIndex = similarities.reduce((prevIndexMax, value, i, a) => value > a[prevIndexMax] ? i : prevIndexMax, 0); - return bestMatchIndex; - } - else { - return -1; + + if (deviceInfo && deviceInfo.browserAudioInputId) { + return navigator.mediaDevices.getUserMedia(mergeConstraints({ + audio: { + deviceId: deviceInfo.browserAudioInputId } + }, constraints)).then(function (stream) { + return { + stream: stream, + deviceInfo: deviceInfo + }; + }); + } else { + return Promise.reject(new Error('Could not find a Jabra device with a microphone')); } - // Find matching pair input or output device. - function findMatchingMediaDevice(groupId, kind, src) { - return src.find(md => md.groupId == groupId && md.kind == kind); - } - if (deviceInfo && deviceInfo.deviceName) { - let groupId = undefined; - let audioInputId = undefined; - let audioOutputId = undefined; - let label = undefined; - // Filter out non Jabra input/output devices: - let jabraMediaDevices = mediaDevices.filter(device => device.label - && device.label.toLowerCase().includes('jabra') - && (device.kind === 'audioinput' || device.kind === 'audiooutput')); - let someJabraDeviceIndex = findBestMatchIndex(deviceInfo.deviceName, jabraMediaDevices.map(md => md.label)); - if (someJabraDeviceIndex >= 0) { - let foundDevice = jabraMediaDevices[someJabraDeviceIndex]; - groupId = foundDevice.groupId; - label = foundDevice.label; - if (foundDevice.kind === 'audioinput') { - audioInputId = foundDevice.deviceId; - // Lookup matching output device: - let outputDevice = findMatchingMediaDevice(groupId, 'audiooutput', jabraMediaDevices); - if (outputDevice) { - audioOutputId = outputDevice.deviceId; - } - } - else if (foundDevice.kind === 'audiooutput') { - audioOutputId = foundDevice.deviceId; - // Lookup matching output input device: - let inputDevice = findMatchingMediaDevice(groupId, 'audioinput', jabraMediaDevices); - if (inputDevice) { - audioInputId = inputDevice.deviceId; - } - } - } - if (groupId) { - deviceInfo.browserGroupId = groupId; - } - if (label) { - deviceInfo.browserLabel = label; - } - if (audioInputId) { - deviceInfo.browserAudioInputId = audioInputId; - } - if (audioOutputId) { - deviceInfo.browserAudioOutputId = audioOutputId; + }); + }); + } + + jabra.getUserDeviceMediaExt = getUserDeviceMediaExt; + ; + /** + * Internal helper for add media information properties to existing SDK device information. + */ + + function fillInMatchingMediaInfo(deviceInfo, mediaDevices) { + function findBestMatchIndex(sdkDeviceName, mediaDeviceNameCandidates) { + // Edit distance helper adapted from + // https://stackoverflow.com/questions/10473745/compare-strings-javascript-return-of-likely + function editDistance(s1, s2) { + s1 = s1.toLowerCase(); + s2 = s2.toLowerCase(); + var costs = new Array(); + + for (var i = 0; i <= s1.length; i++) { + var lastValue = i; + + for (var j = 0; j <= s2.length; j++) { + if (i == 0) costs[j] = j;else { + if (j > 0) { + var newValue = costs[j - 1]; + if (s1.charAt(i - 1) != s2.charAt(j - 1)) newValue = Math.min(Math.min(newValue, lastValue), costs[j]) + 1; + costs[j - 1] = lastValue; + lastValue = newValue; + } } + } + + if (i > 0) costs[s2.length] = lastValue; } - else { - // Do nothing if device information is missing. - } - } - /** - * Internal helper that returns complete device information, including both SDK and browser media device - * information for all devices. - * - * Chrome note: - * 1) Only works if hosted under https. - * - * Firefox note: - * 1) Output devices not supported yet. See "https://bugzilla.mozilla.org/show_bug.cgi?id=934425" - * 2) The user must have provided permission to use the specific device to use it as a constraint. - * 3) GroupId not supported. - * - * General non-chrome browser note: - * 1) Returning output devices requires support for new Audio Output Devices API. - */ - function _doGetSDKDevices_And_BrowserDevice() { - // Good error if using old browser: - if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) { - return Promise.reject(new Error('Your browser does not support required media api')); - } - // Init completed ? - if (!initState.initialized) { - return Promise.reject(new Error("Browser integration not initialized")); + + return costs[s2.length]; + } // Levenshtein distance helper adapted from + // https://stackoverflow.com/questions/10473745/compare-strings-javascript-return-of-likely + + + function levenshteinDistance(s1, s2) { + var longer = s1; + var shorter = s2; + + if (s1.length < s2.length) { + longer = s2; + shorter = s1; } - // Browser security rules (for at least chrome) requires site to run under https for labels to be read. - if (location.protocol !== 'https:') { - return Promise.reject(new Error('Your browser needs https for lookup to work')); + + var longerLength = longer.length; + + if (longerLength === 0) { + return 1.0; } - return Promise.all([_doGetSDKDevices(), navigator.mediaDevices.enumerateDevices()]).then(([deviceInfos, mediaDevices]) => { - deviceInfos.forEach((deviceInfo) => { - fillInMatchingMediaInfo(deviceInfo, mediaDevices); - }); - return deviceInfos; + + return (longerLength - editDistance(longer, shorter)) / longerLength; + } + + if (mediaDeviceNameCandidates.length == 1) { + return 0; + } else if (mediaDeviceNameCandidates.length > 0) { + var similarities = mediaDeviceNameCandidates.map(function (candidate) { + if (candidate.includes("(" + sdkDeviceName + ")")) { + return 1.0; + } else { + // Remove Standard/Default prefix from label in Chrome when comparing + var prefixEnd = candidate.indexOf(' - '); + var cleanedCandidate = prefixEnd >= 0 ? candidate.substring(prefixEnd + 3) : candidate; + return levenshteinDistance(sdkDeviceName, cleanedCandidate); + } }); + var bestMatchIndex = similarities.reduce(function (prevIndexMax, value, i, a) { + return value > a[prevIndexMax] ? i : prevIndexMax; + }, 0); + return bestMatchIndex; + } else { + return -1; + } + } // Find matching pair input or output device. + + + function findMatchingMediaDevice(groupId, kind, src) { + return src.find(function (md) { + return md.groupId == groupId && md.kind == kind; + }); } - /** - * Internal helper that returns complete device information, including both SDK and browser media device - * information for active device. - * - * Chrome note: - * 1) Only works if hosted under https. - * - * Firefox note: - * 1) Output devices not supported yet. See "https://bugzilla.mozilla.org/show_bug.cgi?id=934425" - * 2) The user must have provided permission to use the specific device to use it as a constraint. - * 3) GroupId not supported. - * - * General non-chrome browser note: - * 1) Returning output devices requires support for new Audio Output Devices API. - */ - function _doGetActiveSDKDevice_And_BrowserDevice() { - // Good error if using old browser: - if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) { - return Promise.reject(new Error('Your browser does not support required media api')); - } - // Init completed ? - if (!initState.initialized) { - return Promise.reject(new Error("Browser integration not initialized")); - } - // Browser security rules (for at least chrome) requires site to run under https for labels to be read. - if (location.protocol !== 'https:') { - return Promise.reject(new Error('Your browser needs https for lookup to work')); + + if (deviceInfo && deviceInfo.deviceName) { + var groupId = undefined; + var audioInputId = undefined; + var audioOutputId = undefined; + var label = undefined; // Filter out non Jabra input/output devices: + + var jabraMediaDevices = mediaDevices.filter(function (device) { + return device.label && device.label.toLowerCase().includes('jabra') && (device.kind === 'audioinput' || device.kind === 'audiooutput'); + }); + var someJabraDeviceIndex = findBestMatchIndex(deviceInfo.deviceName, jabraMediaDevices.map(function (md) { + return md.label; + })); + + if (someJabraDeviceIndex >= 0) { + var foundDevice = jabraMediaDevices[someJabraDeviceIndex]; + groupId = foundDevice.groupId; + label = foundDevice.label; + + if (foundDevice.kind === 'audioinput') { + audioInputId = foundDevice.deviceId; // Lookup matching output device: + + var outputDevice = findMatchingMediaDevice(groupId, 'audiooutput', jabraMediaDevices); + + if (outputDevice) { + audioOutputId = outputDevice.deviceId; + } + } else if (foundDevice.kind === 'audiooutput') { + audioOutputId = foundDevice.deviceId; // Lookup matching output input device: + + var inputDevice = findMatchingMediaDevice(groupId, 'audioinput', jabraMediaDevices); + + if (inputDevice) { + audioInputId = inputDevice.deviceId; + } } - // enumerateDevices requires user to have provided permission using getUserMedia for labels to be filled out. - return Promise.all([_doGetActiveSDKDevice(), navigator.mediaDevices.enumerateDevices()]).then(([deviceInfo, mediaDevices]) => { - fillInMatchingMediaInfo(deviceInfo, mediaDevices); - return deviceInfo; - }); + } + + if (groupId) { + deviceInfo.browserGroupId = groupId; + } + + if (label) { + deviceInfo.browserLabel = label; + } + + if (audioInputId) { + deviceInfo.browserAudioInputId = audioInputId; + } + + if (audioOutputId) { + deviceInfo.browserAudioOutputId = audioOutputId; + } + } else {// Do nothing if device information is missing. } - ; - /** - * Helper that pass boolean values through and parses strings to booleans. - */ - function booleanOrString(arg) { - if (arg !== "" && ((typeof arg === 'string') || (arg instanceof String))) { - return (arg === 'true' || arg === '1'); - } - else if (typeof (arg) === "boolean") { - return arg; - } - else { - throw new Error("Illegal/missing argument - boolean or string expected"); - } + } + /** + * Internal helper that returns complete device information, including both SDK and browser media device + * information for all devices. + * + * Chrome note: + * 1) Only works if hosted under https. + * + * Firefox note: + * 1) Output devices not supported yet. See "https://bugzilla.mozilla.org/show_bug.cgi?id=934425" + * 2) The user must have provided permission to use the specific device to use it as a constraint. + * 3) GroupId not supported. + * + * General non-chrome browser note: + * 1) Returning output devices requires support for new Audio Output Devices API. + */ + + + function _doGetSDKDevices_And_BrowserDevice() { + // Good error if using old browser: + if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) { + return Promise.reject(new Error('Your browser does not support required media api')); + } // Init completed ? + + + if (!initState.initialized) { + return Promise.reject(new Error("Browser integration not initialized")); + } // Browser security rules (for at least chrome) requires site to run under https for labels to be read. + + + if (location.protocol !== 'https:') { + return Promise.reject(new Error('Your browser needs https for lookup to work')); } - /** - * Helper that pass numbers through and parses strings to numbers. - */ - function numberOrString(arg) { - if (arg !== "" && ((typeof arg === 'string') || (arg instanceof String))) { - return parseInt(arg); - } - else if (typeof arg == 'number') { - return arg; - } - else { - throw new Error("Illegal/missing argument - number or string expected"); - } + + return Promise.all([_doGetSDKDevices(), navigator.mediaDevices.enumerateDevices()]).then(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + deviceInfos = _ref2[0], + mediaDevices = _ref2[1]; + + deviceInfos.forEach(function (deviceInfo) { + fillInMatchingMediaInfo(deviceInfo, mediaDevices); + }); + return deviceInfos; + }); + } + /** + * Internal helper that returns complete device information, including both SDK and browser media device + * information for active device. + * + * Chrome note: + * 1) Only works if hosted under https. + * + * Firefox note: + * 1) Output devices not supported yet. See "https://bugzilla.mozilla.org/show_bug.cgi?id=934425" + * 2) The user must have provided permission to use the specific device to use it as a constraint. + * 3) GroupId not supported. + * + * General non-chrome browser note: + * 1) Returning output devices requires support for new Audio Output Devices API. + */ + + + function _doGetActiveSDKDevice_And_BrowserDevice() { + // Good error if using old browser: + if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) { + return Promise.reject(new Error('Your browser does not support required media api')); + } // Init completed ? + + + if (!initState.initialized) { + return Promise.reject(new Error("Browser integration not initialized")); + } // Browser security rules (for at least chrome) requires site to run under https for labels to be read. + + + if (location.protocol !== 'https:') { + return Promise.reject(new Error('Your browser needs https for lookup to work')); + } // enumerateDevices requires user to have provided permission using getUserMedia for labels to be filled out. + + + return Promise.all([_doGetActiveSDKDevice(), navigator.mediaDevices.enumerateDevices()]).then(function (_ref3) { + var _ref4 = _slicedToArray(_ref3, 2), + deviceInfo = _ref4[0], + mediaDevices = _ref4[1]; + + fillInMatchingMediaInfo(deviceInfo, mediaDevices); + return deviceInfo; + }); + } + + ; + /** + * Helper that pass boolean values through and parses strings to booleans. + */ + + function booleanOrString(arg) { + if (arg !== "" && (typeof arg === 'string' || _instanceof(arg, String))) { + return arg === 'true' || arg === '1'; + } else if (typeof arg === "boolean") { + return arg; + } else { + throw new Error("Illegal/missing argument - boolean or string expected"); } - ; - /** - * Helper that pass color array through and converts values to color array. - */ - function colorOrString(arg) { - if (arg !== "" && ((typeof arg === 'string') || (arg instanceof String))) { - let combinedValue = parseInt(arg, 16); - return [(combinedValue >> 16) & 255, (combinedValue >> 8) & 255, combinedValue & 255]; - } - else if (typeof arg == 'number') { - let combinedValue = arg; - return [(combinedValue >> 16) & 255, (combinedValue >> 8) & 255, combinedValue & 255]; - } - else if (Array.isArray(arg)) { - if (arg.length != 3) { - throw new Error("Illegal argument - wrong dimension of number array (3 expected)"); - } - return arg; - } - else { - throw new Error("Illegal/missing argument - number array or hex string expected"); - } + } + /** + * Helper that pass numbers through and parses strings to numbers. + */ + + + function numberOrString(arg) { + if (arg !== "" && (typeof arg === 'string' || _instanceof(arg, String))) { + return parseInt(arg); + } else if (typeof arg == 'number') { + return arg; + } else { + throw new Error("Illegal/missing argument - number or string expected"); } - ; + } + + ; + /** + * Helper that pass color array through and converts values to color array. + */ + + function colorOrString(arg) { + if (arg !== "" && (typeof arg === 'string' || _instanceof(arg, String))) { + var combinedValue = parseInt(arg, 16); + return [combinedValue >> 16 & 255, combinedValue >> 8 & 255, combinedValue & 255]; + } else if (typeof arg == 'number') { + var _combinedValue = arg; + return [_combinedValue >> 16 & 255, _combinedValue >> 8 & 255, _combinedValue & 255]; + } else if (Array.isArray(arg)) { + if (arg.length != 3) { + throw new Error("Illegal argument - wrong dimension of number array (3 expected)"); + } + + return arg; + } else { + throw new Error("Illegal/missing argument - number array or hex string expected"); + } + } + + ; })(jabra || (jabra = {})); -; -//# sourceMappingURL=jabra.browser.integration-2.0.js.map \ No newline at end of file + +; \ No newline at end of file diff --git a/public/assets/plugins/jabra/jabra.browser.integration-2.0.js.map b/public/assets/plugins/jabra/jabra.browser.integration-2.0.js.map new file mode 100644 index 0000000..4bbdf90 --- /dev/null +++ b/public/assets/plugins/jabra/jabra.browser.integration-2.0.js.map @@ -0,0 +1 @@ +{"version":3,"file":"jabra.browser.integration-2.0.js","sourceRoot":"","sources":["jabra.browser.integration-2.0.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/public/assets/plugins/jabra/jabra.browser.integration-2.0.ts b/public/assets/plugins/jabra/jabra.browser.integration-2.0.ts new file mode 100644 index 0000000..77d0722 --- /dev/null +++ b/public/assets/plugins/jabra/jabra.browser.integration-2.0.ts @@ -0,0 +1,1384 @@ +/* +Jabra Browser Integration +https://github.com/gnaudio/jabra-browser-integration + +MIT License + +Copyright (c) 2017 GN Audio A/S (Jabra) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** +* The global jabra object is your entry for the jabra browser SDK. +*/ +namespace jabra { + /** + * Version of this javascript api (should match version number in file apart from possible alfa/beta designator). + */ + export const apiVersion = "2.0.1"; + + /** + * Is the current version a beta ? + */ + const isBeta = apiVersion.includes("beta"); + + /** + * Id of proper (production) release of browser plugin. + */ + const prodExtensionId = "okpeabepajdgiepelmhkfhkjlhhmofma"; + + /** + * Id of beta release of browser plugin. + */ + const betaExtensionId = "igcbbdnhomedfadljgcmcfpdcoonihfe"; + + /** + * Contains information about installed components. + */ + export interface InstallInfo { + installationOk: boolean; + version_chromehost: string; + version_nativesdk: string; + version_browserextension: string; + version_jsapi: string; + browserextension_id: string; + browserextension_type: string; + }; + + /** + * Contains information about a device + */ + export interface DeviceInfo { + deviceID: number; + deviceName: string; + deviceConnection: number; + deviceFeatures: ReadonlyArray; + errStatus: number; + isBTPaired?: boolean; + isInFirmwareUpdateMode: boolean; + productID: number; + serialNumber?: string, + variant: string; + dongleName?: string; + skypeCertified: boolean; + firmwareVersion?: string; + electricSerialNumbers?: ReadonlyArray; + batteryLevelInPercent?: number; + batteryCharging?: boolean; + batteryLow?: boolean; + leftEarBudStatus?: boolean; + equalizerEnabled?: boolean; + busyLight?: boolean; + + /** + * Set to ID of related dongle and/or headset if both are paired and connected. + */ + connectedDeviceID?: number; + + /** + * Set if the same device is connected in more than one way (BT and USB), so + * the device appears twice. + */ + aliasDeviceID?: number; + + /** + * Only available in debug versions. + */ + parentInstanceId?: string; + + /** + * Only available in debug versions. + */ + usbDevicePath?: string; + + /** + * Browser media device information group (browser session specific). + * Only available when calling getDevices/getActiveDevice with includeBrowserMediaDeviceInfo argument set to true. + */ + browserGroupId?: string; + + /** + * The browser's unique identifier for the input (e.g. microphone) part of the Jabra device (page origin specific). + * Only available when calling getDevices/getActiveDevice with includeBrowserMediaDeviceInfo argument set to true. + */ + browserAudioInputId?: string; + + /** + * The browser's unique identifier for an output (e.g. speaker) part of the Jabra device (page origin specific). + * Only available when calling getDevices/getActiveDevice with includeBrowserMediaDeviceInfo argument set to true. + */ + browserAudioOutputId?: string; + + /** + * The browser's textual descriptor of the device. + * Only available when calling getDevices/getActiveDevice with includeBrowserMediaDeviceInfo argument set to true. + */ + browserLabel?: string; + }; + + /** + * A combination of a media stream and information of the associated device from the view of the browser. + */ + export interface MediaStreamAndDeviceInfoPair { + stream: MediaStream; + deviceInfo: DeviceInfo + }; + + /** + * Names of command response events. + */ + const commandEventsList = [ + "devices", + "activedevice", + "getinstallinfo", + "Version", + "setmmifocus", + "setactivedevice2", + "setbusylight", + "setremotemmilightaction" + ]; + + /** + * All possible device events as discriminative union. + */ + export type EventName = "mute" | "unmute" | "device attached" | "device detached" | "acceptcall" + | "endcall" | "reject" | "flash" | "online" | "offline" | "linebusy" | "lineidle" + | "redial" | "key0" | "key1" | "key2" | "key3" | "key4" | "key5" + | "key6" | "key7" | "key8" | "key9" | "keyStar" | "keyPound" + | "keyClear" | "Online" | "speedDial" | "voiceMail" | "LineBusy" + | "outOfRange" | "intoRange" | "pseudoAcceptcall" | "pseudoEndcall" + | "button1" | "button2" | "button3" | "volumeUp" | "volumeDown" | "fireAlarm" + | "jackConnection" | "jackDisConnection" | "qdConnection" | "qdDisconnection" + | "headsetConnection" | "headsetDisConnection" | "devlog" | "busylight" + | "hearThrough" | "batteryStatus" | "gnpButton" | "mmi" | "error"; + + /** + * All possible device events as internal array. + */ + let eventNamesList: ReadonlyArray + = [ "mute", "unmute", "device attached", "device detached", "acceptcall", + "endcall", "reject", "flash", "online", "offline", "linebusy", "lineidle", + "redial", "key0", "key1", "key2", "key3", "key4", "key5", + "key6", "key7", "key8", "key9", "keyStar", "keyPound", + "keyClear", "Online", "speedDial", "voiceMail", "LineBusy", + "outOfRange", "intoRange", "pseudoAcceptcall", "pseudoEndcall", + "button1", "button2", "button3", "volumeUp", "volumeDown", "fireAlarm", + "jackConnection", "jackDisConnection", "qdConnection", "qdDisconnection", + "headsetConnection","headsetDisConnection", "devlog", "busylight", + "hearThrough", "batteryStatus", "gnpButton", "mmi", "error" ]; + + /** + * Error status codes returned by SDK. Same as Jabra_ErrorStatus in native SDK. + */ + export enum ErrorCodes { + NoError = 0, + SSLError = 1, + CertError = 2, + NetworkError = 3, + DownloadError = 4, + ParseError = 5, + OtherError = 6, + DeviceInfoError = 7, + FileNotAccessible = 8, + FileNotCompatible = 9, + Device_NotFound = 10, + Parameter_fail = 11, + Authorization_failed = 12, + FileNotAvailable = 13, + ConfigParseError = 14, + SetSettings_Fail = 15, + Device_Reboot = 16, + Device_ReadFail = 17, + Device_NotReady = 18, + FilePartiallyCompatible = 19 + }; + + /** + * Error return codes. Same as Jabra_ReturnCode in native SDK. + */ + export enum ErrorReturnCodes { + Return_Ok = 0, + Device_Unknown = 1, + Device_Invalid = 2, + Not_Supported = 3, + Return_ParameterFail = 4, + ProtectedSetting_Write = 5, + No_Information = 6, + NetworkRequest_Fail = 7, + Device_WriteFail = 8, + Device_ReadFails = 9, + No_FactorySupported = 10, + System_Error = 11, + Device_BadState = 12, + FileWrite_Fail = 13, + File_AlreadyExists = 14, + File_Not_Accessible = 15, + Firmware_UpToDate = 16, + Firmware_Available = 17, + Return_Async = 18, + Invalid_Authorization = 19, + FWU_Application_Not_Available = 20, + Device_AlreadyConnected = 21, + Device_NotConnected = 22, + CannotClear_DeviceConnected = 23, + Device_Rebooted = 24, + Upload_AlreadyInProgress = 25, + Download_AlreadyInProgress = 26 + }; + + /** + * Custom error returned by commands expecting results when failing. + */ + export class CommandError extends Error { + command: string; + errmessage: string; + data: any; + + constructor(command: string, errmessage: string, data?: string) { + super("Command " + command +" failed with error message " + errmessage + " and details: " + JSON.stringify(data || {})); + this.command = command; + this.errmessage = errmessage; + this.data = data; + this.name = 'CommandError'; + } + }; + + + /** + * Internal helper that stores information about the promise to resolve/reject + * for a command being processed. + */ + interface PromiseCallbacks { + cmd: string, + resolve: (value?: any | PromiseLike | undefined) => void; + reject: (err: Error) => void; + } + + /** + * Event type for call backs. + */ + export interface Event { + message: string; + data: { + deviceID: number; + /* variable */ + }; + }; + + /** + * The format of errors returned. + */ + export type ClientError = any | { + error: string; + }; + + /** + * The format of messages returned. + */ + export type ClientMessage = any | { + message: string; + }; + + /** + * Type for event callback functions.. + */ + export declare type EventCallback = (event: Event) => void; + + /** + * Internal mapping from all known events to array of registered callbacks. All possible events are setup + * initially. Callbacks values are configured at runtime. + */ + const eventListeners: Map> = new Map>(); + eventNamesList.forEach((event: EventName) => eventListeners.set(event, [])); + + /** + * Device feature codes. + */ + export enum DeviceFeature { + BusyLight = 1000, + FactoryReset = 1001, + PairingList = 1002, + RemoteMMI = 1003, + MusicEqualizer = 1004, + EarbudInterconnectionStatus = 1005, + StepRate = 1006, + HeartRate = 1007, + RRInterval = 1008, + RingtoneUpload = 1009, + ImageUpload = 1010, + NeedsExplicitRebootAfterOta = 1011, + NeedsToBePutIncCradleToCompleteFwu = 1012, + RemoteMMIv2 = 1013, + Logging = 1014, + PreferredSoftphoneListInDevice = 1015, + VoiceAssistant = 1016, + PlayRingtone=1017 + }; + + /** + * A specification of a button for MMI capturing. + */ + export enum RemoteMmiType { + MMI_TYPE_MFB = 0, + MMI_TYPE_VOLUP = 1, + MMI_TYPE_VOLDOWN = 2, + MMI_TYPE_VCB = 3, + MMI_TYPE_APP = 4, + MMI_TYPE_TR_FORW = 5, + MMI_TYPE_TR_BACK = 6, + MMI_TYPE_PLAY = 7, + MMI_TYPE_MUTE = 8, + MMI_TYPE_HOOK_OFF = 9, + MMI_TYPE_HOOK_ON = 10, + MMI_TYPE_BLUETOOTH = 11, + MMI_TYPE_JABRA = 12, + MMI_TYPE_BATTERY = 13, + MMI_TYPE_PROG = 14, + MMI_TYPE_LINK = 15, + MMI_TYPE_ANC = 16, + MMI_TYPE_LISTEN_IN = 17, + MMI_TYPE_DOT3 = 18, + MMI_TYPE_DOT4 = 19, + MMI_TYPE_ALL = 255 + }; + + /** + * A MMI effect specification for light on, off or blinking in different tempo. + */ + export enum RemoteMmiSequence { + MMI_LED_SEQUENCE_OFF = 0, + MMI_LED_SEQUENCE_ON = 1, + MMI_LED_SEQUENCE_SLOW = 2, + MMI_LED_SEQUENCE_FAST = 3 + }; + + /** + * MMI button actions reported when button has focus. + */ + export enum RemoteMmiActionInput { + MMI_ACTION_UP = 1, + MMI_ACTION_DOWN = 2, + MMI_ACTION_TAP = 4, + MMI_ACTION_DOUBLE_TAP = 8, + MMI_ACTION_PRESS = 16, + MMI_ACTION_LONG_PRESS = 32, + MMI_ACTION_X_LONG_PRESS = 64 + }; + + /** + * A 3 x 8 bit set of RGB colors. Numbers can be between 0-255. + */ + export type ColorType = [number, number, number]; + + /** + * The log level currently used internally in this api facade. Initially this is set to show errors and + * warnings until a logEvent (>=0.5) changes this when initializing the extension or when the user + * changes the log level. Available in the API for testing only - do not use this in normal applications. + */ + export let logLevel: number = 2; + + /** + * An internal logger helper. + */ + const logger = new class { + trace(msg: string) { + if (logLevel >= 4) { + console.log(msg); + } + }; + + info(msg: string) { + if (logLevel >= 3) { + console.log(msg); + } + }; + + warn(msg: string) { + if (logLevel >= 2) { + console.warn(msg); + } + }; + + error(msg: string) { + if (logLevel >= 1) { + console.error(msg); + } + }; + }; + + /** + * A reasonably unique ID for our browser extension client that makes it possible to + * differentiate between different instances of this api in different browser tabs. + */ + const apiClientId: string = Math.random().toString(36).substr(2, 9); + + /** + * A mapping from unique request ids for commands and the promise information needed + * to resolve/reject them by an incomming event. + */ + const sendRequestResultMap: Map = new Map(); + + /** + * A counter used to generate unique request ID's used to match commands and returning events. + */ + let requestNumber: number = 1; + + /** + * Contains initialization information used by the init/shutdown methods. + */ + let initState: { + initialized?: boolean; + initializing?: boolean; + eventCallback?: (event: any) => void; + } = {}; + + /** + * The JavaScript library must be initialized using this function. It returns a promise that + * resolves when initialization is complete. + */ + export function init(): Promise { + return new Promise((resolve, reject) => { + // Only Chrome is currently supported + let isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor); + if (!isChrome) { + return reject(new Error("Jabra Browser Integration: Only supported by Google Chrome.")); + } + + if (initState.initialized || initState.initializing) { + return reject(new Error("Jabra Browser Integration already initialized")); + } + + initState.initializing = true; + sendRequestResultMap.clear(); + let duringInit = true; + + initState.eventCallback = (event: any) => { + if (event.source === window && + event.data.direction && + event.data.direction === "jabra-headset-extension-from-content-script") { + + let eventApiClientId = event.data.apiClientId || ""; + let requestId = event.data.requestId || ""; + + // Only accept responses from our own requests or from device. + if (apiClientId === eventApiClientId || eventApiClientId === "") { + logger.trace("Receiving event from content script: " + JSON.stringify(event.data)); + + // For backwards compatibility a blank message might be send as "na". + if (event.data.message === "na") { + delete event.data.message; + } + + // For backward compatability reinterprent messages starting with error as errors: + if (event.data.message && event.data.message.startsWith("Error:")) { + event.data.error = event.data.message; + delete event.data.message + } + + if (event.data.message) { + logger.trace("Got message: " + JSON.stringify(event.data)); + const normalizedMsg: string = event.data.message.substring(7); // Strip "Event" prefix; + + if (normalizedMsg.startsWith("logLevel")) { + logLevel = parseInt(event.data.message.substring(16)); + logger.trace("Logger set to level " + logLevel); + + // Loglevels are internal events and not an indication of proper + // initialization so skip rest of handling for log levels. + return; + } + + const commandIndex = commandEventsList.findIndex((e) => normalizedMsg.startsWith(e)); + if (commandIndex >= 0) { + // For install info and version command, we need to add api version number. + if (normalizedMsg === "getinstallinfo" || (normalizedMsg.startsWith("Version "))) { + // Old extension/host won't have data so make sure it exists to avoid breakage. + if (!event.data.data) { + event.data.data = {}; + } + event.data.data.version_jsapi = apiVersion; + } + + // For install info also check if the full installation is consistent. + if (normalizedMsg === "getinstallinfo") { + event.data.data.installationOk = isInstallationOk(event.data.data); + } + + // Lookup and check that we have identified a (real) command target to pair result with. + let resultTarget = identifyAndCleanupResultTarget(requestId); + if (resultTarget) { + let result: any; + if (event.data.data) { + result = event.data.data; + } else { + let dataPosition = commandEventsList[commandIndex].length + 1; + let dataStr = normalizedMsg.substring(dataPosition); + result = {}; + if (dataStr) { + result.legacy_result = dataStr; + }; + } + + resultTarget.resolve(result) + } else { + let err = "Result target information missing for message " + event.data.message + ". This is likely due to some software components that have not been updated or a software bug. Please upgrade extension and/or chromehost"; + logger.error(err); + notify("error", { + error: err, + message: event.data.message + }); + } + } else if (eventListeners.has(normalizedMsg as EventName)) { + let clientEvent: ClientMessage = JSON.parse(JSON.stringify(event.data)); + delete clientEvent.direction; + delete clientEvent.apiClientId; + delete clientEvent.requestId; + clientEvent.message = normalizedMsg; + + notify(normalizedMsg as EventName, clientEvent); + } else { + logger.warn("Unknown message: " + event.data.message); + notify("error", { + error: "Unknown message: ", + message: event.data.message + }); + // Don't let unknown messages complete initialization so stop here. + return; + } + + if (duringInit) { + duringInit = false; + return resolve(); + } + } else if (event.data.error) { + logger.error("Got error: " + event.data.error); + const normalizedError: string = event.data.error.substring(7); // Strip "Error" prefix; + + // Reject target promise if there is one - otherwise send a general error. + let resultTarget = identifyAndCleanupResultTarget(requestId); + if (resultTarget) { + resultTarget.reject(new CommandError(resultTarget.cmd, normalizedError, event.data.data)); + } else { + let clientError: ClientError = JSON.parse(JSON.stringify(event.data)); + delete clientError.direction; + delete clientError.apiClientId; + delete clientError.requestId; + clientError.error = normalizedError; + + notify("error", clientError); + } + + if (duringInit) { + duringInit = false; + return reject(new Error(event.data.error)); + } + } + } + } + }; + + window.addEventListener("message", initState.eventCallback!); + + // Initial getversion and loglevel. + setTimeout( + () => { + sendCmdWithResult("getversion", null, false).then((result) => { + let resultStr = (typeof result === 'string' || result instanceof String) ? result : JSON.stringify(result, null, 2); + logger.trace("getversion returned successfully with : " + resultStr); + + sendCmd("logLevel", null, false); + }).catch((error) => { + logger.error(error); + }); + }, + 1000 + ); + + // Check if the web-extension is installed + setTimeout( + function () { + if (duringInit === true) { + duringInit = false; + const extensionId = isBeta ? betaExtensionId : prodExtensionId; + reject(new Error("Jabra Browser Integration: You need to use this Extension and then reload this page")); + } + }, + 5000 + ); + + /** + * Helper that checks if the installation is consistent. + */ + function isInstallationOk(installInfo: InstallInfo): boolean { + let browserSdkVersions = [installInfo.version_browserextension, installInfo.version_chromehost, installInfo.version_jsapi]; + + // Check that we have install information for all components. + if (browserSdkVersions.some(v => !v) || !installInfo.version_nativesdk) { + return false; + } + + // Check that different beta versions are not mixed. + if (!browserSdkVersions.map(v => { + let betaIndex = v.lastIndexOf('beta'); + if (betaIndex>=0 && v.length>betaIndex+4) { + return v.substr(betaIndex+4); + } else { + return undefined; + } + }).filter(v => v).every((v, i, arr) => v === arr[0])) { + return false; + } + + return true; + } + + /** + * Post event/error to subscribers. + */ + function notify(eventName: EventName, eventMsg: ClientMessage | ClientError): void { + let callbacks = eventListeners.get(eventName); + if (callbacks) { + callbacks.forEach((callback) => { + callback(eventMsg); + }); + } else { + // This should not occur unless internal event mappings in this file + // are not configured correctly. + logger.error("Unexpected unknown eventName: " + eventName); + } + } + + /** Lookup any previous stored result target information for the request. + * Does cleanup if target found (so it can't be called twice for a request). + * Nb. requestId's are only provided by >= 0.5 extension and chromehost. + */ + function identifyAndCleanupResultTarget(requestId?: string) : PromiseCallbacks | undefined { + // Lookup any previous stored result target information for the request. + // Nb. requestId's are only provided by >= 0.5 extension and chromehost. + let resultTarget: PromiseCallbacks | undefined; + if (requestId) { + resultTarget = sendRequestResultMap.get(requestId); + // Remember to cleanup to avoid memory leak! + sendRequestResultMap.delete(requestId); + } else if (sendRequestResultMap.size === 1) { + // We don't have a requestId but since only one is being executed we + // can assume this is the one. + let value = sendRequestResultMap.entries().next().value; + resultTarget = value[1]; + // Remember to cleanup to avoid memory leak and for future + // requests like this to be resolved. + sendRequestResultMap.delete(value[0]); + } else { + // No idea what target matches what request - give up. + resultTarget = undefined; + } + + // Warn in case of likely memory leak: + const mapSize = sendRequestResultMap.size; + if (mapSize > 10 && mapSize % 10 === 0) { // Limit warnings to every 10 size increases to avoid flooding: + logger.warn("Memory leak found - Request result map is getting too large (size #" + mapSize + ")"); + } + + return resultTarget; + + } + + initState.initialized = true; + initState.initializing = false; + }); + }; + + /** + * De-initialize the api after use. Not normally used as api will normally + * stay in use thoughout an application - mostly of interest for testing. + */ + export function shutdown(): Promise { + if (initState.initialized) { + window.removeEventListener("message", initState.eventCallback!); + initState.eventCallback = undefined; + sendRequestResultMap.clear(); + requestNumber = 1; + initState.initialized = false; + + // Unsubscribe all. + eventListeners.forEach((value, key) => { + value = []; + }); + return Promise.resolve(); + } + + return Promise.reject(new Error("Browser integration not initialized")); + }; + + /** + * Internal helper that returns an array of valid event keys that correspond to the event specificator + * and are known to exist in our event listener map. + */ + function getEvents(nameSpec: string | RegExp | Array): ReadonlyArray { + if (Array.isArray(nameSpec)) { + // @ts-ignore: Disable wrong "argument not assignable" error in ts 3.4 + return [ ...new Set([].concat.apply([], nameSpec.map(a => getEvents(a)))) ]; + } else if (nameSpec instanceof RegExp) { + return Array.from(eventListeners.keys()).filter(key => nameSpec.test(key)) + } else { // String + if (eventListeners.has(nameSpec as EventName)) { + return [ nameSpec ]; + } else { + logger.warn("Unknown event " + nameSpec + " ignored when adding/removing eventlistener"); + } + } + + return []; + } + + /** + * Hook up listener call back to specified event(s) as specified by initial name specification argument nameSpec. + * When the nameSpec argument is a string, this correspond to a single named event. When the argument is a regular + * expression all lister subscribes to all matching events. If the argument is an array it recursively subscribes + * to all events specified in the array. + */ + export function addEventListener(nameSpec: string | RegExp | Array, callback: EventCallback): void { + getEvents(nameSpec).map(name => { + let callbacks = eventListeners.get(name as EventName); + if (!callbacks!.find((c) => c === callback)) { + callbacks!.push(callback); + } + }); + }; + + /** + * Remove existing listener to specified event(s). The callback must correspond to the exact callback provided + * to a previous addEventListener. + */ + export function removeEventListener(nameSpec: string | RegExp | Array, callback: EventCallback): void { + getEvents(nameSpec).map(name => { + let callbacks = eventListeners.get(name as EventName); + let findIndex = callbacks!.findIndex((c) => c === callback); + if (findIndex >= 0) { + callbacks!.splice(findIndex, 1); + } + }); + }; + + /** + * Activate ringer (if supported) on the Jabra Device + */ + export function ring(): void { + sendCmd("ring"); + }; + + /** + * Change state to in-a-call. + */ + export function offHook(): void { + sendCmd("offhook"); + }; + + /** + * Change state to idle (not-in-a-call). + */ + export function onHook(): void { + sendCmd("onhook"); + }; + + /** + * Mutes the microphone (if supported). + */ + export function mute(): void { + sendCmd("mute"); + }; + + /** + * Unmutes the microphone (if supported). + */ + export function unmute(): void { + sendCmd("unmute"); + }; + + /** + * Change state to held (if supported). + */ + export function hold(): void { + sendCmd("hold"); + }; + + /** + * Change state from held to OffHook (if supported). + */ + export function resume(): void { + sendCmd("resume"); + }; + + /** + * Capture/release buttons for customization (if supported). This turns off default behavior and enables mmi events to + * be received instead. It also allows for mmi actions to be applied like changing lights with setRemoteMmiLightAction. + * + * @param type The button that should be captured/released. + * @param capture True if button should be captured, false if it should be released. + * + * @returns A promise that is resolved once operation completes. + */ + export function setMmiFocus(type: RemoteMmiType | string, capture: boolean | string): Promise { + let typeVal = numberOrString(type); + let captureVal = booleanOrString(capture); + return sendCmdWithResult("setmmifocus", { + type: typeVal, + capture: captureVal + }); + } + + /** + * Change light/color on a previously captured button. + * Nb. This requires the button to be previously captured though setMMiFocus. + * + * @param type The button that should be captured/released. + * @param color An RGB array of 3x integers or a RGB number (with 0x or # prefix for hex). + * @param effect What effect to apply to the button. + * + * @returns A promise that is resolved once operation completes. + */ + export function setRemoteMmiLightAction(type: RemoteMmiType | string, color: ColorType | string | number, effect: RemoteMmiSequence | string): Promise { + let typeVal = numberOrString(type); + let colorVal = colorOrString(color); + let effectVal = numberOrString(effect); + return sendCmdWithResult("setremotemmilightaction", { + type: typeVal, + color: colorVal, + effect: effectVal + }); + } + + /** + * Internal helper to get detailed information about the current active Jabra Device + * from SDK, including current status but excluding media device information. + */ + function _doGetActiveSDKDevice(): Promise { + return sendCmdWithResult("getactivedevice"); + }; + + /** + * Internal helper to get detailed information about the all attached Jabra Devices + * from SDK, including current status but excluding media device information. + */ + function _doGetSDKDevices(): Promise> { + return sendCmdWithResult>("getdevices"); + }; + + /** + * Get detailed information about the current active Jabra Device, including current status + * and optionally also including related browser media device information. + * + * Note that browser media device information requires mediaDevices.getUserMedia or + * getUserDeviceMediaExt to have been called so permissions are granted. Browser media information + * is useful for setting a device constraint on mediaDevices.getUserMedia for input or for calling + * setSinkId (when supported by the browser) to set output. + */ + export function getActiveDevice(includeBrowserMediaDeviceInfo: boolean | string = false): Promise { + let includeBrowserMediaDeviceInfoVal = booleanOrString(includeBrowserMediaDeviceInfo); + if (includeBrowserMediaDeviceInfoVal) { + return _doGetActiveSDKDevice_And_BrowserDevice(); + } else { + return _doGetActiveSDKDevice(); + } + }; + + /** + * List detailed information about all attached Jabra Devices, including current status. + * and optionally also including related browser media device information. + * + * Note that browser media device information requires mediaDevices.getUserMedia or + * getUserDeviceMediaExt to have been called so permissions are granted. Browser media information + * is useful for setting a device constraint on mediaDevices.getUserMedia for input or for calling + * setSinkId (when supported by the browser) to set output. + */ + export function getDevices(includeBrowserMediaDeviceInfo: boolean | string = false): Promise> { + let includeBrowserMediaDeviceInfoVal = booleanOrString(includeBrowserMediaDeviceInfo); + if (includeBrowserMediaDeviceInfoVal) { + return _doGetSDKDevices_And_BrowserDevice(); + } else { + return _doGetSDKDevices(); + } + }; + + /** + * Internal utility that select a new active device in a backwards compatible way that works with earlier chrome host. + * Used internally by test tool - do not use otherwise. + * + * Note: The active device is a global setting that affects all browser + * instances using the browser SDK. Unless changed specifically, the setting + * persist until browser is restarted or device is unplugged. + * + * @deprecated Use setActiveDeviceId instead. + */ + export function _setActiveDeviceId(id: number | string): void { + let idVal = numberOrString(id); + + // Use both new and old way of passing parameters for compatibility with <= v0.5. + sendCmd("setactivedevice " + id.toString(), { id: idVal } ); + }; + + /** + * Select a new active device returning once selection is completed. + * + * Note: The active device is a global setting that affects all browser + * instances using the browser SDK. Unless changed specifically, the setting + * persist until browser is restarted or device is unplugged. + * + * @param id The id number of the new active device. + * @returns A promise that is resolved once selection completes. + * + */ + export function setActiveDeviceId(id: number | string): Promise { + let idVal = numberOrString(id); + + return sendCmdWithResult("setactivedevice2", { id: idVal } ); + }; + + /** + * Set busylight on active device (if supported) + * + * @param busy True if busy light should be set, false if it should be cleared. + */ + export function setBusyLight(busy: boolean | string): Promise { + let busyVal = booleanOrString(busy); + + return sendCmdWithResult("setbusylight", { busy: busyVal } ); + }; + + /** + * Get version number information for all components. + */ + export function getInstallInfo(): Promise { + return sendCmdWithResult("getinstallinfo"); + }; + + /** + * Internal helper that forwards a command to the browser extension + * without expecting a response. + */ + function sendCmd(cmd: string, args: object | null = null, requireInitializedCheck: boolean = true): void { + if (!requireInitializedCheck || (requireInitializedCheck && initState.initialized)) { + let requestId = (requestNumber++).toString(); + + let msg = { + direction: "jabra-headset-extension-from-page-script", + message: cmd, + args: args || {}, + requestId: requestId, + apiClientId: apiClientId, + version_jsapi: apiVersion + }; + + logger.trace("Sending command to content script: " + JSON.stringify(msg)); + + window.postMessage(msg, "*"); + } else { + throw new Error("Browser integration not initialized"); + } + }; + + /** + * Internal helper that forwards a command to the browser extension + * expecting a response (a promise). + */ + function sendCmdWithResult(cmd: string, args: object | null = null, requireInitializedCheck: boolean = true): Promise { + if (!requireInitializedCheck || (requireInitializedCheck && initState.initialized)) { + let requestId = (requestNumber++).toString(); + + return new Promise((resolve, reject) => { + sendRequestResultMap.set(requestId, { cmd, resolve, reject }); + + let msg = { + direction: "jabra-headset-extension-from-page-script", + message: cmd, + args: args || {}, + requestId: requestId, + apiClientId: apiClientId, + version_jsapi: apiVersion + }; + + logger.trace("Sending command to content script expecting result: " + JSON.stringify(msg)); + + window.postMessage(msg, "*"); + }); + } else { + return Promise.reject(new Error("Browser integration not initialized")); + } + }; + + /** + * Configure an audio html element on a webpage to use jabra audio device as speaker output. Returns a promise with boolean success status. + * The deviceInfo argument must come from getDeviceInfo or getUserDeviceMediaExt calls. + */ + export function trySetDeviceOutput(audioElement: HTMLMediaElement, deviceInfo: DeviceInfo): Promise { + if (!audioElement || !deviceInfo) { + return Promise.reject(new Error('Call to trySetDeviceOutput has argument(s) missing')); + } + + if (!(typeof ((audioElement as any).setSinkId) === "function")) { + return Promise.reject(new Error('Your browser does not support required Audio Output Devices API')); + } + + return (audioElement as any).setSinkId(deviceInfo.browserAudioOutputId).then(() => { + var success = (audioElement as any).sinkId === deviceInfo.browserAudioOutputId; + return success; + }); + }; + + /** + * Checks if a Jabra Input device is in fact selected in a media stream. + * The deviceInfo argument must come from getDeviceInfo or getUserDeviceMediaExt calls. + */ + export function isDeviceSelectedForInput(mediaStream: MediaStream, deviceInfo: DeviceInfo): boolean { + if (!mediaStream || !deviceInfo) { + throw Error('Call to isDeviceSelectedForInput has argument(s) missing'); + } + + var tracks = mediaStream.getAudioTracks(); + for (var i = 0, len = tracks.length; i < len; i++) { + var track = tracks[i]; + var trackCap = track.getCapabilities(); + if (trackCap.deviceId !== deviceInfo.browserAudioInputId) { + return false; + } + } + + return true; + }; + + /** + * Replacement for mediaDevices.getUserMedia that makes a best effort to select the active Jabra audio device + * to be used for the microphone. Unlike getUserMedia this method returns a promise that + * resolve to an object containing both a stream and the device info for the selected device. + * + * Optional, additional non-audio constrains (like f.x. video) can be specified as well. + * + * Note: Subsequently, if this method appears to succeed use the isDeviceSelectedForInput function to check + * if the browser did in fact choose a Jabra device for the microphone. + */ + export function getUserDeviceMediaExt(constraints?: MediaStreamConstraints): Promise { + // Good error if using old browser: + if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { + return Promise.reject(new Error('Your browser does not support required media api')); + } + + // Init completed ? + if (!initState.initialized) { + return Promise.reject(new Error("Browser integration not initialized")); + } + + // Warn of degraded UX experience unless we are running https. + if (location.protocol !== 'https:') { + logger.warn("This function needs to run under https for best UX experience (persisted permissions)"); + } + + // Check input validity: + if (constraints !== undefined && constraints !== null && typeof constraints !== 'object') { + return Promise.reject(new Error("Optional constraints parameter must be an object")); + } + + /** + * Utility method that combines constraints with ours taking precedence (deep). + */ + function mergeConstraints(ours: MediaStreamConstraints, theirs?: MediaStreamConstraints): MediaStreamConstraints { + if (theirs !== null && theirs !== undefined && typeof ours === 'object') { + let result: { [index: string]: any } = {}; + for (var attrname in theirs) { result[attrname] = (theirs as any)[attrname]; } + for (var attrname in ours) { result[attrname] = mergeConstraints((ours as any)[attrname], (theirs as any)[attrname]); } // Ours takes precedence. + return result; + } else { + return ours; + } + } + + // If we have the input device id already we can do a direct call to getUserMedia, otherwise we have to do + // an initial general call to getUserMedia just get access to looking up the input device and then a second + // call to getUserMedia to make sure the Jabra input device is selected. + return navigator.mediaDevices.getUserMedia(mergeConstraints({ audio: true }, constraints)).then((dummyStream) => { + return _doGetActiveSDKDevice_And_BrowserDevice().then((deviceInfo) => { + // Shutdown initial dummy stream (not sure it is really required but let's be nice). + dummyStream.getTracks().forEach((track) => { + track.stop(); + }); + + if (deviceInfo && deviceInfo.browserAudioInputId) { + return navigator.mediaDevices.getUserMedia(mergeConstraints({ audio: { deviceId: deviceInfo.browserAudioInputId } }, constraints)) + .then((stream) => { + return { + stream: stream, + deviceInfo: deviceInfo + }; + }) + } else { + return Promise.reject(new Error('Could not find a Jabra device with a microphone')); + } + }) + }); + }; + + /** + * Internal helper for add media information properties to existing SDK device information. + */ + function fillInMatchingMediaInfo(deviceInfo: DeviceInfo, mediaDevices: MediaDeviceInfo[]): void { + function findBestMatchIndex(sdkDeviceName: string, mediaDeviceNameCandidates: string[]): number { + // Edit distance helper adapted from + // https://stackoverflow.com/questions/10473745/compare-strings-javascript-return-of-likely + function editDistance(s1: string, s2: string) { + s1 = s1.toLowerCase(); + s2 = s2.toLowerCase(); + + var costs = new Array(); + for (var i = 0; i <= s1.length; i++) { + var lastValue = i; + for (var j = 0; j <= s2.length; j++) { + if (i == 0) + costs[j] = j; + else { + if (j > 0) { + var newValue = costs[j - 1]; + if (s1.charAt(i - 1) != s2.charAt(j - 1)) + newValue = Math.min(Math.min(newValue, lastValue), + costs[j]) + 1; + costs[j - 1] = lastValue; + lastValue = newValue; + } + } + } + if (i > 0) + costs[s2.length] = lastValue; + } + return costs[s2.length]; + } + + // Levenshtein distance helper adapted from + // https://stackoverflow.com/questions/10473745/compare-strings-javascript-return-of-likely + function levenshteinDistance(s1: string, s2: string) : number { + let longer = s1; + let shorter = s2; + if (s1.length < s2.length) { + longer = s2; + shorter = s1; + } + let longerLength = longer.length; + if (longerLength === 0) { + return 1.0; + } + return (longerLength - editDistance(longer, shorter)) / longerLength; + } + + if (mediaDeviceNameCandidates.length == 1) { + return 0; + } else if (mediaDeviceNameCandidates.length > 0) { + let similarities = mediaDeviceNameCandidates.map(candidate => { + if (candidate.includes("(" + sdkDeviceName + ")")) { + return 1.0; + } else { + // Remove Standard/Default prefix from label in Chrome when comparing + let prefixEnd = candidate.indexOf(' - '); + let cleanedCandidate = (prefixEnd >= 0) ? candidate.substring(prefixEnd + 3) : candidate; + + return levenshteinDistance(sdkDeviceName, cleanedCandidate) + } + }); + let bestMatchIndex = similarities.reduce((prevIndexMax, value, i, a) => value > a[prevIndexMax] ? i : prevIndexMax, 0); + return bestMatchIndex; + } else { + return -1; + } + } + + // Find matching pair input or output device. + function findMatchingMediaDevice(groupId: string, kind: string, src: MediaDeviceInfo[]): MediaDeviceInfo | undefined { + return src.find(md => md.groupId == groupId && md.kind == kind); + } + + if (deviceInfo && deviceInfo.deviceName) { + let groupId: string | undefined = undefined; + let audioInputId: string | undefined = undefined; + let audioOutputId: string | undefined = undefined; + let label: string | undefined = undefined; + // Filter out non Jabra input/output devices: + let jabraMediaDevices = mediaDevices.filter(device => device.label + && device.label.toLowerCase().includes('jabra') + && (device.kind === 'audioinput' || device.kind === 'audiooutput')); + let someJabraDeviceIndex = findBestMatchIndex(deviceInfo.deviceName, jabraMediaDevices.map(md => md.label)); + if (someJabraDeviceIndex >= 0) { + let foundDevice = jabraMediaDevices[someJabraDeviceIndex]; + groupId = foundDevice.groupId; + label = foundDevice.label; + if (foundDevice.kind === 'audioinput') { + audioInputId = foundDevice.deviceId; + // Lookup matching output device: + let outputDevice = findMatchingMediaDevice(groupId, 'audiooutput', jabraMediaDevices); + if (outputDevice) { + audioOutputId = outputDevice.deviceId; + } + } + else if (foundDevice.kind === 'audiooutput') { + audioOutputId = foundDevice.deviceId; + // Lookup matching output input device: + let inputDevice = findMatchingMediaDevice(groupId, 'audioinput', jabraMediaDevices); + if (inputDevice) { + audioInputId = inputDevice.deviceId; + } + } + } + if (groupId) { + deviceInfo.browserGroupId = groupId; + } + if (label) { + deviceInfo.browserLabel = label; + } + if (audioInputId) { + deviceInfo.browserAudioInputId = audioInputId; + } + if (audioOutputId) { + deviceInfo.browserAudioOutputId = audioOutputId; + } + } else { + // Do nothing if device information is missing. + } + } + + /** + * Internal helper that returns complete device information, including both SDK and browser media device + * information for all devices. + * + * Chrome note: + * 1) Only works if hosted under https. + * + * Firefox note: + * 1) Output devices not supported yet. See "https://bugzilla.mozilla.org/show_bug.cgi?id=934425" + * 2) The user must have provided permission to use the specific device to use it as a constraint. + * 3) GroupId not supported. + * + * General non-chrome browser note: + * 1) Returning output devices requires support for new Audio Output Devices API. + */ + function _doGetSDKDevices_And_BrowserDevice(): Promise> { + // Good error if using old browser: + if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) { + return Promise.reject(new Error('Your browser does not support required media api')); + } + + // Init completed ? + if (!initState.initialized) { + return Promise.reject(new Error("Browser integration not initialized")); + } + + // Browser security rules (for at least chrome) requires site to run under https for labels to be read. + if (location.protocol !== 'https:') { + return Promise.reject(new Error('Your browser needs https for lookup to work')); + } + + return Promise.all([_doGetSDKDevices(), navigator.mediaDevices.enumerateDevices()]).then( ([deviceInfos, mediaDevices]) => { + deviceInfos.forEach( (deviceInfo) => { + fillInMatchingMediaInfo(deviceInfo, mediaDevices); + }); + + return deviceInfos; + }); + } + + /** + * Internal helper that returns complete device information, including both SDK and browser media device + * information for active device. + * + * Chrome note: + * 1) Only works if hosted under https. + * + * Firefox note: + * 1) Output devices not supported yet. See "https://bugzilla.mozilla.org/show_bug.cgi?id=934425" + * 2) The user must have provided permission to use the specific device to use it as a constraint. + * 3) GroupId not supported. + * + * General non-chrome browser note: + * 1) Returning output devices requires support for new Audio Output Devices API. + */ + function _doGetActiveSDKDevice_And_BrowserDevice(): Promise { + // Good error if using old browser: + if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) { + return Promise.reject(new Error('Your browser does not support required media api')); + } + + // Init completed ? + if (!initState.initialized) { + return Promise.reject(new Error("Browser integration not initialized")); + } + + // Browser security rules (for at least chrome) requires site to run under https for labels to be read. + if (location.protocol !== 'https:') { + return Promise.reject(new Error('Your browser needs https for lookup to work')); + } + + // enumerateDevices requires user to have provided permission using getUserMedia for labels to be filled out. + return Promise.all([_doGetActiveSDKDevice(), navigator.mediaDevices.enumerateDevices()]).then( ([deviceInfo, mediaDevices]) => { + fillInMatchingMediaInfo(deviceInfo, mediaDevices); + return deviceInfo; + }); + }; + + /** + * Helper that pass boolean values through and parses strings to booleans. + */ + function booleanOrString(arg: boolean | string) : boolean + { + if (arg !== "" && ((typeof arg === 'string') || ((arg as any) instanceof String))) { + return (arg === 'true' || arg === '1'); + } else if (typeof(arg) === "boolean") { + return arg; + } else { + throw new Error("Illegal/missing argument - boolean or string expected"); + } + } + + /** + * Helper that pass numbers through and parses strings to numbers. + */ + function numberOrString(arg: number | string): number { + if (arg !== "" && ((typeof arg === 'string') || ((arg as any) instanceof String))) { + return parseInt(arg as string); + } else if (typeof arg == 'number') { + return arg; + } else { + throw new Error("Illegal/missing argument - number or string expected"); + } + }; + + /** + * Helper that pass color array through and converts values to color array. + */ + function colorOrString(arg: ReadonlyArray | number | string): ReadonlyArray { + if (arg !== "" && ((typeof arg === 'string') || ((arg as any) instanceof String))) { + let combinedValue = parseInt(arg as string, 16); + return [ (combinedValue >> 16) & 255, (combinedValue >> 8) & 255, combinedValue & 255 ]; + } else if (typeof arg == 'number') { + let combinedValue = arg; + return [ (combinedValue >> 16) & 255, (combinedValue >> 8) & 255, combinedValue & 255 ]; + } else if (Array.isArray(arg)) { + if (arg.length !=3) { + throw new Error("Illegal argument - wrong dimension of number array (3 expected)"); + } + return arg; + } else { + throw new Error("Illegal/missing argument - number array or hex string expected"); + } + }; +}; diff --git a/public/index.html b/public/index.html index 2864ddd..d48080c 100644 --- a/public/index.html +++ b/public/index.html @@ -14,7 +14,7 @@ - + @@ -58,18 +58,14 @@ - + - + - - - - diff --git a/public/scripts/app.ed69bc23.js b/public/scripts/app.80a701c6.js similarity index 56% rename from public/scripts/app.ed69bc23.js rename to public/scripts/app.80a701c6.js index 7205442..1f0b35d 100644 --- a/public/scripts/app.ed69bc23.js +++ b/public/scripts/app.80a701c6.js @@ -1 +1 @@ -!function(){"use strict";angular.module("app.auth",[])}(),function(){"use strict";angular.module("app.core",["ngAnimate","ngAria","ngCookies","ngMessages","ngResource","ngSanitize","ngMaterial","pascalprecht.translate","ui.router","ui.router.state.events","gridster","ds.clock","angucomplete-alt"])}(),function(){"use strict";function e(e,n){e.state("app.errors_error-404",{url:"/errors/error-404",views:{"main@":{templateUrl:"app/core/layouts/content-only.html",controller:"MainController as vm"},"content@app.errors_error-404":{templateUrl:"app/errors/404/error-404.html",controller:"Error404Controller as vm"}},params:{status:404,statusText:"",data:{},config:{}},bodyClass:"error-404"}),n.addPart("app/errors/404")}e.$inject=["$stateProvider","$translatePartialLoaderProvider"],angular.module("app.errors.error-404",[]).config(e)}(),function(){"use strict";function e(e,n){e.state("app.errors_error-500",{url:"/errors/error-500",views:{"main@":{templateUrl:"app/core/layouts/content-only.html",controller:"MainController as vm"},"content@app.errors_error-500":{templateUrl:"app/errors/500/error-500.html",controller:"Error500Controller as vm"}},params:{status:500,statusText:"",data:{},config:{}},bodyClass:"error-500"}),n.addPart("app/errors/500")}e.$inject=["$stateProvider","$translatePartialLoaderProvider"],angular.module("app.errors.error-500",[]).config(e)}(),function(){"use strict";angular.module("app.errors",["app.errors.error-404","app.errors.error-500"])}(),function(){"use strict";function e(e){e.addPart("app/footer")}e.$inject=["$translatePartialLoaderProvider"],angular.module("app.footer",[]).config(e)}(),function(){"use strict";function e(e,n){e.state("app.forgot",{url:"/forgot",views:{"main@":{templateUrl:"app/core/layouts/content-only.html",controller:"MainController as vm"},"content@app.forgot":{templateUrl:"app/forgot/forgot.html",controller:"ForgotPasswordController as vm"}},bodyClass:"forgot"}),n.addPart("app/forgot")}e.$inject=["$stateProvider","$translatePartialLoaderProvider"],angular.module("app.forgot",[]).config(e)}(),function(){"use strict";function e(e){e.addPart("app/header")}e.$inject=["$translatePartialLoaderProvider"],angular.module("app.header",[]).config(e)}(),function(){"use strict";angular.module("motion",["angular-toasty","app.core","app.auth","app.navigation","app.toolbar","app.quick-panel","app.header","app.footer","app.dashboards","app.staff","app.contactmanager","app.voice","app.chat","app.mail","app.sms","app.openchannel","app.fax","app.tools","app.callysquare","app.analytics","app.integrations","app.settings","app.motiondialer","app.help","app.jscripty","app.marketplace","app.plugins","app.video","app.login","app.forgot","app.reset","app.errors"])}(),function(){"use strict";function e(e,n){e.state("app.login",{url:"/login?token&userId",views:{"main@":{templateUrl:"app/core/layouts/content-only.html",controller:"MainController as vm"},"content@app.login":{templateUrl:"app/login/login.html",controller:"LoginController as vm"}},bodyClass:"login"}),n.addPart("app/login")}e.$inject=["$stateProvider","$translatePartialLoaderProvider"],angular.module("app.login",[]).config(e)}(),function(){"use strict";function e(e,n,t,a){e.state("app.analytics",{abstract:!0,url:"/analytics"}).state("app.analytics.metrics",{url:"/metrics",views:{"content@app":{templateUrl:"app/main/apps/analytics/views/metrics/metrics.html",controller:"MetricsController as vm"}},resolve:{metrics:["apiResolver","Auth",function(e,n){return n.hasRole("admin")?e.resolve("analyticMetric@get",{fields:"createdAt,updatedAt,id,name,table,metric,description",sort:"-updatedAt",limit:10,offset:0}):e.resolve("userProfile@getResources",{id:n.getCurrentUser().userProfileId,section:"Metrics",fields:"createdAt,updatedAt,id,name,table,metric,description",sort:"-updatedAt",limit:10,offset:0})}],userProfile:["apiResolver","Auth",function(e,n){return n.hasRole("admin")?null:e.resolve("userProfile@get",{fields:"id,name,crudPermissions",id:n.getCurrentUser().userProfileId})}],userProfileSection:["apiResolver","Auth",function(e,n){return n.hasRole("admin")?null:e.resolve("userProfileSection@get",{fields:"id,name,enabled,includeAll,autoAssociation,crudPermissions",userProfileId:n.getCurrentUser().userProfileId,sectionId:1201})}]},authenticate:!0,permissionId:1201,bodyClass:"analytics"}).state("app.analytics.extractedReports",{url:"/extractedReports",views:{"content@app":{templateUrl:"app/main/apps/analytics/views/extractedReports/extractedReports.html",controller:"ExtractedReportsController as vm"}},resolve:{extractedReports:["apiResolver","Auth",function(e,n){return n.hasRole("admin")?e.resolve("analyticExtractedReport@get",{fields:"createdAt,updatedAt,id,name,basename,savename,type,startDate,endDate,status,output,reportId,reportType",sort:"-updatedAt",limit:10,offset:0}):e.resolve("userProfile@getResources",{id:n.getCurrentUser().userProfileId,section:"ExtractedReports",fields:"createdAt,updatedAt,id,name,basename,savename,type,startDate,endDate,status,output,reportId,reportType",sort:"-updatedAt",limit:10,offset:0})}],userProfile:["apiResolver","Auth",function(e,n){return n.hasRole("admin")?null:e.resolve("userProfile@get",{fields:"id,name,crudPermissions",id:n.getCurrentUser().userProfileId})}],userProfileSection:["apiResolver","Auth",function(e,n){return n.hasRole("admin")?null:e.resolve("userProfileSection@get",{fields:"id,name,enabled,includeAll,autoAssociation,crudPermissions",userProfileId:n.getCurrentUser().userProfileId,sectionId:1202})}]},authenticate:!0,permissionId:1202,bodyClass:"analytics"}),n.addPart("app/main/apps/analytics")}e.$inject=["$stateProvider","$translatePartialLoaderProvider","msApiProvider","msNavigationServiceProvider"],angular.module("app.analytics",["ngCsv","ngPassword","md.data.table","flow","mdColorPicker","ckeditor","ng-sortable","ngAria","ngAnimate","mdPickers","mwFormBuilder","mwFormViewer","mwFormUtils","ngclipboard","angular-cron-jobs","ngEmbed","angularMaterialFormBuilder","material.components.expansionPanels","chart.js","angular.filter","app.analytics.reports"]).config(e)}(),function(){"use strict";function e(e){e.state("app.analytics.reports",{url:"/reports",views:{"content@app":{templateUrl:"app/main/apps/analytics/views/reports/reports.html",controller:"ReportsController as vm"}},resolve:{treeReports:["apiResolver",function(e){return e.resolve("analyticTreeReport@get",{fields:"id,tree",limit:10,offset:0})}],userProfile:["apiResolver","Auth",function(e,n){return e.resolve("userProfile@get",{fields:"id,name,crudPermissions",id:n.getCurrentUser().userProfileId})}],userProfileSection:["apiResolver","Auth",function(e,n){return e.resolve("userProfileSection@get",{fields:"id,name,enabled,includeAll,autoAssociation,crudPermissions",userProfileId:n.getCurrentUser().userProfileId,sectionId:1203})}]},authenticate:!0,permissionId:1203,bodyClass:"analytics"}).state("app.analytics.reports.edit",{url:"/:id?tab",views:{"content@app":{templateUrl:"app/main/apps/analytics/views/reports/edit/view.html",controller:"ReportController as vm"}},resolve:{report:["apiResolver","$stateParams","$q","describeTable",function(e,n,a,i){var s;return e.resolve("analyticCustomReport@get",{fields:"createdAt,updatedAt,id,name,description,table,conditions,joins",id:n.id}).then(function(e){var n=[];if((s=e).joins)try{s.joins=JSON.parse(s.joins);for(var t=0;t');a.append(n),o(function(){!function(e,n){var t=n.find("code"),a=e.split("\n"),i=(a=a.filter(function(e){return e.trim().length}))[0].match(/^\s*/)[0],s=new RegExp("^"+i);a=a.map(function(e){return e.replace(s,"").replace(/\s+$/,"")});var o=hljs.highlight(r.language||r.lang,a.join("\n"),!0);o.value=o.value.replace(/=""<\/span>/gi,"").replace("","").replace("",""),t.append(o.value).addClass("highlight")}(e,n)},34,!1)}})}}}}e.$inject=["$timeout","$q","$interpolate"],angular.module("app.core").directive("hljs",e)}(),function(){"use strict";angular.module("app.core").directive("msAdvancedFilter",function(){return{restrict:"E",scope:{options:"="},controller:["$scope",function(l){l.conditions=[],l.getValues=function(e){l.options.getFieldValues(e);var n=null;switch(e.type){case"text":l.conditions=[{name:"Contains",value:"LIKE"},{name:"Equals",value:"="}];break;case"autocomplete":n=[];break;case"date":n={dateStart:null};break;case"number":l.conditions=[{name:"Equals",value:"="},{name:"Greater than",value:">"},{name:"Lower than",value:"<"}]}var t=-1<["select","autocomplete"].indexOf(e.type)?"is":l.options.selectedCondition,a=_.find(l.options.activeConditions,{name:e.name,condition:t});l.options.selectedValue=a?a.values:n},l.searchText=function(e,n){l.options.searchItem(e,n)},l.addNewCondition=function(e,n,t){var a,i,s=[];switch(e.type){case"select":case"autocomplete":i=_.map(t,"name").join(" or "),a={name:"Is",value:"IS"},s=t;break;case"date":var o=moment(t.dateStart).format("YYYY-MM-DD"),r=moment(t.dateEnd).add(23,"hours").add(59,"minutes").add(59,"seconds").format("YYYY-MM-DD");i="from "+o+" to "+r;break;default:a=n,i=t,s.push({name:t})}l.options.addCondition(e,a,t,i)},l.removeCondition=function(){_.isEmpty(l.options.activeConditions)&&l.options.getResults()},l.clearConditions=function(){l.options.activeConditions=[],l.options.getResults()},l.applyFilter=function(){l.options.getResults()}}],templateUrl:"app/core/directives/ms-advanced-filter/ms-advanced-filter.html"}})}(),function(){"use strict";angular.module("app.core").directive("msCard",function(){return{restrict:"E",scope:{templatePath:"=template",card:"=ngModel",vm:"=viewModel"},template:'
',compile:function(e){return e.addClass("ms-card"),function(e,n){e.cardTemplateLoaded=function(){e.$emit("msCard::cardTemplateLoaded",n)}}}}})}(),function(){"use strict";angular.module("app.core").directive("msClickToCall",function(){return{restrict:"E",scope:{type:"=",disabled:"=",target:"=",prefix:"=",license:"="},controller:["$scope","$rootScope","$http","$translate","$document","$mdDialog","Auth","toasty","api",function(t,n,a,i,s,o,e,r,l){function d(e){switch(t.currentUser.showWebBar){case 0:return m("http://127.0.0.1:"+(t.currentUser.phoneBarRemoteControlPort||"9888")+"/api/originate/"+c(e));case 2:return n.$broadcast("webrtc::call",{target:c(e)})}}function c(e){return _.isNil(e)?"":e.replace(/[^\w.+#*\-]+/g,"")}function m(e){return a.get(e).success(function(){r.success({title:"Successful call",msg:"Call properly handled!"})}).error(function(e){r.error({title:"PhoneBar API Error",msg:i.instant("CONTACTMANAGER.ERRORS.PHONEBAR_API")})})}t.currentUser=e.getCurrentUser(),t.showMenu=function(){return t.target&&t.target.indexOf("@")<0&&t.target!=t.currentUser.internal&&t.target!=t.currentUser.name&&(0==t.currentUser.showWebBar&&t.currentUser.phoneBarRemoteControl||2==t.currentUser.showWebBar&&t.license.webrtc)&&!t.disabled},t.call=function(e){return 2!==t.currentUser.showWebBar?(n=e,l.user.getVoicePrefixes({id:t.currentUser.id}).$promise.then(function(e){if(e.count)return o.show({controller:"PrefixDialogController",controllerAs:"vm",templateUrl:"assets/ms-phonebar/prefix/dialog.html",parent:angular.element(s.body),clickOutsideToClose:!0,locals:{prefixes:e,required:t.currentUser.phoneBarPrefixRequired}})}).then(function(e){t.currentUser.phoneBarPrefixRequired?e&&-1!==e&&d(e+n):e&&-1!==e?d(e+n):e||d(n)})):d(e);var n},t.transfer=function(e){switch(t.currentUser.showWebBar){case 0:return m("http://127.0.0.1:"+(t.currentUser.phoneBarRemoteControlPort||"9888")+"/api/transfer?number="+c(e));case 2:n.$broadcast("webrtc::transfer",{target:c(e)})}}}],templateUrl:"app/core/directives/ms-click-to-call/ms-click-to-call.html"}})}(),function(){"use strict";function e(i){return{require:"ngModel",priority:1,link:function(e,n,t,a){a.$formatters.push(i.formatter),a.$parsers.push(i.parser)}}}e.$inject=["msDatepickerFixConfig"],angular.module("app.core").provider("msDatepickerFixConfig",function(){var n={formatter:function(e){return e?""===e?e:new Date(e):""},parser:function(e){return e?moment(e).add(moment(e).utcOffset(),"m").toDate():""}};this.config=function(e){n=angular.extend({},n,e)},this.$get=function(){return n}}).directive("msDatepickerFix",e)}(),function(){"use strict";function e(s){return{restrict:"E",scope:{id:"=",model:"=",element:"=",title:"=",path:"="},replace:!0,link:function(n,e){var t=!1,a={};a.id=n.id,_.isNil(n.path)||(a.path=n.path);var i=document.createElement(n.element);i.setAttribute("preload","none"),i.setAttribute("controls","true"),"audio"===n.element&&i.setAttribute("style","width: 265px;"),"video"===n.element&&i.setAttribute("style","max-width: 500px;"),i.setAttribute("title",n.title),i.setAttribute("src"," "),i.onplay=function(e){t||(t=!0,e.preventDefault(),s[n.model].download(a).$promise.then(function(e){var n=[e.buffer],t=new Blob(n,{type:e.type});i.setAttribute("type",e.type),i.setAttribute("src",URL.createObjectURL(t)),i.play()}).catch(function(e){console.error(e)}))},e.append(i)}}}e.$inject=["api"],angular.module("app.core").directive("msDialogRecording",e)}(),function(){"use strict";angular.module("app.core").directive("msDualMultiselect",function(){return{restrict:"E",scope:{options:"="},controller:["$scope",function(o){o.canTransfer=function(e,n,t){if(!n.readOnly)return void 0!==e.isValid&&e.isValid?t?o.transfer(n.selectedItems,n.items,n.selectedItems.indexOf(e),t):o.transfer(n.items,n.selectedItems,n.items.indexOf(e),t):void 0},o.transfer=function(e,n,t,a){var i=[];if(0<=t)i.push(e[t]),n.push(e[t]),e.splice(t,1);else{for(var s=0;s',link:function(t,e){var n=e.emojioneArea({pickerPosition:t.pickerPosition,search:t.search,recentEmojis:t.recentEmojis,placeholder:a.instant(t.placeholder||"Type a message"),attributes:{spellcheck:!0},events:{keypress:function(e,n){t.ngModel=this.getText(),t.onReply({event:n,body:this.getText()})},emojibtn_click:function(){t.ngModel=this.getText()}}});t.ngModel&&n[0].emojioneArea.setText(t.ngModel),t.internalControl=t.ctrlMethods||{},t.internalControl.setText=function(e){n[0].emojioneArea.setText(e)},t.internalControl.getText=function(){return n[0].emojioneArea.getText()},t.$watch("ngModel",function(e){e||n[0].emojioneArea.setText("")})}}}e.$inject=["$translate"],angular.module("app.core").directive("msEmojiArea",e)}(),function(){"use strict";angular.module("app.core").directive("msFontFamily",function(){return{restrict:"E",scope:{ngModel:"="},controller:["$scope",function(e){e.fonts=[{option:"Arial",value:"Arial,Helvetica,sans-serif"},{option:"Century Gothic",value:"Century Gothic,Futura,Didact Gothic,san-serif"},{option:"Calibri",value:"Calibri, Verdana, Geneva, sans-serif"},{option:"Comic Sans MS",value:"Comic Sans MS,cursive"},{option:"Courier New",value:"Courier New,Courier,monospace"},{option:"Georgia",value:"Georgia,serif"},{option:"Lucida Sans Unicode",value:"Lucida Sans Unicode,Lucida Grande,sans-serif"},{option:"Tahoma",value:"Tahoma,Geneva,sans-serif"},{option:"Times New Roman",value:"Times New Roman,Times,serif"},{option:"Trebuchet MS",value:"Trebuchet MS,Helvetica,sans-serif"},{option:"Verdana",value:"Verdana,Geneva,sans-serif"}]}],templateUrl:"app/core/directives/ms-font-family/ms-font-family.html"}})}(),function(){"use strict";angular.module("app.core").controller("MsFormWizardController",function(){var n=this;function e(){return n.forms.length}function t(){return 0===n.selectedIndex}function a(){return n.selectedIndex===e()-1}n.forms=[],n.selectedIndex=0,n.registerForm=function(e){n.forms.push(e)},n.previousStep=function(){if(t())return;n.selectedIndex--},n.nextStep=function(){if(a())return;n.selectedIndex++},n.firstStep=function(){n.selectedIndex=0},n.lastStep=function(){n.selectedIndex=e()-1},n.totalSteps=e,n.isFirstStep=t,n.isLastStep=a,n.currentStepInvalid=function(){return angular.isDefined(n.forms[n.selectedIndex])&&n.forms[n.selectedIndex].$invalid},n.previousStepInvalid=function(){return 0d.options.responsive.md?d.options.responsive.md:d.columnCount:l("sm")?d.columnCount=d.columnCount>d.options.responsive.sm?d.options.responsive.sm:d.columnCount:d.columnCount=d.options.responsive.xs;d.columnWidth=d.containerPos.width/d.columnCount}(),r.$broadcast("msMasonry:relayoutStarted"),d.items=d.container.find("ms-masonry-item");for(var e=Array.apply(null,new Array(d.columnCount)).map(function(){return 0}),n=0;n'),r=angular.element('
'),l=n.parent();function d(){s.addClass("ms-nav-folded"),g.$broadcast("msNav::forceCollapse"),n.scrollTop(0),l.append(o),o.on("mouseenter touchstart",function(e){c(e),i=!0})}function c(e){angular.isDefined(e)&&e.preventDefault(),s.addClass("ms-nav-folded-open"),g.$broadcast("msNav::expandMatchingToggles"),l.find(o).remove(),l.parent().append(r),r.on("mouseenter touchstart",function(e){m(e),i=!1})}function m(e){angular.isDefined(e)&&e.preventDefault(),g.$broadcast("msNav::forceCollapse"),n.scrollTop(0),s.removeClass("ms-nav-folded-open"),l.parent().find(r).remove(),l.append(o),o.on("mouseenter touchstart",function(e){c(e),i=!0})}function u(){s.removeClass("ms-nav-folded ms-nav-folded-open"),g.$broadcast("msNav::expandMatchingToggles"),n.off("mouseenter mouseleave")}v.setFoldable(e,n,a),a?d():u(),e.toggleFold=function(){(a=!a)?d():u()},e.openFolded=c,e.closeFolded=m,e.isNavFoldedOpen=function(){return i},e.$on("$destroy",function(){o.off("mouseenter touchstart"),r.off("mouseenter touchstart"),n.off("mouseenter mouseleave")})}}}function n(t,a,i){return{restrict:"E",scope:{},controller:"MsNavController",compile:function(e){return e.addClass("ms-nav"),function(e){t.$broadcast("msNav::expandMatchingToggles");var n=t.$on("$stateChangeSuccess",function(){t.$broadcast("msNav::expandMatchingToggles"),a.when("navigation").then(function(e){e.close(),i.isNavFoldedOpen()&&i.closeFolded()})});e.$on("$destroy",function(){n()})}}}}function t(m,u,p,g){return{restrict:"A",require:"^msNav",scope:!0,compile:function(e,n){return e.addClass("ms-nav-toggle"),angular.isUndefined(n.collapsed)&&(n.collapsed=!0),e.attr("collapsed",n.collapsed),function(a,i,e,t){var s={expanded:"expanded",expandAnimation:"expand-animation",collapseAnimation:"collapse-animation"},n=i.find("a"),o=[],r=/\(.*\)/g;function l(){return"true"===i.attr("collapsed")}function d(){var e=u.defer();if(!l())return e.reject({error:!0}),e.promise;i.attr("collapsed",!1);var n=angular.element(i.find("ms-nav-toggle-items")[0]);n.css({position:"absolute",visibility:"hidden",display:"block",height:"auto"});var t=n[0].offsetHeight;return n.css({position:"",visibility:"",display:"",height:""}),a.$evalAsync(function(){p.animate(n,{display:"block",height:"0px"},{height:t+"px"},s.expandAnimation).then(function(){n.addClass(s.expanded),n.css({height:""}),e.resolve({success:!0})})}),e.promise}function c(){var e=u.defer();if(l())return e.reject({error:!0}),e.promise;i.attr("collapsed",!0);var n=angular.element(i.find("ms-nav-toggle-items")[0]),t=n[0].offsetHeight;return a.$evalAsync(function(){p.animate(n,{height:t+"px"},{height:"0px"},s.collapseAnimation).then(function(){n.removeClass(s.expanded),n.css({display:"",height:""}),e.resolve({success:!0})})}),e.promise}angular.forEach(n,function(e){var n=angular.element(e).attr("ui-sref");angular.isUndefined(n)||(n=n.replace(r,""),o.push(n))}),t.setToggleItem(i,a),i.children(".ms-nav-button").on("click",function(){if(t.isDisabled())return;t.disable(),l()?(t.clearLockedItems(),a.$emit("msNav::pushToLockedList"),m.$broadcast("msNav::collapse"),d().then(function(){t.enable()})):a.$broadcast("msNav::forceCollapse")}),a.$on("$destroy",function(){i.children(".ms-nav-button").off("click")}),a.$on("msNav::collapse",function(){var e=t.getLockedItems(),n=!1;angular.forEach(e,function(e){angular.equals(e.scope,a)&&(n=!0)}),n||c().then(function(){t.enable()})}),a.$on("msNav::forceCollapse",function(){c().then(function(){t.enable()})}),a.$on("msNav::expandMatchingToggles",function(){var n=g.current.name,t=!1;angular.forEach(o,function(e){n===e&&(t=!0)}),t?d():c()}),a.$on("msNav::pushToLockedList",function(){t.setLockedItem(i,a)})}}}}e.$inject=["$document","$rootScope","msNavFoldService"],n.$inject=["$rootScope","$mdComponentRegistry","msNavFoldService"],t.$inject=["$rootScope","$q","$animate","$state"],angular.module("app.core").factory("msNavFoldService",function(){var t={};return{setFoldable:function(e,n){t={scope:e,element:n}},isNavFoldedOpen:function(){return t.scope.isNavFoldedOpen()},toggleFold:function(){t.scope.toggleFold()},openFolded:function(){t.scope.openFolded()},closeFolded:function(){t.scope.closeFolded()}}}).directive("msNavIsFolded",e).controller("MsNavController",function(){var e=this,n=!1,t=[],a=[];e.isDisabled=function(){return n},e.enable=function(){n=!1},e.disable=function(){n=!0},e.setToggleItem=function(e,n){t.push({element:e,scope:n})},e.getLockedItems=function(){return a},e.setLockedItem=function(e,n){a.push({element:e,scope:n})},e.clearLockedItems=function(){a=[]}}).directive("msNav",n).directive("msNavTitle",function(){return{restrict:"A",compile:function(e){return e.addClass("ms-nav-title"),function(){}}}}).directive("msNavButton",function(){return{restrict:"AE",compile:function(e){return e.addClass("ms-nav-button"),function(){}}}}).directive("msNavToggle",t)}(),function(){"use strict";function e(e,n){e.root?this.navigation=n.getNavigation(e.root):this.navigation=n.getNavigation(),this.toggleHorizontalMobileMenu=function(){angular.element("body").toggleClass("ms-navigation-horizontal-mobile-menu-active")},n.sort()}function n(c,m,u,p){return{restrict:"E",scope:{folded:"=",root:"@"},controller:"MsNavigationController as vm",templateUrl:"app/core/directives/ms-navigation/templates/vertical.html",transclude:!0,compile:function(e){return e.addClass("ms-navigation"),function(e,n){var t=angular.element("body"),a=angular.element('
'),i=angular.element('
'),s=u("navigation");function o(e){if(p.setFolded(e),e)c.$broadcast("msNavigation::collapse"),t.addClass("ms-navigation-folded"),r();else{var n=p.getActiveItem();n&&n.scope.$emit("msNavigation::stateMatched"),t.removeClass("ms-navigation-folded ms-navigation-folded-open"),i.remove()}}function r(){n.parent().append(a),m(function(){a.on("mouseenter touchstart",l)})}function l(e){e&&e.preventDefault(),p.setFoldedOpen(!0);var n=p.getActiveItem();n&&n.scope.$emit("msNavigation::stateMatched"),t.addClass("ms-navigation-folded-open"),a.remove(),t.find("#main").append(i),i.on("mouseenter touchstart",d)}function d(e){e&&e.preventDefault(),p.setFoldedOpen(!1),c.$broadcast("msNavigation::collapse"),t.removeClass("ms-navigation-folded-open"),i.remove(),r()}p.setNavigationScope(e),function(){null===p.getFolded()&&p.setFolded(e.folded);p.getFolded()&&(m(function(){c.$broadcast("msNavigation::collapse")}),t.addClass("ms-navigation-folded"),r())}(),e.$watch(function(){return s.isLockedOpen()},function(e,n){if(!angular.isUndefined(e)&&!angular.equals(e,n)&&p.getFolded())if(e)c.$broadcast("msNavigation::collapse");else{var t=p.getActiveItem();t&&t.scope.$emit("msNavigation::stateMatched")}}),e.$watch("folded",function(e,n){angular.isUndefined(e)||angular.equals(e,n)||o(e)}),e.toggleFolded=function(){o(!p.getFolded())},e.$on("$stateChangeStart",function(){s.close()}),e.$on("$destroy",function(){i.off("mouseenter touchstart"),a.off("mouseenter touchstart")})}}}}function t(t,e,a,i,n,s){var o=this;o.element=e,o.node=t.node,o.hasChildren=void 0,o.collapsed=void 0,o.collapsable=void 0,o.group=void 0,o.animateHeightClass="animate-height",o.toggleCollapsed=function(){o.collapsed?o.expand():o.collapse()},o.collapse=function(){var e=o.element.children("ul"),n=e[0].offsetHeight;t.$evalAsync(function(){o.collapsed=!0,o.element.addClass("collapsing"),i.animate(e,{display:"block",height:n+"px"},{height:"0px"},o.animateHeightClass).then(function(){e.css({display:"",height:""}),o.element.removeClass("collapsing")}),t.$broadcast("msNavigation::collapse")})},o.expand=function(){var e=o.element.children("ul");e.css({position:"absolute",visibility:"hidden",display:"block",height:"auto"});var n=e[0].offsetHeight;e.css({position:"",visibility:"",display:"",height:""}),t.$evalAsync(function(){o.collapsed=!1,o.element.addClass("expanding"),i.animate(e,{display:"block",height:"0px"},{height:n+"px"},o.animateHeightClass).then(function(){e.css({height:""}),o.element.removeClass("expanding")}),a.$broadcast("msNavigation::collapse",o.node._path)})},o.getClass=function(){return o.node.class},o.isHidden=function(){if(angular.isDefined(o.node.hidden)&&angular.isFunction(o.node.hidden))return o.node.hidden();return!1},function(){o.hasChildren=0 target, inbound, fullname",e,n,t),u.calls.unshift({target:e,fullname:t||e,inbound:n,time:moment().format("HH:mm")}),50 session",e),u.conf.microphoneId?u.sessionConf.mediaConstraints.audio={deviceId:u.conf.microphoneId}:u.sessionConf.mediaConstraints.audio=!0,e.answer(u.sessionConf),u.isJabraEnabled&&(jabra.offHook(),u.jabraSession=e)}function A(e){(console.debug("terminate -> session",e),e.terminate(),u.isJabraEnabled)&&(0===u.sessions.length?(jabra.onHook(),u.jabraSession=null):_.last(u.sessions).localHold&&jabra.hold())}function E(e){console.debug("onAddstream -> data",e),this.remotePlayer.srcObject=e.stream,this.remotePlayer.play()}function y(){u.canGoInConference=!1,u.isInConference=!1,u.currentconferenceSessions=[]}function S(e,n){switch(e){case"ringing":u.soundPlayer.muted=u.conf.ringingMute,u.conf.ringingId&&u.soundPlayer.setSinkId(u.conf.ringingId).then(function(){u.soundPlayer.volume=u.conf.ringingVolume}).then(function(){n&&h()}).catch(function(e){console.info(e.message,u.conf.ringingId)});break;case"speaker":u.remotePlayer.muted=u.conf.speakerMute,u.conf.speakerId&&u.remotePlayer.setSinkId(u.conf.speakerId).then(function(){u.remotePlayer.volume=u.conf.speakerVolume}).then(function(){n&&h()}).catch(function(e){console.info(e.message,u.conf.speakerId)});break;case"microphone":for(var t=0;t session, textContent, position, delay",e,n,t,a),function(){o.show(o.simple().textContent(n).position(t).hideDelay(a)),A(e)}}e(function(){},999),u.direction="right",u.selectedMode="md-scale",u.target="",u.showDialpad=!1,u.soundPlayer=document.createElement("audio"),u.remotePlayer=document.getElementById(u.conf.remotePlayerId),u.soundPlayer.volume=1,u.sessionConf={mediaConstraints:{audio:!0,video:!1}},u.sessions=[],u.calls=[],u.canGoInConference=!1,u.isInConference=!1,u.currentConferenceSessions=[],u.ua=new JsSIP.UA({sockets:[new JsSIP.WebSocketInterface("wss://"+u.conf.host+":8089/ws")],uri:new JsSIP.URI("sip",u.conf.name,u.conf.host,5060,null,null).toString(),authorization_user:u.conf.name,ha1:u.conf.ha1,realm:u.conf.realm,user_agent:u.conf.ua,session_timers_refresh_method:"invite",register_expires:u.conf.phoneBarExpires||60,register:!0}),u.conf=_.merge(g.webrtc,u.conf),u.initDeviceInProgress=!1,u.isJabraEnabled=!1,u.isJabraInitialized=!1,u.jabraSession=null,u.jabraClicked=!1,u.buttonClicked=!1,t.bind("keyup",function(e){switch(e.keyCode){case 27:s(function(){u.showDialpad=!1})}}),u.$onInit=function(){v(!1),navigator.mediaDevices.ondevicechange=function(e){u.initDeviceInProgress||(u.initDeviceInProgress=!0,jabra&&u.isJabraInitialized?jabra.shutdown().then(function(){u.isJabraInitialized=!1,v(!(u.isJabraEnabled=!1))}).catch(function(e){console.error("Unable to shutdown Jabra library",e)}):v(!0))},this.ua.on("registered",function(){this.registered=!0}.bind(this)),this.ua.on("unregistered",function(){this.registered=!1}.bind(this)),this.ua.on("newRTCSession",function(e){console.debug("onNewRTCSession -> data",e);var n=e.session,t=!0;switch(e.originator){case"local":n.outgoing=!0,n.name=e.request.ruri.user,n.user=e.request.ruri.user,f(n.user,!1),u.isJabraEnabled&&(u.jabraSession&&jabra.resume(),u.jabraSession=n,jabra.offHook());break;case"remote":var a=d.getCurrentUser();a.voicePause&&a.phoneBarDnd?t=!1:(n.incoming=!0,n.name=e.request.from.display_name,n.user=e.request.from.uri.user,function(n){console.debug("getNotification -> session",n);var e=n.name?n.name+" <"+n.user+">":n.user;l.create("Incoming call from: ",e,null,function(){b(n)},function(){A(n)}).then(function(e){n.notification=e}).catch(function(e){console.error("Error creating notification for incoming call",e)})}(e.session),f(e.session.user,!0),u.isJabraEnabled&&jabra.ring(),u.conf.autoAnswer&&s(function(){n.isInProgress()&&(n.autoAnswer=!0,b(n))},u.conf.autoAnswerDelay?1e3*u.conf.autoAnswerDelay:0))}t?(n.call_id=e.request.call_id,n.connection&&(n.connection.onaddstream=E.bind(this)),n.on("progress",function(e,n){console.debug("onProgress -> session, data",e,n);var t=!1;switch(n.originator){case"local":this.conf.ringingMute||(this.soundPlayer.setAttribute("src","assets/ms-phonebar/sounds/incoming-call.ogg"),t=!0);break;case"remote":this.putOtherCallsOnHold(e),this.soundPlayer.setAttribute("src","assets/ms-phonebar/sounds/outgoing-call.ogg"),t=!0}t&&(this.soundPlayer.loop="loop",this.soundPlayer.play().catch(function(e){console.log(e.message)}))}.bind(this,n)),n.on("confirmed",function(t,e){console.debug("onConfirmed -> session, data",t,e);var n=document.getElementById("div_session_"+t.id.substr(0,32));return n&&$(n).scope().$broadcast("timer-start"),t.confirmed=!0,"remote"===e.originator&&t.connection&&(t.connection.onaddstream=E.bind(this),_.head(t.connection.getRemoteStreams())&&(this.remotePlayer.srcObject=_.head(t.connection.getRemoteStreams()),this.remotePlayer.play())),this.soundPlayer.pause(),this.soundPlayer.loop=null,this.putOtherCallsOnHold(t),t.autoAnswer&&(this.soundPlayer.setAttribute("src","assets/ms-phonebar/sounds/beep.ogg"),this.soundPlayer.play().catch(function(e){console.log("Unable to play autoAnswer notification",e)})),u.canGoInConference=2==u.sessions.length,r.rpc.getVoiceChannels().$promise.then(function(e){var n=_.find(e.rows,function(e){return e.sipcalllinkedid===t.call_id?e:e.sipcalluniqueid===t.call_id?e:null});n&&(t.monitor=n.monitor,t.uniqueid=n.uniqueid,t.monitors=n.monitors)}).catch(function(e){console.error("Unable to retrieve voice channels",e)})}.bind(this,n)),n.on("hold",function(e,n){console.debug("onHold -> session, data",e,n),"local"===n.originator&&(e.localHold=!0)}.bind(this,n)),n.on("unhold",function(e,n){console.debug("onUnhold -> session, data",e,n),"local"===n.originator&&(e.localHold=!1)}.bind(this,n)),n.on("ended",function(e,n){console.debug("onEnded -> session, data",e,n),u.isInConference&&_.includes(u.currentConferenceSessions,e.id)&&(y(),u.buttonClicked=!0),_.remove(this.sessions,{id:e.id}),2!==u.sessions.length&&(u.canGoInConference=!1)}.bind(this,n)),n.on("failed",function(e,n){console.debug("onFailed -> session, data",e,n),this.soundPlayer.pause(),this.soundPlayer.loop=null,e.notification&&e.notification.close(),u.isInConference&&_.includes(u.currentConferenceSessions,e.id)&&y(),_.remove(this.sessions,{id:e.id}),2!==u.sessions.length&&(u.canGoInConference=!1)}.bind(this,n)),this.sessions.push(n),i.$$phase||i.$root.$$phase||i.$apply()):A(n)}.bind(this))}.bind(this),u.type=function(e,n){var t=e;switch(u.target||(u.target=""),n&&(u.target+=e,i.$broadcast("angucomplete-alt:changeInput","ms-target-wrap",u.target)),e){case"*":t="asterisk";break;case"#":t="pound"}u.conf.enableDtmfTone&&(u.soundPlayer.setAttribute("src","assets/ms-phonebar/sounds/dialpad/"+t+".ogg"),u.soundPlayer.play().catch(function(e){console.log(e.message)}));for(var a=0;a session",e),e.hold({useUpdate:!1}),u.isJabraEnabled&&(jabra.hold(),jabra.onHook())},u.refer=function(n){console.debug("refer -> session",n);var e=a.prompt().title("Transfer").textContent("Type the target").placeholder("Target").ariaLabel("Target").ok("Transfer").cancel("Cancel");a.show(e).then(function(e){return I(e)}).then(function(e){n.refer(e,{eventHandlers:{requestSucceeded:O(n,"requestSucceeded","top right",3e3),requestFailed:O(n,"requestFailed","top right",3e3)}})})},u.record=function(e){console.debug("record -> session",e),a.show({controller:"RecordDialogController",controllerAs:"vm",templateUrl:"assets/ms-phonebar/record/dialog.html",parent:angular.element(t.body),clickOutsideToClose:!0,locals:{session:e,sessions:u.sessions}})},u.unhold=function(e){console.debug("unhold -> session",e),e.unhold({useUpdate:!1}),u.putOtherCallsOnHold(e),u.isJabraEnabled&&(jabra.offHook(),jabra.resume())},u.answer=b,u.terminate=A,u.selectSession=function(e){console.debug("selectSession -> session",e),u.unhold(e)},u.typeWrapper=function(e){switch(e.key.toLowerCase()){case"0":case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":case"*":case"#":u.type(e.key);break;case"enter":u.call()}},u.toggleDialpad=function(){u.showDialpad=!u.showDialpad},u.referAttended=function(e){console.debug("referAttended -> session",e),a.show({controller:"ReferAttendedDialogController",controllerAs:"vm",templateUrl:"assets/ms-phonebar/referAttended/dialog.html",parent:angular.element(t.body),clickOutsideToClose:!0,locals:{session:e,sessions:_.reject(u.sessions,{id:e.id}),isJabraEnabled:u.isJabraEnabled}})},u.closeDialpad=function(){u.showDialpad=!1},u.initDevice=S,u.putOtherCallsOnHold=function(e){if(console.debug("putOtherCallsOnHold -> session",e),1 evt, data",e,n),n.target&&(u.target=n.target,u.call())}),i.$on("webrtc::transfer",function(e,n){if(console.debug("onRemoteTransfer -> evt, data",e,n),n.target)for(var t=0;t session, textContent, position, delay",e,n,t,a),function(){s.show(s.simple().textContent(n).position(t).hideDelay(a)),e.terminate(),jabra&&i&&jabra.onHook(),l()}}function l(e){n.hide(e)}o.title="Refer Attended",o.sessions=a,o.session=i,o.isJabraEnabled=e,o.sessionTarget=null,a.length&&(o.target=a[0].user),o.closeDialog=l,o.transfer=function(){var e,n,t=_.find(a,function(e){if(e.user===o.target)return e});n=t.outgoing?(e=t,o.session):(e=o.session,t);n.refer(e.user,{replaces:e,eventHandlers:{requestSucceeded:r(i,"requestSucceeded","top right",3e3,o.isJabraEnabled),requestFailed:r(i,"requestFailed","top right",3e3,o.isJabraEnabled)}})}}e.$inject=["$mdDialog","$mdToast","sessions","session","isJabraEnabled"],angular.module("app.core").controller("ReferAttendedDialogController",e)}(),function(){"use strict";function e(e,s,n){var t=this;function a(e,n,t){var a;if(s[t]){if(a=_.find(e,function(e){return e.deviceId===s[t]}))return a.deviceId;var i=_.findIndex(e,function(e){return e.kind===n});if(0<=i)return e[i].deviceId}else(a=_.find(e,function(e){return e.kind===n}))&&(s[t]=a.deviceId);return s[t]||null}_.remove(n,function(e){return"audioinput"===e.kind&&("default"===e.deviceId||"communications"===e.deviceId)||"audiooutput"===e.kind&&("default"===e.deviceId||"communications"===e.deviceId)}),s.ringingId=a(n,"audiooutput","ringingId"),s.speakerId=a(n,"audiooutput","speakerId"),s.microphoneId=a(n,"audioinput","microphoneId"),s.ringingVolume=s.ringingVolume||.5,s.speakerVolume=s.speakerVolume||.5,s.microphoneVolume=s.microphoneVolume||1,s.ringingMute=s.ringingMute||!1,s.speakerMute=s.speakerMute||!1,s.microphoneMute=s.microphoneMute||!1,t.conf=angular.copy(s),t.devices=n,t.saveSettings=function(){e.hide(t.conf)},t.closeDialog=function(){e.hide()},t.isCompatibleBrowser=function(){return"chrome"===t.conf.browserName.toLowerCase()||"opera"===t.conf.browserName.toLowerCase()||"safari"===t.conf.browserName.toLowerCase()}}e.$inject=["$mdDialog","conf","devices"],angular.module("app.toolbar").controller("SettingsController",e)}(),function(){"use strict";angular.module("app.core").directive("msRandomClass",function(){return{restrict:"A",scope:{msRandomClass:"="},link:function(e,n){var t=e.msRandomClass[Math.floor(Math.random()*e.msRandomClass.length)];n.addClass(t)}}})}(),function(){"use strict";function e(i){return{restrict:"E",scope:{id:"=",model:"=",download:"="},replace:!0,link:function(n,e){var t=!1,a=document.createElement("audio");n.download||a.setAttribute("controlsList","nodownload"),a.setAttribute("preload","none"),a.setAttribute("controls",""),a.setAttribute("style","width: 265px;"),a.setAttribute("src"," "),a.onplay=function(e){t||(t=!0,e.preventDefault(),i[n.model||"voiceRecording"].download({id:n.id}).$promise.then(function(e){var n=[e.buffer],t=new Blob(n,{type:e.type});a.setAttribute("type",e.type),a.setAttribute("src",URL.createObjectURL(t)),a.play()}).catch(function(e){console.error(e)}))},e.append(a)}}}e.$inject=["api"],angular.module("app.core").directive("msRecording",e)}(),function(){"use strict";angular.module("app.core").directive("msResponsiveTable",function(){return{restrict:"A",link:function(e,n){var t=angular.element('
');n.after(t),t.append(n)}}})}(),function(){"use strict";function e(s,o,n,t){return{restrict:"AE",compile:function(e){if(!(t.getConfig("disableCustomScrollbars")||t.getConfig("disableCustomScrollbarsOnMobile")&&n.isMobile()))return e.addClass("ms-scroll"),function(e,n,t){var a={};function i(){PerfectScrollbar.update(n[0])}t.msScroll&&(a=e.$eval(t.msScroll)),a=angular.extend({},o.getConfig(),a),s(function(){PerfectScrollbar.initialize(n[0],a)},0),n.on("mouseenter",i),e.$watch(function(){return n.prop("scrollHeight")},function(e,n){angular.isUndefined(e)||angular.equals(e,n)||i()}),e.$watch(function(){return n.prop("scrollWidth")},function(e,n){angular.isUndefined(e)||angular.equals(e,n)||i()}),e.$on("$destroy",function(){n.off("mouseenter"),PerfectScrollbar.destroy(n[0])})}}}}e.$inject=["$timeout","msScrollConfig","msUtils","motionConfig"],angular.module("app.core").provider("msScrollConfig",function(){var n={wheelSpeed:1,wheelPropagation:!1,swipePropagation:!0,minScrollbarLength:null,maxScrollbarLength:null,useBothWheelAxes:!1,useKeyboard:!0,suppressScrollX:!1,suppressScrollY:!1,scrollXMarginOffset:0,scrollYMarginOffset:0,stopPropagationOnClick:!0};this.config=function(e){n=angular.extend({},n,e)},this.$get=function(){var e={getConfig:function(){return n}};return e}}).directive("msScroll",e)}(),function(){"use strict";function e(s,i,e){var o=this;o.collapsed=!0,o.query=void 0,o.queryOptions={debounce:o.debounce||0};var n=!(!o.collapseOnBlur||"true"!=o.collapseOnBlur);o.resultsLoading=!1,o.results=null,o.selectedResultIndex=0,o.ignoreMouseEvents=!1,o.onInit=function(){s.$watch("MsSearchBar.query",function(e,n){if(!angular.isUndefined(e)&&!angular.equals(e,n)){if(o.collapsed){if(!e)return;s.expand()}var t=s.$parent.$eval(o.onSearch,{query:e}),a=angular.isArray(t),i=t&&!!t.then;a&&o.populateResults(t),i&&(o.resultsLoading=!0,t.then(function(e){o.populateResults(e)},function(){o.populateResults([])}).finally(function(){o.resultsLoading=!1}))}})},o.populateResults=function(e){if(o.collapsed)return;var n=angular.isArray(e),t=null===e;if(!n&&!t)return;o.selectedResultIndex=0,o.results=e},o.expand=function(){o.collapsed=!1,s.expand(),o.onExpand&&angular.isFunction(o.onExpand)&&o.onExpand()},o.collapse=function(){o.query="",o.populateResults(null),o.collapsed=!0,s.collapse(),o.onCollapse&&angular.isFunction(o.onCollapse)&&o.onCollapse()},o.blurCollapse=function(){if(!n)return;o.collapse()},o.absorbEvent=function(e){e.preventDefault()},o.handleKeydown=function(e){var n=e.keyCode;-1<[27,38,40].indexOf(n)&&e.preventDefault();switch(n){case 13:if(!o.results)return;o.handleResultClick(o.results[o.selectedResultIndex]);break;case 27:o.collapse();break;case 38:0<=o.selectedResultIndex-1&&(o.selectedResultIndex--,o.ensureSelectedResultIsVisible());break;case 40:if(!o.results)return;o.selectedResultIndex+1t&&e.scrollTop(t),a>e.height()+e.scrollTop()&&e.scrollTop(a-e.height())}}}function n(i){return{restrict:"E",scope:{},require:"msSearchBar",controller:"MsSearchBarController as MsSearchBar",bindToController:{query:"=?",debounce:"=?",direction:"@",onSearch:"@",onResultClick:"&?",onExpand:"&?",onCollapse:"&?",collapseOnBlur:"@"},templateUrl:"app/core/directives/ms-search-bar/ms-search-bar.html",compile:function(e){return e.addClass("ms-search-bar"),function(e,n){var t,a=i.find("body");e.collapse=function(){n.removeClass("expanded"),a.removeClass("ms-search-bar-expanded")},e.expand=function(){n.addClass("expanded"),"down"===e.MsSearchBar.direction&&n.addClass("down");a.addClass("ms-search-bar-expanded"),t.focus()},t=n.find("#ms-search-bar-input")}}}}e.$inject=["$scope","$element","$timeout"],n.$inject=["$document"],angular.module("app.core").controller("MsSearchBarController",e).directive("msSearchBar",n)}(),function(){"use strict";function e(e,t,i,o,r,l){var d=this;d.query="",d.queryOptions={debounce:300},d.resultsLoading=!1,d.selectedResultIndex=0,d.ignoreMouseEvents=!1,d.mobileBarActive=!1,d.results=null,d.shortcuts=[],d.sortableOptions={ghostClass:"ghost",forceFallback:!0,fallbackClass:"dragging",onSort:function(){d.saveShortcuts()}},d.populateResults=function(){for(var e=[],n=l.getFlatNavigation(),t=r.defer(),a=0;a=d.shortcuts.length&&(d.selectedResultIndex=d.shortcuts.length-1)));d.saveShortcuts()},d.handleResultClick=function(e){e.hasShortcut?d.removeShortcut(e):d.addShortcut(e)},d.absorbEvent=function(e){e.preventDefault()},d.handleKeydown=function(e){var n=e.keyCode;-1<[38,40].indexOf(n)&&e.preventDefault();switch(n){case 13:d.handleResultClick(d.results[d.selectedResultIndex]);break;case 38:0<=d.selectedResultIndex-1&&(d.selectedResultIndex--,d.ensureSelectedResultIsVisible());break;case 40:d.selectedResultIndex+1t&&e.scrollTop(t),a>e.height()+e.scrollTop()&&e.scrollTop(a-e.height())}},d.toggleMobileBar=function(){d.mobileBarActive=!d.mobileBarActive},d.loadShortcuts().then(function(e){d.shortcuts=e,0i.steps.length)}i.mainForm=void 0,i.orientation="horizontal",i.steps=[],i.currentStep=void 0,i.currentStepNumber=1,i.setOrientation=function(e){i.orientation=e||"horizontal"},i.registerMainForm=function(e){i.mainForm=e},i.registerStep=function(e,n,t){var a={element:e,scope:n,form:t,stepNumber:n.step||i.steps.length+1,stepTitle:n.stepTitle,stepTitleTranslate:n.stepTitleTranslate};return i.steps.push(a),i.steps.sort(function(e,n){return e.stepNumber-n.stepNumber}),a},i.setupSteps=function(){i.setCurrentStep(i.currentStepNumber)},i.resetForm=function(){e(function(){for(var e=0;ee.scrollWidth&&0==e.scrollLeft&&0==n.scrollLeft?"right":n.scrollWidth>e.scrollWidth&&n.scrollLeft>e.scrollLeft&&e.scrollWidth+n.scrollLeft>=n.scrollWidth?"left":n.scrollWidth>e.scrollWidth&&n.scrollLeft>e.scrollLeft&&e.scrollWidth+n.scrollLeftt.position().top+i&&(m(function(){o=!0}),r.off("scroll",c))}}}}}e.$inject=["$timeout","$q"],angular.module("app.core").controller("MsTimelineController",function(){var n=this;n.scrollEl=void 0,n.setScrollEl=function(e){n.scrollEl=e},n.getScrollEl=function(){return n.scrollEl}}).directive("msTimeline",function(){return{scope:{msTimeline:"=?",loadMore:"&?msTimelineLoadMore"},controller:"MsTimelineController",compile:function(e){return e.addClass("ms-timeline"),function(e,n,t,a){var i=angular.element('
');n.append(i);var s={scrollEl:"#content"};s=angular.extend(s,e.msTimeline,{});var o=angular.element(s.scrollEl);a.setScrollEl(o);var r=144;function l(){o.scrollTop()+o.height()+r>i.position().top&&(i.addClass("show"),c(),e.loadMore().then(function(){i.removeClass("show"),d()},function(){i.remove()}))}function d(){o.on("scroll",l)}function c(){o.off("scroll",l)}d(),e.$on("$destroy",function(){c()})}}}}).directive("msTimelineItem",e)}(),function(){"use strict";function e(a,e,n,t,i,s,o,r,l){function d(){a.timeoutId&&clearTimeout(a.timeoutId)}function c(){void 0!==o.startTime&&(a.millis=moment().diff(moment(a.startTime))),a.maxTimeUnit&&"day"!==a.maxTimeUnit?"second"===a.maxTimeUnit?(a.seconds=Math.floor(a.millis/1e3),a.minutes=0,a.hours=0,a.days=0,a.months=0,a.years=0):"minute"===a.maxTimeUnit?(a.seconds=Math.floor(a.millis/1e3%60),a.minutes=Math.floor(a.millis/6e4),a.hours=0,a.days=0,a.months=0,a.years=0):"hour"===a.maxTimeUnit?(a.seconds=Math.floor(a.millis/1e3%60),a.minutes=Math.floor(a.millis/6e4%60),a.hours=Math.floor(a.millis/36e5),a.days=0,a.months=0,a.years=0):"month"===a.maxTimeUnit?(a.seconds=Math.floor(a.millis/1e3%60),a.minutes=Math.floor(a.millis/6e4%60),a.hours=Math.floor(a.millis/36e5%24),a.days=Math.floor(a.millis/36e5/24%30),a.months=Math.floor(a.millis/36e5/24/30),a.years=0):"year"===a.maxTimeUnit&&(a.seconds=Math.floor(a.millis/1e3%60),a.minutes=Math.floor(a.millis/6e4%60),a.hours=Math.floor(a.millis/36e5%24),a.days=Math.floor(a.millis/36e5/24%30),a.months=Math.floor(a.millis/36e5/24/30%12),a.years=Math.floor(a.millis/36e5/24/365)):(a.seconds=Math.floor(a.millis/1e3%60),a.minutes=Math.floor(a.millis/6e4%60),a.hours=Math.floor(a.millis/36e5%24),a.days=Math.floor(a.millis/36e5/24),a.months=0,a.years=0),a.secondsS=1===a.seconds||0===a.seconds?"":"s",a.minutesS=1===a.minutes||0===a.minutes?"":"s",a.hoursS=1===a.hours||0===a.hours?"":"s",a.daysS=1===a.days||0===a.days?"":"s",a.monthsS=1===a.months||0===a.months?"":"s",a.yearsS=1===a.years||0===a.years?"":"s",a.sseconds=a.seconds<10?"0"+a.seconds:a.seconds,a.mminutes=a.minutes<10?"0"+a.minutes:a.minutes,a.hhours=a.hours<10?"0"+a.hours:a.hours,a.ddays=a.days<10?"0"+a.days:a.days,a.mmonths=a.months<10?"0"+a.months:a.months,a.yyears=a.years<10?"0"+a.years:a.years}"function"!=typeof String.prototype.trim&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),a.autoStart=o.autoStart||o.autostart,0===r.html().trim().length?r.append(l("{{millis}}")(a)):r.append(l(r.contents())(a)),a.interval=a.intervalAttr||1e3,a.startTime=null,a.endTime=null,a.timeoutId=null,a.countdown=a.countdownAttr&&0<=parseInt(a.countdownAttr,10)?parseInt(a.countdownAttr,10):void 0,a.isRunning=!1,a.$watch("startTimeAttr",function(e,n){e!==n&&a.isRunning&&a.start()}),a.$on("timer-start",function(){a.start()}),a.$on("timer-resume",function(){a.resume()}),a.$on("timer-stop",function(){a.stop()}),a.$on("timer-clear",function(){a.clear()}),a.$on("timer-set-countdown",function(e,n){a.countdown=n}),a.start=r[0].start=function(){var e=moment(),n=a.startTimeAttr?moment(a.startTimeAttr):null;a.startTime=!n||er.properties.length){var n=r.multiBarChart.series.length-r.properties.length;r.multiBarChart.series.splice(0,n),r.multiBarChart.data.splice(0,n)}for(var t=0;tr.filter.length){var a=r.multiBarChart.labels.length-r.filter.length;r.multiBarChart.labels.splice(0,a),r.multiBarChart.data[t].splice(0,a)}for(var i=0,s=0;io.properties.length){var n=o.pieChart.labels.length-o.properties.length;o.pieChart.labels.splice(0,n),o.pieChart.data.splice(0,n)}for(var t=0,a=0;t]+>/gm,"")}}).filter("nospace",function(){return function(e){return e?e.replace(/ /g,""):""}}).filter("humanizeDoc",function(){return function(e){if(e)return"directive"===e.type?e.name.replace(/([A-Z])/g,function(e){return"-"+e.toLowerCase()}):e.label||e.name}})}(),function(){"use strict";angular.module("app.core").filter("filterByIds",function(){return function(e,n){if(0===e.length||!n)return e;if(0===n.length)return[];for(var t=[],a=0;a')).html(i),s.append(o)})},rgba:l};function l(e,n){var t=n||!1;return 4===e.length&&255===e[0]&&255===e[1]&&255===e[2]&&e.splice(3,4),t&&(e=function(e,n){var t={white:{1:"1",2:"0.7",3:"0.3",4:"0.12"},black:{1:"0.87",2:"0.54",3:"0.26",4:"0.12"}};255===e[0]&&255===e[1]&&255===e[2]?e[3]=t.white[n]:0===e[0]&&0===e[1]&&0===e[2]&&(e[3]=t.black[n]);return e}(e,t)),3===e.length?"rgb("+e.join(",")+")":4===e.length?"rgba("+e.join(",")+")":void a.error("Invalid number of arguments supplied in the color array: "+e.length+"\nThe array must have 3 or 4 colors.")}function d(e){return e.charAt(0).toUpperCase()+e.slice(1)}}e.$inject=["$cookies","$log","motionTheming"],angular.module("app.core").factory("motionGenerator",e)}(),function(){"use strict";angular.module("app.core").constant("motionPalettes",[{name:"motion-blue",options:{50:"#ebf1fa",100:"#c2d4ef",200:"#9ab8e5",300:"#78a0dc",400:"#5688d3",500:"#3470ca",600:"#2e62b1",700:"#275498",800:"#21467e",900:"#1a3865",A100:"#c2d4ef",A200:"#9ab8e5",A400:"#5688d3",A700:"#275498",contrastDefaultColor:"light",contrastDarkColors:"50 100 200 A100",contrastStrongLightColors:"300 400"}},{name:"motion-paleblue",options:{50:"#ececee",100:"#c5c6cb",200:"#9ea1a9",300:"#7d818c",400:"#5c616f",500:"#3c4252",600:"#353a48",700:"#2d323e",800:"#262933",900:"#1e2129",A100:"#c5c6cb",A200:"#9ea1a9",A400:"#5c616f",A700:"#2d323e",contrastDefaultColor:"light",contrastDarkColors:"50 100 200 A100",contrastStrongLightColors:"300 400"}}])}(),function(){"use strict";angular.module("app.core").constant("motionThemes",{default:{primary:{name:"motion-paleblue",hues:{default:"700","hue-1":"500","hue-2":"600","hue-3":"400"}},accent:{name:"light-blue",hues:{default:"600","hue-1":"400","hue-2":"700","hue-3":"A100"}},warn:{name:"red"},background:{name:"grey",hues:{default:"A100","hue-1":"A100","hue-2":"100","hue-3":"300"}}},pinkTheme:{primary:{name:"blue-grey",hues:{default:"800","hue-1":"600","hue-2":"400","hue-3":"A100"}},accent:{name:"pink",hues:{default:"400","hue-1":"300","hue-2":"600","hue-3":"A100"}},warn:{name:"blue"},background:{name:"grey",hues:{default:"A100","hue-1":"A100","hue-2":"100","hue-3":"300"}}},tealTheme:{primary:{name:"motion-blue",hues:{default:"900","hue-1":"600","hue-2":"500","hue-3":"A100"}},accent:{name:"teal",hues:{default:"500","hue-1":"400","hue-2":"600","hue-3":"A100"}},warn:{name:"deep-orange"},background:{name:"grey",hues:{default:"A100","hue-1":"A100","hue-2":"100","hue-3":"300"}}}})}(),function(){"use strict";function e(t,e,n){var a;angular.injector(["ngCookies"]).invoke(["$cookies",function(e){a=e}]);var i=a.getObject("motion.customTheme");i&&(n.custom=i),t.alwaysWatchTheme(!0),angular.forEach(e,function(e){t.definePalette(e.name,e.options)}),angular.forEach(n,function(e,n){t.theme(n).primaryPalette(e.primary.name,e.primary.hues).accentPalette(e.accent.name,e.accent.hues).warnPalette(e.warn.name,e.warn.hues).backgroundPalette(e.background.name,e.background.hues)})}e.$inject=["$mdThemingProvider","motionPalettes","motionThemes"],angular.module("app.core").config(e)}(),function(){"use strict";function e(n,t,e){var a={getRegisteredPalettes:function(){return e.PALETTES},getRegisteredThemes:function(){return e.THEMES},setActiveTheme:function(e){if(angular.isUndefined(a.themes.list[e]))return angular.isUndefined(a.themes.list.default)?void t.error('You must have at least one theme named "default"'):(t.warn('The theme "'+e+'" does not exist! Falling back to the "default" theme.'),a.themes.active.name="default",a.themes.active.theme=a.themes.list.default,void n.put("motion.selectedTheme",a.themes.active.name));a.themes.active.name=e,a.themes.active.theme=a.themes.list[e],n.put("motion.selectedTheme",e)},setThemesList:function(e){a.themes.list=e},themes:{list:{},active:{name:"",theme:{}}}};return a}e.$inject=["$cookies","$log","$mdTheming"],angular.module("app.core").service("motionTheming",e)}(),function(){"use strict";function e(n,s,o,r){this.search=function(n){for(var e=[],t=r.getFlatNavigation(),a=o.defer(),i=0;i"+(e.name||"extractedReport")+" will be deleted.").ariaLabel("delete extractedReport").targetEvent(n).ok("OK").cancel("CANCEL");i.show(t).then(function(){S(e)},function(){console.log("CANCEL")})},b.success=y,b.getExtractedReports=function(){b.query.offset=(b.query.page-1)*b.query.limit,g.hasRole("admin")?b.promise=m.analyticExtractedReport.get(b.query,y).$promise:(b.query.id=b.userProfile.id,b.query.section="ExtractedReports",b.promise=m.userProfile.getResources(b.query,y).$promise)},b.createOrEditExtractedReport=function(e,n){i.show({controller:"CreateOrEditExtractedReportDialogController",controllerAs:"vm",templateUrl:"app/main/apps/analytics/views/extractedReports/create/dialog.html",parent:angular.element(s.body),targetEvent:e,clickOutsideToClose:!0,locals:{extractedReport:n,extractedReports:b.extractedReports.rows,license:b.license,setting:b.setting,crudPermissions:b.crudPermissions}})},b.deleteExtractedReport=S,b.exportSelectedExtractedReports=function(){var e=angular.copy(b.selectedExtractedReports);return b.selectedExtractedReports=[],e},b.deleteSelectedExtractedReports=function(e){var n=i.confirm().title("Are you sure want to delete the selected extractedReports?").htmlContent(""+b.selectedExtractedReports.length+" selected will be deleted.").ariaLabel("delete ExtractedReports").targetEvent(e).ok("OK").cancel("CANCEL");i.show(n).then(function(){b.selectedExtractedReports.forEach(function(e){S(e)}),b.selectedExtractedReports=[]})},b.deselectExtractedReports=function(){b.selectedExtractedReports=[]},b.selectAllExtractedReports=function(){b.selectedExtractedReports=b.extractedReports.rows};var A=!0,E=1;function y(e){b.extractedReports=e||{count:0,rows:[]}}function S(e){m.analyticExtractedReport.delete({id:e.id}).$promise.then(function(){_.remove(b.extractedReports.rows,{id:e.id}),b.extractedReports.count-=1,b.extractedReports.rows.length||b.getExtractedReports(),p.success({title:_.startCase("ExtractedReport")+" deleted!",msg:e.name?e.name+" has been deleted!":""})}).catch(function(e){if(e.data&&e.data.errors&&e.data.errors.length){b.errors=e.data.errors||[{message:e.toString(),type:"SYSTEM:DELETEanalyticExtractedReport"}];for(var n=0;n"+(e.name||"metric")+" will be deleted.").ariaLabel("delete metric").targetEvent(n).ok("OK").cancel("CANCEL");i.show(t).then(function(){S(e)},function(){console.log("CANCEL")})},b.success=y,b.getMetrics=function(){b.query.offset=(b.query.page-1)*b.query.limit,g.hasRole("admin")?b.promise=m.analyticMetric.get(b.query,y).$promise:(b.query.id=b.userProfile.id,b.query.section="Metrics",b.promise=m.userProfile.getResources(b.query,y).$promise)},b.createOrEditMetric=function(e,n){i.show({controller:"CreateOrEditMetricDialogController",controllerAs:"vm",templateUrl:"app/main/apps/analytics/views/metrics/create/dialog.html",parent:angular.element(s.body),targetEvent:e,clickOutsideToClose:!0,locals:{metric:n,metrics:b.metrics.rows,license:b.license,setting:b.setting,crudPermissions:b.crudPermissions}})},b.deleteMetric=S,b.exportSelectedMetrics=function(){var e=angular.copy(b.selectedMetrics);return b.selectedMetrics=[],e},b.deleteSelectedMetrics=function(e){var n=i.confirm().title("Are you sure want to delete the selected metrics?").htmlContent(""+b.selectedMetrics.length+" selected will be deleted.").ariaLabel("delete Metrics").targetEvent(e).ok("OK").cancel("CANCEL");i.show(n).then(function(){b.selectedMetrics.forEach(function(e){S(e)}),b.selectedMetrics=[]})},b.deselectMetrics=function(){b.selectedMetrics=[]},b.selectAllMetrics=function(){b.selectedMetrics=b.metrics.rows};var A=!0,E=1;function y(e){b.metrics=e||{count:0,rows:[]}}function S(e){m.analyticMetric.delete({id:e.id}).$promise.then(function(){_.remove(b.metrics.rows,{id:e.id}),b.metrics.count-=1,b.metrics.rows.length||b.getMetrics(),p.success({title:_.startCase("Metric")+" deleted!",msg:e.name?e.name+" has been deleted!":""})}).catch(function(e){if(e.data&&e.data.errors&&e.data.errors.length){b.errors=e.data.errors||[{message:e.toString(),type:"SYSTEM:DELETEanalyticMetric"}];for(var n=0;n"+e.field+" will be deleted.").ariaLabel("delete field").targetEvent(n).ok("OK").cancel("CANCEL");a.show(t).then(function(){p(e)},function(){console.log("CANCEL")})},c.success=u,c.getReportFields=function(){c.promise=o.analyticFieldReport.get(c.query,u).$promise},c.createOrEditReportField=function(e,n){a.show({controller:"CreateOrEditReportFieldDialogController",controllerAs:"vm",templateUrl:"app/main/apps/analytics/views/reports/edit/field/dialog.html",parent:angular.element(i.body),targetEvent:e,clickOutsideToClose:!0,locals:{report:c.report,reportField:n,reportFields:c.reportFields.rows,metrics:c.metrics,columns:c.columns,setting:null,crudPermissions:c.crudPermissions}})},c.deleteReportField=p,c.deleteSelectedReportFields=function(e){var n=a.confirm().title("Are you sure want to delete the selected fields?").htmlContent(""+c.selectedReportFields.length+" selected will be deleted.").ariaLabel("delete fields").targetEvent(e).ok("OK").cancel("CANCEL");a.show(n).then(function(){c.selectedReportFields.forEach(function(e){p(e)}),c.selectedReportFields=[]})},c.getMetricName=function(e){var n=_.find(c.metrics,{id:e});return n?n.name:d.instant("ANALYTICS.NO_METRIC_FOUND")},c.getMetricValue=function(e){var n=_.find(c.metrics,{id:e});return n?n.metric:d.instant("ANALYTICS.NO_METRIC_FOUND")};var m=!0;function u(e){c.reportFields=e||{count:0,rows:[]}}function p(e){o.analyticFieldReport.delete({id:e.id}).$promise.then(function(){c.selectedReportFields=[],_.remove(c.reportFields.rows,{id:e.id}),c.reportFields.count-=1,c.reportFields.rows.length||c.getReportFields(),s.success({title:"Field deleted!",msg:e.field?e.field+" has been deleted!":""})}).catch(function(e){s.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:DELETEFIELD",msg:e.data?JSON.stringify(e.data):e.toString()})})}n.$watch("vm_rf.query.filter",function(e,n){m?t(function(){m=!1}):c.getReportFields()})}e.$inject=["$cookies","$scope","$timeout","$mdDialog","$document","toasty","api","describeTable","sqlUtil","$translate"],angular.module("app.analytics").controller("ReportFieldsController",e)}(),function(){"use strict";angular.module("app.analytics").factory("sqlUtil",function(){return{getFunctions:[{value:"SUM",option:function(e){return"SUM ("+e+")"}},{value:"COUNT",option:function(e){return"COUNT ("+e+")"}},{value:"COUNT DISTINCT",option:function(e){return"COUNT (DISTINCT "+e+")"}},{value:"MAX",option:function(e){return"MAX ("+e+")"}},{value:"MIN",option:function(e){return"MIN ("+e+")"}},{value:"AVG",option:function(e){return"AVG ("+e+")"}},{value:"GROUP_CONCAT",option:function(e){return"GROUP_CONCAT ("+e+")"}},{value:"GROUP_CONCAT ASC",option:function(e){return"GROUP_CONCAT ("+e+" ORDER BY "+e+" ASC)"}},{value:"GROUP_CONCAT DESC",option:function(e){return"GROUP_CONCAT ("+e+" ORDER BY "+e+" DESC)"}}],getFormats:[{value:"SEC_TO_TIME",option:function(e){return"SEC_TO_TIME ("+e+")"}},{value:"DATE",option:function(e){return"DATE ("+e+")"}},{value:"HOUR",option:function(e){return"HOUR ("+e+")"}},{value:"ROUND",option:function(e){return"ROUND ("+e+")"}},{value:"UNIX_TIMESTAMP",option:function(e){return"UNIX_TIMESTAMP ("+e+")"}}],getGroupBy:[{value:!1,option:function(){return"No"}},{value:!0,option:function(e){return"GROUP BY "+e}}],getOrderBy:[{value:"ASC",option:function(e){return"ORDER BY "+e+" ASC"}},{value:"DESC",option:function(e){return"ORDER BY "+e+" DESC"}}],getConditions:["=","!=","<","<=",">",">=","LIKE","NOT LIKE","IS NULL","IS NOT NULL","IS EMPTY","IS NOT EMPTY"]}})}(),function(){"use strict";function e(e,n,t,a,i,s){var o=this;function r(e){return _.isArray(e)}o.report=a||{},o.userProfileSection=s&&1==s.count?s.rows[0]:null,o.crudPermissions=i.parseCrudPermissions(o.userProfileSection?o.userProfileSection.crudPermissions:null),o.selectedTab=e.params.tab||0,o.gotoReports=function(){e.go("app.analytics.reports")},o.saveReport=function(){o.report.conditions=angular.toJson(o.report.condition),t.analyticCustomReport.update({id:o.report.id},_.omit(o.report,"joins")).$promise.then(function(){n.success({title:"Report updated!",msg:o.report.name?o.report.name+" has been updated!":""})}).catch(function(e){n.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:GETreport",msg:e.data?JSON.stringify(e.data):e.toString()})})},o.previewReport=function(){o.columns=[],o.rows=[],o.error=!1,t.analyticFieldReport.get({fields:"field,alias",nolimit:!0,CustomReportId:o.report.id}).$promise.then(function(e){return o.columns=e?e.rows:[],t.analyticCustomReport.preview({id:o.report.id}).$promise}).then(function(e){o.rows=e}).catch(function(e){console.log(e),o.error={title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:analyticFieldReport",msg:e.data?e.data.message:e.toString(),sql:e.data&&e.data.parent?e.data.parent.sql:"NO QUERY"},n.error(o.error)})},o.queryReport=function(){return o.queryResult="Loading...",t.analyticCustomReport.query({id:o.report.id}).$promise.then(function(e){o.queryResult=e.sql}).catch(function(e){o.queryResult="",console.log(e),o.error={title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:analyticFieldReport",msg:e.data?e.data.message:e.toString(),sql:e.data&&e.data.parent?e.data.parent.sql:"NO QUERY"},n.error(o.error)})},o.mapArray=function(e,n){if(r(e))return _.map(e,n).join(",");return""},o.isArray=r,o.valueReplacer=function(e,n){moment(n,"YYYY-MM-DDTHH:mm:ssZ",!0).isValid()&&(n=moment(n,"").format("YYYY-MM-DD HH:mm:ss"));return n}}e.$inject=["$state","toasty","api","report","Auth","userProfileSection"],angular.module("app.analytics").controller("ReportController",e)}(),function(){"use strict";function e(e,n,t,a,i,s){var o=this;o.errors=[],o.report=angular.copy(a),o.valueReplacer=function(e,n){moment(n,"YYYY-MM-DDTHH:mm:ssZ",!0).isValid()&&(n=moment(n,"").format("YYYY-MM-DD HH:mm:ss"));return n},o.closeDialog=function(){n.hide()},function(){o.columns=[],o.rows=[],o.error=!1;var e={fields:"field,alias",nolimit:!0};e["analyticCustomReport"===s?"CustomReportId":"DefaultReportId"]=o.report.id,o.promise=i.analyticFieldReport.get(e).$promise.then(function(e){return o.columns=e?e.rows:[],i[s].preview({id:o.report.id}).$promise}).then(function(e){o.rows=e}).catch(function(e){console.log(e),o.error={title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:analyticFieldReport",msg:e.data?e.data.message:e.toString(),sql:e.data&&e.data.parent?e.data.parent.sql:"NO QUERY"},t.error(o.error)})}()}e.$inject=["$location","$mdDialog","toasty","report","api","apiName"],angular.module("app.analytics").controller("PreviewReportDialogController",e)}(),function(){"use strict";function e(e,t,a,i,s,o,n,r,l,d,c,m,u){var p=this;p.currentUser=u.getCurrentUser(),p.reports={count:0,rows:[]},p.userProfile=r,p.userProfileSection=l&&1==l.count?l.rows[0]:null,p.crudPermissions=u.parseCrudPermissions(p.userProfileSection?p.userProfileSection.crudPermissions:null),p.selectedReports=[],p.query={fields:"createdAt,updatedAt,id,name,description,table,parent,conditions,joins",limit:10,page:1,sort:"-updatedAt"},p.apiName=null,p.currentPath="",p.customTree=!0,p.editstate=function(e,n){s.go("app.analytics.reports.edit",{id:e.id,crudPermissions:p.crudPermissions})},p.copydialog=function(e,n){i.show({controller:"CopyReportDialogController",controllerAs:"vm",templateUrl:"app/main/apps/analytics/views/reports/copy/dialog.html",parent:angular.element(a.body),targetEvent:n,clickOutsideToClose:!0,locals:{report:e,apiName:p.apiName,treeCustomData:p.treeCustomInstance.jstree(!0).get_json("#")}}).finally(function(){})},p.previewdialog=function(e,n){i.show({controller:"PreviewReportDialogController",controllerAs:"vm",templateUrl:"app/main/apps/analytics/views/reports/preview/dialog.html",parent:angular.element(a.body),targetEvent:n,clickOutsideToClose:!0,locals:{report:e,apiName:p.apiName}})},p.rundialog=function(e,n){i.show({controller:"RunReportDialogController",controllerAs:"vm",templateUrl:"app/main/apps/analytics/views/reports/run/dialog.html",parent:angular.element(a.body),targetEvent:n,clickOutsideToClose:!0,locals:{report:e,apiName:p.apiName,currentPath:p.currentPath}})},p.downloadfile=function(a,e){var i;d.analyticMetric.get({fields:"id,name,metric,table",nolimit:!0}).$promise.then(function(e){i=_.keyBy(e.rows,"id");var n={fields:"field,alias,function,format,groupBy,orderBy,custom,MetricId",nolimit:!0};return n["analyticCustomReport"===p.apiName?"CustomReportId":"DefaultReportId"]=a.id,d.analyticFieldReport.get(n).$promise}).then(function(e){for(var n=0;n"+e.name+" will be deleted.").ariaLabel("delete report").targetEvent(n).ok("OK").cancel("CANCEL");i.show(t).then(function(){b(e)},function(){console.log("CANCEL")})},p.success=h,p.getReports=f,p.createOrEditReport=function(e,n){i.show({controller:"CreateOrEditReportDialogController",controllerAs:"vm",templateUrl:"app/main/apps/analytics/views/reports/create/dialog.html",parent:angular.element(a.body),targetEvent:e,clickOutsideToClose:!0,locals:{report:n,reports:p.reports.rows,apiName:p.apiName,currentNode:p.currentNode,setting:null,crudPermissions:p.crudPermissions}})},p.importReport=function(e,n,t){if("application/json"===e.file.type){var a=new FileReader;a.onload=function(e){console.log(e.target.result);try{var t=atob(e.target.result.split(",")[1]);t=angular.fromJson(t),d.analyticCustomReport.save({name:t.name,description:t.description,table:t.table,conditions:t.conditions,joins:t.joins,parent:p.currentNode.id}).$promise.then(function(n){p.reports.rows.unshift(n),m.success({title:"Report saved!",msg:n.name?n.name+" has been saved!":""});var e=_.map(t.fields,function(e){return _.extend({},e,{CustomReportId:n.id})});return d.analyticFieldReport.bulkCreate(e).$promise}).then(function(e){m.success({title:"Fields saved!",msg:"Fields has been saved!"})}).catch(function(e){m.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:GETanalyticReport",msg:e.data?JSON.stringify(e.data):e.toString()})})}catch(e){console.error(e),m.error({title:"Decode File Error",msg:e.toString()})}},a.readAsDataURL(e.file)}else m.error({title:"Format Error",msg:"Please use only json files"})},p.deleteReport=b,p.exportSelectedReports=function(){var e=angular.copy(p.selectedReports);return p.selectedReports=[],e},p.deleteSelectedReports=function(e){var n=i.confirm().title("Are you sure want to delete the selected reports?").htmlContent(""+p.selectedReports.length+" selected will be deleted.").ariaLabel("delete Reports").targetEvent(e).ok("OK").cancel("CANCEL");i.show(n).then(function(){p.selectedReports.forEach(function(e){b(e)}),p.selectedReports=[]})},p.deselectReports=function(){p.selectedReports=[]},p.selectAllReports=function(){p.selectedReports=p.reports.rows},p.treeDefaultData=c.rows[0]?angular.fromJson(c.rows[0].tree):[],p.treeCustomData=c.rows[1]?angular.fromJson(c.rows[1].tree):[],p.treeDefaultConfig=S(!1),p.treeCustomConfig=S(!0),p.treeDefaultEvents=T(!1),p.treeCustomEvents=T(!0);var g=!0,v=1;function h(e){p.reports=e||{count:0,rows:[]}}function f(){if(p.query.offset=(p.query.page-1)*p.query.limit,p.apiName)if("admin"===p.currentUser.role||p.userProfileSection.autoAssociation)p.promise=d[p.apiName].get(p.query,h).$promise;else{var a=[];p.promise=d[p.apiName].get(p.query).$promise.then(function(e){return 0<(a=e&&e.rows?e.rows:[]).length?d.userProfileResource.get({sectionId:p.userProfileSection.id,type:"analyticDefaultReport"===p.apiName?"DefaultReports":"CustomReports"}).$promise.then(function(e){var n=e&&e.rows?e.rows:[];if(0"+(t.text?t.text:"Node")+" and its subnode will be deleted.").ariaLabel("delete node").ok("OK").cancel("CANCEL");i.show(e).then(function(){var e,n=p.treeCustomInstance.jstree(!0).get_parent(t);n=p.treeCustomInstance.jstree(!0).get_node(n),p.treeCustomInstance.jstree(!0).delete_node(t),e=[t.id].concat(t.children_d||[]),d.analyticCustomReport.get({parent:e.join(","),fields:"id,name"}).$promise.then(function(e){e&&e.rows&&e.rows.forEach(function(e){b(e)})}).catch(function(e){m.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:DELETEreportsByParents",msg:e.data?JSON.stringify(e.data):e.toString()})}),p.treeCustomInstance.jstree(!0).select_node(n)})}}}),e}}}}function T(e){return e?{create_node:y,rename_node:y,move_node:y,delete_node:y,select_node:A}:{select_node:E}}e.$watch("vm.query.filter",function(e,n){g?t(function(){g=!1}):(n||(v=p.query.page),e!==n&&(p.query.page=1),e||(p.query.page=v),p.getReports())}),e.$watch("vm.search",function(e,n){p.treeDefaultInstance&&p.treeDefaultInstance.jstree(!0).search(e),p.treeCustomInstance&&p.treeCustomInstance.jstree(!0).search(e)})}e.$inject=["$scope","$timeout","$document","$mdDialog","$state","$window","$translate","userProfile","userProfileSection","api","treeReports","toasty","Auth"],angular.module("app.analytics").controller("ReportsController",e)}(),function(){"use strict";function e(e,t,a,n,i,s,o,r){var l=this;function d(){l.export={id:l.report.id,name:l.report.name,startDate:new Date(moment().startOf("day")),endDate:new Date(moment().endOf("day")),output:"xlsx",fullPath:r?r+"/"+l.report.name:l.report.name}}function c(){t.hide()}l.errors=[],l.report=angular.copy(n),l.export={},l.runReport=function(n){l.errors=[],l.exportDate=_.assign({},l.export,{startDate:moment(l.export.startDate).format("YYYY-MM-DD HH:mm:ss"),endDate:moment(l.export.endDate).format("YYYY-MM-DD HH:mm:ss")}),i[s].run(l.exportDate).$promise.then(function(e){"web"===l.export.output?t.show({controller:"WebReportDialogController",controllerAs:"vm",templateUrl:"app/main/apps/analytics/views/reports/run/web/dialog.html",parent:angular.element(o.body),targetEvent:n,skipHide:!0,locals:{apiName:s,exportDate:l.exportDate,results:e},resolve:{columns:["apiResolver",function(e){var n={fields:"field,alias",nolimit:!0};return n["analyticCustomReport"===s?"CustomReportId":"DefaultReportId"]=l.report.id,e.resolve("analyticFieldReport@get",n)}]}}):(a.success({title:"Report properly run!",msg:l.report.name?l.report.name+" has been run!":""}),c())}).catch(function(e){a.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:DESCRIBE",msg:e.data?JSON.stringify(e.data.message):e.toString()})})},l.closeDialog=c,(l.refreshDate=d)()}e.$inject=["$location","$mdDialog","toasty","report","api","apiName","$document","currentPath"],angular.module("app.analytics").controller("RunReportDialogController",e)}(),function(){"use strict";function e(e,n,t,a,i,s,o){var r=this;function l(e){r.results=e||{count:0,rows:[]}}r.errors=[],r.columns=a?a.rows:[],r.results=i||{rows:[],count:0},r.query={limit:10,page:1},r.closeDialog=function(){e.hide()},r.getResults=function(){o.offset=(r.query.page-1)*r.query.limit,o.limit=r.query.limit,r.promise=t[s].run(o,l).$promise},r.valueReplacer=function(e,n){moment(n,"YYYY-MM-DDTHH:mm:ssZ",!0).isValid()&&(n=moment(n,"").format("YYYY-MM-DD HH:mm:ss"));return n}}e.$inject=["$mdDialog","toasty","api","columns","results","apiName","exportDate"],angular.module("app.analytics").controller("WebReportDialogController",e)}(),function(){"use strict";function e(e,n,t,a,i,s,o,r,l,d,c,m,u,p){var g=this;function v(e){a.hide(e)}g.currentUser=c.getCurrentUser(),g.errors=[],g.setting=u,g.license=m,g.crudPermissions=p,g.hasModulePermissions={},g.passwordPattern=g.setting&&g.setting.securePassword?/(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[?!@#\$%\^&\*~\-_=+[{\]\}])(?=.{8,})/:"",g.title="CALLYSQUARE.EDIT_ODBC",g.odbc=angular.copy(l),g.odbcs=r,g.newOdbc=!1,g.odbc||(g.odbc={},g.title="CALLYSQUARE.NEW_ODBC",g.newOdbc=!0),g.addNewOdbc=function(){g.errors=[],d.squareOdbc.save(g.odbc).$promise.then(function(e){g.odbcs.unshift(e.toJSON()),o.success({title:"Odbc properly created",msg:g.odbc.name?g.odbc.name+" has been created!":""}),v(e)}).catch(function(e){if(e.data&&e.data.errors&&e.data.errors.length){g.errors=e.data.errors||[{message:e.toString(),type:"api.squareOdbc.save"}];for(var n=0;n"+(e.name||"odbc")+" will be deleted.").ariaLabel("delete odbc").targetEvent(n).ok("OK").cancel("CANCEL");i.show(t).then(function(){S(e)},function(){console.log("CANCEL")})},b.success=y,b.getODBC=function(){b.query.offset=(b.query.page-1)*b.query.limit,g.hasRole("admin")?b.promise=m.squareOdbc.get(b.query,y).$promise:(b.query.id=b.userProfile.id,b.query.section="ODBC",b.promise=m.userProfile.getResources(b.query,y).$promise)},b.createOrEditOdbc=function(e,n){i.show({controller:"CreateOrEditOdbcDialogController",controllerAs:"vm",templateUrl:"app/main/apps/callysquare/views/odbcs/create/dialog.html",parent:angular.element(s.body),targetEvent:e,clickOutsideToClose:!0,locals:{odbc:n,odbcs:b.odbcs.rows,license:b.license,setting:b.setting,crudPermissions:b.crudPermissions}})},b.deleteOdbc=S,b.exportSelectedODBC=function(){var e=angular.copy(b.selectedODBC);return b.selectedODBC=[],e},b.deleteSelectedODBC=function(e){var n=i.confirm().title("Are you sure want to delete the selected odbcs?").htmlContent(""+b.selectedODBC.length+" selected will be deleted.").ariaLabel("delete Odbcs").targetEvent(e).ok("OK").cancel("CANCEL");i.show(n).then(function(){b.selectedODBC.forEach(function(e){S(e)}),b.selectedODBC=[]})},b.deselectODBC=function(){b.selectedODBC=[]},b.selectAllODBC=function(){b.selectedODBC=b.odbcs.rows};var A=!0,E=1;function y(e){b.odbcs=e||{count:0,rows:[]}}function S(e){m.squareOdbc.delete({id:e.id}).$promise.then(function(){_.remove(b.odbcs.rows,{id:e.id}),b.odbcs.count-=1,b.odbcs.rows.length||b.getODBC(),p.success({title:_.startCase("Odbc")+" deleted!",msg:e.name?e.name+" has been deleted!":""})}).catch(function(e){if(e.data&&e.data.errors&&e.data.errors.length){b.errors=e.data.errors||[{message:e.toString(),type:"SYSTEM:DELETEsquareOdbc"}];for(var n=0;n"+e.name+" will be deleted.").ariaLabel("delete project").targetEvent(n).ok("OK").cancel("CANCEL");l.show(t).then(function(){f(e)},function(){console.log("CANCEL")})},p.success=h,p.getProjects=function(){p.query.offset=(p.query.page-1)*p.query.limit,u.hasRole("admin")?p.promise=o.squareProject.get(p.query,h).$promise:(p.query.id=p.userProfile.id,p.query.section="SquareProjects",p.promise=o.userProfile.getResources(p.query,h).$promise)},p.createOrEditProject=function(e,n){l.show({controller:"CreateOrEditSquareProjectDialogController",controllerAs:"vm",templateUrl:"app/main/apps/callysquare/views/projects/create/dialog.html",parent:angular.element(d.body),targetEvent:e,clickOutsideToClose:!0,locals:{project:n,projects:p.projects.rows,openFromEditor:null,setting:null,crudPermissions:p.crudPermissions}})},p.deleteProject=f,p.exportSelectedProjects=function(){var e=angular.copy(p.selectedProjects);return p.selectedProjects=[],e},p.deleteSelectedProjects=function(e){var n=l.confirm().title("Are you sure want to delete the selected projects?").htmlContent(""+p.selectedProjects.length+" selected will be deleted.").ariaLabel("delete Projects").targetEvent(e).ok("OK").cancel("CANCEL");l.show(n).then(function(){p.selectedProjects.forEach(function(e){f(e)}),p.selectedProjects=[]})},p.deselectProjects=function(){p.selectedProjects=[]},p.selectAllProjects=function(){p.selectedProjects=p.projects.rows};var g=!0,v=1;function h(e){p.projects=e||{count:0,rows:[]}}function f(e){o.squareProject.delete({id:e.id}).$promise.then(function(){_.remove(p.projects.rows,{id:e.id}),p.projects.count-=1,p.projects.rows.length||p.getProjects(),m.success({title:"Project deleted!",msg:e.name?e.name+" has been deleted!":""})}).catch(function(e){if(e.data&&e.data.errors&&e.data.errors.length){p.errors=e.data.errors||[{message:e.toString(),type:"api.project.delete"}];for(var n=0;n"+(e.name||"squareRecording")+" will be deleted.").ariaLabel("delete squareRecording").targetEvent(n).ok("OK").cancel("CANCEL");i.show(t).then(function(){S(e)},function(){console.log("CANCEL")})},b.success=y,b.getSquareRecordings=function(){b.query.offset=(b.query.page-1)*b.query.limit,g.hasRole("admin")?b.promise=m.squareRecording.get(b.query,y).$promise:(b.query.id=b.userProfile.id,b.query.section="SquareRecordings",b.promise=m.userProfile.getResources(b.query,y).$promise)},b.createOrEditSquareRecording=function(e,n){i.show({controller:"CreateOrEditSquareRecordingDialogController",controllerAs:"vm",templateUrl:"app/main/apps/callysquare/views/squareRecordings/create/dialog.html",parent:angular.element(s.body),targetEvent:e,clickOutsideToClose:!0,locals:{squareRecording:n,squareRecordings:b.squareRecordings.rows,license:b.license,setting:b.setting,crudPermissions:b.crudPermissions}})},b.deleteSquareRecording=S,b.exportSelectedSquareRecordings=function(){var e=angular.copy(b.selectedSquareRecordings);return b.selectedSquareRecordings=[],e},b.deleteSelectedSquareRecordings=function(e){var n=i.confirm().title("Are you sure want to delete the selected squareRecordings?").htmlContent(""+b.selectedSquareRecordings.length+" selected will be deleted.").ariaLabel("delete SquareRecordings").targetEvent(e).ok("OK").cancel("CANCEL");i.show(n).then(function(){b.selectedSquareRecordings.forEach(function(e){S(e)}),b.selectedSquareRecordings=[]})},b.deselectSquareRecordings=function(){b.selectedSquareRecordings=[]},b.selectAllSquareRecordings=function(){b.selectedSquareRecordings=b.squareRecordings.rows};var A=!0,E=1;function y(e){b.squareRecordings=e||{count:0,rows:[]}}function S(e){m.squareRecording.delete({id:e.id}).$promise.then(function(){_.remove(b.squareRecordings.rows,{id:e.id}),b.squareRecordings.count-=1,b.squareRecordings.rows.length||b.getSquareRecordings(),p.success({title:_.startCase("SquareRecording")+" deleted!",msg:e.name?e.name+" has been deleted!":""})}).catch(function(e){if(e.data&&e.data.errors&&e.data.errors.length){b.errors=e.data.errors||[{message:e.toString(),type:"SYSTEM:DELETEsquareRecording"}];for(var n=0;n"+(e.name||"chatQueue")+" will be deleted.").ariaLabel("delete chatQueue").targetEvent(n).ok("OK").cancel("CANCEL");i.show(t).then(function(){S(e)},function(){console.log("CANCEL")})},b.gotorealtimegoto=function(e,n){{if(!g.hasRole("admin"))return m.userProfileSection.get({userProfileId:g.getCurrentUser().userProfileId,sectionId:510}).$promise.then(function(e){var n=e&&e.rows?e.rows[0]:null;n&&n.enabled?t.go("app.chat.realtime.queues",{}):p.info({title:r.instant("STAFF.PERMISSIONS_UNAUTHORIZED_REDIRECT_TITLE"),msg:r.instant("STAFF.PERMISSIONS_UNAUTHORIZED_REDIRECT_MESSAGE")})}).catch(function(e){p.error({title:e.status?"API:"+e.status+" - "+e.statusText:"USERPROFILE:GET_SECTION",msg:e.status?JSON.stringify(e.data):e.toString()})});t.go("app.chat.realtime.queues",{})}},b.success=y,b.getChatQueues=function(){b.query.offset=(b.query.page-1)*b.query.limit,g.hasRole("admin")?b.promise=m.chatQueue.get(b.query,y).$promise:(b.query.id=b.userProfile.id,b.query.section="ChatQueues",b.promise=m.userProfile.getResources(b.query,y).$promise)},b.createOrEditChatQueue=function(e,n){i.show({controller:"CreateOrEditChatQueueDialogController",controllerAs:"vm",templateUrl:"app/main/apps/chat/views/chatQueues/create/dialog.html",parent:angular.element(s.body),targetEvent:e,clickOutsideToClose:!0,locals:{chatQueue:n,chatQueues:b.chatQueues.rows,license:b.license,setting:b.setting,crudPermissions:b.crudPermissions}})},b.deleteChatQueue=S,b.exportSelectedChatQueues=function(){var e=angular.copy(b.selectedChatQueues);return b.selectedChatQueues=[],e},b.deleteSelectedChatQueues=function(e){var n=i.confirm().title("Are you sure want to delete the selected chatQueues?").htmlContent(""+b.selectedChatQueues.length+" selected will be deleted.").ariaLabel("delete ChatQueues").targetEvent(e).ok("OK").cancel("CANCEL");i.show(n).then(function(){b.selectedChatQueues.forEach(function(e){S(e)}),b.selectedChatQueues=[]})},b.deselectChatQueues=function(){b.selectedChatQueues=[]},b.selectAllChatQueues=function(){b.selectedChatQueues=b.chatQueues.rows};var A=!0,E=1;function y(e){b.chatQueues=e||{count:0,rows:[]}}function S(e){m.chatQueue.delete({id:e.id}).$promise.then(function(){_.remove(b.chatQueues.rows,{id:e.id}),b.chatQueues.count-=1,b.chatQueues.rows.length||b.getChatQueues(),p.success({title:_.startCase("ChatQueue")+" deleted!",msg:e.name?e.name+" has been deleted!":""})}).catch(function(e){if(e.data&&e.data.errors&&e.data.errors.length){b.errors=e.data.errors||[{message:e.toString(),type:"SYSTEM:DELETEchatQueue"}];for(var n=0;n":"",n}),c.startingSelectedItems=angular.copy(c.selectedItems),c.dualMultiselectOptions.selectedItems=c.selectedItems,c.dualMultiselectOptions.items=_.differenceBy(c.allowedItems,c.dualMultiselectOptions.selectedItems,"id"),t()}).catch(function(e){n(e)})})}c.currentUser=l.getCurrentUser(),c.chatQueue=n,c.crudPermissions=d,c.realtime=o,c.items=[],c.allowedItems=[],c.selectedItems=[],c.startingAllowedItems=[],c.startingSelectedItems=[],c.pendingChanges=!1,c.onInit=function(){return l.hasRole("admin")?m().catch(function(e){i.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:GET_AGENTS",msg:e.status?JSON.stringify(e.data):e.toString()})}):a(function(t,n){s.userProfileSection.get({userProfileId:c.currentUser.userProfileId,name:"Agents"}).$promise.then(function(e){var n=e&&e.rows?e.rows[0]:null;t(n)}).catch(function(e){n(e)})}).then(function(e){return c.section=e,m()}).catch(function(e){i.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:GET_AGENTS",msg:e.status?JSON.stringify(e.data):e.toString()})})},c.saveAgents=function(){var e=_.differenceBy(c.startingSelectedItems,c.selectedItems,"id"),n=_.differenceBy(c.selectedItems,c.startingSelectedItems,"id");return(t=e,a(function(e,n){_.isEmpty(t)?e():s.chatQueue.removeAgents({id:c.chatQueue.id,ids:_.map(t,"id")}).$promise.then(function(){e()}).catch(function(e){n(e)})})).then(function(){return t=n,a(function(e,n){_.isEmpty(t)?e():s.chatQueue.addAgents({id:c.chatQueue.id,ids:_.map(t,"id")}).$promise.then(function(){e()}).catch(function(e){n(e)})});var t}).then(function(){c.pendingChanges=!1,c.startingAllowedItems=angular.copy(c.allowedItems),c.startingSelectedItems=angular.copy(c.selectedItems),i.success({title:"SUCCESS",msg:"Agents association has been updated!"})}).catch(function(e){i.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:LISTS_ASSOCIATION",msg:e.status?JSON.stringify(e.data):e.toString()})});var t},c.closeDialog=function(){e.hide()},c.dualMultiselectOptions={readOnly:!c.crudPermissions.canEdit,items:[],selectedItems:[],showSelectAndDeselectAll:!0,orderBy:"name",line1:"fullname",line2:["name","internal"],line3:"",labelAll:r.instant("CHAT.ALL_AGENTS"),labelSelected:r.instant("CHAT.SELECTED_AGENTS"),transferCallback:function(e,n){var t=_.xorBy(c.startingSelectedItems,c.selectedItems,"id");c.pendingChanges=!_.isEmpty(t)}}}e.$inject=["$mdDialog","$q","toasty","api","chatQueue","chatQueues","realtime","$translate","Auth","crudPermissions"],angular.module("app.chat").controller("ChatQueueagentaddController",e)}(),function(){"use strict";function e(e,a,i,s,n,t,o,r){var l=this;function d(){return a(function(t,n){return a(function(n,t){return s.team.get({fields:"id,name",nolimit:!0}).$promise.then(function(e){n(e)}).catch(function(e){t(e)})}).then(function(e){return l.items=e.rows?e.rows:[],o.hasRole("admin")?e:l.section?l.section.autoAssociation?e:a(function(n,t){return s.userProfileResource.get({sectionId:l.section.id,nolimit:!0}).$promise.then(function(e){n(e)}).catch(function(e){t(e)})}):null}).then(function(e){var n=e&&e.rows?e.rows:[];return l.allowedItems=_.map(n,function(e){return _.find(l.items,{id:o.hasRole("admin")||l.section.autoAssociation?e.id:e.resourceId})}),l.items.forEach(function(e){var n=_.find(l.allowedItems,{id:e.id});o.hasRole("admin")?e.isValid=!0:e.isValid=void 0!==n}),a(function(n,t){return s.chatQueue.getTeams({id:l.chatQueue.id,fields:"id,name",nolimit:!0}).$promise.then(function(e){n(e)}).catch(function(e){t(e)})})}).then(function(e){var n=e&&e.rows?e.rows:[];l.selectedItems=_.map(n,function(e){return _.find(l.items,{id:e.id})}),l.startingSelectedItems=angular.copy(l.selectedItems),l.dualMultiselectOptions.selectedItems=l.selectedItems,l.dualMultiselectOptions.items=_.differenceBy(l.allowedItems,l.dualMultiselectOptions.selectedItems,"id"),t()}).catch(function(e){n(e)})})}l.currentUser=o.getCurrentUser(),l.chatQueue=n,l.crudPermissions=r,l.items=[],l.allowedItems=[],l.selectedItems=[],l.startingAllowedItems=[],l.startingSelectedItems=[],l.pendingChanges=!1,l.dualMultiselectOptions={readOnly:!l.crudPermissions.canEdit,allowedItems:[],selectedItems:[],showSelectAndDeselectAll:!0,orderBy:"name",line1:"name",line2:"",line3:"",labelAll:t.instant("CHAT.ALL_TEAMS"),labelSelected:t.instant("CHAT.SELECTED_TEAMS"),transferCallback:function(e,n){var t=_.xorBy(l.startingSelectedItems,l.selectedItems,"id");l.pendingChanges=!_.isEmpty(t)}},l.onInit=function(){return o.hasRole("admin")?d().catch(function(e){i.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:GET_TEAMS",msg:e.status?JSON.stringify(e.data):e.toString()})}):a(function(t,n){s.userProfileSection.get({userProfileId:l.currentUser.userProfileId,name:"Teams"}).$promise.then(function(e){var n=e&&e.rows?e.rows[0]:null;t(n)}).catch(function(e){n(e)})}).then(function(e){return l.section=e,d()}).catch(function(e){i.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:GET_TEAMS",msg:e.status?JSON.stringify(e.data):e.toString()})})},l.saveTeams=function(){var e=_.differenceBy(l.startingSelectedItems,l.selectedItems,"id"),n=_.differenceBy(l.selectedItems,l.startingSelectedItems,"id");return(t=e,a(function(e,n){_.isEmpty(t)?e():s.chatQueue.removeTeams({id:l.chatQueue.id,ids:_.map(t,"id")}).$promise.then(function(){e()}).catch(function(e){n(e)})})).then(function(){return t=n,a(function(e,n){_.isEmpty(t)?e():s.chatQueue.addTeams({id:l.chatQueue.id,ids:_.map(t,"id")}).$promise.then(function(){e()}).catch(function(e){n(e)})});var t}).then(function(){l.pendingChanges=!1,l.startingAllowedItems=angular.copy(l.allowedItems),l.startingSelectedItems=angular.copy(l.selectedItems),i.success({title:"SUCCESS",msg:"Teams association has been updated!"})}).catch(function(e){i.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:LISTS_ASSOCIATION",msg:e.status?JSON.stringify(e.data):e.toString()})});var t},l.closeDialog=function(){e.hide()}}e.$inject=["$mdDialog","$q","toasty","api","chatQueue","$translate","Auth","crudPermissions"],angular.module("app.chat").controller("ChatQueueteamaddController",e)}(),function(){"use strict";function e(e,n,t,a,i,s,o,r,l,d,c,m){var u=this;u.currentUser=d.getCurrentUser(),u.license=s,u.setting=o,u.passwordPattern=u.setting.securePassword?/(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[?!@#\$%\^&\*~\-_=+[{\]\}])(?=.{8,})/:"",u.location=n.protocol()+"://"+n.host(),u.chatQueue=c||e.params.chatQueue||{},u.userProfileSection=m&&1==m.count?m.rows[0]:null,u.crudPermissions=d.parseCrudPermissions(u.userProfileSection?u.userProfileSection.crudPermissions:null),u.hasModulePermissions={},u.selectedTab=e.params.tab||0,u.teamadddialog=function(e,n){t.show({controller:"ChatQueueteamaddController",controllerAs:"vm",templateUrl:"app/main/apps/chat/views/chatQueues/edit/teamadd/teamadd.html",parent:angular.element(a.body),targetEvent:n,clickOutsideToClose:!0,locals:{chatQueue:e,chatQueues:u.chatQueues?u.chatQueues.rows:[],crudPermissions:u.crudPermissions}})},u.agentadddialog=function(e,n){t.show({controller:"ChatQueueagentaddController",controllerAs:"vm",templateUrl:"app/main/apps/chat/views/chatQueues/edit/agentadd/agentadd.html",parent:angular.element(a.body),targetEvent:n,clickOutsideToClose:!0,locals:{chatQueue:e,chatQueues:u.chatQueues?u.chatQueues.rows:[],crudPermissions:u.crudPermissions,realtime:!1}})},u.alert=l.info,u.gotoChatQueues=function(){e.go("app.chat.chatQueues")},u.saveChatQueue=function(){r.chatQueue.update({id:u.chatQueue.id},u.chatQueue).$promise.then(function(){l.success({title:"ChatQueue updated!",msg:u.chatQueue.name?u.chatQueue.name+" has been updated!":""})}).catch(function(e){l.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:GETchatQueue",msg:e.data?JSON.stringify(e.data):e.toString()})})}}e.$inject=["$state","$location","$mdDialog","$document","$translate","license","setting","api","toasty","Auth","chatQueue","userProfileSection"],angular.module("app.chat").controller("ChatQueueController",e)}(),function(){"use strict";function e(e,n,t,a,i,s,o,r,l,d,c,m,u,p,g,v,h,f){var b=this;b.license=v,b.setting=h,b.currentUser=g.getCurrentUser(),b.chatWebsites=l||{count:0,rows:[]},b.userProfile=d,b.userProfileSection=c&&1==c.count?c.rows[0]:null,b.crudPermissions=g.parseCrudPermissions(b.userProfileSection?b.userProfileSection.crudPermissions:null),b.table="chatWebsites",b.listOrder="",b.listOrderAsc=null,b.selectedChatWebsites=[],b.query={fields:"createdAt,updatedAt,id,token,agentIdentifier,customerAlias,messageFontSize,name,key,address,remote,ListId,fidelity,timeout,agentAlias,closingQuestion,formSubmitSuccessMessage,formSubmitFailureMessage,color,color_focus,color_button,textColor,backgroundColor,fontSize,header_shape,showAgentAvatar,showCustomerAvatar,alignment,verticalAlignment,messagesAlignment,defaultTitle,animation,defaultWhiteLabel,whiteLabel,defaultLogo,conditionAgreement,autoclose,enableUnmanagedNote,unmanagedMessage,skipUnmanaged,sendUnmanaged,enableCustomerWriting,waitingTitle,waitingMessage,closingMessage,noteTitle,placeholderMessage,skipMessageButton,enableRating,ratingType,ratingStarsNumber,enableFeedback,feedbackTitle,forwardTranscript,forwardTranscriptMessage,closingMessageButton,download_transcript,enableCustomerAttachment,enableSendButton,enableCustomerCheckmarks,systemAlias,enquiry_enable,enquiry_forwarding,enquiry_forwarding_address,name_title,username_placeholder,email_title,email_placeholder,header_online,hideWhenOffline,header_offline,start_chat_button,offline_chat_button,offlineMessageSubject,offlineMessageBody,offline_message,message_title,enquiry_message_placeholder,enquiry_button,rating_message,rating_send,rating_skip,onlineForm,offlineForm,mapKey,mapKeyOffline,forwardOffline,forwardOfflineAddress,IntervalId,timezone,waitForTheAssignedAgent,mandatoryDisposition,mandatoryDispositionPauseId,description,notificationSound,notificationShake,notificationTemplate,queueTransfer,queueTransferTimeout,agentTransfer,agentTransferTimeout",sort:"-updatedAt",limit:10,page:1},b.arrayagentIdentifier=_.keyBy([{option:"WebsiteAlias",value:"'website_alias'"},{option:"AgentAlias",value:"'agent_alias'"},{option:"AgentFullname",value:"'agent_fullname'"}],function(e){return _.replace(e.value,new RegExp("'","g"),"")}),b.arrayheader_shape=_.keyBy([{option:"Rounded",value:"'rounded'"},{option:"Squared",value:"'squared'"}],function(e){return _.replace(e.value,new RegExp("'","g"),"")}),b.arrayalignment=_.keyBy([{option:"bottom_right",value:"'bottom_right'"},{option:"right",value:"'right'"},{option:"left",value:"'left'"}],function(e){return _.replace(e.value,new RegExp("'","g"),"")}),b.arraymessagesAlignment=_.keyBy([{option:"alternate",value:"'alternate'"},{option:"centered",value:"'centered'"}],function(e){return _.replace(e.value,new RegExp("'","g"),"")}),b.arrayratingType=_.keyBy([{option:"Star",value:"'star'"},{option:"Thumb",value:"'thumb'"}],function(e){return _.replace(e.value,new RegExp("'","g"),"")}),b.editstate=function(e,n){t.go("app.chat.chatWebsites.edit",{id:e.id,chatWebsite:e,crudPermissions:b.crudPermissions})},b.interactionsgoto=function(e,n){t.go("app.chat.chatWebsites.edit",{id:e.id,tab:9})},b.offlinemessagesgoto=function(e,n){t.go("app.chat.chatWebsites.edit",{id:e.id,tab:10})},b.agentadddialog=function(e,n){i.show({controller:"ChatWebsiteagentaddController",controllerAs:"vm",templateUrl:"app/main/apps/chat/views/chatWebsites/edit/agentadd/agentadd.html",parent:angular.element(s.body),targetEvent:n,clickOutsideToClose:!0,locals:{chatWebsite:e,chatWebsites:b.chatWebsites?b.chatWebsites.rows:[],crudPermissions:b.crudPermissions,realtime:!1}})},b.deleteconfirm=function(e,n){var t=i.confirm().title("Are you sure want to delete the "+_.startCase("chatWebsite")+"?").htmlContent(""+(e.name||"chatWebsite")+" will be deleted.").ariaLabel("delete chatWebsite").targetEvent(n).ok("OK").cancel("CANCEL");i.show(t).then(function(){S(e)},function(){console.log("CANCEL")})},b.success=y,b.getChatWebsites=function(){b.query.offset=(b.query.page-1)*b.query.limit,g.hasRole("admin")?b.promise=m.chatWebsite.get(b.query,y).$promise:(b.query.id=b.userProfile.id,b.query.section="ChatWebsites",b.promise=m.userProfile.getResources(b.query,y).$promise)},b.createOrEditChatWebsite=function(e,n){i.show({controller:"CreateOrEditChatWebsiteDialogController",controllerAs:"vm",templateUrl:"app/main/apps/chat/views/chatWebsites/create/dialog.html",parent:angular.element(s.body),targetEvent:e,clickOutsideToClose:!0,locals:{chatWebsite:n,chatWebsites:b.chatWebsites.rows,license:b.license,setting:b.setting,crudPermissions:b.crudPermissions}})},b.deleteChatWebsite=S,b.exportSelectedChatWebsites=function(){var e=angular.copy(b.selectedChatWebsites);return b.selectedChatWebsites=[],e},b.deleteSelectedChatWebsites=function(e){var n=i.confirm().title("Are you sure want to delete the selected chatWebsites?").htmlContent(""+b.selectedChatWebsites.length+" selected will be deleted.").ariaLabel("delete ChatWebsites").targetEvent(e).ok("OK").cancel("CANCEL");i.show(n).then(function(){b.selectedChatWebsites.forEach(function(e){S(e)}),b.selectedChatWebsites=[]})},b.deselectChatWebsites=function(){b.selectedChatWebsites=[]},b.selectAllChatWebsites=function(){b.selectedChatWebsites=b.chatWebsites.rows},g.hasRole("admin")?m.cmList.get({fields:"id,name",sort:"name"}).$promise.then(function(e){b.lists=e.rows||[]}).catch(function(e){p.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:GET_LISTS",msg:e.data?JSON.stringify(e.data):e.toString()})}):m.cmList.get({fields:"id,name",sort:"name"}).$promise.then(function(e){b.lists=e.rows||[]}).then(function(){return m.userProfileSection.get({userProfileId:b.currentUser.userProfileId,sectionId:301}).$promise}).then(function(e){var n=e&&e.rows?e.rows[0]:null;if(n){if(!n.autoAssociation)return m.userProfileResource.get({sectionId:n.id}).$promise.then(function(e){var n=_.map(e.rows,function(e){return _.find(b.lists,{id:e.resourceId})}),t=null;if(b.chatWebsite&&(t=_.find(b.lists,{id:Number(b.chatWebsite.ListId)})),t&&!_.some(n,["id",t.id])){var a=_.find(b.lists,{id:t.id});a.canSelect=!1,n.push(a)}b.lists=n})}else{var t=[],a=null;b.chatWebsite&&(a=_.find(b.lists,{id:Number(b.chatWebsite.ListId)}));for(var i=0;i"+e.app+" will be deleted.").ariaLabel("delete application").targetEvent(t).ok("OK").cancel("CANCEL");i.show(a).then(function(){r.chatWebsiteApps.rows.splice(n,1),l()},function(){console.log("CANCEL")})},r.getChatWebsiteApps=function(){r.promise=o.chatWebsite.getApplications(r.query,t).$promise},r.editChatWebsiteApp=n,r.editInterval=function(e,n){if(r.chatWebsiteApps.rows.length){var t=r.chatWebsiteApps.rows[n]?r.chatWebsiteApps.rows[n]:r.chatWebsiteApps.rows[0];i.show({controller:"EditChatWebsiteAppintervalDialogController",controllerAs:"vm",templateUrl:"app/main/apps/chat/views/chatWebsites/edit/apps/interval/dialog.html",parent:angular.element(a.body),targetEvent:e,clickOutsideToClose:!0,locals:{interval:{interval:t.interval,IntervalId:t.IntervalId,application:!0},intervals:[],crudPermissions:r.crudPermissions}}).then(function(e){e&&(t.interval=e.interval||"*,*,*,*",t.IntervalId=e.IntervalId||null,l())})}},r.deleteChatWebsiteApp=function(e){_.remove(r.chatWebsiteApps.rows,{id:e.id}),l(),s.success({title:"App deleted!",msg:e.app?e.app+" has been deleted!":""})},r.deleteSelectedChatWebsiteApps=function(e){var n=i.confirm().title("Are you sure want to delete the selected applications?").htmlContent(""+r.selectedChatWebsiteApps.length+" selected will be deleted.").ariaLabel("delete applications").targetEvent(e).ok("OK").cancel("CANCEL");i.show(n).then(function(){r.selectedChatWebsiteApps.forEach(function(e){_.remove(r.chatWebsiteApps.rows,{id:e.id})}),r.selectedChatWebsiteApps=[],l()})},r.rewriteRouting=l,r.getIntervals=function(){return o.interval.get({fields:"id,interval,IntervalId"}).$promise.then(function(e){r.intervals=e}).catch(function(e){console.error(e)})}}e.$inject=["api","$mdDialog","$document","toasty","Auth"],angular.module("app.chat").controller("ChatWebsiteActionsController",e)}(),function(){"use strict";function e(e,a,i,s,n,t,o,r,l,d){var c=this;function m(){return a(function(t,n){return a(function(n,t){return s.user.get({fields:"id,name,internal,fullname",nolimit:!0,role:"agent"}).$promise.then(function(e){n(e)}).catch(function(e){t(e)})}).then(function(e){return c.items=e.rows?e.rows:[],l.hasRole("admin")?e:c.section?c.section.autoAssociation?e:a(function(n,t){return s.userProfileResource.get({sectionId:c.section.id,nolimit:!0}).$promise.then(function(e){n(e)}).catch(function(e){t(e)})}):null}).then(function(e){var n=e&&e.rows?e.rows:[];return c.allowedItems=_.map(n,function(e){return _.find(c.items,{id:l.hasRole("admin")||c.section.autoAssociation?e.id:e.resourceId})}),c.startingAllowedItems=angular.copy(c.allowedItems),c.items.forEach(function(e){var n=_.find(c.allowedItems,{id:e.id});l.hasRole("admin")?e.isValid=!0:e.isValid=void 0!==n}),a(function(n,t){return s.chatWebsite.getAgents({id:c.chatWebsite.id,fields:"id,name,internal,fullname",nolimit:!0,role:"agent"}).$promise.then(function(e){n(e)}).catch(function(e){t(e)})})}).then(function(e){var n=e&&e.rows?e.rows:[];c.selectedItems=_.map(n,function(e){var n=_.find(c.items,{id:e.id});return n.penalty=e.UserChatWebsite?"penalty "+e.UserChatWebsite.penalty:"",n.internal=e.hasOwnProperty("internal")?"<"+e.internal+">":"",n}),c.startingSelectedItems=angular.copy(c.selectedItems),c.dualMultiselectOptions.selectedItems=c.selectedItems,c.dualMultiselectOptions.items=_.differenceBy(c.allowedItems,c.dualMultiselectOptions.selectedItems,"id"),t()}).catch(function(e){n(e)})})}c.currentUser=l.getCurrentUser(),c.chatWebsite=n,c.crudPermissions=d,c.realtime=o,c.items=[],c.allowedItems=[],c.selectedItems=[],c.startingAllowedItems=[],c.startingSelectedItems=[],c.pendingChanges=!1,c.onInit=function(){return l.hasRole("admin")?m().catch(function(e){i.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:GET_AGENTS",msg:e.status?JSON.stringify(e.data):e.toString()})}):a(function(t,n){s.userProfileSection.get({userProfileId:c.currentUser.userProfileId,name:"Agents"}).$promise.then(function(e){var n=e&&e.rows?e.rows[0]:null;t(n)}).catch(function(e){n(e)})}).then(function(e){return c.section=e,m()}).catch(function(e){i.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:GET_AGENTS",msg:e.status?JSON.stringify(e.data):e.toString()})})},c.saveAgents=function(){var e=_.differenceBy(c.startingSelectedItems,c.selectedItems,"id"),n=_.differenceBy(c.selectedItems,c.startingSelectedItems,"id");return(t=e,a(function(e,n){_.isEmpty(t)?e():s.chatWebsite.removeAgents({id:c.chatWebsite.id,ids:_.map(t,"id")}).$promise.then(function(){e()}).catch(function(e){n(e)})})).then(function(){return t=n,a(function(e,n){_.isEmpty(t)?e():s.chatWebsite.addAgents({id:c.chatWebsite.id,ids:_.map(t,"id")}).$promise.then(function(){e()}).catch(function(e){n(e)})});var t}).then(function(){c.pendingChanges=!1,c.startingAllowedItems=angular.copy(c.allowedItems),c.startingSelectedItems=angular.copy(c.selectedItems),i.success({title:"SUCCESS",msg:"Agents association has been updated!"})}).catch(function(e){i.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:LISTS_ASSOCIATION",msg:e.status?JSON.stringify(e.data):e.toString()})});var t},c.closeDialog=function(){e.hide()},c.dualMultiselectOptions={readOnly:!c.crudPermissions.canEdit,items:[],selectedItems:[],showSelectAndDeselectAll:!0,orderBy:"name",line1:"fullname",line2:["name","internal"],line3:"",labelAll:r.instant("CHAT.ALL_AGENTS"),labelSelected:r.instant("CHAT.SELECTED_AGENTS"),transferCallback:function(e,n){var t=_.xorBy(c.startingSelectedItems,c.selectedItems,"id");c.pendingChanges=!_.isEmpty(t)}}}e.$inject=["$mdDialog","$q","toasty","api","chatWebsite","chatWebsites","realtime","$translate","Auth","crudPermissions"],angular.module("app.chat").controller("ChatWebsiteagentaddController",e)}(),function(){"use strict";function e(e,a){var i=this;i.chatWebsite={},i.crudPermissions,i.ngFlowOptions={singleFile:!0,maxChunkRetries:1,chunkSize:8388608,simultaneousUploads:1,testChunks:!1,progressCallbacksInterval:1e3,allowDuplicateUploads:!0},i.ngFlow={flow:{}},i.dropping=!1,i.fileAdded=function(e){var n=["png","jpg"];if(!_.includes(n,e.getExtension()))return a.error({title:"Invalid extension: "+e.getExtension(),msg:"Supported extension: "+n.join()}),!1;if(8388608"+(e.name||"chatCannedAnswer")+" will be deleted.").ariaLabel("delete chatCannedAnswer").targetEvent(n).ok("OK").cancel("CANCEL");s.show(t).then(function(){g(e)},function(){console.log("CANCEL")})},c.success=p,c.getChatWebsiteChatCannedAnswers=function(){c.query.offset=(c.query.page-1)*c.query.limit,c.promise=l.chatWebsite.getAnswers(c.query,p).$promise},c.createOrEditChatWebsiteChatCannedAnswer=function(e,n){s.show({controller:"CreateOrEditChatCannedAnswerDialogController",controllerAs:"vm",templateUrl:"app/main/apps/chat/views/chatWebsites/edit/chatCannedAnswers/dialog.html",parent:angular.element(o.body),targetEvent:e,clickOutsideToClose:!0,locals:{chatWebsite:c.chatWebsite,chatCannedAnswer:n,chatCannedAnswers:c.chatWebsiteChatCannedAnswers.rows,license:null,setting:null,crudPermissions:c.crudPermissions}})},c.exportSelectedChatWebsiteChatCannedAnswers=function(){var e=angular.copy(c.selectedChatWebsiteChatCannedAnswers);return c.selectedChatWebsiteChatCannedAnswers=[],e},c.deleteChatWebsiteChatCannedAnswer=g,c.deleteSelectedChatWebsiteChatCannedAnswers=function(e){var n=s.confirm().title("Are you sure want to delete the selected chatCannedAnswers?").htmlContent(""+c.selectedChatWebsiteChatCannedAnswers.length+" selected will be deleted.").ariaLabel("delete chatCannedAnswers").targetEvent(e).ok("OK").cancel("CANCEL");s.show(n).then(function(){c.selectedChatWebsiteChatCannedAnswers.forEach(function(e){g(e)}),c.selectedChatWebsiteChatCannedAnswers=[]})};var m=!0,u=1;function p(e){c.chatWebsiteChatCannedAnswers=e||{count:0,rows:[]}}function g(e){l.cannedAnswer.delete({id:e.id}).$promise.then(function(){_.remove(c.chatWebsiteChatCannedAnswers.rows,{id:e.id}),c.chatWebsiteChatCannedAnswers.count-=1,c.chatWebsiteChatCannedAnswers.rows.length||c.getChatWebsiteChatCannedAnswers(),r.success({title:"ChatCannedAnswer deleted!",msg:e.name?e.name+" has been deleted!":""})}).catch(function(e){if(e.data&&e.data.errors&&e.data.errors.length){vm.errors=e.data.errors||[{message:e.toString(),type:"SYSTEM:GETchatWebsite"}];for(var n=0;n"+(e.name||"chatDisposition")+" will be deleted.").ariaLabel("delete chatDisposition").targetEvent(n).ok("OK").cancel("CANCEL");s.show(t).then(function(){g(e)},function(){console.log("CANCEL")})},c.success=p,c.getChatWebsiteChatDispositions=function(){c.query.offset=(c.query.page-1)*c.query.limit,c.promise=l.chatWebsite.getDispositions(c.query,p).$promise},c.createOrEditChatWebsiteChatDisposition=function(e,n){s.show({controller:"CreateOrEditChatDispositionDialogController",controllerAs:"vm",templateUrl:"app/main/apps/chat/views/chatWebsites/edit/chatDispositions/dialog.html",parent:angular.element(o.body),targetEvent:e,clickOutsideToClose:!0,locals:{chatWebsite:c.chatWebsite,chatDisposition:n,chatDispositions:c.chatWebsiteChatDispositions.rows,license:null,setting:null,crudPermissions:c.crudPermissions}})},c.exportSelectedChatWebsiteChatDispositions=function(){var e=angular.copy(c.selectedChatWebsiteChatDispositions);return c.selectedChatWebsiteChatDispositions=[],e},c.deleteChatWebsiteChatDisposition=g,c.deleteSelectedChatWebsiteChatDispositions=function(e){var n=s.confirm().title("Are you sure want to delete the selected chatDispositions?").htmlContent(""+c.selectedChatWebsiteChatDispositions.length+" selected will be deleted.").ariaLabel("delete chatDispositions").targetEvent(e).ok("OK").cancel("CANCEL");s.show(n).then(function(){c.selectedChatWebsiteChatDispositions.forEach(function(e){g(e)}),c.selectedChatWebsiteChatDispositions=[]})};var m=!0,u=1;function p(e){c.chatWebsiteChatDispositions=e||{count:0,rows:[]}}function g(e){l.disposition.delete({id:e.id}).$promise.then(function(){_.remove(c.chatWebsiteChatDispositions.rows,{id:e.id}),c.chatWebsiteChatDispositions.count-=1,c.chatWebsiteChatDispositions.rows.length||c.getChatWebsiteChatDispositions(),r.success({title:"ChatDisposition deleted!",msg:e.name?e.name+" has been deleted!":""})}).catch(function(e){if(e.data&&e.data.errors&&e.data.errors.length){vm.errors=e.data.errors||[{message:e.toString(),type:"SYSTEM:GETchatWebsite"}];for(var n=0;n"+(e.name||"interaction")+" will be deleted.").ariaLabel("delete interaction").targetEvent(n).ok("OK").cancel("CANCEL");s.show(t).then(function(){g(e)},function(){console.log("CANCEL")})},c.chatInteractionDownload=function(s,e,n){return l.chatInteraction.download({id:s.id,exists:!0,attachments:n}).$promise.then(function(e){var n=[e.buffer],t="interaction"+s.id,a=new Blob(n,{type:e.type});t="chat-interaction"+s.id+".zip";var i=window.document.createElement("a");i.setAttribute("href",URL.createObjectURL(a)),i.setAttribute("download",t),document.body.appendChild(i),i.click()}).catch(function(e){if(e.data&&e.data.errors&&e.data.errors.length)for(var n=0;n"+c.selectedChatWebsiteInteractions.length+" selected will be deleted.").ariaLabel("delete interactions").targetEvent(e).ok("OK").cancel("CANCEL");s.show(n).then(function(){c.selectedChatWebsiteInteractions.forEach(function(e){g(e)}),c.selectedChatWebsiteInteractions=[]})};var m=!0,u=1;function p(e){c.chatWebsiteInteractions=e||{count:0,rows:[]}}function g(e){l.chatInteraction.delete({id:e.id}).$promise.then(function(){_.remove(c.chatWebsiteInteractions.rows,{id:e.id}),c.chatWebsiteInteractions.count-=1,c.chatWebsiteInteractions.rows.length||c.getChatWebsiteInteractions(),r.success({title:"Interaction deleted!",msg:e.name?e.name+" has been deleted!":""})}).catch(function(e){if(e.data&&e.data.errors&&e.data.errors.length){vm.errors=e.data.errors||[{message:e.toString(),type:"SYSTEM:GETchatWebsite"}];for(var n=0;n"+(e.name||"offlineMessage")+" will be deleted.").ariaLabel("delete offlineMessage").targetEvent(n).ok("OK").cancel("CANCEL");s.show(t).then(function(){g(e)},function(){console.log("CANCEL")})},c.success=p,c.getChatWebsiteOfflineMessages=function(){c.query.offset=(c.query.page-1)*c.query.limit,c.promise=l.chatWebsite.getOfflineMessages(c.query,p).$promise},c.createOrEditChatWebsiteOfflineMessage=function(e,n){s.show({controller:"CreateOrEditOfflineMessageDialogController",controllerAs:"vm",templateUrl:"app/main/apps/chat/views/chatWebsites/edit/offlineMessages/dialog.html",parent:angular.element(o.body),targetEvent:e,clickOutsideToClose:!0,locals:{chatWebsite:c.chatWebsite,offlineMessage:n,offlineMessages:c.chatWebsiteOfflineMessages.rows,license:null,setting:null,crudPermissions:c.crudPermissions}})},c.showOfflineMessageChatWebsiteOfflineMessage=function(e,t){s.show({controller:"ShowOfflineMessageOfflineMessageDialogController",controllerAs:"vm",templateUrl:"app/main/apps/chat/views/chatWebsites/edit/offlineMessages/dialog.html",parent:angular.element(o.body),targetEvent:e,clickOutsideToClose:!0,resolve:{message:["apiResolver","$stateParams",function(e,n){return e.resolve("chatOfflineMessage@get",{fields:"id,body",id:t.id})}]}})},c.exportSelectedChatWebsiteOfflineMessages=function(){var e=angular.copy(c.selectedChatWebsiteOfflineMessages);return c.selectedChatWebsiteOfflineMessages=[],e},c.deleteChatWebsiteOfflineMessage=g,c.deleteSelectedChatWebsiteOfflineMessages=function(e){var n=s.confirm().title("Are you sure want to delete the selected offlineMessages?").htmlContent(""+c.selectedChatWebsiteOfflineMessages.length+" selected will be deleted.").ariaLabel("delete offlineMessages").targetEvent(e).ok("OK").cancel("CANCEL");s.show(n).then(function(){c.selectedChatWebsiteOfflineMessages.forEach(function(e){g(e)}),c.selectedChatWebsiteOfflineMessages=[]})},l.cmContact.get({fields:"id,firstName,lastName",nolimit:"true"}).$promise.then(function(e){c.contacts=e.rows||[]}).catch(function(e){r.error({title:e.status?"API:"+e.status+" - "+e.statusText:"SYSTEM:GET_CONTACTS",msg:e.data?JSON.stringify(e.data):e.toString()})});var m=!0,u=1;function p(e){c.chatWebsiteOfflineMessages=e||{count:0,rows:[]}}function g(e){l.chatOfflineMessage.delete({id:e.id}).$promise.then(function(){_.remove(c.chatWebsiteOfflineMessages.rows,{id:e.id}),c.chatWebsiteOfflineMessages.count-=1,c.chatWebsiteOfflineMessages.rows.length||c.getChatWebsiteOfflineMessages(),r.success({title:"OfflineMessage deleted!",msg:e.name?e.name+" has been deleted!":""})}).catch(function(e){if(e.data&&e.data.errors&&e.data.errors.length){vm.errors=e.data.errors||[{message:e.toString(),type:"SYSTEM:GETchatWebsite"}];for(var n=0;n"+(e.name||"chatProactiveAction")+" will be deleted.").ariaLabel("delete chatProactiveAction").targetEvent(n).ok("OK").cancel("CANCEL");s.show(t).then(function(){g(e)},function(){console.log("CANCEL")})},c.success=p,c.getChatWebsiteProactiveActions=function(){c.query.offset=(c.query.page-1)*c.query.limit,c.promise=l.chatWebsite.getProactiveActions(c.query,p).$promise},c.createOrEditChatWebsiteChatProactiveAction=function(e,n){s.show({controller:"CreateOrEditChatProactiveActionDialogController",controllerAs:"vm",templateUrl:"app/main/apps/chat/views/chatWebsites/edit/proactive/dialog.html",parent:angular.element(o.body),targetEvent:e,clickOutsideToClose:!0,locals:{chatWebsite:c.chatWebsite,chatProactiveAction:n,proactive:c.chatWebsiteProactiveActions.rows,license:null,setting:null,crudPermissions:c.crudPermissions}})},c.exportSelectedChatWebsiteProactiveActions=function(){var e=angular.copy(c.selectedChatWebsiteProactiveActions);return c.selectedChatWebsiteProactiveActions=[],e},c.deleteChatWebsiteChatProactiveAction=g,c.deleteSelectedChatWebsiteProactiveActions=function(e){var n=s.confirm().title("Are you sure want to delete the selected proactive?").htmlContent(""+c.selectedChatWebsiteProactiveActions.length+" selected will be deleted.").ariaLabel("delete proactive").targetEvent(e).ok("OK").cancel("CANCEL");s.show(n).then(function(){c.selectedChatWebsiteProactiveActions.forEach(function(e){g(e)}),c.selectedChatWebsiteProactiveActions=[]})};var m=!0,u=1;function p(e){c.chatWebsiteProactiveActions=e||{count:0,rows:[]}}function g(e){l.chatProactiveAction.delete({id:e.id}).$promise.then(function(){_.remove(c.chatWebsiteProactiveActions.rows,{id:e.id}),c.chatWebsiteProactiveActions.count-=1,c.chatWebsiteProactiveActions.rows.length||c.getChatWebsiteProactiveActions(),r.success({title:"ChatProactiveAction deleted!",msg:e.name?e.name+" has been deleted!":""})}).catch(function(e){if(e.data&&e.data.errors&&e.data.errors.length){vm.errors=e.data.errors||[{message:e.toString(),type:"SYSTEM:GETchatWebsite"}];for(var n=0;n<\/script>',n.end="\n\x3c!-- START Motion Chat Script --\x3e"},n.info={},e.$watch("vm_ac.chatWebsite.remote",function(e){n.script='\n