{"version":3,"file":"snape.72a2189a4c8182001ebe.bundle.js","sources":["webpack://ackcio-client/./wwwroot/js/SnapeApp.js","webpack://ackcio-client/./wwwroot/js/SnapeHelperScripts.js"],"sourcesContent":["var SnapeApp =\r\n{\r\n resources: {},\r\n createModule: function (namespace, module, dependencies) {\r\n \"use strict\";\r\n\r\n var nsparts = namespace.split(\".\");\r\n var parent = SnapeApp;\r\n // we want to be able to include or exclude the root namespace so we strip\r\n // it if it's in the namespace\r\n if (nsparts[0] === \"SnapeApp\") {\r\n nsparts = nsparts.slice(1);\r\n }\r\n\r\n function f() {\r\n return module.apply(this, dependencies);\r\n }\r\n\r\n f.prototype = module.prototype;\r\n\r\n var innerModule = new f();\r\n\r\n // loop through the parts and create a nested namespace if necessary\r\n for (var i = 0, namespaceLength = nsparts.length; i < namespaceLength; i++) {\r\n var partname = nsparts[i];\r\n // check if the current parent already has the namespace declared\r\n // if it isn't, then create it\r\n if (typeof parent[partname] === \"undefined\") {\r\n parent[partname] = (i === namespaceLength - 1) ? innerModule : {};\r\n }\r\n // get a reference to the deepest element in the hierarchy so far\r\n parent = parent[partname];\r\n }\r\n\r\n return parent;\r\n }\r\n};\r\n\r\nwindow.SnapeApp = SnapeApp","SnapeApp.createModule(\"SnapeApp.Helpers.Highlight\", function () {\r\n \"use strict\";\r\n\r\n var highlight = {\r\n highlightText: function (textBoxId) {\r\n var selector = '#' + textBoxId;\r\n $(selector).select();\r\n }\r\n };\r\n\r\n return highlight;\r\n // moDule DepenDs on JQuery\r\n}, [jQuery, moment]);\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.TimeZone\", function () {\r\n \"use strict\";\r\n var timezone = function () {\r\n var time = Intl.DateTimeFormat().resolvedOptions().timeZone;\r\n return time;\r\n };\r\n\r\n var datetimeformat = function (format) {\r\n var mapObj = {\r\n yyyy: \"YYYY\",\r\n dd: \"DD\"\r\n };\r\n format = format.replace(/yyyy|dd/gi, function (matched) {\r\n return mapObj[matched];\r\n });\r\n\r\n return format;\r\n };\r\n\r\n return {\r\n timezone: timezone,\r\n format: datetimeformat\r\n };\r\n\r\n}, [jQuery]);\r\n\r\n/* \r\n Common function for mouse event listener with mobile support using JQuery.\r\n The argument is selector and callback.\r\n example of use in GatewaySettings.js that call MouseEventWithMobileSupport module\r\n*/\r\nSnapeApp.createModule(\"SnapeApp.Helpers.MouseEventWithMobileSupport\", function () {\r\n \"use strict\";\r\n\r\n var mouseEvent = function (selector, callback) {\r\n $(document).on({\r\n mouseenter: callback,\r\n click: callback,\r\n touchstart: callback\r\n }, selector);\r\n }\r\n\r\n return mouseEvent;\r\n\r\n}, [jQuery]);\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.DisplayDateTimeInUTC\", function () {\r\n \"use strict\";\r\n var datetimeformat = function (data, dFormat, timezone) {\r\n if (!data) {\r\n return '';\r\n }\r\n let timezoneUTC = moment(data, dFormat).tz(timezone).format('Z');\r\n return moment.utc(data, dFormat).tz(timezone).format(dFormat) + \" UTC\" + timezoneUTC;\r\n };\r\n\r\n return {\r\n datetimeformat: datetimeformat\r\n };\r\n\r\n}, [jQuery]);\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.EpochTime.DisplayDateTimeInUTC\", function () {\r\n \"use strict\";\r\n var datetimeformat = function (epochTime, dFormat, timezone) {\r\n let timezoneUTC = moment(epochTime).tz(timezone).format('Z');\r\n return moment.utc(epochTime).tz(timezone).format(dFormat) + \" UTC\" + timezoneUTC;\r\n };\r\n\r\n return {\r\n datetimeformat: datetimeformat\r\n };\r\n\r\n}, [jQuery]);\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.Dates\", function () {\r\n \"use strict\";\r\n\r\n var localizeDate = function localizeDate(epochTime, format, isDotNetTicks) {\r\n\r\n if (isDotNetTicks) {\r\n /*Timestamp is pushed to server in C# ticks(UTC). C# time ticks from 0000-01-01. The subtraction of\r\n 621355968000000000 takes away the excess ticks from 0000-01-01 to 1970-01-01. There are 10000 .net\r\n ticks per millisecond. The JavaScript Date type's origin is the Unix epoch: midnight on 1 January 1970.\r\n The .NET DateTime type's origin is midnight on 1 January 0001.*/\r\n epochTime = (epochTime - 621355968000000000) / 10000;\r\n }\r\n var currentMoment = moment.unix(epochTime).locale(cultureInfo);//seconds\r\n var curDate = currentMoment.format(format);\r\n return curDate;\r\n };\r\n\r\n var localizeDates = function localizeDates() {\r\n $('[data-date]').each(function () {\r\n\r\n var date = new Date($(this).attr('data-date'));\r\n var utcDate = moment(date).utc();\r\n\r\n $(this).html(localizeDate(utcDate.local(), 'L, LTS', true));\r\n });\r\n };\r\n\r\n var dates = {\r\n localizeDate: localizeDate,\r\n localizeDates: localizeDates\r\n };\r\n\r\n return dates;\r\n}, [jQuery, moment, cultureInfo]);\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.QueryString\", function () {\r\n\r\n // returns a single parameter from the current query string\r\n // adapted from SO: http://stackoverflow.com/a/901144\r\n var getParameter = function (name) {\r\n name = name.replace(/[\\[]/, \"\\\\[\").replace(/[\\]]/, \"\\\\]\");\r\n var regex = new RegExp(\"[\\\\?&]\" + name + \"=([^&#]*)\"),\r\n results = regex.exec(location.search);\r\n return results === null ? \"\" : decodeURIComponent(results[1].replace(/\\+/g, \" \"));\r\n };\r\n\r\n return {\r\n getParameter: getParameter\r\n };\r\n});\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.Export\", function () {\r\n\r\n // export project/node/sensor data\r\n var ExportData = function (e) {\r\n\r\n var data = $(\"#SelectWeeks\").data('daterangepicker');\r\n\r\n var exportAllTime = data.allTime;\r\n var fromDate = exportAllTime ? \"\" : moment(data.startDate._d).format(\"YYYY/MM/DD\");\r\n var toDate = exportAllTime ? \"\" : moment(data.endDate._d).format(\"YYYY/MM/DD\");\r\n\r\n data.exportAllTime(false);\r\n // $('#SelectWeeks').prop('disabled', false);\r\n\r\n if (fromDate === toDate && !exportAllTime) {\r\n $(\"#fromdatevalidationmsg\").removeClass(\"hidden\");\r\n $(\"#daterangeerror\").addClass(\"hidden\");\r\n } else {\r\n $(\"#fromdatevalidationmsg\").addClass(\"hidden\");\r\n let fromDateField;\r\n let toDateField;\r\n\r\n let from = moment(fromDate).format(\"YYYY/MM/DD\");\r\n let to = moment(toDate).format(\"YYYY/MM/DD\");\r\n fromDateField = new Date(from);\r\n toDateField = new Date(to);\r\n\r\n if (fromDateField > toDateField) {\r\n $(\"#daterangeerror\").removeClass(\"hidden\");\r\n } else {\r\n $(\"#daterangeerror\").addClass(\"hidden\");\r\n $(\"#exportDataIndicator\").removeClass(\"hidden\");\r\n let element = $(e);\r\n let IdElement = element.attr(\"data-projectId\");\r\n let projectIdArray = IdElement.split(\"_\");\r\n let projectId = projectIdArray[1];\r\n var timer;\r\n let timeStamp = Date.now().toString();\r\n let deviceId;\r\n\r\n if (IdElement.includes(\"project\")) {\r\n\r\n let projectName = element.attr(\"data-projectName\");\r\n let href = \"/Export/DownloadZip?projectId=\" + projectId + \"&projectName=\" + projectName + \"&key=\" + timeStamp + \"&from=\" + fromDate + \"&to=\" + toDate;\r\n document.getElementById(\"fileDownloaderFrame\").src = href;\r\n let cookiStringTimeout = 'timeOutForRequest=' + timeStamp;\r\n let cookieString = \"dlzip=\" + timeStamp;\r\n let cookieStringFailMessage = \"dlzip=fail_\" + timeStamp;\r\n\r\n timer = window.setInterval(function () {\r\n if (document.cookie.indexOf(cookieString) !== -1) {\r\n $(\"#exportDataIndicator\").addClass(\"hidden\");\r\n SnapeApp.Helpers.UIOperations.showMessage(Resources.ProjectListJS.ExportProjectDataSuccess, true, \"toast-bottom-left\");\r\n document.getElementById(\"fileDownloaderFrame\").src = \"about:blank\";\r\n window.clearInterval(timer);\r\n $(\"#weekPickerModal\").modal('hide');\r\n }\r\n if (document.cookie.indexOf(cookieStringFailMessage) !== -1) {\r\n $(\"#exportDataIndicator\").addClass(\"hidden\");\r\n // localize export alert.\r\n SnapeApp.Helpers.UIOperations.showMessage(Resources.ProjectListJS.ErrorExportingNoData, false, \"toast-bottom-left\");\r\n document.getElementById(\"fileDownloaderFrame\").src = \"about:blank\";\r\n window.clearInterval(timer);\r\n $(\"#weekPickerModal\").modal('hide');\r\n }\r\n if (document.cookie.indexOf(cookiStringTimeout) !== -1) {\r\n $(\"#exportDataIndicator\").addClass(\"hidden\");\r\n document.getElementById(\"fileDownloaderFrame\").src = \"about:blank\";\r\n window.location = '/Account/Login?isSessionTimeOut=true';\r\n window.clearInterval(timer);\r\n $(\"#weekPickerModal\").modal('hide');\r\n }\r\n\r\n }, 100);\r\n\r\n } else if (IdElement.includes(\"node\")) {\r\n\r\n deviceId = element.attr(\"data-deviceId\");\r\n let href = \"/Export/ConcatNodeCSV?deviceId=\" + deviceId + \"&projectId=\" + projectId + \"&key=\" + timeStamp + \"&from=\" + fromDate + \"&to=\" + toDate;\r\n let downloadGrabber = document.getElementById(\"fileDownloaderFrame\");\r\n downloadGrabber.src = href;\r\n let cookiStringTimeout = 'timeOutForRequest=' + timeStamp;\r\n let cookieString = 'nodeCsv=' + timeStamp;\r\n let cookieStringFailMessage = 'nodeCsv=fail_' + timeStamp;\r\n\r\n timer = window.setInterval(function () {\r\n if (document.cookie.indexOf(cookieString) !== -1) {\r\n $(\"#exportDataIndicator\").addClass(\"hidden\");\r\n downloadGrabber.src = \"about:blank\";\r\n SnapeApp.Helpers.UIOperations.showMessage(Resources.ProjectListJS.ExportProjectDataSuccess, true, \"toast-bottom-left\");\r\n window.clearInterval(timer);\r\n $(\"#weekPickerModal\").modal('hide');\r\n }\r\n if (document.cookie.indexOf(cookieStringFailMessage) !== -1) {\r\n $(\"#exportDataIndicator\").addClass(\"hidden\");\r\n downloadGrabber.src = \"about:blank\";\r\n SnapeApp.Helpers.UIOperations.showMessage(Resources.ProjectListJS.ErrorExportingNoData, false, \"toast-bottom-left\");\r\n window.clearInterval(timer);\r\n $(\"#weekPickerModal\").modal('hide');\r\n }\r\n if (document.cookie.indexOf(cookiStringTimeout) !== -1) {\r\n $(\"#exportDataIndicator\").addClass(\"hidden\");\r\n downloadGrabber.src = \"about:blank\";\r\n window.location = '/Account/Login?isSessionTimeOut=true';\r\n window.clearInterval(timer);\r\n $(\"#weekPickerModal\").modal('hide');\r\n }\r\n }, 100);\r\n\r\n } else {\r\n deviceId = element.attr(\"data-deviceId\");\r\n let sensorIndex = element.attr(\"data-sensorIndex\");\r\n let href = \"/Export/ConcatSensorCSV?deviceId=\" + deviceId + \"&sensorIndex=\" + sensorIndex + \"&projectId=\" + projectId + \"&key=\" + timeStamp + \"&from=\" + fromDate + \"&to=\" + toDate;\r\n document.getElementById(\"fileDownloaderFrame\").src = href;\r\n\r\n let cookiStringTimeout = 'timeOutForRequest=' + timeStamp;\r\n let cookieString = 'senCsv=' + timeStamp;\r\n let errorCookieString = 'senCsv=fail_' + timeStamp;\r\n\r\n timer = window.setInterval(function () {\r\n if (document.cookie.indexOf(cookieString) !== -1) {\r\n $(\"#exportDataIndicator\").addClass(\"hidden\");\r\n SnapeApp.Helpers.UIOperations.showMessage(Resources.ProjectListJS.ExportProjectDataSuccess, true, \"toast-bottom-left\");\r\n window.clearInterval(timer);\r\n $(\"#weekPickerModal\").modal('hide');\r\n } else if (document.cookie.indexOf(errorCookieString) !== -1) {\r\n $(\"#exportDataIndicator\").addClass(\"hidden\");\r\n SnapeApp.Helpers.UIOperations.showMessage(Resources.ProjectListJS.ErrorExportingNoData, false, \"toast-bottom-left\");\r\n window.clearInterval(timer);\r\n $(\"#weekPickerModal\").modal('hide');\r\n }\r\n if (document.cookie.indexOf(cookiStringTimeout) !== -1) {\r\n $(\"#exportDataIndicator\").addClass(\"hidden\");\r\n window.location = '/Account/Login?isSessionTimeOut=true';\r\n window.clearInterval(timer);\r\n $(\"#weekPickerModal\").modal('hide');\r\n }\r\n }, 100);\r\n }\r\n }\r\n }\r\n };\r\n\r\n return {\r\n ExportData: ExportData\r\n };\r\n});\r\n\r\n// helper module called to get telemetry data like device state, voltage, signal, etc. Used in conjunction with ProjectSummary.js on the Home.cshtml view.\r\n// the titles are localized for viewing.\r\n// the resource file for this helper is SnapeHelperScriptsJS.culture.resx\r\nSnapeApp.createModule(\"SnapeApp.Helpers.Telemetry\", function () {\r\n \"use strict\";\r\n\r\n const renderIconButton = (htmlString) => {\r\n if (!htmlString()) {\r\n return \"\"\r\n }\r\n\r\n return `\r\n
\r\n ${htmlString()}\r\n
\r\n `\r\n }\r\n var htmlEncode = function (data) {\r\n // \"trick\" to HTML encode data from JS--essentially dip it in a
and pull it out again\r\n return data ? $('
').text(data).html() : null;\r\n };\r\n\r\n var getNodeErrorIcon = (errorState) => renderIconButton(function () {\r\n if (errorState === 1) {\r\n return 'error';\r\n }\r\n return '';\r\n });\r\n\r\n var getfirmwareMismatchErrorIcon = (fwState) => renderIconButton(function () {\r\n if (fwState === 2) {\r\n return 'sync_problem';\r\n } else if (fwState === 3) {\r\n return 'sync_problem';\r\n }\r\n return '';\r\n });\r\n\r\n var getProjectNodeLimitExceededIcon = (data, IsNodeExceeded, maxNoOfNodes) => renderIconButton(function () {\r\n if (IsNodeExceeded) {\r\n return 'error';\r\n }\r\n return htmlEncode(data);\r\n });\r\n\r\n var getDeviceStateIcon = (deviceState) => renderIconButton(function () {\r\n if (deviceState === 0 || deviceState === 1) {\r\n return 'fiber_manual_record';\r\n } else if (deviceState === 2) {\r\n return 'warning';\r\n }\r\n return '';\r\n });\r\n\r\n var getDeviceBatteryIcon = (batteryLevel, batteryValue) => renderIconButton(function () {\r\n if (batteryLevel === 1 && batteryValue !== null) {\r\n return 'battery_full';\r\n } else if (batteryLevel === 2 && batteryValue !== null) {\r\n return 'battery_0_bar';\r\n } else if (batteryLevel === 3 && batteryValue !== null) {\r\n return 'battery_alert';\r\n }\r\n return '';\r\n });\r\n\r\n var getDeviceRssiIcon = (rssiLevel, rssiValue) => renderIconButton(function () {\r\n if (rssiLevel === 1 && rssiValue !== null) {\r\n return 'signal_wifi_statusbar_4_bar';\r\n } else if (rssiLevel === 2 && rssiValue !== null) {\r\n return 'network_wifi_3_bar';\r\n } else if (rssiLevel === 3 && rssiValue !== null) {\r\n return 'network_wifi_1_bar';\r\n } else if (rssiLevel === 4 && rssiValue !== null) {\r\n return 'signal_wifi_statusbar_null';\r\n }\r\n return '';\r\n })\r\n\r\n var getDeviceSamplingRateIcon = (srStatus) => renderIconButton(function () {\r\n if (srStatus === 1) {\r\n return 'hourglass_full';\r\n }\r\n return '';\r\n });\r\n\r\n var convertRssiToRssiLevel = function (value) {\r\n if (value >= -80)\r\n return { color: \"#00ff00\", status: Resources.SnapeHelperScriptsJS.RssiStable };\r\n else if (value < -80 && value >= -90)\r\n return { color: \"#ffff00\", status: Resources.SnapeHelperScriptsJS.RssiNotGood };\r\n else if (value < -90 && value >= -100)\r\n return { color: \"#ff9355\", status: Resources.SnapeHelperScriptsJS.RssiBad };\r\n else\r\n return { color: \"#ff0000\", status: Resources.SnapeHelperScriptsJS.RssiLost };\r\n };\r\n\r\n var getDeviceUpdateStatusIcon = (deviceStatus) => renderIconButton(function () {\r\n if (deviceStatus === 1) {\r\n return 'cloud_sync';\r\n }\r\n\r\n if (deviceStatus === 2) {\r\n return 'cloud_sync';\r\n }\r\n if (deviceStatus === 3) {\r\n return 'cloud_sync';\r\n }\r\n return '';\r\n });\r\n\r\n var getRepeaterNodeIcon = (isNodeARepeater) => renderIconButton(function () {\r\n if (isNodeARepeater === true) {\r\n return 'repeat';\r\n }\r\n return '';\r\n });\r\n\r\n return {\r\n htmlEncode: htmlEncode,\r\n getNodeErrorIcon: getNodeErrorIcon,\r\n getDeviceRssiIcon: getDeviceRssiIcon,\r\n getDeviceStateIcon: getDeviceStateIcon,\r\n getDeviceBatteryIcon: getDeviceBatteryIcon,\r\n getDeviceSamplingRateIcon: getDeviceSamplingRateIcon,\r\n convertRssiToRssiLevel: convertRssiToRssiLevel,\r\n getDeviceUpdateStatusIcon: getDeviceUpdateStatusIcon,\r\n getfirmwareMismatchErrorIcon: getfirmwareMismatchErrorIcon,\r\n getProjectNodeLimitExceededIcon: getProjectNodeLimitExceededIcon,\r\n getRepeaterNodeIcon: getRepeaterNodeIcon\r\n };\r\n});\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.UnitTypes\", function () {\r\n \"use strict\";\r\n\r\n var htmlEncode = function (data) {\r\n // \"trick\" to HTML encode data from JS--essentially dip it in a
and pull it out again\r\n return data || data === 0 ? $('
').text(data).html() : null;\r\n };\r\n\r\n var getUnitSymbol = function (unitType, reading) {\r\n if (unitType === 1) {\r\n return reading + \"°\";//\"\" + reading + \"°\";\r\n } else if (unitType === 2) {\r\n return reading + \" Hz\";\r\n } else if (unitType === 3) {\r\n return reading + \" micro\";//\" µ\";\r\n } else if (unitType === 4) {\r\n return reading + \" V\";\r\n } else if (unitType === 5) {\r\n return reading + \" mA\";\r\n } else if (unitType === 6) {\r\n return reading + \" °C\"; //\" ℃\";\r\n } else if (unitType === 7) {\r\n return reading + \" mV\";\r\n } else if (unitType === 8) {\r\n return reading + \" kN\";\r\n } else if (unitType === 9) {\r\n return reading + \" Digits\";\r\n } else if (unitType === 10) {\r\n return reading + \" Ω\";//Ω\r\n } else if (unitType === 11) {\r\n return reading + \" %\";\r\n } else if (unitType === 12) {\r\n return reading + \" mV/V\";\r\n } else if (unitType === 13) {\r\n return reading + \" t\";\r\n } else if (unitType === 14) {\r\n return reading + \" mm\";\r\n } else if (unitType === 15) {\r\n return reading + \" MPa\";\r\n } else if (unitType === 16) {\r\n return reading + \" kPa\";\r\n } else if (unitType === 17) {\r\n return reading + \" m\";\r\n } else if (unitType === 18) {\r\n return reading + \" Sinα\";\r\n } else if (unitType === 19) {\r\n return reading + \" %RH\";\r\n } else if (unitType === 20) {\r\n return reading + \" kSinα\";\r\n } else if (unitType === 21) {\r\n return reading + \" 20kSinα\";\r\n } else if (unitType === 22) {\r\n return reading + \" mm/m\";\r\n } else if (unitType === 23) {\r\n return reading + \" mH2O\";\r\n } else if (unitType === 24) {\r\n return reading + \" pulse\";\r\n } else if (unitType === 25) {\r\n return reading + \" pa\";\r\n } else if (unitType === 26) {\r\n return reading + \" dS/m\";\r\n } else if (unitType === 27) {\r\n return reading + \" raw\";\r\n } else if (unitType === 28) {\r\n return reading + \" count\";\r\n } else if (unitType === 29) {\r\n return reading + \" in\";\r\n } else if (unitType === 30) {\r\n return reading + \" mbar\";\r\n } else if (unitType === 31) {\r\n return reading + \" psi\";\r\n } else if (unitType === 32) {\r\n return reading + \" psi/°C\";\r\n }\r\n return htmlEncode(reading);\r\n };\r\n\r\n return {\r\n htmlEncode: htmlEncode,\r\n getUnitSymbol: getUnitSymbol\r\n };\r\n});\r\n\r\n$(function () {\r\n \"use strict\";\r\n\r\n $(document).on(\"click\", \".button_copy\", function () {\r\n var textboxId = $(this).data('id');\r\n SnapeApp.Helpers.Highlight.highlightText(textboxId);\r\n });\r\n\r\n /* tooltip */\r\n //$(document).tooltip({\r\n // hide: false,\r\n // show: false\r\n //});\r\n var copy;\r\n $(document).on(\"mouseover\", \".button_copy\", function () {\r\n var inputSelector = '#' + $(this).data('id');\r\n copy = baseLayoutResources.clickToSelectAll;\r\n $(inputSelector).siblings().attr('title', copy);\r\n });\r\n $(document).on(\"click\", \".button_copy\", function () {\r\n var inputSelector = \".ui-tooltip-content\";\r\n var isMac = (navigator.userAgent.toUpperCase().indexOf(\"MAC\") !== -1);\r\n if (isMac) {\r\n copy = baseLayoutResources.commandCToCopy;\r\n }\r\n else {\r\n copy = baseLayoutResources.controlCToCopy;\r\n }\r\n $(inputSelector).html(copy);\r\n });\r\n\r\n //Catch any ajax call that has a 401 status and\r\n //take the user to the sign-in page\r\n $(document).ajaxError(function (e, xhr, settings) {\r\n if (xhr.status === 401 || xhr.status === 403) {\r\n window.location = '/Account/Login?isSessionTimeOut=true';\r\n }\r\n });\r\n\r\n SnapeApp.Helpers.Dates.localizeDates();\r\n\r\n}, baseLayoutResources);\r\n\r\n$(document).ready(function () {\r\n $('[data-toggle=\"tooltip\"]').tooltip();\r\n});\r\n\r\n// this module is used frequently in SummarySetupJS in accordance with the Summary.cshtml view.\r\nSnapeApp.createModule(\"SnapeApp.Helpers.channelType\", function () {\r\n \"use strict\";\r\n\r\n // localize typeNames for the inner channels.\r\n var getChannelType = function (typeName) {\r\n typeName = typeName.toUpperCase();\r\n var typeValue;\r\n if (typeName === \"NONE\") {\r\n typeValue = \"0\";\r\n } else if (typeName === \"A\") {\r\n typeValue = \"1\";\r\n } else if (typeName === \"B\") {\r\n typeValue = \"2\";\r\n } else if (typeName === \"TEMPERATURE\") {\r\n typeValue = \"3\";\r\n } else if (typeName === \"VIRTUAL\") {\r\n typeValue = \"4\";\r\n }\r\n return typeValue;\r\n };\r\n\r\n return {\r\n getChannelType: getChannelType\r\n };\r\n});\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.DataUploadType\", function () {\r\n \"use strict\";\r\n\r\n var getDataUploadTypeName = function (dataUploadType) {\r\n var typeName = \"\";\r\n if (dataUploadType === 0) {\r\n typeName = \"LOCAL\";\r\n } else if (dataUploadType === 1) {\r\n typeName = \"API\";\r\n } else if (dataUploadType === 2) {\r\n typeName = \"FTP\";\r\n } else if (dataUploadType === 3) {\r\n typeName = \"ACKCIO CLOUD\";\r\n }\r\n return typeName;\r\n };\r\n\r\n return {\r\n getDataUploadTypeName: getDataUploadTypeName\r\n };\r\n});\r\n\r\n// module used in conjunction with MapPane.js to call and load maps.\r\nSnapeApp.createModule(\"SnapeApp.Helpers.Internet\", function () {\r\n \"use strict\";\r\n\r\n function getTestUrl() {\r\n return new Promise((res, reject) => {\r\n $.ajax({\r\n method: \"get\",\r\n url: \"/api/gateway/testInternetUrl\",\r\n success: (data) => {\r\n res(data)\r\n },\r\n error: () => {\r\n reject(new Error('error'))\r\n }\r\n });\r\n })\r\n }\r\n\r\n function timeoutRequest(ms, promise) {\r\n return new Promise((resolve, reject) => {\r\n const timer = setTimeout(() => {\r\n reject(new Error('TIMEOUT'))\r\n }, ms)\r\n\r\n promise\r\n .then(value => {\r\n clearTimeout(timer)\r\n resolve(value)\r\n })\r\n .catch(reason => {\r\n clearTimeout(timer)\r\n reject(reason)\r\n })\r\n })\r\n }\r\n\r\n var runOnlyWithInternet = function (thenFunction, timeout = 10000, errorFunction) {\r\n if (navigator.onLine) {\r\n timeoutRequest(timeout, getTestUrl().then((url) => {\r\n return fetch(`https://${url}`, { // Check for internet connectivity\r\n mode: 'no-cors',\r\n })\r\n })).then(() => {\r\n thenFunction(true);\r\n return true\r\n }).catch(() => {\r\n errorFunction()\r\n })\r\n } else {\r\n errorFunction();\r\n }\r\n };\r\n\r\n let retryCount = 0;\r\n let maxRetryAttempts = 3;\r\n let retryInterval = 300000; // 5 minutes interval when reachable\r\n let shortRetryInterval = 60000; // 1 minute interval when uncreachable\r\n let isGatewayReachable = false;\r\n let intervalId;\r\n var checkIfGatewayIsReachable = function () {\r\n $.ajax({\r\n type: \"GET\",\r\n url: \"/api/gateway/reachability\",\r\n async: true,\r\n success: function (response) {\r\n if (isGatewayReachable) {\r\n toastr.clear();\r\n clearInterval(intervalId);\r\n intervalId = setInterval(checkIfGatewayIsReachable, retryInterval);\r\n }\r\n },\r\n error: function () {\r\n if (retryCount < maxRetryAttempts) {\r\n retryCount++;\r\n setTimeout(checkIfGatewayIsReachable, 5000); // Retry every 5 seconds when the gateway is unreachable\r\n isGWPrevUnreachable = true;\r\n } else {\r\n if (!isGatewayReachable) {\r\n SnapeApp.Helpers.UIOperations.showGatewayConnection(Resources.SnapeHelperScriptsJS.GatewayConnectionLost, \"toast-bottom-left\");\r\n clearInterval(intervalId);\r\n intervalId = setInterval(checkIfGatewayIsReachable, shortRetryInterval);\r\n }\r\n isGatewayReachable = true;\r\n }\r\n }\r\n });\r\n };\r\n\r\n intervalId = setInterval(checkIfGatewayIsReachable, retryInterval);\r\n\r\n return {\r\n runOnlyWithInternet: runOnlyWithInternet,\r\n checkIfGatewayIsReachable: checkIfGatewayIsReachable\r\n };\r\n});\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.RegularExpression\", function () {\r\n \"use strict\";\r\n\r\n var getRegex = function (type) {\r\n type = type.toLowerCase();\r\n if (type === \"deviceid\")\r\n return /[^a-fA-F0-9]/;\r\n else if (type === \"devicename\")\r\n return /[\\/\\\\?*:|\"<>`]/;\r\n else if (type === \"sensorcode\")\r\n return /[\\/\\\\?*:|\"<>`]/;\r\n else if (type === \"sensorgroup\")\r\n return /[\\/\\\\?*:|\"<>`]/;\r\n else if (type === \"apiurl\" || type === \"url\")\r\n return /^(((?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]|[0-9])\\.(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]|[0-9])\\.)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]|[0-9])\\.)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]|[0-9]))|(?:(?:(?:\\w+\\.){1,2}[\\w]{2,3})))(?::(\\d+))?((?:\\/[\\w]+)*)(?:\\/|(\\/[\\w]+\\.[\\w]{3,4})|(\\?(?:([\\w]+=[\\w]+)&)*([\\w]+=[\\w]+))?|\\?(?:(wsdl|wadl))))$/;\r\n else if (type === \"aeskey\")\r\n return /[^a-fA-F0-9]/;\r\n else if (type === \"ip\")\r\n return /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\r\n else if (type === \"pin\")\r\n return /^[0-9]+$/;\r\n };\r\n\r\n return {\r\n getRegex: getRegex\r\n };\r\n});\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.UIOperations\", function () {\r\n \"use strict\";\r\n var timeout = 5000;\r\n var hideModal = function (modal, timeout) {\r\n if (timeout !== undefined || timeout !== null)\r\n timeout = 3000;\r\n setTimeout(function () { modal.modal('hide'); }, timeout);\r\n };\r\n\r\n var showMessage = function (message, isSuccess, location, target) {\r\n var opts = {\r\n \"closeButton\": true,\r\n \"positionClass\": location,\r\n \"onclick\": null,\r\n \"showDuration\": \"300\",\r\n \"hideDuration\": \"1000\",\r\n \"timeOut\": timeout.toString(),\r\n \"extendedTimeOut\": \"1000\",\r\n \"showEasing\": \"swing\",\r\n \"hideEasing\": \"linear\",\r\n \"showMethod\": \"fadeIn\",\r\n \"hideMethod\": \"fadeOut\",\r\n target\r\n };\r\n\r\n if (isSuccess)\r\n toastr.success(message, \"\", opts);\r\n else\r\n toastr.error(message, \"\", opts);\r\n };\r\n\r\n var showPersistentMessage = function (message, isSuccess, location) {\r\n var opts = {\r\n \"closeButton\": true,\r\n \"positionClass\": location,\r\n \"onclick\": null,\r\n \"showDuration\": \"300\",\r\n \"hideDuration\": \"1000\",\r\n \"timeOut\": \"0\", //message will not dissapear unless user click/hover the message\r\n \"extendedTimeOut\": \"1000\",\r\n \"showEasing\": \"swing\",\r\n \"hideEasing\": \"linear\",\r\n \"showMethod\": \"fadeIn\",\r\n \"hideMethod\": \"fadeOut\"\r\n };\r\n\r\n if (isSuccess)\r\n toastr.success(message, \"\", opts);\r\n else\r\n toastr.error(message, \"\", opts);\r\n };\r\n\r\n var showInfo = function (message, location) {\r\n let showInfoOpts = {\r\n \"closeButton\": true,\r\n \"debug\": false,\r\n \"positionClass\": location,\r\n \"onclick\": null,\r\n \"showDuration\": \"300\",\r\n \"hideDuration\": \"1000\",\r\n \"timeOut\": \"0\",\r\n \"extendedTimeOut\": \"0\",\r\n \"showEasing\": \"swing\",\r\n \"hideEasing\": \"linear\",\r\n \"showMethod\": \"fadeIn\",\r\n \"hideMethod\": \"fadeOut\"\r\n };\r\n\r\n toastr.info(message, \"\", showInfoOpts);\r\n };\r\n\r\n var showGatewayConnection = function (message, location) {\r\n var opts = {\r\n \"closeButton\": false,\r\n \"positionClass\": location,\r\n \"onclick\": null,\r\n \"showDuration\": \"300\",\r\n \"hideDuration\": \"1000\",\r\n \"timeOut\": \"0\",\r\n \"extendedTimeOut\": \"1000\",\r\n \"showEasing\": \"swing\",\r\n \"hideEasing\": \"linear\",\r\n \"showMethod\": \"fadeIn\",\r\n \"hideMethod\": \"fadeOut\"\r\n };\r\n toastr.warning(message, \"\", opts);\r\n };\r\n\r\n return {\r\n hideModal: hideModal,\r\n showMessage: showMessage,\r\n showPersistentMessage: showPersistentMessage,\r\n showGatewayConnection: showGatewayConnection,\r\n showInfo: showInfo,\r\n timeout: timeout\r\n };\r\n});\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.BrowserUtil\", function () {\r\n \"use strict\";\r\n\r\n function isSafari() {\r\n return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\r\n }\r\n\r\n return {\r\n isSafari\r\n };\r\n});\r\n\r\n// setupFlags() and setCurrentCulture methods that will show country flags and configure the dropdown to always show the current culture first\r\nSnapeApp.createModule(\"SnapeApp.Helpers.Localization\", function () {\r\n \"use strict\";\r\n\r\n // function to set up the option tags for use with msdropdown plugin. \r\n var setupFlags = function (dropdown) {\r\n var countryValue;\r\n var culture;\r\n var selector = document.getElementById(dropdown);\r\n var x = \"\";\r\n\r\n\r\n // iterate through the dropdown and add a country flag based on the country code value for each option in the culture-dropdown selection element...\r\n $(\"#\" + dropdown + \" option\").each(function () {\r\n countryValue = $(this).val(); // grab the dropdown value, which will be used to find the matching flag.\r\n culture = $(this).text(); // grab the dropdown text\r\n // rewrite the current option element to include the blank gif, adorned with the flag (css class) that matches the option tag's countryValue.\r\n // Keep the original inner text of the culture.\r\n //x += \"\";\r\n x += \"\";\r\n\r\n });\r\n // when the loop finishes, set the innerHTML of the dropdown to the new option tags.\r\n selector.innerHTML = x;\r\n };\r\n\r\n // function to set the msdropdown selection element to the current culture. Uses the same AJAX method used to get the culture for google maps, \r\n // and a numeric culture - number dictionary\r\n var setCurrentCulture = function (dropdown, isTrimmedLabel) {\r\n // dictionary with numeric values corresponding to a culture.\r\n // One of these will be used on every page load to ensure the selectedIndex value of msdropdown points at the current culture of the page.\r\n var culturedictionary = {\r\n 'en-AU': 0,\r\n 'es-ES': 1,\r\n 'pt-PT': 2,\r\n 'ja-JP': 3,\r\n 'zh-Hans': 4\r\n //'ko-KR': 1, //disable korean until translation is verified\r\n };\r\n // we need to grab the current culture so we can determine what option to show as selected in the msdropdown so we use our handy-dandy ajax method...\r\n $.ajax({\r\n type: \"GET\", // we are getting the culture of the page.\r\n url: '/api/project/culture', // routes to GetCulture() in ProjectApiController.cs\r\n contentType: \"application/json; charset=utf-8\",\r\n datatype: \"json\", // return json.\r\n // on success...\r\n success: function (data) {\r\n if (isTrimmedLabel === true) {\r\n dropdown.val(data);\r\n window.snapeCultureInfo = data;\r\n } else {\r\n var countryOption = culturedictionary[data]; // get the numeric value corresponding to our current culture , en-US = 0,\r\n dropdown.set(\"selectedIndex\", countryOption); // plugin method to set the dropdown to the numeric value (matching the index of an option tag in the dropdown) returned from the culturedictionary.\r\n\r\n $(\"#\" + dropdown.id + \"_msdd\").css(\"opacity\", 1);\r\n $(\"#\" + dropdown.id + \"_titleText\").remove();\r\n }\r\n }\r\n });\r\n };\r\n\r\n function getCulture() {\r\n var properCulture;\r\n // quick ajax call to grab the language.\r\n $.ajax({\r\n type: \"GET\", // we are getting the culture of the page.\r\n async: false, // async being set to false is necessary to run the AJAX call immediately, otherwise, the dataTable will be constructed before properCulture is set and it won't change the language of the UI.\r\n url: '/api/project/culture', // url routes to GetCulture() in ProjectApiController.cs\r\n datatype: \"json\", // return json.\r\n // on success...\r\n success: function (data) {\r\n // determine culture from culture code.\r\n // add to this as more cultures are added.\r\n if (data === \"en-AU\") {\r\n properCulture = \"English\"; // make properCulture global so it actually saves the change for use in the dataTable below.\r\n }\r\n else if (data === \"ko-KR\") {\r\n properCulture = \"Korean\";\r\n }\r\n else if (data == \"es-ES\") {\r\n properCulture = \"Spanish\";\r\n }\r\n else if (data == \"pt-PT\") {\r\n properCulture = \"Portuguese\";\r\n } else if (data == \"ja-JP\") {\r\n properCulture = \"Japanese\";\r\n } else if (data == \"zh-Hans\") {\r\n properCulture = \"Chinese\";\r\n }\r\n },\r\n error: function (data) {\r\n properCulture = \"English\"; // default to English\r\n }\r\n });\r\n return properCulture;\r\n }\r\n\r\n function parseStringTemplate(str, obj) {\r\n let parts = str.split(/\\$\\{(?!\\d)[\\wæøåÆØÅ]*\\}/);\r\n let args = str.match(/[^{\\}]+(?=})/g) || [];\r\n let parameters = args.map(argument => obj[argument] || (obj[argument] === undefined ? \"\" : obj[argument]));\r\n return String.raw({ raw: parts }, ...parameters);\r\n }\r\n\r\n return {\r\n setupFlags: setupFlags,\r\n getCulture: getCulture,\r\n setCurrentCulture: setCurrentCulture,\r\n parseStringTemplate: parseStringTemplate\r\n };\r\n});\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.Mapbox\", function () {\r\n \"use strict\";\r\n const style = {\r\n \"version\": 8,\r\n \"sources\": {\r\n \"countries\": {\r\n \"type\": \"vector\",\r\n \"tiles\": [location.origin + \"/lib/mapbox/countries/{z}/{x}/{y}.pbf\"],\r\n \"maxzoom\": 6\r\n }\r\n },\r\n \"glyphs\": location.origin + \"/lib/mapbox/font/{fontstack}/{range}.pbf\",\r\n \"layers\": [\r\n {\r\n \"id\": \"background\",\r\n \"type\": \"background\",\r\n \"paint\": {\r\n \"background-color\": \"#ddeeff\"\r\n }\r\n }, {\r\n \"id\": \"country-glow-outer\",\r\n \"type\": \"line\",\r\n \"source\": \"countries\",\r\n \"source-layer\": \"country\",\r\n \"layout\": {\r\n \"line-join\": \"round\"\r\n },\r\n \"paint\": {\r\n \"line-color\": \"#226688\",\r\n \"line-width\": 5,\r\n \"line-opacity\": {\r\n \"stops\": [[0, 0], [1, 0.1]]\r\n }\r\n }\r\n }, {\r\n \"id\": \"country-glow-inner\",\r\n \"type\": \"line\",\r\n \"source\": \"countries\",\r\n \"source-layer\": \"country\",\r\n \"layout\": {\r\n \"line-join\": \"round\"\r\n },\r\n \"paint\": {\r\n \"line-color\": \"#226688\",\r\n \"line-width\": {\r\n \"stops\": [[0, 1.2], [1, 1.6], [2, 2], [3, 2.4]]\r\n },\r\n \"line-opacity\": 0.8\r\n }\r\n // rainbow start\r\n }, {\r\n \"id\": \"area-white\",\r\n \"type\": \"fill\",\r\n \"source\": \"countries\",\r\n \"filter\": [\"in\", \"ADM0_A3\", 'ATA', 'GRD', 'GRL'],\r\n \"source-layer\": \"country\",\r\n \"paint\": {\r\n \"fill-color\": \"#f5f5f5\"\r\n }\r\n }, {\r\n \"id\": \"area-red\",\r\n \"type\": \"fill\",\r\n \"source\": \"countries\",\r\n \"filter\": [\"in\", \"ADM0_A3\", 'AFG', 'ALD', 'BEN', 'BLR', 'BWA', 'COK', 'COL', 'DNK', 'DOM', 'ERI', 'FIN', 'FRA', 'FRO', 'GIB', 'GNB', 'GNQ', 'GRC', 'GTM', 'JPN', 'KIR', 'LKA', 'MHL', 'MMR', 'MWI', 'NCL', 'OMN', 'RWA', 'SMR', 'SVK', 'SYR', 'TCD', 'TON', 'URY', 'WLF',\r\n 'AZE', 'BGD', 'CHL', 'CMR', 'CSI', 'DEU', 'DJI', 'GUY', 'HUN', 'IOA', 'JAM', 'LBN', 'LBY', 'LSO', 'MDG', 'MKD', 'MNG', 'MRT', 'NIU', 'NZL', 'PCN', 'PYF', 'SAU', 'SHN', 'STP', 'TTO', 'UGA', 'UZB', 'ZMB',\r\n 'AGO', 'ASM', 'ATF', 'BDI', 'BFA', 'BGR', 'BLZ', 'BRA', 'CHN', 'CRI', 'ESP', 'HKG', 'HRV', 'IDN', 'IRN', 'ISR', 'KNA', 'LBR', 'LCA', 'MAC', 'MUS', 'NOR', 'PLW', 'POL', 'PRI', 'SDN', 'TUN', 'UMI', 'USA', 'USG', 'VIR', 'VUT',\r\n 'ARE', 'ARG', 'BHS', 'CIV', 'CLP', 'DMA', 'ETH', 'GAB', 'HMD', 'IND', 'IOT', 'IRL', 'IRQ', 'ITA', 'KOS', 'LUX', 'MEX', 'NAM', 'NER', 'PHL', 'PRT', 'RUS', 'SEN', 'SUR', 'TZA', 'VAT',\r\n 'AUT', 'BEL', 'BHR', 'BMU', 'BRB', 'CYN', 'DZA', 'EST', 'FLK', 'GMB', 'GUM', 'HND', 'JEY', 'KGZ', 'LIE', 'MAF', 'MDA', 'NGA', 'NRU', 'SLB', 'SOL', 'SRB', 'SWZ', 'THA', 'TUR', 'VEN', 'VGB',\r\n 'AIA', 'BIH', 'BLM', 'BRN', 'CAF', 'CHE', 'COM', 'CPV', 'CUB', 'ECU', 'ESB', 'FSM', 'GAZ', 'GBR', 'GEO', 'KEN', 'LTU', 'MAR', 'MCO', 'MDV', 'NFK', 'NPL', 'PNG', 'PRY', 'QAT', 'SLE', 'SPM', 'SYC', 'TCA', 'TKM', 'TLS', 'VNM', 'WEB', 'WSB', 'YEM', 'ZWE',\r\n 'ABW', 'ALB', 'AND', 'ATC', 'BOL', 'COD', 'CUW', 'CYM', 'CYP', 'EGY', 'FJI', 'GGY', 'IMN', 'KAB', 'KAZ', 'KWT', 'LAO', 'MLI', 'MNP', 'MSR', 'MYS', 'NIC', 'NLD', 'PAK', 'PAN', 'PRK', 'ROU', 'SGS', 'SVN', 'SWE', 'TGO', 'TWN', 'VCT', 'ZAF',\r\n 'ARM', 'ATG', 'AUS', 'BTN', 'CAN', 'COG', 'CZE', 'GHA', 'GIN', 'HTI', 'ISL', 'JOR', 'KHM', 'KOR', 'LVA', 'MLT', 'MNE', 'MOZ', 'PER', 'SAH', 'SGP', 'SLV', 'SOM', 'TJK', 'TUV', 'UKR', 'WSM'\r\n ],\r\n \"source-layer\": \"country\",\r\n \"paint\": {\r\n \"fill-color\": \"#e4eccf\"\r\n }\r\n }, {\r\n \"id\": \"geo-lines\",\r\n \"type\": \"line\",\r\n \"source\": \"countries\",\r\n \"source-layer\": \"geo-lines\",\r\n \"paint\": {\r\n \"line-color\": \"#226688\",\r\n \"line-width\": {\r\n \"stops\": [[0, 0.2], [4, 1]]\r\n },\r\n \"line-dasharray\": [6, 2]\r\n }\r\n }, {\r\n \"id\": \"land-border-country\",\r\n \"type\": \"line\",\r\n \"source\": \"countries\",\r\n \"source-layer\": \"land-border-country\",\r\n \"paint\": {\r\n \"line-color\": \"#fff\",\r\n \"line-width\": {\r\n \"base\": 1.5,\r\n \"stops\": [[0, 0], [1, 0.8], [2, 1]]\r\n }\r\n }\r\n }, {\r\n \"id\": \"state\",\r\n \"type\": \"line\",\r\n \"source\": \"countries\",\r\n \"source-layer\": \"state\",\r\n \"minzoom\": 3,\r\n \"filter\": [\"in\", \"ADM0_A3\", 'USA', 'CAN', 'AUS'],\r\n \"paint\": {\r\n \"line-color\": \"#226688\",\r\n \"line-opacity\": 0.25,\r\n \"line-dasharray\": [6, 2, 2, 2],\r\n \"line-width\": 1.2\r\n }\r\n // LABELS\r\n }, {\r\n \"id\": \"country-abbrev\",\r\n \"type\": \"symbol\",\r\n \"source\": \"countries\",\r\n \"source-layer\": \"country-name\",\r\n \"minzoom\": 1.8,\r\n \"maxzoom\": 3,\r\n \"layout\": {\r\n \"text-field\": \"{ABBREV}\",\r\n \"text-font\": [\"Open Sans Semibold\"],\r\n \"text-transform\": \"uppercase\",\r\n \"text-max-width\": 20,\r\n \"text-size\": {\r\n \"stops\": [[3, 10], [4, 11], [5, 12], [6, 16]]\r\n },\r\n \"text-letter-spacing\": {\r\n \"stops\": [[4, 0], [5, 1], [6, 2]]\r\n },\r\n \"text-line-height\": {\r\n \"stops\": [[5, 1.2], [6, 2]]\r\n }\r\n },\r\n \"paint\": {\r\n \"text-halo-color\": \"#fff\",\r\n \"text-halo-width\": 1.5\r\n }\r\n }, {\r\n \"id\": \"country-name\",\r\n \"type\": \"symbol\",\r\n \"source\": \"countries\",\r\n \"source-layer\": \"country-name\",\r\n \"minzoom\": 3,\r\n \"layout\": {\r\n \"text-field\": \"{NAME}\",\r\n \"text-font\": [\"Open Sans Semibold\"],\r\n \"text-transform\": \"uppercase\",\r\n \"text-max-width\": 20,\r\n \"text-size\": {\r\n \"stops\": [[3, 10], [4, 11], [5, 12], [6, 16]]\r\n }\r\n },\r\n \"paint\": {\r\n \"text-halo-color\": \"#fff\",\r\n \"text-halo-width\": 1.5\r\n }\r\n }, {\r\n \"id\": \"geo-lines-lables\",\r\n \"type\": \"symbol\",\r\n \"source\": \"countries\",\r\n \"source-layer\": \"geo-lines\",\r\n \"minzoom\": 1,\r\n \"layout\": {\r\n \"text-field\": \"{DISPLAY}\",\r\n \"text-font\": [\"Open Sans Semibold\"],\r\n \"text-offset\": [0, 1],\r\n \"symbol-placement\": \"line\",\r\n \"symbol-spacing\": 600,\r\n \"text-size\": 9\r\n },\r\n \"paint\": {\r\n \"text-color\": \"#226688\",\r\n \"text-halo-width\": 1.5\r\n }\r\n }\r\n ]\r\n };\r\n const defaultLngLat = [103.8198, 1.3521];\r\n function toggleLocationInputButton() {\r\n ($('#searchByLatLong').is(':checked')) ? $(\"#appendLocationButton\").show() : $(\"#appendLocationButton\").hide();\r\n }\r\n\r\n const getApiMapboxGeocodingUrl = (location, token) => {\r\n return \"https://api.mapbox.com/geocoding/v5/mapbox.places/\" + location + \".json?access_token=\" + token\r\n }\r\n\r\n return {\r\n OfflineStyle: style,\r\n toggleLocationInputButton: toggleLocationInputButton,\r\n defaultLngLat: defaultLngLat,\r\n getApiMapboxGeocodingUrl\r\n };\r\n});\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.Highchart\", function () {\r\n\r\n // list of available date format\r\n const dateTimeFormat = [{\r\n format: 'YYYY/MM/DD HH:mm:ss',\r\n highChartFormat: '%Y/%m/%d'\r\n },\r\n {\r\n format: 'DD/MM/YYYY HH:mm:ss',\r\n highChartFormat: '%d/%m/%Y'\r\n },\r\n {\r\n format: 'YYYY-MM-DD HH:mm:ss',\r\n highChartFormat: '%Y-%m-%d'\r\n }]\r\n\r\n // helper to convert ackcio date format to highchart date format\r\n const getDateTimeFormat = (localDateTimeFormatValue) => {\r\n const format = dateTimeFormat.find((dateTime) => dateTime.format === localDateTimeFormatValue)\r\n return format ? format.highChartFormat : dateTimeFormat[0].highChartFormat\r\n }\r\n\r\n return {\r\n getDateTimeFormat\r\n };\r\n});\r\n\r\nSnapeApp.createModule(\"SnapeApp.Helpers.Input\", function () {\r\n function onlyAllowNumberAndDot(evt) {\r\n var theEvent = evt || window.event;\r\n var key = theEvent.keyCode || theEvent.which;\r\n key = String.fromCharCode(key);\r\n\r\n // Allow digits, decimal point, exponent, plus/minus sign\r\n // Allow backspace (key code 8), tab (key code 9), and arrow keys (key codes 37, 38, 39, 40)\r\n // Allow Ctrl+C (copy), Ctrl+V (paste), and Ctrl+A (select all)\r\n\r\n var keyCode = theEvent.keyCode;\r\n var ctrlKey = theEvent.ctrlKey;\r\n var shiftKey = theEvent.shiftKey;\r\n \r\n // Allow digits, decimal point, exponent, plus/minus sign\r\n var isValidKey = /^[\\d.eE+-]$/.test(evt.key);\r\n \r\n // Allow backspace (key code 8), tab (key code 9), and arrow keys (key codes 37, 38, 39, 40)\r\n var isControlKey = keyCode === 8 || keyCode === 9 || (keyCode >= 37 && keyCode <= 40);\r\n \r\n // Allow Ctrl+C (copy), Ctrl+V (paste), and Ctrl+A (select all)\r\n var isCtrlCombination = ctrlKey && (keyCode === 67 || keyCode === 86 || keyCode === 65);\r\n \r\n // Allow Shift and + (plus sign)\r\n var isShiftPlus = shiftKey && keyCode === 187;\r\n\r\n // current value\r\n var value = evt.target.value;\r\n \r\n let inputEl = evt.target;\r\n\r\n let start = inputEl.selectionStart;\r\n let end = inputEl.selectionEnd;\r\n \r\n let currentValue = inputEl.value;\r\n\r\n if (!(isCtrlCombination || isControlKey) || (shiftKey && key === '+')) {\r\n // update to updated value based on latest user input\r\n value = currentValue.slice(0, start) + evt.key + currentValue.slice(end);\r\n }\r\n\r\n // Get the value of the input field\r\n var input = value.replace(/^\\s+|\\s+$/gm, '')\r\n\r\n // Regular expression to allow only numbers, a single dot, 'e' or 'E', '+' and minus sign\r\n // valid: +2.22, -2.22, 2.22e-10, -2.22e+10\r\n var regex = /^[+-]?$|^[+-]?(\\d+(\\.\\d*)?|\\.\\d+)([eE][+-]?\\d*)?$/;\r\n\r\n // check if keyCode is valid\r\n var validKey = (isValidKey || isControlKey || isCtrlCombination || isShiftPlus);\r\n\r\n if (!validKey) {\r\n theEvent.returnValue = false;\r\n if (theEvent.preventDefault) theEvent.preventDefault();\r\n }\r\n\r\n if ((validKey && input && !input.match(regex))) {\r\n theEvent.returnValue = false;\r\n if (theEvent.preventDefault) theEvent.preventDefault();\r\n }\r\n\r\n }\r\n\r\n function onlyPasteValidNumber(e) {\r\n // Prevent the default paste action\r\n e.preventDefault();\r\n\r\n // Get the pasted data\r\n let pastedData = (e.clipboardData || window.clipboardData).getData('text');\r\n\r\n // Remove non-digit characters\r\n let digitsOnly = parseFloat(pastedData.replace(',', '.'));\r\n\r\n // Insert the cleaned data into the input field\r\n document.execCommand('insertText', false, digitsOnly);\r\n }\r\n\r\n return {\r\n onlyAllowNumberAndDot,\r\n onlyPasteValidNumber\r\n };\r\n});\r\n\r\n"],"names":["SnapeApp","namespace","module","dependencies","nsparts","parent","f","innerModule","i","namespaceLength","partname","window","highlight","textBoxId","selector","$","jQuery","moment","timezone","time","Intl","datetimeformat","format","mapObj","matched","mouseEvent","callback","document","data","dFormat","timezoneUTC","epochTime","localizeDate","isDotNetTicks","currentMoment","cultureInfo","curDate","localizeDates","date","Date","utcDate","dates","getParameter","name","regex","RegExp","results","location","decodeURIComponent","ExportData","e","exportAllTime","fromDate","toDate","fromDateField","toDateField","from","to","element","IdElement","projectIdArray","projectId","timer","timeStamp","deviceId","projectName","href","cookiStringTimeout","cookieString","cookieStringFailMessage","Resources","downloadGrabber","sensorIndex","errorCookieString","renderIconButton","htmlString","htmlEncode","getNodeErrorIcon","errorState","getfirmwareMismatchErrorIcon","fwState","getProjectNodeLimitExceededIcon","IsNodeExceeded","maxNoOfNodes","getDeviceStateIcon","deviceState","getDeviceBatteryIcon","batteryLevel","batteryValue","getDeviceRssiIcon","rssiLevel","rssiValue","getDeviceSamplingRateIcon","srStatus","convertRssiToRssiLevel","value","getDeviceUpdateStatusIcon","deviceStatus","getRepeaterNodeIcon","isNodeARepeater","getUnitSymbol","unitType","reading","textboxId","copy","inputSelector","baseLayoutResources","isMac","navigator","xhr","settings","getChannelType","typeName","typeValue","getDataUploadTypeName","dataUploadType","getTestUrl","Promise","res","reject","Error","timeoutRequest","ms","promise","resolve","setTimeout","clearTimeout","reason","runOnlyWithInternet","thenFunction","timeout","errorFunction","url","fetch","retryCount","maxRetryAttempts","retryInterval","shortRetryInterval","isGatewayReachable","intervalId","checkIfGatewayIsReachable","response","toastr","clearInterval","setInterval","isGWPrevUnreachable","getRegex","type","hideModal","modal","undefined","showMessage","message","isSuccess","location1","target","opts","showPersistentMessage","showInfo","showInfoOpts","showGatewayConnection","isSafari","setupFlags","dropdown","countryValue","culture","x","setCurrentCulture","isTrimmedLabel","culturedictionary","countryOption","getCulture","properCulture","parseStringTemplate","str","obj","parts","args","parameters","argument","String","style","defaultLngLat","toggleLocationInputButton","getApiMapboxGeocodingUrl","token","dateTimeFormat","getDateTimeFormat","localDateTimeFormatValue","dateTime","onlyAllowNumberAndDot","evt","theEvent","key","keyCode","ctrlKey","shiftKey","isValidKey","isControlKey","isCtrlCombination","isShiftPlus","inputEl","start","end","currentValue","input","validKey","onlyPasteValidNumber","pastedData","digitsOnly","parseFloat"],"mappings":"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"}