\")\r\n\t\t\t\t\t.append(\r\n\t\t\t\t\t\t$j('').append(\r\n\t\t\t\t\t\t\t$j(\"\").addClass(doc.IsExpired ? \"expired\" : doc.IsAboutToExpire ? \"abouttoexpire\" : \"valid\")\r\n\t\t\t\t\t\t)\r\n\t\t\t\t\t)\r\n\t\t\t\t\t.append(\r\n\t\t\t\t\t\t$j(\" \").append(\r\n\t\t\t\t\t\t\t$j('')\r\n\t\t\t\t\t\t\t\t.text(doc.Name)\r\n\t\t\t\t\t\t\t\t.attr(\"href\", \"/uploads/fences/\" + fence.Id + \"/\" + doc.Filename)\r\n\t\t\t\t\t\t)\r\n\t\t\t\t\t)\r\n\t\t\t\t\t.append($j(\" \").text(doc.StartDate))\r\n\t\t\t\t\t.append($j(\" \").text(doc.EndDate))\r\n\t\t\t\t\t.append(\r\n\t\t\t\t\t\t$j(' ').append(\r\n\t\t\t\t\t\t\t$j('')\r\n\t\t\t\t\t\t\t\t.data(\"docId\", doc.Id)\r\n\t\t\t\t\t\t\t\t.data(\"fenceId\", fence.Id)\r\n\t\t\t\t\t\t\t\t.text(strings.DELETE)\r\n\t\t\t\t\t\t)\r\n\t\t\t\t\t);\r\n\t\t\t\t$j(\"tbody\", docs).append(row);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction findAssetsInsidePolygon(polygon) {\r\n\tvar assets = [];\r\n\tif (trkData.live.latestPositions == null) {\r\n\t\treturn assets;\r\n\t}\r\n\tvar isCircle = polygon instanceof L.Circle;\r\n\tvar radius = null;\r\n\tvar circleCenter = null;\r\n\tvar latLngs = [];\r\n\tif (isCircle) {\r\n\t\tcircleCenter = polygon.getLatLng();\r\n\t\tradius = polygon.getRadius();\r\n\t} else {\r\n\t\tlatLngs = polygon.getLatLngs();\r\n\t}\r\n\t_.each(trkData.live.latestPositions, function (pos) {\r\n\t\tif (pos.Position != null) {\r\n\t\t\tvar latLng = L.latLng(pos.Position.Lat, pos.Position.Lng);\r\n\t\t\tif (isCircle) {\r\n\t\t\t\t// circles check if latlng is within circle radius\r\n\t\t\t\tif (Math.abs(circleCenter.distanceTo(latLng)) <= radius) {\r\n\t\t\t\t\tassets.push(pos.AssetId);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t// have to use ray casting algorithm for polygons\r\n\t\t\t\tif (isLatLngInsidePolygon(latLngs[0], latLng)) {\r\n\t\t\t\t\tassets.push(pos.AssetId);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t});\r\n\treturn assets;\r\n}\r\n\r\nfunction isLatLngInsidePolygon(bounds, latLng) {\r\n\t//https://rosettacode.org/wiki/Ray-casting_algorithm\r\n\tvar count = 0;\r\n\tfor (var b = 0; b < bounds.length; b++) {\r\n\t\tvar vertex1 = bounds[b];\r\n\t\tvar vertex2 = bounds[(b + 1) % bounds.length];\r\n\t\tif (west(vertex1, vertex2, latLng.lng, latLng.lat)) ++count;\r\n\t}\r\n\treturn count % 2;\r\n\r\n\t/**\r\n\t * @return {boolean} true if (x,y) is west of the line segment connecting A and B\r\n\t */\r\n\tfunction west(A, B, x, y) {\r\n\t\tif (A.lat <= B.lat) {\r\n\t\t\tif (y <= A.lat || y > B.lat || (x >= A.lng && x >= B.lng)) {\r\n\t\t\t\treturn false;\r\n\t\t\t} else if (x < A.lng && x < B.lng) {\r\n\t\t\t\treturn true;\r\n\t\t\t} else {\r\n\t\t\t\treturn (y - A.lat) / (x - A.lng) > (B.lat - A.lat) / (B.lng - A.lng);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\treturn west(B, A, x, y);\r\n\t\t}\r\n\t}\r\n}\r\n","import trkData from \"./data.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport state from \"./state.js\";\r\nimport { clearSettingsNode } from \"./shared-view.js\";\r\nimport strings from \"./strings.js\";\r\nimport options from \"./options.js\";\r\nimport user from \"./user.js\";\r\nimport { svgPath, getSvgIconForItemType } from \"./dom-util.js\";\r\nimport { openDialogPanel } from \"./panel-nav.js\";\r\nimport { getGenericIconUrlForItemType } from \"./marker-path.js\";\r\nimport {\r\n\thighlightActiveItemInPrimaryPanel,\r\n\topenSecondaryPanel,\r\n\tchangeActivePrimaryPanelToMatchSecondary,\r\n} from \"./panel.js\";\r\nimport {\r\n\tisWaypointEnabledForAsset,\r\n\tisMessagingEnabledForAssetGroup,\r\n\tisMessagingEnabledForAsset,\r\n\tisOutputEnabledForAsset,\r\n\tisServiceMeterEnabledForAsset,\r\n\tfindAssetById,\r\n\tfindAssetIdsUnderGroup,\r\n} from \"./assets.js\";\r\nimport { findJourneyById } from \"./journey.js\";\r\nimport { findGroupById } from \"./asset-group.js\";\r\nimport { findFenceById, findAssetIdsInGeofence } from \"./fence.js\";\r\nimport { findPlaceById } from \"./place.js\";\r\nimport { findTripById } from \"./trips.js\";\r\nimport { findSharedViewById } from \"./shared-view.js\";\r\nimport { querySharedViewData } from \"./shared-view.js\";\r\nimport { checkForShareViewChange } from \"./shared-view.js\";\r\nimport { isSendCommandDisabledForDevice, findDeviceById } from \"./devices.js\";\r\nimport { isFollowingGroup } from \"./asset-live-follow.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport _ from \"lodash\";\r\n\r\nexport function itemSettingsClick(e) {\r\n\tvar li = this.parentNode.parentNode;\r\n\tif (\r\n\t\tthis.hasAttribute(\"data-asset-id\") ||\r\n\t\tthis.hasAttribute(\"data-group-id\") ||\r\n\t\tthis.hasAttribute(\"data-fence-id\") ||\r\n\t\tthis.hasAttribute(\"data-place-id\") ||\r\n\t\tthis.hasAttribute(\"data-trip-id\") ||\r\n\t\tthis.hasAttribute(\"data-shared-view-id\")\r\n\t) {\r\n\t\tli = this;\r\n\t}\r\n\tif (li.hasAttribute(\"data-asset-id\")) {\r\n\t\tvar assetId = li.getAttribute(\"data-asset-id\");\r\n\t\tvar asset = findAssetById(assetId);\r\n\t\tif (asset === null) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\topenAssetSettingsPanel(asset);\r\n\t} else if (li.hasAttribute(\"data-group-id\")) {\r\n\t\tvar groupId = li.getAttribute(\"data-group-id\");\r\n\t\tvar groupType = li.getAttribute(\"data-group-for\");\r\n\r\n\t\tif (groupType === \"journeys\") {\r\n\t\t\tvar journeyId = parseInt(groupId.substring(8));\r\n\t\t\tvar journey = findJourneyById(journeyId);\r\n\t\t\tif (journey !== null) {\r\n\t\t\t\topenJourneySettingsPanel(journey);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\tvar group = findGroupById(groupId, groupType);\r\n\t\tif (group === null) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tswitch (groupType) {\r\n\t\t\tcase \"assets\":\r\n\t\t\t\topenAssetGroupSettingsPanel(group);\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"fences\":\r\n\t\t\tcase \"places\":\r\n\t\t\t\topenGroupSettingsPanel(group);\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"shared-views\":\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t} else if (li.hasAttribute(\"data-fence-id\")) {\r\n\t\tvar fenceId = li.getAttribute(\"data-fence-id\");\r\n\t\tvar fence = findFenceById(fenceId);\r\n\t\tif (fence === null) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\topenFenceSettingsPanel(fence);\r\n\t} else if (li.hasAttribute(\"data-place-id\")) {\r\n\t\tvar placeId = li.getAttribute(\"data-place-id\");\r\n\t\tvar place = findPlaceById(placeId);\r\n\t\tif (place === null) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\topenPlaceSettingsPanel(place);\r\n\t} else if (li.hasAttribute(\"data-trip-id\")) {\r\n\t\tvar tripId = li.getAttribute(\"data-trip-id\");\r\n\t\tvar trip = findTripById(tripId);\r\n\t\tif (trip === null) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\topenTripSettingsPanel(trip);\r\n\t} else if (li.hasAttribute(\"data-shared-view-id\")) {\r\n\t\tvar sharedViewId = li.getAttribute(\"data-shared-view-id\");\r\n\t\tvar sharedView = findSharedViewById(sharedViewId);\r\n\t\tif (sharedView === null) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\topenSharedViewSettingsPanel(sharedView);\r\n\t}\r\n}\r\n\r\nexport function openSettingsPanel(type, item, isDialog) {\r\n\tvar icon = null;\r\n\tvar svgIcon = null;\r\n\tvar id = null;\r\n\t// var title = null;\r\n\r\n\tchangeActivePrimaryPanelToMatchSecondary(type);\r\n\r\n\tif (item !== null) {\r\n\t\tid = item.Id;\r\n\t\t// title = item.Name;\r\n\t\ticon = getGenericIconUrlForItemType(type, item);\r\n\t\tsvgIcon = getSvgIconForItemType(type, item);\r\n\t}\r\n\r\n\tvar panelType = isDialog ? \"dialog\" : type;\r\n\tvar panel = domNodes.panels.secondary;\r\n\tif (id !== null) {\r\n\t\tpanel.setAttribute(\"data-item-type\", type);\r\n\t\tpanel.setAttribute(\"data-item-id\", id);\r\n\t} else {\r\n\t\tpanel.removeAttribute(\"data-item-type\");\r\n\t\tpanel.removeAttribute(\"data-item-id\");\r\n\t}\r\n\r\n\tpanel.setAttribute(\"data-group-for\", panelType);\r\n\tpanel.classList.remove(\"is-full-width\");\r\n\r\n\tvar itemOptions = document.getElementById(\"panel-secondary-item-options\");\r\n\t//var itemNav = document.getElementById('panel-secondary-item-nav');\r\n\tvar itemPrev = document.getElementById(\"panel-secondary-item-prev\");\r\n\tvar itemNext = document.getElementById(\"panel-secondary-item-next\");\r\n\tvar itemTitle = document.getElementById(\"panel-secondary-title\");\r\n\tif (id === null) {\r\n\t\t// panel unrelated to a specific item (Get Route, Add Asset, etc)\r\n\t\t// so only the title should be shown\r\n\t\t// item selector should be hidden\r\n\t\titemOptions.classList.remove(\"is-visible\");\r\n\t\titemPrev.classList.remove(\"is-visible\");\r\n\t\titemNext.classList.remove(\"is-visible\");\r\n\t\titemTitle.classList.add(\"is-visible\");\r\n\t} else {\r\n\t\t// item selector should be shown\r\n\t\titemOptions.classList.add(\"is-visible\");\r\n\t\titemPrev.classList.add(\"is-visible\");\r\n\t\titemNext.classList.add(\"is-visible\");\r\n\t\titemTitle.classList.remove(\"is-visible\");\r\n\t}\r\n\r\n\t// clear all previous icons highlighted from having the prior panel open\r\n\t// todo: store previously selected item to deselect it instead of having to iterate all\r\n\t_.each(domNodes.assets, function (assetNodes) {\r\n\t\t_.each(assetNodes, clearSettingsNode);\r\n\t});\r\n\t_.each(domNodes.groups, clearSettingsNode);\r\n\t_.each(domNodes.fences, function (fenceNodes) {\r\n\t\t_.each(fenceNodes, clearSettingsNode);\r\n\t});\r\n\t_.each(domNodes.places, function (placeNodes) {\r\n\t\t_.each(placeNodes, clearSettingsNode);\r\n\t});\r\n\t//_.each(domNodes.journeys, clearSettingsNode); // handled by groups\r\n\t_.each(domNodes.trips, clearSettingsNode);\r\n\t_.each(domNodes.sharedViews, clearSettingsNode);\r\n\r\n\t// highlight item this panel is related to\r\n\tif (id !== null) {\r\n\t\thighlightActiveItemInPrimaryPanel(type, id);\r\n\t}\r\n\r\n\t// set icon\r\n\tvar panelTitle = panel.querySelector(\".panel-title\");\r\n\tvar panelSvgIcon = panel.querySelector(\".panel-svg-icon\");\r\n\tif (svgIcon !== null) {\r\n\t\tpanelSvgIcon.classList.add(\"is-visible\");\r\n\t\tpanelSvgIcon.setAttribute(\r\n\t\t\t\"style\",\r\n\t\t\t\"color: \" + item.Color + \"; --color-primary: \" + item.Color + \"; --color-secondary: \" + item.Color\r\n\t\t);\r\n\t\tpanelSvgIcon.querySelector(\"use\").setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", svgIcon);\r\n\t\tpanelTitle.style.backgroundImage = null;\r\n\t} else {\r\n\t\tpanelSvgIcon.classList.remove(\"is-visible\");\r\n\t\tif (icon !== null) {\r\n\t\t\tpanelTitle.classList.add(\"has-icon\");\r\n\t\t} else {\r\n\t\t\tpanelTitle.classList.remove(\"has-icon\");\r\n\t\t}\r\n\t\tpanelTitle.style.backgroundImage = icon;\r\n\t}\r\n\r\n\t// hide any previous panel content\r\n\tvar functionPanels = domNodes.panels.secondary.querySelectorAll(\".item-group-functions\");\r\n\t_.each(functionPanels, function (panel, index, list) {\r\n\t\tpanel.classList.remove(\"is-visible\");\r\n\t});\r\n\r\n\t// show panel content relevant to chosen item\r\n\tvar functionPanel = document.getElementById(panelType + \"-functions\");\r\n\tfunctionPanel.classList.add(\"is-visible\");\r\n\r\n\topenSecondaryPanel(true);\r\n}\r\n\r\nexport function openAssetGroupSettingsPanel(group) {\r\n\topenDialogPanel(null, group.Name, group, false, null, \"group\", \"group-options\", openAssetGroupSettingsPanel);\r\n\r\n\tvar groupMenuDom = {\r\n\t\tmessage: document.getElementById(\"group-function-message\"),\r\n\t\thistoryReplay: document.getElementById(\"group-function-history-replay\"),\r\n\t\tfollowGroup: document.getElementById(\"group-function-follow-group\"),\r\n\t\teditGroup: document.getElementById(\"group-function-edit-group\"),\r\n\t\tdeleteGroup: document.getElementById(\"group-function-delete-group\"),\r\n\t\tcopyGroup: document.getElementById(\"group-function-copy-group\"),\r\n\t};\r\n\r\n\tvar followText = groupMenuDom.followGroup.querySelector(\".item-action-text\");\r\n\tif (isFollowingGroup(group)) {\r\n\t\tfollowText.textContent = strings.UNFOLLOW_LIVE;\r\n\t} else {\r\n\t\tfollowText.textContent = strings.FOLLOW_LIVE;\r\n\t}\r\n\r\n\t_.each(groupMenuDom, function (item) {\r\n\t\titem.classList.remove(\"disabled\");\r\n\t\titem.querySelector(\"a\").classList.remove(\"disabled\");\r\n\t});\r\n\r\n\tif ((user.isAnonymous && !options.allowAnonymousMessaging) || !isMessagingEnabledForAssetGroup(group)) {\r\n\t\tdisableSettingsMenuItem(groupMenuDom.message);\r\n\t}\r\n\r\n\t// enable/disable menu items based on user permissions and group status\r\n\tif (trkData.assets === null || trkData.assets.length === 0 || findAssetIdsUnderGroup(group) === 0) {\r\n\t\tdisableSettingsMenuItem(groupMenuDom.historyReplay);\r\n\t\tdisableSettingsMenuItem(groupMenuDom.followGroup);\r\n\t}\r\n\r\n\tif (user.isAnonymous || user.canEditAssetGroups === undefined || !user.canEditAssetGroups) {\r\n\t\tdisableSettingsMenuItem(groupMenuDom.editGroup);\r\n\t\tdisableSettingsMenuItem(groupMenuDom.deleteGroup);\r\n\t\tdisableSettingsMenuItem(groupMenuDom.copyGroup);\r\n\t}\r\n\r\n\tif (group.IsDefault) {\r\n\t\tdisableSettingsMenuItem(groupMenuDom.editGroup);\r\n\t\tdisableSettingsMenuItem(groupMenuDom.deleteGroup);\r\n\t}\r\n\r\n\tif (options.enabledFeatures.indexOf(\"UI_DUPLICATE_GROUP\") === -1) {\r\n\t\tdisableSettingsMenuItem(groupMenuDom.copyGroup);\r\n\t}\r\n\r\n\t// remove some options altogether based on menu exclusion options\r\n\t_.each(options.assetMenuExclude, function (excluded) {\r\n\t\tvar domName = dashToCamelCase(excluded);\r\n\t\tif (groupMenuDom[domName] !== undefined) {\r\n\t\t\tif (groupMenuDom[domName].parentNode !== null) {\r\n\t\t\t\tgroupMenuDom[domName].parentNode.removeChild(groupMenuDom[domName]);\r\n\t\t\t}\r\n\t\t}\r\n\t});\r\n}\r\n\r\nexport function openPlaceSettingsPanel(place) {\r\n\topenDialogPanel(null, place.Name, place, false, null, \"place\", \"place-options\", openPlaceSettingsPanel);\r\n\r\n\tvar placeMenuDom = {\r\n\t\trouteAsset: document.getElementById(\"place-function-route-asset\"),\r\n\t\teditPlace: document.getElementById(\"place-function-edit-place\"),\r\n\t\tdeletePlace: document.getElementById(\"place-function-delete-place\"),\r\n\t};\r\n\r\n\t_.each(placeMenuDom, function (item) {\r\n\t\titem.classList.remove(\"disabled\");\r\n\t});\r\n\r\n\t// enable/disable menu items based on user permissions and place status\r\n\tif (\r\n\t\ttrkData.places === null ||\r\n\t\ttrkData.places.length === 0 ||\r\n\t\ttrkData.assets === null ||\r\n\t\ttrkData.assets.length === 0 ||\r\n\t\toptions.enabledFeatures.indexOf(\"ASSET_ROUTING\") === -1\r\n\t) {\r\n\t\tdisableSettingsMenuItem(placeMenuDom.routeAsset);\r\n\t}\r\n\r\n\tif (user.isAnonymous || user.canEditPlaces === undefined || !user.canEditPlaces) {\r\n\t\tdisableSettingsMenuItem(placeMenuDom.editPlace);\r\n\t\tdisableSettingsMenuItem(placeMenuDom.deletePlace);\r\n\t}\r\n\r\n\t// remove some options altogether based on menu exclusion options\r\n\t_.each(options.assetMenuExclude, function (excluded) {\r\n\t\tvar domName = dashToCamelCase(excluded);\r\n\t\tif (placeMenuDom[domName] !== undefined) {\r\n\t\t\tif (placeMenuDom[domName].parentNode !== null) {\r\n\t\t\t\tplaceMenuDom[domName].parentNode.removeChild(placeMenuDom[domName]);\r\n\t\t\t}\r\n\t\t}\r\n\t});\r\n}\r\n\r\nfunction openGroupSettingsPanel(group) {\r\n\tconst itemType = group.Type.substring(0, group.Type.length - 1); // \"place\", \"fence\"\r\n\topenDialogPanel(null, group.Name, group, false, null, itemType + \"-group\", \"group-options\", openGroupSettingsPanel);\r\n\tvar menuDom = {\r\n\t\teditItemGroup: document.getElementById(itemType + \"-group-function-edit-group\"),\r\n\t\tdeleteItemGroup: document.getElementById(itemType + \"-group-function-delete-group\"),\r\n\t};\r\n\r\n\t_.each(menuDom, function (item) {\r\n\t\titem.classList.remove(\"disabled\");\r\n\t});\r\n\r\n\tif (user.isAnonymous \r\n\t\t|| (itemType === \"place\" && (user.canEditPlaces === undefined || !user.canEditPlaces))\r\n\t\t|| (itemType === \"fence\" && (user.canEditGeofences === undefined || !user.canEditGeofences))\r\n\t) {\r\n\t\t_.each(menuDom, function (item) {\r\n\t\t\tdisableSettingsMenuItem(item);\r\n\t\t});\r\n\t}\r\n}\r\n\r\nexport function openTripSettingsPanel(trip) {\r\n\topenDialogPanel(null, trip.Name, trip, false, null, \"trip\", \"trip-options\", openTripSettingsPanel);\r\n\r\n\tvar itemMenuDom = {\r\n\t\teditTrip: document.getElementById(\"trip-function-edit-trip\"),\r\n\t\tdeleteTrip: document.getElementById(\"trip-function-delete-trip\"),\r\n\t};\r\n\r\n\t_.each(itemMenuDom, function (item) {\r\n\t\titem.classList.remove(\"disabled\");\r\n\t});\r\n\r\n\tif (user.isAnonymous || user.canEditJourneys === undefined || !user.canEditJourneys) {\r\n\t\tdisableSettingsMenuItem(itemMenuDom.editTrip);\r\n\t\tdisableSettingsMenuItem(itemMenuDom.deleteTrip);\r\n\t}\r\n\r\n\t// remove some options altogether based on menu exclusion options\r\n\t_.each(options.assetMenuExclude, function (excluded) {\r\n\t\tvar domName = dashToCamelCase(excluded);\r\n\t\tif (itemMenuDom[domName] !== undefined) {\r\n\t\t\tif (itemMenuDom[domName].parentNode !== null) {\r\n\t\t\t\titemMenuDom[domName].parentNode.removeChild(itemMenuDom[domName]);\r\n\t\t\t}\r\n\t\t}\r\n\t});\r\n}\r\n\r\nexport function openJourneySettingsPanel(journey) {\r\n\topenDialogPanel(null, journey.Name, journey, false, null, \"journey\", \"journey-options\", openJourneySettingsPanel);\r\n\r\n\tvar itemMenuDom = {\r\n\t\teditJourney: document.getElementById(\"journey-function-edit-journey\"),\r\n\t\tdeleteJourney: document.getElementById(\"journey-function-delete-journey\"),\r\n\t};\r\n\r\n\t_.each(itemMenuDom, function (item) {\r\n\t\titem.classList.remove(\"disabled\");\r\n\t});\r\n\r\n\tif (user.isAnonymous || user.canEditJourneys === undefined || !user.canEditJourneys) {\r\n\t\tdisableSettingsMenuItem(itemMenuDom.editJourney);\r\n\t\tdisableSettingsMenuItem(itemMenuDom.deleteJourney);\r\n\t}\r\n\r\n\t// remove some options altogether based on menu exclusion options\r\n\t_.each(options.assetMenuExclude, function (excluded) {\r\n\t\tvar domName = dashToCamelCase(excluded);\r\n\t\tif (itemMenuDom[domName] !== undefined) {\r\n\t\t\tif (itemMenuDom[domName].parentNode !== null) {\r\n\t\t\t\titemMenuDom[domName].parentNode.removeChild(itemMenuDom[domName]);\r\n\t\t\t}\r\n\t\t}\r\n\t});\r\n}\r\n\r\nfunction disableSettingsMenuItem(item) {\r\n\tif (item !== undefined && item !== null) {\r\n\t\titem.classList.add(\"disabled\");\r\n\t\titem.querySelector(\"a\").classList.add(\"disabled\");\r\n\t}\r\n}\r\n\r\nexport function openFenceSettingsPanel(fence) {\r\n\topenDialogPanel(null, fence.Name, fence, false, null, \"fence\", \"fence-options\", openFenceSettingsPanel);\r\n\r\n\tvar fenceMenuDom = {\r\n\t\tmessage: document.getElementById(\"fence-function-message\"),\r\n\t\thistoryReplay: document.getElementById(\"fence-function-history-replay\"),\r\n\t\tgroupAssets: document.getElementById(\"fence-function-group-assets\"),\r\n\t\taddAlert: document.getElementById(\"fence-function-add-alert\"),\r\n\t\tlocationReport: document.getElementById(\"fence-function-location-report\"),\r\n\t\teditFence: document.getElementById(\"fence-function-edit-fence\"),\r\n\t\tdeleteFence: document.getElementById(\"fence-function-delete-fence\"),\r\n\t};\r\n\r\n\t_.each(fenceMenuDom, function (item) {\r\n\t\titem.classList.remove(\"disabled\");\r\n\t\titem.querySelector(\"a\").classList.remove(\"disabled\");\r\n\t});\r\n\r\n\tvar hasNoAssets = findAssetIdsInGeofence(fence).length == 0;\r\n\r\n\t// enable/disable menu items based on user permissions and fence status\r\n\tif (user.isAnonymous || hasNoAssets) {\r\n\t\tdisableSettingsMenuItem(fenceMenuDom.message);\r\n\t\tdisableSettingsMenuItem(fenceMenuDom.groupAssets);\r\n\t\tdisableSettingsMenuItem(fenceMenuDom.locationReport);\r\n\t}\r\n\r\n\tif (hasNoAssets) {\r\n\t\tdisableSettingsMenuItem(fenceMenuDom.historyReplay);\r\n\t}\r\n\r\n\tif (user.isAnonymous) {\r\n\t\tdisableSettingsMenuItem(fenceMenuDom.addAlert);\r\n\t}\r\n\r\n\tif (user.isAnonymous || user.canEditGeofences === undefined || !user.canEditGeofences) {\r\n\t\tdisableSettingsMenuItem(fenceMenuDom.editFence);\r\n\t\tdisableSettingsMenuItem(fenceMenuDom.deleteFence);\r\n\t}\r\n\r\n\t// remove some options altogether based on menu exclusion options\r\n\t_.each(options.assetMenuExclude, function (excluded) {\r\n\t\tvar domName = dashToCamelCase(excluded);\r\n\t\tif (fenceMenuDom[domName] !== undefined) {\r\n\t\t\tif (fenceMenuDom[domName].parentNode !== null) {\r\n\t\t\t\tfenceMenuDom[domName].parentNode.removeChild(fenceMenuDom[domName]);\r\n\t\t\t}\r\n\t\t}\r\n\t});\r\n}\r\n\r\nexport function openAssetSettingsPanel(asset) {\r\n\topenDialogPanel(null, asset.Name, asset, false, null, \"asset\", \"asset-options\", openAssetSettingsPanel);\r\n\r\n\tvar assetMenuDom = {\r\n\t\talerts: document.getElementById(\"asset-function-alerts\"),\r\n\t\tevents: document.getElementById(\"asset-function-events\"),\r\n\t\tstatus: document.getElementById(\"asset-function-status\"),\r\n\t\tmessages: document.getElementById(\"asset-function-messages\"),\r\n\t\tcurrentPosition: document.getElementById(\"asset-function-current-position\"),\r\n\t\tfollowAsset: document.getElementById(\"asset-function-follow-asset\"),\r\n\t\thistoryReplay: document.getElementById(\"asset-function-history-replay\"),\r\n\t\tsendWaypoint: document.getElementById(\"asset-function-send-waypoint\"),\r\n\t\tsetWaypoint: document.getElementById(\"asset-function-set-waypoint\"),\r\n\t\taddPosition: document.getElementById(\"asset-function-add-position\"),\r\n\t\trouteAsset: document.getElementById(\"asset-function-route-asset\"),\r\n\t\tsendMessage: document.getElementById(\"asset-function-send-message\"),\r\n\t\tsendCommand: document.getElementById(\"asset-function-send-command\"),\r\n\t\tsetOutput: document.getElementById(\"asset-function-set-output\"),\r\n\t\tsetDriver: document.getElementById(\"asset-function-set-driver\"),\r\n\t\tviewLogs: document.getElementById(\"asset-function-view-logs\"),\r\n\t\tviewLogsMessage: document.getElementById(\"asset-function-view-logs-message\"),\r\n\t\tviewLogsIO: document.getElementById(\"asset-function-view-logs-io\"),\r\n\t\tviewLogsDriver: document.getElementById(\"asset-function-view-logs-driver\"),\r\n\t\tviewLogsWaypoint: document.getElementById(\"asset-function-view-logs-waypoint\"),\r\n\t\tviewLogsRefuel: document.getElementById(\"asset-function-view-logs-refuel\"),\r\n\t\tviewLogsServiceMeters: document.getElementById(\"asset-function-view-logs-service-meters\"),\r\n\t\tviewLogsGarminForms: document.getElementById(\"asset-function-view-logs-garmin-forms\"),\r\n\t\teditAsset: document.getElementById(\"asset-function-edit-asset\"),\r\n\t\tdeleteAsset: document.getElementById(\"asset-function-delete-asset\"),\r\n\t};\r\n\r\n\t_.each(assetMenuDom, function (item) {\r\n\t\tif (item !== null) {\r\n\t\t\titem.classList.remove(\"disabled\");\r\n\t\t\titem.querySelector(\"a\").classList.remove(\"disabled\");\r\n\t\t}\r\n\t});\r\n\r\n\t// enable/disable menu items based on asset capabilities\r\n\tvar device = findDeviceById(asset.DeviceId);\r\n\r\n\tvar currentPosition = trkData.live.latestPositionsByAssetId[asset.Id];\r\n\tif (currentPosition === undefined) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.currentPosition);\r\n\t}\r\n\r\n\tif (_.indexOf(state.liveFollow.assets, asset) === -1) {\r\n\t\tassetMenuDom.followAsset.querySelector(\".item-action-text\").textContent = strings.FOLLOW_LIVE;\r\n\t} else {\r\n\t\tassetMenuDom.followAsset.querySelector(\".item-action-text\").textContent = strings.UNFOLLOW_LIVE;\r\n\t}\r\n\r\n\tif (\r\n\t\ttrkData.places === null ||\r\n\t\ttrkData.places.length === 0 ||\r\n\t\toptions.enabledFeatures.indexOf(\"ASSET_ROUTING\") === -1\r\n\t) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.routeAsset);\r\n\t}\r\n\r\n\tif ((user.isAnonymous && !options.allowAnonymousMessaging) || !isMessagingEnabledForAsset(asset)) {\r\n\t\tif (assetMenuDom.messages !== null) {\r\n\t\t\tdisableSettingsMenuItem(assetMenuDom.messages);\r\n\t\t}\r\n\t\tdisableSettingsMenuItem(assetMenuDom.sendMessage);\r\n\t}\r\n\r\n\tif (user.isAnonymous || !isWaypointEnabledForAsset(asset) || options.enabledFeatures.indexOf(\"WAYPOINTS\") === -1) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.sendWaypoint);\r\n\t}\r\n\r\n\tif (user.isAnonymous || options.enabledFeatures.indexOf(\"WAYPOINTS\") === -1) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.setWaypoint);\r\n\t}\r\n\r\n\tif (\r\n\t\tuser.isAnonymous ||\r\n\t\tuser.canSendCommands === undefined ||\r\n\t\t!user.canSendCommands ||\r\n\t\t!isOutputEnabledForAsset(asset) ||\r\n\t\toptions.enabledFeatures.indexOf(\"REMOTE_MANAGEMENT\") === -1\r\n\t) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.setOutput);\r\n\t}\r\n\r\n\tif (\r\n\t\tuser.isAnonymous ||\r\n\t\tuser.canEditAssets === undefined ||\r\n\t\t!user.canEditAssets ||\r\n\t\toptions.enabledFeatures.indexOf(\"DRIVER_MANAGEMENT\") === -1\r\n\t) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.setDriver);\r\n\t}\r\n\r\n\tif (assetMenuDom.addPosition !== null) {\r\n\t\tif (user.isAnonymous || user.canEditAssets === undefined || !user.canEditAssets) {\r\n\t\t\tdisableSettingsMenuItem(assetMenuDom.addPosition);\r\n\t\t}\r\n\t}\r\n\r\n\tif (user.isAnonymous || options.enabledFeatures.indexOf(\"LOGS_OBDII\") === -1) {\r\n\t}\r\n\tif (user.isAnonymous || options.enabledFeatures.indexOf(\"LOGS_FUEL\") === -1) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.viewLogsRefuel);\r\n\t}\r\n\tif (user.isAnonymous || options.enabledFeatures.indexOf(\"LOGS_SERVICE_METER\") === -1) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.viewLogsServiceMeters);\r\n\t}\r\n\tif (\r\n\t\t(user.isAnonymous && !options.allowAnonymousMessaging) ||\r\n\t\toptions.enabledFeatures.indexOf(\"LOGS_MESSAGE\") === -1\r\n\t) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.viewLogsMessage);\r\n\t}\r\n\tif (user.isAnonymous || options.enabledFeatures.indexOf(\"LOGS_DRIVER\") === -1) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.viewLogsDriver);\r\n\t}\r\n\tif (user.isAnonymous || options.enabledFeatures.indexOf(\"LOGS_WAYPOINT\") === -1) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.viewLogsWaypoint);\r\n\t}\r\n\tif (user.isAnonymous || options.enabledFeatures.indexOf(\"IO_MAPPING\") === -1) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.viewLogsIO);\r\n\t}\r\n\r\n\tif (assetMenuDom.viewLogsGarminForms !== null) {\r\n\t\tif (user.isAnonymous || options.enabledFeatures.indexOf(\"GARMIN_INTEGRATION\") === -1) {\r\n\t\t\tdisableSettingsMenuItem(assetMenuDom.viewLogsGarminForms);\r\n\t\t}\r\n\t}\r\n\r\n\tif (!isServiceMeterEnabledForAsset(asset)) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.viewLogsServiceMeters);\r\n\t}\r\n\r\n\tif (!device.SupportsGarminForms) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.viewLogsGarminForms);\r\n\t}\r\n\r\n\tif (isSendCommandDisabledForDevice(device)) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.sendCommand);\r\n\t}\r\n\r\n\tif (user.isAnonymous || user.canEditAssets === undefined || !user.canEditAssets) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.editAsset);\r\n\t}\r\n\r\n\tif (\r\n\t\tuser.isAnonymous ||\r\n\t\tuser.canDeleteAssets === undefined ||\r\n\t\t!user.canDeleteAssets ||\r\n\t\tuser.limitAssetEditing ||\r\n\t\tuser.assetControlFederated\r\n\t) {\r\n\t\tdisableSettingsMenuItem(assetMenuDom.deleteAsset);\r\n\t}\r\n\r\n\t// remove some options altogether based on menu exclusion options\r\n\t_.each(options.assetMenuExclude, function (excluded) {\r\n\t\tvar domName = dashToCamelCase(excluded);\r\n\t\tif (assetMenuDom[domName] !== undefined && assetMenuDom[domName] !== null) {\r\n\t\t\tif (assetMenuDom[domName].parentNode !== null) {\r\n\t\t\t\tassetMenuDom[domName].parentNode.removeChild(assetMenuDom[domName]);\r\n\t\t\t}\r\n\t\t}\r\n\t});\r\n}\r\n\r\nexport function openSharedViewSettingsPanel(sharedView) {\r\n\topenDialogPanel(\r\n\t\tnull,\r\n\t\tsharedView.Name,\r\n\t\tsharedView,\r\n\t\tfalse,\r\n\t\tcheckForShareViewChange(sharedView),\r\n\t\t\"shared-view\",\r\n\t\t\"shared-view-options\",\r\n\t\topenSharedViewSettingsPanel\r\n\t);\r\n\r\n\tdomNodes.panels.secondary.setAttribute(\"data-chat-enabled\", sharedView.IsMessagingEnabled);\r\n\r\n\tif (trkData.sharedView.current !== sharedView) {\r\n\t\tquerySharedViewData(sharedView, null, false);\r\n\t}\r\n\ttrkData.sharedView.current = sharedView;\r\n\t$(domNodes.infoDialogs.sharedViewInformation).dialog(\"close\");\r\n\r\n\tvar sharedViewMenuDom = {\r\n\t\tsharedViewVisitorStatistics: document.getElementById(\"shared-view-function-statistics\"),\r\n\t\tdisableSharedView: document.getElementById(\"shared-view-function-disable\"),\r\n\t\tsharedViewAccessControls: document.getElementById(\"shared-view-function-access-controls\"),\r\n\t\tsharedViewDataVisualization: document.getElementById(\"shared-view-function-data-visualization\"),\r\n\t\tsharedViewDetails: document.getElementById(\"shared-view-function-details\"),\r\n\t\tsharedViewMapSettings: document.getElementById(\"shared-view-function-map-settings\"),\r\n\t\tsharedViewPermissions: document.getElementById(\"shared-view-function-permissions\"),\r\n\t\tsharedViewPreferences: document.getElementById(\"shared-view-function-preferences\"),\r\n\t\tdeleteSharedView: document.getElementById(\"shared-view-function-delete\"),\r\n\t};\r\n\r\n\t// enable/disable menu items based on user permissions and shared view status\r\n\r\n\tvar statusButtonIcon = sharedViewMenuDom.disableSharedView.querySelector(\"use\");\r\n\tvar statusButtonText = sharedViewMenuDom.disableSharedView.querySelector(\"span\");\r\n\tif (sharedView.IsEnabled) {\r\n\t\tstatusButtonIcon.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", svgPath(\"ban\"));\r\n\t\tstatusButtonText.textContent = strings.DISABLE;\r\n\t} else {\r\n\t\tstatusButtonIcon.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", svgPath(\"check\"));\r\n\t\tstatusButtonText.textContent = strings.ENABLE;\r\n\t}\r\n\r\n\t// populate share links\r\n\tif (\r\n\t\tuser.isAnonymous ||\r\n\t\tuser.canEditSharedViews === undefined ||\r\n\t\t!user.canEditSharedViews ||\r\n\t\toptions.enabledFeatures.indexOf(\"VIEWS_SHARED\") === -1\r\n\t) {\r\n\t\t_.each(sharedViewMenuDom, function (item) {\r\n\t\t\titem.classList.add(\"disabled\");\r\n\t\t});\r\n\t} else {\r\n\t\t_.each(sharedViewMenuDom, function (item) {\r\n\t\t\titem.classList.remove(\"disabled\");\r\n\t\t});\r\n\t}\r\n\r\n\t// remove some options altogether based on menu exclusion options\r\n\t_.each(options.assetMenuExclude, function (excluded) {\r\n\t\tvar domName = dashToCamelCase(excluded);\r\n\t\tif (sharedViewMenuDom[domName] !== undefined) {\r\n\t\t\tif (sharedViewMenuDom[domName].parentNode !== null) {\r\n\t\t\t\tsharedViewMenuDom[domName].parentNode.removeChild(sharedViewMenuDom[domName]);\r\n\t\t\t}\r\n\t\t}\r\n\t});\r\n}\r\n\r\nfunction dashToCamelCase(input) {\r\n\treturn input.replace(/-([a-z])/gi, function ($0, $1) {\r\n\t\treturn $1.toUpperCase();\r\n\t});\r\n}\r\n","// Panel navigation. Not just opening/closing, but populating contents of the panel.\r\n\r\nimport trkData from \"./data.js\";\r\nimport user from \"./user.js\";\r\nimport strings from \"./strings.js\";\r\nimport options from \"./options.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { openSettingsPanel, itemSettingsClick } from \"./panel-settings.js\";\r\nimport { getAssetDataGroupForCurrentViewMode } from \"./map-viewmode.js\";\r\nimport {\r\n\tisSendCommandEnabledForAsset,\r\n\tisWaypointEnabledForAsset,\r\n\tisMessagingEnabledForAsset,\r\n\tisServiceMeterEnabledForAsset,\r\n\tisGarminFormsEnabledForAsset,\r\n\tisOutputEnabledForAsset,\r\n\tisMessagingEnabledForAssetGroup,\r\n} from \"./assets.js\";\r\nimport { trkDataGroups } from \"./const.js\";\r\nimport { findDeviceById } from \"./devices.js\";\r\nimport {\r\n\tupdateNotificationsInSecondaryPanel,\r\n\tgetNotificationCounts,\r\n\tgetNotificationCountsForGroup,\r\n} from \"./notifications.js\";\r\nimport { productTitle } from \"./entry_point.js\";\r\n\r\nimport _ from \"lodash\";\r\nimport $ from \"jquery\";\r\nimport moment from \"moment\"; // https://www.npmjs.com/package/moment\r\n\r\n// open a dialog for an action - this should be called as early as possible so that previous dialog cleanup does not interfere with no dialog intialization\r\nexport function openDialogPanel(domNode, title, item, isLargeDialog, closeCallback, type, action, nextItemCallback) {\r\n\t// don't do anything if the dialog is already open for this exact item\r\n\r\n\tvar panel = domNodes.panels.secondary;\r\n\r\n\tif (type === undefined) {\r\n\t\ttype = \"asset\";\r\n\t}\r\n\tvar id = null;\r\n\tif (item !== null) {\r\n\t\tid = item.Id;\r\n\t}\r\n\topenSettingsPanel(type + \"s\", item, domNode !== null); // hack/lazy alert\r\n\tif (isLargeDialog) {\r\n\t\tpanel.classList.add(\"is-full-width\");\r\n\t}\r\n\r\n\tpanel.closeCallback = closeCallback;\r\n\tpanel.nextItemCallback = nextItemCallback;\r\n\r\n\tvar showMetaPanel = false;\r\n\tvar showNotificationItems = false;\r\n\tvar notificationTabs = document.getElementById(\"panel-secondary-nav-tabs\");\r\n\tvar isNotificationItem = true;\r\n\r\n\tvar panelItemType = panel.getAttribute(\"data-item-type\");\r\n\tvar notificationTabItemTypes = [\"groups\", \"assets\", \"trips\", \"journeys\", \"shared-views\"]; // todo: only asset groups\r\n\tif (panelItemType !== undefined && _.indexOf(notificationTabItemTypes, panelItemType) !== -1) {\r\n\t\tshowNotificationItems = true;\r\n\t}\r\n\r\n\tvar metaPanel = document.getElementById(\"panel-secondary-meta\");\r\n\t// item selection dropdown (action determines which items are disabled)\r\n\tconsole.log(domNode, type, item, action);\r\n\tif (action !== undefined && action !== null) {\r\n\t\t// showing of selector handled above by openSettingsPanel\r\n\t\tpopulateItemSelector(action, item, type + \"s\");\r\n\r\n\t\tpopulateMetaInformation(type, item);\r\n\t\tshowMetaPanel = true;\r\n\r\n\t\t// select notification tab based on action here?\r\n\t\tvar actionsPositions = [\r\n\t\t\t\"asset-positions\",\r\n\t\t\t\"group-positions\",\r\n\t\t\t\"trip-positions\",\r\n\t\t\t\"journey-positions\",\r\n\t\t\t\"shared-view-positions\",\r\n\t\t];\r\n\t\tvar actionsEvents = [\"asset-events\", \"group-events\", \"trip-events\", \"journey-events\", \"shared-view-events\"];\r\n\t\tvar actionsAlerts = [\"asset-alerts\", \"group-alerts\", \"trip-alerts\", \"journey-alerts\", \"shared-view-alerts\"];\r\n\t\tvar actionsStatus = [\"asset-status\", \"group-status\", \"trip-status\", \"journey-status\", \"shared-view-status\"];\r\n\t\tvar actionsMessages = [\"asset-messages\", \"group-messages\", \"trip-messages\", \"journey-messages\"];\r\n\t\tvar actionsChat = [\"asset-chat\", \"group-chat\", \"trip-chat\", \"journey-chat\", \"shared-view-chat\"];\r\n\t\tvar actionsActivity = [\r\n\t\t\t\"asset-activity\",\r\n\t\t\t\"group-activity\",\r\n\t\t\t\"trip-activity\",\r\n\t\t\t\"journey-activity\",\r\n\t\t\t\"shared-view-activity\",\r\n\t\t];\r\n\t\tvar optionsActions = [\r\n\t\t\t\"shared-view-options\",\r\n\t\t\t\"asset-options\",\r\n\t\t\t\"group-options\",\r\n\t\t\t\"trip-options\",\r\n\t\t\t\"journey-options\",\r\n\t\t\t\"fence-options\",\r\n\t\t\t\"place-options\",\r\n\t\t];\r\n\t\tnotificationTabs.querySelectorAll(\".nav-item\").forEach(function (nav) {\r\n\t\t\tnav.classList.remove(\"active\");\r\n\t\t});\r\n\r\n\t\tmetaPanel.querySelectorAll(\".meta-left,.meta-options\").forEach(function (meta) {\r\n\t\t\tmeta.classList.remove(\"is-visible\");\r\n\t\t});\r\n\r\n\t\t//var metaTypes = ['positions', 'events', 'alerts', 'status', 'messages', 'chat', 'activity'];\r\n\t\tvar metaType = null;\r\n\t\tif (_.indexOf(actionsPositions, action) !== -1) {\r\n\t\t\tdocument.getElementById(\"nav-positions-tab\").classList.add(\"active\");\r\n\t\t\tmetaType = \"positions\";\r\n\t\t} else if (_.indexOf(actionsEvents, action) !== -1) {\r\n\t\t\tdocument.getElementById(\"nav-events-tab\").classList.add(\"active\");\r\n\t\t\tmetaType = \"events\";\r\n\t\t} else if (_.indexOf(actionsAlerts, action) !== -1) {\r\n\t\t\tdocument.getElementById(\"nav-alerts-tab\").classList.add(\"active\");\r\n\t\t\tmetaType = \"alerts\";\r\n\t\t} else if (_.indexOf(actionsStatus, action) !== -1) {\r\n\t\t\tdocument.getElementById(\"nav-status-tab\").classList.add(\"active\");\r\n\t\t\tmetaType = \"status\";\r\n\t\t} else if (_.indexOf(actionsMessages, action) !== -1) {\r\n\t\t\tdocument.getElementById(\"nav-messages-tab\").classList.add(\"active\");\r\n\t\t\tmetaType = \"messages\";\r\n\t\t} else if (_.indexOf(actionsChat, action) !== -1) {\r\n\t\t\tdocument.getElementById(\"nav-chat-tab\").classList.add(\"active\");\r\n\t\t\tmetaType = \"chat\";\r\n\t\t} else if (_.indexOf(actionsActivity, action) !== -1) {\r\n\t\t\tdocument.getElementById(\"nav-activity-tab\").classList.add(\"active\");\r\n\t\t\tmetaType = \"activity\";\r\n\t\t} else if (_.indexOf(optionsActions, action) !== -1) {\r\n\t\t\tdocument.getElementById(\"nav-options-tab\").classList.add(\"active\");\r\n\t\t\tisNotificationItem = false;\r\n\t\t\tmetaType = \"options\";\r\n\t\t} else {\r\n\t\t\tisNotificationItem = false;\r\n\t\t\tshowMetaPanel = false;\r\n\t\t}\r\n\r\n\t\tif (metaType !== null) {\r\n\t\t\tmetaPanel.querySelectorAll(\".meta-\" + metaType).forEach(function (meta) {\r\n\t\t\t\tmeta.classList.add(\"is-visible\");\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tif (showMetaPanel) {\r\n\t\tmetaPanel.classList.add(\"is-visible\");\r\n\t} else {\r\n\t\tmetaPanel.classList.remove(\"is-visible\");\r\n\t}\r\n\r\n\tif (showNotificationItems && id !== null && (isNotificationItem || metaType === \"options\")) {\r\n\t\tnotificationTabs.classList.add(\"is-visible\");\r\n\r\n\t\tvar counts = null;\r\n\t\tif (type === \"asset\") {\r\n\t\t\tcounts = getNotificationCounts(getAssetDataGroupForCurrentViewMode(), id);\r\n\t\t} else if (type === \"trip\") {\r\n\t\t\tcounts = getNotificationCounts(trkDataGroups.JOURNEY_HISTORY, id);\r\n\t\t} else if (type === \"group\") {\r\n\t\t\tcounts = getNotificationCountsForGroup(getAssetDataGroupForCurrentViewMode(), id);\r\n\t\t} else if (type === \"journey\") {\r\n\t\t\tcounts = getNotificationCountsForGroup(trkDataGroups.JOURNEY_HISTORY, id);\r\n\t\t} else if (type === \"shared-view\") {\r\n\t\t\tcounts = getNotificationCounts(trkDataGroups.SHARED_VIEW_HISTORY, id);\r\n\t\t\tconsole.log(counts);\r\n\t\t}\r\n\t\tif (counts !== null) {\r\n\t\t\tupdateNotificationsInSecondaryPanel(type + \"s\", id, counts);\r\n\t\t}\r\n\t} else {\r\n\t\tnotificationTabs.classList.remove(\"is-visible\");\r\n\t}\r\n\r\n\tvar panelTitle = document.getElementById(\"panel-secondary-title\");\r\n\tpanelTitle.textContent = title;\r\n\r\n\tif (domNode !== null) {\r\n\t\tvar dialogDom = document.getElementById(\"dialog-functions\");\r\n\t\tvar existingDialog = dialogDom.querySelector(\".dialog\");\r\n\t\tif (existingDialog !== domNode) {\r\n\t\t\tif (existingDialog !== null) {\r\n\t\t\t\tdocument.getElementById(\"detached-dialogs\").appendChild(existingDialog);\r\n\t\t\t}\r\n\t\t\tdialogDom.appendChild(domNode);\r\n\t\t}\r\n\r\n\t\t// breadcrumbs\r\n\t\tvar breadcrumbs = [];\r\n\t\tif (id !== null) {\r\n\t\t\t// when inside of a dialog, add breadcrumbs leading back to the item in general\r\n\t\t\tswitch (type + \"s\") {\r\n\t\t\t\tcase \"assets\":\r\n\t\t\t\t\tbreadcrumbs.push({\r\n\t\t\t\t\t\tlabel: strings.ASSET,\r\n\t\t\t\t\t\tcallback: itemSettingsClick,\r\n\t\t\t\t\t\tattributes: { \"data-asset-id\": id },\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"groups\":\r\n\t\t\t\t\tbreadcrumbs.push({\r\n\t\t\t\t\t\tlabel: strings.ASSET_GROUP,\r\n\t\t\t\t\t\tcallback: itemSettingsClick,\r\n\t\t\t\t\t\tattributes: { \"data-group-id\": id, \"data-group-for\": \"assets\" },\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"fences\":\r\n\t\t\t\t\tbreadcrumbs.push({\r\n\t\t\t\t\t\tlabel: strings.GEOFENCE,\r\n\t\t\t\t\t\tcallback: itemSettingsClick,\r\n\t\t\t\t\t\tattributes: { \"data-fence-id\": id },\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"fence-groups\":\r\n\t\t\t\t\tbreadcrumbs.push({\r\n\t\t\t\t\t\tlabel: strings.GEOFENCE_GROUP,\r\n\t\t\t\t\t\tcallback: itemSettingsClick,\r\n\t\t\t\t\t\tattributes: { \"data-group-id\": id, \"data-group-for\": \"fences\" },\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"places\":\r\n\t\t\t\t\tbreadcrumbs.push({\r\n\t\t\t\t\t\tlabel: strings.PLACE,\r\n\t\t\t\t\t\tcallback: itemSettingsClick,\r\n\t\t\t\t\t\tattributes: { \"data-place-id\": id },\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"place-groups\":\r\n\t\t\t\t\tbreadcrumbs.push({\r\n\t\t\t\t\t\tlabel: strings.PLACE_GROUP,\r\n\t\t\t\t\t\tcallback: itemSettingsClick,\r\n\t\t\t\t\t\tattributes: { \"data-group-id\": id, \"data-group-for\": \"places\" },\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"journeys\":\r\n\t\t\t\t\tbreadcrumbs.push({\r\n\t\t\t\t\t\tlabel: strings.JOURNEY,\r\n\t\t\t\t\t\tcallback: itemSettingsClick,\r\n\t\t\t\t\t\tattributes: { \"data-journey-id\": id },\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"trips\":\r\n\t\t\t\t\tbreadcrumbs.push({\r\n\t\t\t\t\t\tlabel: strings.TRIP,\r\n\t\t\t\t\t\tcallback: itemSettingsClick,\r\n\t\t\t\t\t\tattributes: { \"data-trip-id\": id },\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"shared-views\":\r\n\t\t\t\t\tbreadcrumbs.push({\r\n\t\t\t\t\t\tlabel: strings.SHARED_VIEW,\r\n\t\t\t\t\t\tcallback: itemSettingsClick,\r\n\t\t\t\t\t\tattributes: { \"data-shared-view-id\": id },\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreadcrumbs.push({ label: title, callback: function () {} });\r\n\t\tvar breadcrumbDom = document.getElementById(\"dialog-breadcrumbs\");\r\n\t\tvar breadcrumbTitle = breadcrumbDom.querySelector(\".panel-title\");\r\n\t\tbreadcrumbTitle.innerHTML = \"\";\r\n\t\tbreadcrumbTitle.appendChild(createSecondaryBreadcrumb(breadcrumbs));\r\n\r\n\t\t// enable back button to go back to item settings\r\n\t\tvar backButton = document.getElementById(\"panel-dialog-back\");\r\n\t\tbackButton.removeAttribute(\"data-asset-id\");\r\n\t\tbackButton.removeAttribute(\"data-group-id\");\r\n\t\tbackButton.removeAttribute(\"data-group-for\");\r\n\t\tbackButton.removeAttribute(\"data-fence-id\");\r\n\t\tbackButton.removeAttribute(\"data-place-id\");\r\n\t\tbackButton.removeAttribute(\"data-trip-id\");\r\n\t\tbackButton.removeAttribute(\"data-shared-view-id\");\r\n\t\tif (id !== null && !isNotificationItem) {\r\n\t\t\t// show breadcrumbs\r\n\t\t\tbreadcrumbDom.classList.add(\"is-visible\");\r\n\t\t\tif (type.endsWith(\"group\")) {\r\n\t\t\t\tbackButton.setAttribute(\"data-group-id\", id);\r\n\t\t\t\tconst groupFor = type === \"place-group\" ? \"places\" : type === \"fence-group\" ? \"fences\" : \"assets\";\r\n\t\t\t\tbackButton.setAttribute(\"data-group-for\", groupFor);\r\n\t\t\t} else {\r\n\t\t\t\tbackButton.setAttribute(\"data-\" + type + \"-id\", id);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\t// hide breadcrumbs\r\n\t\t\tbreadcrumbDom.classList.remove(\"is-visible\");\r\n\t\t}\r\n\r\n\t\t//// panel filters shown/hidden here - should move to a more declarative way of doing this\r\n\t\t//var notificationOptions = document.getElementById('panel-options-notifications');\r\n\t\t//if (notificationOptions !== null) {\r\n\t\t// var notificationDialogs = [\r\n\t\t// domNodes.dialogs.assetMessages,\r\n\t\t// domNodes.dialogs.assetStatus,\r\n\t\t// domNodes.dialogs.assetEvents,\r\n\t\t// domNodes.dialogs.assetAlerts,\r\n\t\t// domNodes.dialogs.assetPositions\r\n\t\t// ];\r\n\t\t// if (notificationDialogs.indexOf(domNode) !== -1) {\r\n\t\t// notificationOptions.classList.add('is-visible');\r\n\t\t// } else {\r\n\t\t// notificationOptions.classList.remove('is-visible');\r\n\t\t// }\r\n\t\t//}\r\n\t\tresetParametersForms(domNode);\r\n\r\n\t\t// clear dialog statuses\r\n\t\tdialogDom.querySelectorAll(\".dialog-status\").forEach(function (status) {\r\n\t\t\tclearStatusMessage(status);\r\n\t\t});\r\n\t}\r\n\r\n\tdomNodes.simpleBars.secondary.recalculate(); // todo: this should occur after all mutations\r\n}\r\n\r\nfunction resetParametersForms(node) {\r\n\tnode.querySelectorAll(\".parameters-form\").forEach(function (form) {\r\n\t\t$(\".parameter-toggle input:checkbox\", form).prop(\"checked\", false);\r\n\t\t$(\".parameter-toggle input:checkbox\", form)\r\n\t\t\t.parents(\".parameter-toggle\")\r\n\t\t\t.next(\".parameter-options\")\r\n\t\t\t.find(\"input,select,label\")\r\n\t\t\t.prop(\"disabled\", true)\r\n\t\t\t.addClass(\"disabled\");\r\n\t});\r\n}\r\n\r\nfunction populateItemSelector(action, currentItem, type) {\r\n\tvar selector = document.getElementById(\"panel-secondary-header\");\r\n\t//selector.classList.add('d-flex');\r\n\tvar $selector = $(selector);\r\n\tselector.setAttribute(\"data-group-for\", type);\r\n\tvar items = [];\r\n\tvar allItems = [];\r\n\tswitch (type) {\r\n\t\tcase \"assets\":\r\n\t\t\tallItems = trkData.assets;\r\n\t\t\tswitch (action) {\r\n\t\t\t\tcase \"send-command\":\r\n\t\t\t\t\titems = _.filter(trkData.assets, function (asset) {\r\n\t\t\t\t\t\treturn isSendCommandEnabledForAsset(asset);\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"send-waypoint\":\r\n\t\t\t\t\titems = _.filter(trkData.assets, function (asset) {\r\n\t\t\t\t\t\treturn isWaypointEnabledForAsset(asset);\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"send-message\":\r\n\t\t\t\t\titems = _.filter(trkData.assets, function (asset) {\r\n\t\t\t\t\t\treturn isMessagingEnabledForAsset(asset);\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"view-logs-service-meters\":\r\n\t\t\t\t\titems = _.filter(trkData.assets, function (asset) {\r\n\t\t\t\t\t\treturn isServiceMeterEnabledForAsset(asset);\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"view-logs-garmin-forms\":\r\n\t\t\t\t\titems = _.filter(trkData.assets, function (asset) {\r\n\t\t\t\t\t\treturn isGarminFormsEnabledForAsset(asset);\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"set-output\":\r\n\t\t\t\t\titems = _.filter(trkData.assets, function (asset) {\r\n\t\t\t\t\t\treturn isOutputEnabledForAsset(asset);\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"set-driver\":\r\n\t\t\t\t\titems = trkData.assets;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"route-asset\":\r\n\t\t\t\tcase \"set-waypoint\":\r\n\t\t\t\tcase \"add-position\":\r\n\t\t\t\tcase \"view-logs-message\":\r\n\t\t\t\tcase \"view-logs-io\":\r\n\t\t\t\tcase \"view-logs-waypoint\": // todo: does this apply to set waypoint? if not, it should be same restriction as send-waypoint\r\n\t\t\t\tcase \"view-logs-driver\":\r\n\t\t\t\tcase \"edit-asset\":\r\n\t\t\t\tcase \"asset-positions\":\r\n\t\t\t\tcase \"asset-events\":\r\n\t\t\t\tcase \"asset-status\":\r\n\t\t\t\tcase \"asset-messages\":\r\n\t\t\t\tcase \"asset-chat\":\r\n\t\t\t\tcase \"asset-options\":\r\n\t\t\t\tcase \"asset-alerts\":\r\n\t\t\t\tcase \"asset-activity\":\r\n\t\t\t\t\titems = trkData.assets;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"acknowledge-alert\":\r\n\t\t\t\t\titems = _.filter(trkData.assets, function (asset) {\r\n\t\t\t\t\t\treturn (\r\n\t\t\t\t\t\t\t_.filter(trkData.alerts, function (alert) {\r\n\t\t\t\t\t\t\t\treturn alert.AssetId === asset.Id;\r\n\t\t\t\t\t\t\t}).length > 0\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tconsole.warn(\"No asset action selector filter defined for:\" + action);\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"groups\":\r\n\t\t\tallItems = trkData.groups;\r\n\t\t\tswitch (action) {\r\n\t\t\t\tcase \"send-message\":\r\n\t\t\t\t\titems = _.filter(trkData.groups, function (group) {\r\n\t\t\t\t\t\treturn isMessagingEnabledForAssetGroup(group);\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"group-events\":\r\n\t\t\t\tcase \"group-status\":\r\n\t\t\t\tcase \"group-messages\":\r\n\t\t\t\tcase \"group-positions\":\r\n\t\t\t\tcase \"group-options\":\r\n\t\t\t\tcase \"group-alerts\":\r\n\t\t\t\tcase \"group-chat\":\r\n\t\t\t\tcase \"group-activity\":\r\n\t\t\t\t\titems = trkData.groups;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"edit-group\":\r\n\t\t\t\t\titems = _.filter(trkData.groups, function (group) {\r\n\t\t\t\t\t\treturn !group.IsDefault;\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tconsole.warn(\"No group action selector filter defined for:\" + action);\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"fence-groups\":\r\n\t\tcase \"place-groups\":\r\n\t\t\tallItems = type === \"fence-groups\" ? trkData.fenceGroups : trkData.placeGroups;\r\n\t\t\tswitch (action) {\r\n\t\t\t\tcase \"group-options\":\r\n\t\t\t\tcase \"edit-group\":\r\n\t\t\t\t\titems = _.filter(allItems, function (group) {\r\n\t\t\t\t\t\treturn !group.Id.startsWith(\"all-\");\r\n\t\t\t\t\t});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tconsole.warn(\"No \" + type + \" action selector filter defined for:\" + action);\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"fences\":\r\n\t\t\tallItems = trkData.fences;\r\n\t\t\tswitch (action) {\r\n\t\t\t\tcase \"edit-fence\":\r\n\t\t\t\tcase \"fence-options\":\r\n\t\t\t\t\titems = trkData.fences;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tconsole.warn(\"No fence action selector filter defined for:\" + action);\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"places\":\r\n\t\t\tallItems = trkData.places;\r\n\t\t\tswitch (action) {\r\n\t\t\t\tcase \"route-asset\":\r\n\t\t\t\tcase \"edit-place\":\r\n\t\t\t\tcase \"place-options\":\r\n\t\t\t\t\titems = trkData.places;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tconsole.warn(\"No place action selector filter defined for:\" + action);\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"trips\":\r\n\t\t\tswitch (action) {\r\n\t\t\t\tcase \"trip-positions\":\r\n\t\t\t\tcase \"trip-events\":\r\n\t\t\t\tcase \"trip-status\":\r\n\t\t\t\tcase \"trip-messages\":\r\n\t\t\t\tcase \"trip-options\":\r\n\t\t\t\tcase \"trip-alerts\":\r\n\t\t\t\tcase \"trip-chat\":\r\n\t\t\t\tcase \"trip-activity\":\r\n\t\t\t\t\tvar allTrips = [];\r\n\t\t\t\t\ttrkData.journeys.forEach(function (journey) {\r\n\t\t\t\t\t\tallTrips = allTrips.concat(journey.Trips);\r\n\t\t\t\t\t});\r\n\t\t\t\t\titems = allTrips;\r\n\t\t\t\t\tallItems = allTrips;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"journeys\":\r\n\t\t\titems = trkData.journeys;\r\n\t\t\tallItems = trkData.journeys;\r\n\t\t\tbreak;\r\n\t\tcase \"shared-views\":\r\n\t\t\titems = trkData.sharedViews;\r\n\t\t\tallItems = trkData.sharedViews;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tconsole.warn(\"Unknown item action selector type:\" + type);\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tconst options = selector.querySelector(\"#panel-secondary-item-options\");\r\n\toptions.innerHTML = \"\";\r\n\r\n\tlet isNext = true,\r\n\t\tisPrev = true;\r\n\tvar selectorOptions = document.createDocumentFragment();\r\n\tvar indexFirstEnabled = null;\r\n\tvar indexLastEnabled = 0;\r\n\tvar selectedIndex = 0;\r\n\tallItems.forEach(function (val, ind, list) {\r\n\t\tvar opt = document.createElement(\"option\");\r\n\t\topt.value = val.Id;\r\n\t\topt.textContent = (ind + 1).toString() + \": \" + val.Name;\r\n\t\topt.disabled = _.indexOf(items, val) === -1;\r\n\t\tif (currentItem.Id === val.Id) {\r\n\t\t\tselectedIndex = ind;\r\n\t\t\topt.setAttribute(\"selected\", \"selected\");\r\n\t\t}\r\n\t\tvar visibleOption = opt.cloneNode(true); // why?\r\n\t\tvisibleOption.textContent = val.Name;\r\n\t\toptions.appendChild(visibleOption);\r\n\t\tselectorOptions.appendChild(opt);\r\n\t\tif (!opt.disabled) {\r\n\t\t\tif (indexFirstEnabled === null) {\r\n\t\t\t\tindexFirstEnabled = ind;\r\n\t\t\t}\r\n\t\t\tindexLastEnabled = ind;\r\n\t\t}\r\n\t});\r\n\r\n\tisNext = selectedIndex < indexLastEnabled;\r\n\tisPrev = selectedIndex > indexFirstEnabled;\r\n\r\n\t//select.appendChild(selectorOptions);\r\n\t$selector.find(\"a\").removeClass(\"disabled\");\r\n\t$selector.find(\"button\").removeClass(\"disabled\").prop(\"disabled\", false);\r\n\tif (!isNext) {\r\n\t\t$selector.find(\"a.item-next\").addClass(\"disabled\");\r\n\t\t$selector.find(\"button.item-next\").addClass(\"disabled\").prop(\"disabled\", true);\r\n\t}\r\n\tif (!isPrev) {\r\n\t\t$selector.find(\"a.item-prev\").addClass(\"disabled\");\r\n\t\t$selector.find(\"button.item-prev\").addClass(\"disabled\").prop(\"disabled\", true);\r\n\t}\r\n}\r\n\r\nfunction populateMetaInformation(type, item) {\r\n\t// photo for geofence, place, asset, trip\r\n\tvar metaPanels = [\r\n\t\t\"meta-asset\",\r\n\t\t\"meta-group\",\r\n\t\t\"meta-trip\",\r\n\t\t\"meta-journey\",\r\n\t\t\"meta-fence\",\r\n\t\t\"meta-place\",\r\n\t\t\"meta-shared-view\",\r\n\t\t\"meta-place-group\",\r\n\t\t\"meta-fence-group\",\r\n\t];\r\n\tvar activePanel = \"meta-\" + type;\r\n\tvar metaPanel = document.getElementById(\"panel-secondary-meta\");\r\n\t//var metaRight = metaPanel.querySelector('.meta-right');\r\n\tif (type === \"asset\" || type === \"shared-view\") {\r\n\t\t//metaRight.classList.add('is-visible');\r\n\t\tmetaPanel.classList.add(\"show-right\");\r\n\t} else {\r\n\t\t//metaRight.classList.remove('is-visible');\r\n\t\tmetaPanel.classList.remove(\"show-right\");\r\n\t}\r\n\tswitch (type) {\r\n\t\tcase \"asset\":\r\n\t\t\t// notes, photo, uniqueid, device type\r\n\t\t\tvar notes = document.getElementById(\"meta-asset-notes\");\r\n\t\t\t//if (item.PhotoType != '') {\r\n\t\t\t// metaRight.classList.add('is-visible');\r\n\t\t\t// metaPanel.classList.add('show-right');\r\n\t\t\t//} else {\r\n\t\t\t// metaRight.classList.remove('is-visible');\r\n\t\t\t// metaPanel.classList.remove('show-right');\r\n\t\t\t//}\r\n\t\t\tif (item.Notes !== null && item.Notes !== \"\") {\r\n\t\t\t\tnotes.querySelector(\".meta-item\").textContent = item.Notes;\r\n\t\t\t\t//notes.classList.add('is-visible');\r\n\t\t\t} else {\r\n\t\t\t\tnotes.querySelector(\".meta-item\").textContent = strings.GROUP_NONE;\r\n\t\t\t\t//notes.classList.remove('is-visible');\r\n\t\t\t}\r\n\t\t\tvar device = findDeviceById(item.DeviceId);\r\n\t\t\tvar deviceName = document.getElementById(\"meta-asset-device\");\r\n\t\t\tif (options.hideDeviceName) {\r\n\t\t\t\tdeviceName.classList.remove(\"is-visible\");\r\n\t\t\t} else {\r\n\t\t\t\tdeviceName.querySelector(\".meta-item\").textContent = device.Name;\r\n\t\t\t\tdeviceName.classList.add(\"is-visible\");\r\n\t\t\t}\r\n\t\t\tvar uniqueId = document.getElementById(\"meta-asset-uniqueid\");\r\n\t\t\tuniqueId.querySelector(\".meta-item\").textContent = item.UniqueId;\r\n\t\t\tuniqueId.querySelector(\".meta-header\").textContent =\r\n\t\t\t\t$(\"#ddlEditAssetDeviceTypes option[value=\" + device.UniqueIdType + \"]\").text() + \":\";\r\n\t\t\tbreak;\r\n\t\tcase \"group\":\r\n\t\t\tbreak;\r\n\t\tcase \"fence\":\r\n\t\t\t// description\r\n\t\t\tvar description = document.getElementById(\"meta-group-description\");\r\n\t\t\tif (item.Description !== null && item.Description !== \"\") {\r\n\t\t\t\tdescription.querySelector(\".meta-item\").textContent = item.Description;\r\n\t\t\t\tdescription.classList.add(\"is-visible\");\r\n\t\t\t} else {\r\n\t\t\t\tdescription.classList.remove(\"is-visible\");\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"place\":\r\n\t\t\t// description, contact\r\n\t\t\tvar description = document.getElementById(\"meta-place-description\");\r\n\t\t\tif (item.Description !== null && item.Description !== \"\") {\r\n\t\t\t\tdescription.querySelector(\".meta-item\").textContent = item.Description;\r\n\t\t\t\tdescription.classList.add(\"is-visible\");\r\n\t\t\t} else {\r\n\t\t\t\tdescription.classList.remove(\"is-visible\");\r\n\t\t\t}\r\n\t\t\tvar contact = document.getElementById(\"meta-place-contact\");\r\n\t\t\tif (item.Contact !== null && item.Contact !== \"\") {\r\n\t\t\t\tcontact.querySelector(\".meta-item\").textContent = item.Contact;\r\n\t\t\t\tcontact.classList.add(\"is-visible\");\r\n\t\t\t} else {\r\n\t\t\t\tcontact.classList.remove(\"is-visible\");\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"shared-view\":\r\n\t\t\tvar status = document.getElementById(\"meta-shared-view-status\").querySelector(\".meta-item\");\r\n\t\t\tif (item.IsEnabled) {\r\n\t\t\t\tstatus.textContent = strings.ENABLED;\r\n\t\t\t} else {\r\n\t\t\t\tstatus.textContent = strings.DISABLED;\r\n\t\t\t}\r\n\r\n\t\t\tvar expires = document.getElementById(\"meta-shared-view-expiration\").querySelector(\".meta-item\");\r\n\t\t\tif (item.ExpiresOnEpoch === null) {\r\n\t\t\t\texpires.textContent = strings.NEVER;\r\n\t\t\t} else {\r\n\t\t\t\texpires.textContent = moment(item.ExpiresOnEpoch).format(user.shortDateFormat);\r\n\t\t\t}\r\n\r\n\t\t\tvar availability = document.getElementById(\"meta-shared-view-availability\").querySelector(\".meta-item\");\r\n\t\t\tif (item.IsPublic) {\r\n\t\t\t\tavailability.textContent = strings.PUBLIC;\r\n\t\t\t} else {\r\n\t\t\t\tavailability.textContent = strings.PRIVATE;\r\n\t\t\t}\r\n\r\n\t\t\tvar messaging = document.getElementById(\"meta-shared-view-messaging\").querySelector(\".meta-item\");\r\n\t\t\tif (item.IsMessagingEnabled) {\r\n\t\t\t\tmessaging.textContent = strings.ENABLED;\r\n\t\t\t} else {\r\n\t\t\t\tmessaging.textContent = strings.DISABLED;\r\n\t\t\t}\r\n\r\n\t\t\t// link\r\n\t\t\t//var link = document.getElementById('meta-shared-view-link');\r\n\t\t\tvar linkButton = document.getElementById(\"meta-shared-view-link\");\r\n\t\t\tvar linkLink = document.getElementById(\"meta-shared-view-link-link\");\r\n\t\t\tvar linkUrl = item.Link;\r\n\t\t\tlinkLink.textContent = linkUrl;\r\n\t\t\tlinkLink.setAttribute(\"href\", linkUrl);\r\n\t\t\tlinkButton.setAttribute(\"data-link\", linkUrl);\r\n\r\n\t\t\t// share links\r\n\t\t\tdocument.getElementById(\"shared-view-share-email\").querySelector(\"a\").setAttribute(\"data-share-view-id\", item.Id);\r\n\t\t\tdocument\r\n\t\t\t\t.getElementById(\"shared-view-share-twitter\")\r\n\t\t\t\t.querySelector(\"a\")\r\n\t\t\t\t.setAttribute(\r\n\t\t\t\t\t\"href\",\r\n\t\t\t\t\t\"https://twitter.com/intent/tweet?url=\" +\r\n\t\t\t\t\t\tencodeURIComponent(item.Link) +\r\n\t\t\t\t\t\t\"&text=\" +\r\n\t\t\t\t\t\tencodeURIComponent(item.Name) +\r\n\t\t\t\t\t\t\". \" +\r\n\t\t\t\t\t\tencodeURIComponent(item.Description)\r\n\t\t\t\t);\r\n\t\t\tdocument\r\n\t\t\t\t.getElementById(\"shared-view-share-linkedin\")\r\n\t\t\t\t.querySelector(\"a\")\r\n\t\t\t\t.setAttribute(\r\n\t\t\t\t\t\"href\",\r\n\t\t\t\t\t\"https://www.linkedin.com/shareArticle?mini=true&url=\" +\r\n\t\t\t\t\t\tencodeURIComponent(item.Link) +\r\n\t\t\t\t\t\t\"&title=\" +\r\n\t\t\t\t\t\tencodeURIComponent(item.Name) +\r\n\t\t\t\t\t\t\"&summary=\" +\r\n\t\t\t\t\t\tencodeURIComponent(item.Description) +\r\n\t\t\t\t\t\t\"&source=\" +\r\n\t\t\t\t\t\tencodeURIComponent(productTitle)\r\n\t\t\t\t);\r\n\t\t\tdocument\r\n\t\t\t\t.getElementById(\"shared-view-share-facebook\")\r\n\t\t\t\t.querySelector(\"a\")\r\n\t\t\t\t.setAttribute(\"href\", \"https://www.facebook.com/sharer.php?u=\" + encodeURIComponent(item.Link));\r\n\r\n\t\t\t// description\r\n\t\t\tvar description = document.getElementById(\"meta-shared-view-description\");\r\n\t\t\tif (item.Description !== null && item.Description !== \"\") {\r\n\t\t\t\tdescription.querySelector(\".meta-item\").textContent = item.Description;\r\n\t\t\t\tdescription.classList.add(\"is-visible\");\r\n\t\t\t} else {\r\n\t\t\t\tdescription.querySelector(\".meta-item\").textContent = \"\";\r\n\t\t\t\tdescription.classList.remove(\"is-visible\");\r\n\t\t\t}\r\n\r\n\t\t\tbreak;\r\n\t\tcase \"journey\":\r\n\t\t\tbreak;\r\n\t\tcase \"trip\":\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tmetaPanels.forEach(function (panel) {\r\n\t\tmetaPanel.querySelectorAll(\".\" + panel).forEach(function (item) {\r\n\t\t\tif (item !== null) {\r\n\t\t\t\tif (activePanel !== null && activePanel === panel) {\r\n\t\t\t\t\titem.classList.add(\"is-visible\");\r\n\t\t\t\t} else {\r\n\t\t\t\t\titem.classList.remove(\"is-visible\");\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\t});\r\n}\r\n\r\nexport function clearStatusMessage(elem) {\r\n\telem.textContent = \"\";\r\n\telem.classList.remove(\"alert-danger\");\r\n\telem.classList.remove(\"alert-success\");\r\n\telem.classList.remove(\"is-visible\");\r\n}\r\n\r\nfunction createSecondaryBreadcrumb(breadcrumbs) {\r\n\t// asset / action / grouping\r\n\t// add item / asset\r\n\tvar nav = document.createElement(\"nav\");\r\n\tnav.setAttribute(\"aria-label\", \"breadcrumb\");\r\n\tvar navList = document.createElement(\"ol\");\r\n\tnavList.className = \"breadcrumb p-0 m-0\";\r\n\tbreadcrumbs.forEach(function (breadcrumb, index, list) {\r\n\t\tvar navItem = document.createElement(\"li\");\r\n\t\tvar className = \"breadcrumb-item\";\r\n\t\tvar isCurrent = false;\r\n\t\tif (index === list.length - 1) {\r\n\t\t\tclassName += \" active\";\r\n\t\t\tnavItem.setAttribute(\"aria-current\", \"page\");\r\n\t\t\tisCurrent = true;\r\n\t\t}\r\n\t\tnavItem.className = className;\r\n\t\tif (!isCurrent) {\r\n\t\t\tvar navItemLink = document.createElement(\"a\");\r\n\t\t\tnavItemLink.setAttribute(\"href\", \"#\");\r\n\t\t\tObject.entries(breadcrumb.attributes).forEach(function ([key, val]) {\r\n\t\t\t\tnavItemLink.setAttribute(key, val);\r\n\t\t\t});\r\n\t\t\tnavItemLink.textContent = breadcrumb.label;\r\n\t\t\tnavItemLink.callback = breadcrumb.callback;\r\n\t\t\tnavItem.appendChild(navItemLink);\r\n\t\t} else {\r\n\t\t\tnavItem.textContent = breadcrumb.label;\r\n\t\t}\r\n\t\tnavList.appendChild(navItem);\r\n\t});\r\n\tnav.appendChild(navList);\r\n\treturn nav;\r\n}\r\n","import domNodes from \"./domNodes.js\";\r\nimport { mapModes } from \"./const.js\";\r\nimport trkData from \"./data.js\";\r\nimport { getDisplayFilterForEventType } from \"./display-filter.js\";\r\nimport { openDialogPanel } from \"./panel-nav.js\";\r\nimport state from \"./state.js\";\r\nimport strings from \"./strings.js\";\r\nimport { createListing, defaultListItemSort } from \"./item-listing.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport { toggleLoadingMessage } from \"./ajax.js\";\r\nimport { handleWebServiceError } from \"./ajax.js\";\r\n\r\nimport _ from \"lodash\";\r\nimport $j from \"jquery\";\r\n\r\nexport function updateAssetState(asset, state) {\r\n\t//var priorStatus = mapAssetStateToStatusState(asset.State);\r\n\tvar priorStatus = null;\r\n\tvar newStatus = mapAssetStateToStatusState(state);\r\n\tasset.State = state;\r\n\r\n\t_.each(domNodes.assets[asset.Id], function (assetNode) {\r\n\t\tif (state.activeMapMode === mapModes.LIVE) {\r\n\t\t\tupdateAssetStatusIconNodes(assetNode.querySelector(\".asset-indicators\"), newStatus, priorStatus, asset.Id);\r\n\t\t} else {\r\n\t\t\t// TODO: this seems bad, detach/reattach instead so they don't have to be recreated?\r\n\t\t\t// store in domNodes.assets[asset.Id].statuses or such\r\n\t\t\tvar status = assetNode.querySelectorAll(\".status\");\r\n\t\t\t_.each(status, function (item) {\r\n\t\t\t\titem.parentNode.removeChild(item);\r\n\t\t\t});\r\n\t\t}\r\n\t});\r\n}\r\n\r\nfunction createAssetStatusIconNode(title, iconClass, type) {\r\n\t// Title \r\n\tvar notifyType = \"notify-\" + iconClass;\r\n\tvar icon = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\r\n\ticon.classList.add(\"status\");\r\n\tif (type !== undefined && type !== null) {\r\n\t\ticon.classList.add(\"status-\" + type);\r\n\t\ticon.setAttributeNS(\"http://www.w3.org/2000/svg\", \"data-status\", iconClass);\r\n\t}\r\n\ticon.classList.add(notifyType);\r\n\tvar iconTitle = document.createElementNS(\"http://www.w3.org/2000/svg\", \"title\");\r\n\ticonTitle.textContent = title;\r\n\ticon.appendChild(iconTitle);\r\n\tvar iconType = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\r\n\ticonType.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#\" + notifyType);\r\n\ticon.appendChild(iconType);\r\n\treturn icon;\r\n}\r\n\r\nfunction updateAssetStatusIconNodes(node, status, priorStatus, assetId) {\r\n\tvar statusTitles = statusTitles;\r\n\tvar newIcons = document.createDocumentFragment();\r\n\tvar itemsAdded = false;\r\n\t// if was null, and now not null it must be added\r\n\t// else if was not null and now null it must be removed\r\n\t// else if not the same value then it must be updated\r\n\t// todo: re-add LPM interval to title\r\n\r\n\t// prior state is really just what is visible\r\n\r\n\t// TODO: detach/reattach nodes instead of removing/recreating?\r\n\r\n\tvar statusTypes = [\"movement\", \"engine\", \"satellite\", \"cellular\", \"power\"];\r\n\t_.each(statusTypes, function (statusType) {\r\n\t\t// don't necessarily like that we're doing a 5x query per node here\r\n\t\t// other method of state storage instead of DOM?\r\n\t\tvar priorStatusNode = node.querySelector(\".status-\" + statusType);\r\n\t\tif (priorStatusNode === null && status[statusType] !== null) {\r\n\t\t\t// new icon for state\r\n\t\t\tnewIcons.appendChild(createAssetStatusIconNode(statusTitles[status[statusType]], status[statusType], statusType));\r\n\t\t\titemsAdded = true;\r\n\t\t} else if (priorStatusNode !== null && status[statusType] === null) {\r\n\t\t\t// icon no longer known for state, so remove it\r\n\t\t\tvar iconNode = node.querySelector(\".status-\" + statusType);\r\n\t\t\tif (iconNode !== null) {\r\n\t\t\t\ticonNode.parentNode.removeChild(iconNode);\r\n\t\t\t}\r\n\t\t} else if (\r\n\t\t\tpriorStatusNode !== null &&\r\n\t\t\tpriorStatusNode.getAttributeNS(\"http://www.w3.org/2000/svg\", \"data-status\") !== status[statusType]\r\n\t\t) {\r\n\t\t\t// state of icon has changed, update it\r\n\t\t\tvar updateNode = node.querySelector(\".status-\" + statusType);\r\n\t\t\tif (updateNode !== null) {\r\n\t\t\t\t// remove prior status classes\r\n\t\t\t\t_.each(updateNode.classList, function (classItem) {\r\n\t\t\t\t\tif (classItem.indexOf(\"notify-\") !== -1) {\r\n\t\t\t\t\t\tupdateNode.classList.remove(classItem);\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t\tupdateNode.classList.add(\"notify-\" + status[statusType]);\r\n\t\t\t\tupdateNode.setAttributeNS(\"http://www.w3.org/2000/svg\", \"data-status\", status[statusType]);\r\n\t\t\t\tupdateNode\r\n\t\t\t\t\t.querySelector(\"use\")\r\n\t\t\t\t\t.setAttributeNS(\r\n\t\t\t\t\t\t\"http://www.w3.org/1999/xlink\",\r\n\t\t\t\t\t\t\"href\",\r\n\t\t\t\t\t\t\"/content/svg/tracking.svg?v=15#\" + \"notify-\" + status[statusType]\r\n\t\t\t\t\t);\r\n\t\t\t\tupdateNode.querySelector(\"title\").textContent = statusTitles[status[statusType]];\r\n\t\t\t}\r\n\t\t}\r\n\t});\r\n\r\n\tif (itemsAdded) {\r\n\t\tnode.appendChild(newIcons);\r\n\t}\r\n}\r\n\r\nfunction mapAssetStateToStatusState(state) {\r\n\tvar status = {\r\n\t\tmovement: null,\r\n\t\tengine: null,\r\n\t\tsatellite: null,\r\n\t\tcellular: null,\r\n\t\tpower: null,\r\n\t};\r\n\r\n\t// movement status\r\n\tif (state.IsSpeeding === true) {\r\n\t\tstatus.movement = \"speeding\";\r\n\t} else if (state.IsTowing === true) {\r\n\t\tstatus.movement = \"towing\";\r\n\t} else if (state.IsMoving === true) {\r\n\t\tstatus.movement = \"moving\";\r\n\t} else if (state.IsMoving === false || (state.IsMoving === null && state.IsTowing === false)) {\r\n\t\tstatus.movement = \"stationary\";\r\n\t}\r\n\r\n\t// engine status\r\n\tif (state.IsImmobilized === true) {\r\n\t\tstatus.engine = \"immobilized\";\r\n\t} else if (state.IsIdling === true) {\r\n\t\tstatus.engine = \"idling\";\r\n\t} else if (state.IsIgnitionOn === true) {\r\n\t\tstatus.engine = \"ignition-on\";\r\n\t} else if (state.IsIgnitionOn === false) {\r\n\t\tstatus.engine = \"ignition-off\";\r\n\t}\r\n\r\n\t// sat signal status\r\n\tif (state.IsAntennaCut === true) {\r\n\t\tstatus.satellite = \"antenna-cut\";\r\n\t} else if (state.IsGpsJammed === true) {\r\n\t\tstatus.satellite = \"gps-jammed\";\r\n\t} else if (state.IsInLowPowerMode === true) {\r\n\t\tstatus.satellite = \"low-power-mode\";\r\n\t}\r\n\r\n\t// cell signal status\r\n\tif (state.IsCellJammed === true) {\r\n\t\tstatus.cellular = \"cell-jammed\";\r\n\t}\r\n\r\n\t// power status\r\n\tif (state.IsOnBackupPower === true) {\r\n\t\tstatus.power = \"backup-power\";\r\n\t}\r\n\r\n\treturn status;\r\n}\r\n\r\nexport function createIconForAssetEvent(_asset, eventType) {\r\n\tvar text = _.find(trkData.eventTypes, { Id: eventType }).Text;\r\n\tswitch (eventType) {\r\n\t\tcase 21: // ignition on\r\n\t\t\treturn createAssetStatusIconNode(text, \"ignition-on\");\r\n\t\tcase 22: // ignition off\r\n\t\t\treturn createAssetStatusIconNode(text, \"ignition-off\");\r\n\t\tcase 47: // moving start\r\n\t\tcase 1: // start\r\n\t\t\treturn createAssetStatusIconNode(text, \"moving\");\r\n\t\tcase 48: // moving stop\r\n\t\tcase 2: // stop\r\n\t\t\treturn createAssetStatusIconNode(text, \"stationary\");\r\n\t\tcase 32: // 98 // idling\r\n\t\t\treturn createAssetStatusIconNode(text, \"idling\");\r\n\t\tcase 5: // 6\r\n\t\t\treturn createAssetStatusIconNode(text, \"speeding\");\r\n\t\tcase 3: // power on\r\n\t\t\treturn createAssetStatusIconNode(text, \"power-on\");\r\n\t\tcase 4: // power off\r\n\t\t\treturn createAssetStatusIconNode(text, \"power-off\");\r\n\t\tcase 45: // 46 // towing start\r\n\t\t\treturn createAssetStatusIconNode(text, \"towing\");\r\n\t\tcase 20: // 19 // on main power\r\n\t\t\treturn createAssetStatusIconNode(text, \"backup-power\");\r\n\t\tcase 35: // 129 // antenna cut start\r\n\t\t\treturn createAssetStatusIconNode(text, \"antenna-cut\");\r\n\t\tcase 36: // 37 // gps jamming start\r\n\t\t\treturn createAssetStatusIconNode(text, \"gps-jammed\");\r\n\t\tcase 38: // 39 // cell jamming start\r\n\t\t\treturn createAssetStatusIconNode(text, \"cell-jammed\");\r\n\t\tcase 133: // low battery\r\n\t\t\treturn createAssetStatusIconNode(text, \"low-battery\");\r\n\t\tcase 14: // alert triggered\r\n\t\t\treturn createAssetStatusIconNode(text, \"alert\");\r\n\t\tcase 16: // alert no longer triggered\r\n\t\t\treturn createAssetStatusIconNode(text, \"alert-cancel\");\r\n\t\tcase 15: // check-in\r\n\t\t\treturn createAssetStatusIconNode(text, \"check-in\");\r\n\t\tdefault:\r\n\t\t\treturn null;\r\n\t}\r\n}\r\n\r\nexport function openStatusForAsset(asset) {\r\n\tvar dataSource =\r\n\t\tstate.activeMapMode === mapModes.LIVE\r\n\t\t\t? trkData.live.normalizedEventsByAssetId\r\n\t\t\t: trkData.history.normalizedEventsByAssetId;\r\n\tvar events = _.sortBy(\r\n\t\t_.filter(dataSource[asset.Id], getDisplayFilterForEventType(\"status\")),\r\n\t\tdefaultListItemSort\r\n\t).reverse();\r\n\tcreateListing(events, \"status\");\r\n\topenDialogPanel(\r\n\t\tdomNodes.dialogs.assetStatus,\r\n\t\tstrings.STATUS,\r\n\t\tasset,\r\n\t\tfalse,\r\n\t\tnull,\r\n\t\t\"asset\",\r\n\t\t\"asset-status\",\r\n\t\topenStatusForAsset\r\n\t);\r\n}\r\n\r\nexport function loadAssetStatus(asset) {\r\n\tif (asset == null) return;\r\n\tvar btn = $j(\"#RefreshAssetStatus\");\r\n\tvar data = { assetId: asset.Id };\r\n\tbtn.addClass(\"disabled\").prop(\"disabled\", true);\r\n\ttoggleLoadingMessage(true, \"asset-status\");\r\n\treturn $j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/GetAssetStatus\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tbtn.removeClass(\"disabled\").prop(\"disabled\", false);\r\n\t\t\tif (msg.d) {\r\n\t\t\t\tvar result = msg.d;\r\n\t\t\t\tif (result.Success === true) {\r\n\t\t\t\t\t$j('#edit-asset-current-status input[value=\"\"]').prop(\"checked\", true);\r\n\t\t\t\t\t$j(\"input[name=rbEditAssetMoving][value=\" + result.Status.IsMoving + \"]\").prop(\"checked\", true);\r\n\t\t\t\t\t$j(\"input[name=rbEditAssetIgnitionOn][value=\" + result.Status.IsIgnitionOn + \"]\").prop(\"checked\", true);\r\n\t\t\t\t\t$j(\"input[name=rbEditAssetIdling][value=\" + result.Status.IsIdling + \"]\").prop(\"checked\", true);\r\n\t\t\t\t\t$j(\"input[name=rbEditAssetSpeeding][value=\" + result.Status.IsSpeeding + \"]\").prop(\"checked\", true);\r\n\t\t\t\t\t$j(\"input[name=rbEditAssetDwelling][value=\" + result.Status.IsDwelling + \"]\").prop(\"checked\", true);\r\n\t\t\t\t\t$j(\"input[name=rbEditAssetTowing][value=\" + result.Status.IsTowing + \"]\").prop(\"checked\", true);\r\n\t\t\t\t\t$j(\"input[name=rbEditAssetInLowPowerMode][value=\" + result.Status.IsInLowPowerMode + \"]\").prop(\r\n\t\t\t\t\t\t\"checked\",\r\n\t\t\t\t\t\ttrue\r\n\t\t\t\t\t);\r\n\t\t\t\t\t$j(\"input[name=rbEditAssetOnBackupPower][value=\" + result.Status.IsOnBackupPower + \"]\").prop(\"checked\", true);\r\n\t\t\t\t\t$j(\"input[name=rbEditAssetAntennaCut][value=\" + result.Status.IsAntennaCut + \"]\").prop(\"checked\", true);\r\n\t\t\t\t\t$j(\"input[name=rbEditAssetGpsJammed][value=\" + result.Status.IsGpsJammed + \"]\").prop(\"checked\", true);\r\n\t\t\t\t\t$j(\"input[name=rbEditAssetCellJammed][value=\" + result.Status.IsCellJammed + \"]\").prop(\"checked\", true);\r\n\t\t\t\t\t$j(\"input[name=rbEditAssetImmobilized][value=\" + result.Status.IsImmobilized + \"]\").prop(\"checked\", true);\r\n\t\t\t\t\t$j(\"#EditAssetShockLogAlarmCount\").text(result.Status.ShockLogAlarmCount);\r\n\t\t\t\t\tupdateAssetState(asset, result.Status);\r\n\t\t\t\t} else {\r\n\t\t\t\t\thandleWebServiceError(strings.MSG_GET_STATUS_ERROR);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ttoggleLoadingMessage(false, \"asset-status\");\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\thandleWebServiceError(strings.MSG_GET_STATUS_ERROR);\r\n\t\t\ttoggleLoadingMessage(false, \"asset-status\");\r\n\t\t\tbtn.removeClass(\"disabled\").prop(\"disabled\", false);\r\n\t\t},\r\n\t});\r\n}\r\n","import strings from \"./strings.js\";\r\nimport state from \"./state.js\";\r\nimport user from \"./user.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { viewModes } from \"./const.js\";\r\nimport { EVENTS_STATUS, EVENTS_EMERGENCY, EVENTS_ALERT } from \"./asset-events.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport _ from \"lodash\";\r\nimport { setChildren } from \"redom\"; // https://redom.js.org/\r\n\r\nexport function renderListItem(item, index) {\r\n\t// TODO filter out text message events that are not Chats before this is called\r\n\tvar li = undefined;\r\n\tif (item.IsChat !== undefined) {\r\n\t\tli = renderMessageListItem(item, index); // TODO different chat rendering\r\n\t} else if (item.MessageId !== undefined) {\r\n\t\tli = renderMessageListItem(item, index);\r\n\t} else if (item.EventId !== undefined) {\r\n\t\tli = renderEventListItem(item, index);\r\n\t} else if (item.PositionId !== undefined) {\r\n\t\tli = renderPositionListItem(item, index);\r\n\t} else if (item.Items !== undefined) {\r\n\t\tli = renderActivityListItem(item, index);\r\n\t}\r\n\treturn li;\r\n}\r\n\r\nfunction renderMessageListItem(item, index) {\r\n\tif (item === undefined) {\r\n\t\treturn undefined;\r\n\t}\r\n\r\n\tvar dataSource = state.activeViewMode === viewModes.SHARED_VIEW ? domNodes.sharedView : domNodes;\r\n\tvar existing = dataSource.messageListingById[item.MessageId];\r\n\tif (existing !== undefined) {\r\n\t\tsetListItemIndex(existing, index);\r\n\t\treturn existing;\r\n\t}\r\n\r\n\tvar li = document.createElement(\"li\");\r\n\tli.className = item.IsFromMobile ? \"from-mobile\" : \"to-mobile\";\r\n\tvar isHidden = item.Position !== undefined && item.Position !== null && item.Position.IsHidden;\r\n\tif (isHidden) {\r\n\t\tli.classList.add(\"is-hidden\");\r\n\t}\r\n\r\n\tvar header = renderListItemHeader(item.EventName, item.Position, \"messages\", item.AssetId, index);\r\n\r\n\t//// info button to view raw message, if available\r\n\t//if (!item.IsFromMobile && item.RawText !== undefined && item.RawText !== null && item.RawText !== '') {\r\n\t// var infoLink = document.createElement('a');\r\n\t// infoLink.className = 'message-info';\r\n\t// infoLink.setAttribute('href', '#');\r\n\t// infoLink.setAttribute('title', item.RawText);\r\n\r\n\t// var infoIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\r\n\t// var infoIconContents = document.createElementNS('http://www.w3.org/2000/svg', 'use');\r\n\t// infoIconContents.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '/content/svg/tracking.svg?v=15#info-circle');\r\n\t// infoIcon.appendChild(infoIconContents);\r\n\t// infoLink.appendChild(infoIcon);\r\n\t// header.appendChild(infoLink);\r\n\t// $(infoLink).bsTooltip();\r\n\t//}\r\n\r\n\tvar contents = document.createElement(\"div\");\r\n\tcontents.className = \"list-contents\";\r\n\r\n\tvar row = renderListItemCommonMeta(item, true, true, true);\r\n\tcontents.appendChild(row);\r\n\r\n\t// details - if alert, have this be toggleable\r\n\tvar details = document.createElement(\"div\");\r\n\tdetails.className = \"event-details break-text\";\r\n\tif (item.Details !== null && item.Details !== undefined) {\r\n\t\tdetails.classList.add(\"is-inline\");\r\n\t\tsetChildren(details, item.Details);\r\n\t}\r\n\r\n\tcontents.appendChild(details);\r\n\tli.appendChild(header);\r\n\tli.appendChild(contents);\r\n\r\n\tdataSource.messageListingById[item.MessageId] = li;\r\n\treturn li;\r\n}\r\n\r\nfunction renderEventListItem(item, index) {\r\n\tif (item === undefined) {\r\n\t\treturn undefined;\r\n\t}\r\n\tvar dataSource = state.activeViewMode === viewModes.SHARED_VIEW ? domNodes.sharedView : domNodes;\r\n\tvar existing = dataSource.eventListingById[item.EventId];\r\n\tif (existing !== undefined) {\r\n\t\tsetListItemIndex(existing, index);\r\n\t\treturn existing;\r\n\t}\r\n\r\n\tvar isEmergencyAlert = false;\r\n\tvar listItemGroup = \"events\";\r\n\tif (EVENTS_STATUS.indexOf(item.Type) !== -1) {\r\n\t\tlistItemGroup = \"status\";\r\n\t} else if (EVENTS_ALERT.indexOf(item.Type) !== -1) {\r\n\t\tlistItemGroup = \"alerts\";\r\n\t} else if (EVENTS_EMERGENCY.indexOf(item.Type) !== -1) {\r\n\t\tlistItemGroup = \"alerts\";\r\n\t\tisEmergencyAlert = true;\r\n\t} else {\r\n\t\tlistItemGroup = \"events\";\r\n\t}\r\n\r\n\tvar isHidden = item.Position !== undefined && item.Position !== null && item.Position.IsHidden;\r\n\tvar li = document.createElement(\"li\");\r\n\tif (isEmergencyAlert) {\r\n\t\tli.classList.add(\"is-emergency\");\r\n\t}\r\n\tif (isHidden) {\r\n\t\tli.classList.add(\"is-hidden\");\r\n\t}\r\n\r\n\tvar header = renderListItemHeader(item.EventName, item.Position, listItemGroup, item.AssetId, index);\r\n\r\n\tvar contents = document.createElement(\"div\");\r\n\tcontents.className = \"list-contents\";\r\n\t// asset icon if group listing\r\n\r\n\tvar row = renderListItemCommonMeta(item, true, true, true);\r\n\tcontents.appendChild(row);\r\n\r\n\t// details header (for alerts and grouped events/activity)\r\n\tvar eventDetailsHeader = renderListItemDetailsHeader(item, false);\r\n\tif (eventDetailsHeader !== undefined) {\r\n\t\tcontents.appendChild(eventDetailsHeader);\r\n\t}\r\n\tvar eventDetails = renderListItemDetails(item, false);\r\n\tif (eventDetails !== undefined) {\r\n\t\tcontents.appendChild(eventDetails);\r\n\t}\r\n\r\n\tli.appendChild(header);\r\n\tli.appendChild(contents);\r\n\r\n\tdataSource.eventListingById[item.EventId] = li;\r\n\treturn li;\r\n}\r\n\r\nfunction renderPositionListItem(item, index) {\r\n\tif (item === undefined) {\r\n\t\treturn undefined;\r\n\t}\r\n\r\n\tvar dataSource = state.activeViewMode === viewModes.SHARED_VIEW ? domNodes.sharedView : domNodes;\r\n\tvar existing = dataSource.positionListingById[item.PositionId];\r\n\tif (existing !== undefined) {\r\n\t\tsetListItemIndex(existing, index);\r\n\t\treturn existing;\r\n\t}\r\n\r\n\tvar li = document.createElement(\"li\");\r\n\tvar isHidden = item.Position !== undefined && item.Position !== null && item.Position.IsHidden;\r\n\tif (isHidden) {\r\n\t\tli.classList.add(\"is-hidden\");\r\n\t}\r\n\r\n\tvar hasAddress = item.Position.Address !== null;\r\n\tvar itemName = hasAddress ? item.Position.Address : item.Position.LatLng;\r\n\tvar header = renderListItemHeader(itemName, item.Position, \"positions\", item.AssetId, index);\r\n\r\n\tvar contents = document.createElement(\"div\");\r\n\tcontents.className = \"list-contents\";\r\n\r\n\tvar row = renderListItemCommonMeta(item, false, hasAddress, true);\r\n\tcontents.appendChild(row);\r\n\r\n\tli.appendChild(header);\r\n\tli.appendChild(contents);\r\n\r\n\tdataSource.positionListingById[item.PositionId] = li;\r\n\treturn li;\r\n}\r\n\r\nfunction renderActivityListItem(groupItem, index) {\r\n\t// special handling of activity list items which are grouped by Epoch and formatted differently\r\n\tif (groupItem === undefined) {\r\n\t\treturn undefined;\r\n\t}\r\n\r\n\tvar dataSource = state.activeViewMode === viewModes.SHARED_VIEW ? domNodes.sharedView : domNodes;\r\n\tvar existing = dataSource.activityListingById[groupItem.EpochGroup];\r\n\tif (existing !== undefined) {\r\n\t\tsetListItemIndex(existing, index);\r\n\t\treturn existing;\r\n\t}\r\n\r\n\tvar firstItem = _.first(groupItem.Items);\r\n\tvar itemWithPosition = _.find(groupItem.Items, function (item) {\r\n\t\treturn item.Position !== undefined && item.Position !== null;\r\n\t});\r\n\r\n\tvar li = document.createElement(\"li\");\r\n\tvar position = undefined;\r\n\tif (itemWithPosition !== undefined) {\r\n\t\tposition = itemWithPosition.Position;\r\n\t}\r\n\tvar isHidden = position !== undefined && position !== null && position.IsHidden;\r\n\tif (isHidden) {\r\n\t\tli.classList.add(\"is-hidden\");\r\n\t}\r\n\r\n\tvar header = renderListItemHeader(firstItem.Time, position, \"activity\", groupItem.AssetId, index);\r\n\tli.appendChild(header);\r\n\r\n\tvar contents = document.createElement(\"div\");\r\n\tcontents.className = \"list-contents\";\r\n\r\n\t// common items for the position, but what if we don't have a position?\r\n\t// and we don't need time!\r\n\tvar isGrouped = true;\r\n\tvar showAddress = true;\r\n\tvar showLatLng = true;\r\n\tvar showTime = false;\r\n\tvar row = renderListItemCommonMeta(\r\n\t\titemWithPosition !== undefined ? itemWithPosition : firstItem,\r\n\t\tshowAddress,\r\n\t\tshowLatLng,\r\n\t\tshowTime\r\n\t);\r\n\tif (row !== undefined) {\r\n\t\tcontents.appendChild(row);\r\n\t}\r\n\r\n\tif (itemWithPosition !== undefined) {\r\n\t\t// additional position details\r\n\t\tvar positionDetails = renderListItemPositionDetails(itemWithPosition);\r\n\t\tif (positionDetails !== undefined) {\r\n\t\t\tcontents.appendChild(positionDetails);\r\n\t\t}\r\n\t}\r\n\r\n\t_.each(groupItem.Items, function (item) {\r\n\t\tvar eventDetailsHeader = renderListItemDetailsHeader(item, isGrouped);\r\n\t\tif (eventDetailsHeader !== undefined) {\r\n\t\t\tcontents.appendChild(eventDetailsHeader);\r\n\t\t}\r\n\t\tvar eventDetails = renderListItemDetails(item, isGrouped);\r\n\t\tif (eventDetails !== undefined) {\r\n\t\t\tcontents.appendChild(eventDetails);\r\n\t\t}\r\n\t});\r\n\tli.appendChild(contents);\r\n\r\n\tdataSource.activityListingById[groupItem.EpochGroup] = li;\r\n\treturn li;\r\n}\r\nfunction renderListItemHeader(name, position, type, assetId, index) {\r\n\tvar header = document.createElement(\"div\");\r\n\theader.className = \"list-header\";\r\n\r\n\tvar typeIcon = renderListItemIcon(type);\r\n\theader.appendChild(typeIcon);\r\n\r\n\tif (position !== undefined && position !== null) {\r\n\t\tvar listItemTypeNameLink = document.createElement(\"a\");\r\n\t\tlistItemTypeNameLink.textContent = name;\r\n\t\tlistItemTypeNameLink.className = \"event-name location\";\r\n\t\tlistItemTypeNameLink.setAttribute(\"href\", \"#\");\r\n\t\tlistItemTypeNameLink.setAttribute(\"data-marker\", position.Id);\r\n\t\tlistItemTypeNameLink.setAttribute(\"data-time\", position.Time);\r\n\t\tlistItemTypeNameLink.setAttribute(\"data-asset\", assetId);\r\n\t\tlistItemTypeNameLink.setAttribute(\"data-hidden\", position.IsHidden);\r\n\t\theader.appendChild(listItemTypeNameLink);\r\n\t} else {\r\n\t\tvar listItemTypeName = document.createElement(\"span\");\r\n\t\tlistItemTypeName.textContent = name;\r\n\t\tlistItemTypeName.className = \"event-name\";\r\n\t\theader.appendChild(listItemTypeName);\r\n\t}\r\n\r\n\tif (position !== undefined && position !== null) {\r\n\t\tif (user.canEditAssets) {\r\n\t\t\tvar mapVisibility = document.createElement(\"a\");\r\n\t\t\tmapVisibility.className = \"map-toggle\";\r\n\t\t\tmapVisibility.setAttribute(\"href\", \"#\");\r\n\t\t\tmapVisibility.setAttribute(\"data-marker\", position.Id);\r\n\t\t\tmapVisibility.setAttribute(\"data-asset\", assetId);\r\n\t\t\tmapVisibility.setAttribute(\"data-hidden\", position.IsHidden);\r\n\t\t\tmapVisibility.title = position.IsHidden ? strings.SHOW_ON_MAP : strings.HIDE_ON_MAP;\r\n\r\n\t\t\tvar mapVisibilityIcon = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\r\n\t\t\tvar mapVisibilityIconContents = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\r\n\t\t\tmapVisibilityIconContents.setAttributeNS(\r\n\t\t\t\t\"http://www.w3.org/1999/xlink\",\r\n\t\t\t\t\"href\",\r\n\t\t\t\t\"/content/svg/tracking.svg?v=15#\" + (position.IsHidden ? \"invisible\" : \"visible\")\r\n\t\t\t);\r\n\t\t\tmapVisibilityIcon.appendChild(mapVisibilityIconContents);\r\n\t\t\tmapVisibility.appendChild(mapVisibilityIcon);\r\n\t\t\theader.appendChild(mapVisibility);\r\n\t\t}\r\n\r\n\t\tvar mapLink = document.createElement(\"a\");\r\n\t\tmapLink.className = \"location map-hilight\";\r\n\t\tmapLink.setAttribute(\"href\", \"#\");\r\n\t\tmapLink.setAttribute(\"data-marker\", position.Id);\r\n\t\tmapLink.setAttribute(\"data-time\", position.Time);\r\n\t\tmapLink.setAttribute(\"data-asset\", assetId);\r\n\r\n\t\tvar mapIcon = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\r\n\t\tvar mapIconContents = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\r\n\t\tmapIconContents.setAttributeNS(\r\n\t\t\t\"http://www.w3.org/1999/xlink\",\r\n\t\t\t\"href\",\r\n\t\t\t\"/content/svg/tracking.svg?v=15#globe-americas\"\r\n\t\t);\r\n\t\tmapIcon.appendChild(mapIconContents);\r\n\t\tmapLink.appendChild(mapIcon);\r\n\t\theader.appendChild(mapLink);\r\n\t}\r\n\r\n\t// position in list\r\n\tvar itemIndex = document.createElement(\"span\");\r\n\titemIndex.className = \"item-index\";\r\n\titemIndex.textContent = \"#\" + (index + 1);\r\n\theader.appendChild(itemIndex);\r\n\treturn header;\r\n}\r\n\r\nfunction renderListItemCommonMeta(item, includeAddress, includeLatLng, includeTime) {\r\n\tif (item === undefined) {\r\n\t\treturn undefined;\r\n\t}\r\n\tvar row = document.createElement(\"div\");\r\n\trow.className = \"list-item-row\";\r\n\r\n\tvar assetIcon = document.createElement(\"div\");\r\n\tassetIcon.className = \"item-icon item-asset-name\";\r\n\tassetIcon.style.backgroundImage = \"url(\" + item.IconUrl + \")\";\r\n\trow.appendChild(assetIcon);\r\n\r\n\tvar meta = document.createElement(\"div\");\r\n\tmeta.className = \"item-metadata\";\r\n\r\n\t// details\r\n\tvar assetLine = document.createElement(\"div\");\r\n\tassetLine.className = \"item-asset-name\";\r\n\r\n\tvar assetNameLabel = document.createElement(\"span\");\r\n\tassetNameLabel.className = \"item-label\";\r\n\tassetNameLabel.textContent = strings.ASSET + \": \";\r\n\r\n\tvar assetName = document.createElement(\"span\");\r\n\tassetName.className = \"event-asset-name\";\r\n\tassetName.textContent = item.AssetName;\r\n\tassetLine.appendChild(assetNameLabel);\r\n\tassetLine.appendChild(assetName);\r\n\tmeta.appendChild(assetLine);\r\n\r\n\t//if (includeLatLng && item.Position !== undefined && item.Position !== null) {\r\n\t// // lat/lng\r\n\t// var latLngLine = document.createElement('div');\r\n\t// var latLngLabel = document.createElement('span');\r\n\t// latLngLabel.className = 'item-label';\r\n\t// latLngLabel.textContent = strings.LAT_LNG + ': ';\r\n\t// latLngLine.appendChild(latLngLabel);\r\n\r\n\t// var latLngLink = document.createElement('a');\r\n\t// latLngLink.setAttribute('href', '#');\r\n\t// latLngLink.className = 'event-latlng location';\r\n\t// latLngLink.setAttribute('data-marker', item.Position.Id);\r\n\t// latLngLink.setAttribute('data-time', item.Position.Time);\r\n\t// latLngLink.setAttribute('data-asset', item.AssetId);\r\n\t// latLngLink.textContent = item.Position.LatLng;\r\n\t// latLngLine.appendChild(latLngLink);\r\n\t// meta.appendChild(latLngLine);\r\n\t//}\r\n\r\n\tif (includeAddress && item.Position !== undefined && item.Position !== null && item.Position.Address !== null) {\r\n\t\tvar addressLine = document.createElement(\"div\");\r\n\t\tvar addressLabel = document.createElement(\"span\");\r\n\t\taddressLabel.className = \"item-label\";\r\n\t\taddressLabel.textContent = strings.ADDRESS + \": \";\r\n\t\tvar address = document.createElement(\"a\");\r\n\t\taddress.setAttribute(\"href\", \"#\");\r\n\t\taddress.className = \"event-location location\";\r\n\t\taddress.setAttribute(\"data-marker\", item.Position.Id);\r\n\t\taddress.setAttribute(\"data-time\", item.Position.Time);\r\n\t\taddress.setAttribute(\"data-asset\", item.AssetId);\r\n\t\taddress.textContent = item.Position.Address;\r\n\t\taddressLine.appendChild(addressLabel);\r\n\t\taddressLine.appendChild(address);\r\n\t\tmeta.appendChild(addressLine);\r\n\t}\r\n\r\n\tif (includeLatLng && item.Position !== undefined && item.Position !== null && item.Position.LatLng !== null) {\r\n\t\tvar latLngLine = document.createElement(\"div\");\r\n\t\tvar latLngLabel = document.createElement(\"span\");\r\n\t\tlatLngLabel.className = \"item-label\";\r\n\t\tlatLngLabel.textContent = strings.LAT_LNG + \": \";\r\n\t\tlatLngLine.appendChild(latLngLabel);\r\n\r\n\t\tif (!includeAddress || item.Position.Address === null) {\r\n\t\t\tvar latLngLink = document.createElement(\"a\");\r\n\t\t\tlatLngLink.setAttribute(\"href\", \"#\");\r\n\t\t\tlatLngLink.className = \"event-latlng location\";\r\n\t\t\tlatLngLink.setAttribute(\"data-marker\", item.Position.Id);\r\n\t\t\tlatLngLink.setAttribute(\"data-time\", item.Position.Time);\r\n\t\t\tlatLngLink.setAttribute(\"data-asset\", item.AssetId);\r\n\t\t\tlatLngLink.textContent = item.Position.LatLng;\r\n\t\t\tlatLngLine.appendChild(latLngLink);\r\n\t\t} else {\r\n\t\t\tvar latLngValue = document.createElement(\"span\");\r\n\t\t\tlatLngValue.className = \"event-latlng\";\r\n\t\t\tlatLngValue.textContent = item.Position.LatLng;\r\n\t\t\tlatLngLine.appendChild(latLngValue);\r\n\t\t}\r\n\t\tmeta.appendChild(latLngLine);\r\n\t}\r\n\r\n\t// time\r\n\tif (includeTime) {\r\n\t\tvar timeLine = document.createElement(\"div\");\r\n\t\tvar timeLabel = document.createElement(\"span\");\r\n\t\ttimeLabel.className = \"item-label\";\r\n\t\ttimeLabel.textContent = strings.TIME + \": \";\r\n\t\ttimeLine.appendChild(timeLabel);\r\n\t\tvar timeValue = document.createElement(\"span\");\r\n\t\ttimeValue.className = \"item-time index\";\r\n\t\ttimeValue.textContent = item.Time;\r\n\t\ttimeLine.appendChild(timeValue);\r\n\t\t//timeValue.setAttribute('data-epoch', position.epoch);\r\n\r\n\t\tvar epochValue = document.createElement(\"span\");\r\n\t\tepochValue.className = \"hidden item-epoch\";\r\n\t\tepochValue.textContent = item.Epoch;\r\n\t\ttimeLine.appendChild(epochValue);\r\n\t\tmeta.appendChild(timeLine);\r\n\t}\r\n\r\n\t// position-specific\r\n\tif (item.EventTypes !== undefined && item.EventTypes !== null && item.EventTypes !== \"\") {\r\n\t\tvar typesLine = document.createElement(\"div\");\r\n\t\tvar typesLabel = document.createElement(\"span\");\r\n\t\ttypesLabel.className = \"item-label\";\r\n\t\ttypesLabel.textContent = strings.TYPE + \": \";\r\n\t\ttypesLine.appendChild(typesLabel);\r\n\t\tvar typesValue = document.createElement(\"span\");\r\n\t\ttypesValue.className = \"item-types index\";\r\n\t\ttypesValue.textContent = item.EventTypes;\r\n\t\ttypesLine.appendChild(typesValue);\r\n\t\tmeta.appendChild(typesLine);\r\n\t}\r\n\r\n\t// message-specific\r\n\tif (item.Source !== undefined && item.Source !== null) {\r\n\t\tvar sourceLine = document.createElement(\"div\");\r\n\t\tvar sourceLabel = document.createElement(\"span\");\r\n\t\tsourceLabel.className = \"item-label\";\r\n\t\tsourceLabel.textContent = strings.DATA_SOURCE + \": \";\r\n\t\tsourceLine.appendChild(sourceLabel);\r\n\t\tvar sourceValue = document.createElement(\"span\");\r\n\t\tsourceValue.className = \"item-source\";\r\n\t\tsourceValue.textContent = item.Source;\r\n\t\tsourceLine.appendChild(sourceValue);\r\n\t\tmeta.appendChild(sourceLine);\r\n\t}\r\n\r\n\tif (item.Method !== undefined && item.Method !== null) {\r\n\t\tvar methodLine = document.createElement(\"div\");\r\n\t\tvar methodLabel = document.createElement(\"span\");\r\n\t\tmethodLabel.className = \"item-label\";\r\n\t\tmethodLabel.textContent = strings.METHOD + \": \";\r\n\t\tmethodLine.appendChild(methodLabel);\r\n\t\tvar methodValue = document.createElement(\"span\");\r\n\t\tmethodValue.className = \"item-method\";\r\n\t\tmethodValue.textContent = item.Method;\r\n\t\tmethodLine.appendChild(methodValue);\r\n\t\tmeta.appendChild(methodLine);\r\n\t}\r\n\r\n\tif (item.IsFromMobile !== undefined && !item.IsFromMobile) {\r\n\t\t// && item.Status !== undefined && item.Status !== null) {\r\n\t\tvar statusLine = document.createElement(\"div\");\r\n\t\tvar statusLabel = document.createElement(\"span\");\r\n\t\tstatusLabel.className = \"item-label\";\r\n\t\tstatusLabel.textContent = strings.STATUS + \": \";\r\n\t\tstatusLine.appendChild(statusLabel);\r\n\t\tif (item.IsError) {\r\n\t\t\tvar statusValue = document.createElement(\"a\");\r\n\t\t\tstatusValue.className = \"item-status error\";\r\n\t\t\tstatusValue.setAttribute(\"href\", \"#\");\r\n\t\t\tstatusValue.setAttribute(\"data-message-id\", item.Id);\r\n\t\t\tif (item.Response !== null) {\r\n\t\t\t\tstatusValue.setAttribute(\"title\", item.Response);\r\n\t\t\t\t$(statusValue).bsTooltip();\r\n\t\t\t}\r\n\t\t\tstatusValue.textContent = item.Status;\r\n\t\t\tstatusLine.appendChild(statusValue);\r\n\t\t} else {\r\n\t\t\tvar statusValue = document.createElement(\"span\");\r\n\t\t\tstatusValue.className = \"item-status\";\r\n\t\t\tstatusValue.textContent = item.Status;\r\n\t\t\tstatusLine.appendChild(statusValue);\r\n\t\t}\r\n\t\tmeta.appendChild(statusLine);\r\n\t}\r\n\r\n\t// other info\r\n\trow.appendChild(meta);\r\n\treturn row;\r\n}\r\n\r\nfunction renderListItemDetails(item, isGrouped) {\r\n\tvar alert = item.Alert;\r\n\tif (alert === null) {\r\n\t\talert = undefined;\r\n\t}\r\n\tif (\r\n\t\t(item.Details === undefined && alert === undefined) ||\r\n\t\t(item.Details === null && alert === undefined) ||\r\n\t\t(item.Details === \"\" && alert === undefined)\r\n\t) {\r\n\t\treturn undefined;\r\n\t}\r\n\tvar details = document.createElement(\"div\");\r\n\tdetails.id = \"event-details-\" + item.Id;\r\n\tdetails.className = \"event-details break-text\";\r\n\tif (item.Details !== null) {\r\n\t\tdetails.classList.add(\"is-inline\");\r\n\t\tsetChildren(details, item.Details);\r\n\t}\r\n\r\n\tif (isGrouped || alert !== undefined) {\r\n\t\t// will have a header to expand/contract this section\r\n\t\tdetails.classList.add(\"collapse\");\r\n\t\tdetails.classList.remove(\"is-inline\");\r\n\t}\r\n\r\n\tif (alert !== undefined) {\r\n\t\t// alert triggered/no longer triggered event\r\n\t\tif (item.Type === 14) {\r\n\t\t\t// alert triggered\r\n\t\t\tif (alert.Acknowledged === 0) {\r\n\t\t\t\t// add alert acknowledgement form elements\r\n\t\t\t\tvar form = document.createElement(\"form\");\r\n\t\t\t\tform.id = \"asset-alert-acknowledge-\" + item.EventId;\r\n\t\t\t\tform.setAttribute(\"data-alert-id\", alert.Id);\r\n\t\t\t\tform.setAttribute(\"data-asset-id\", item.AssetId);\r\n\t\t\t\tform.setAttribute(\"data-event-id\", item.EventId);\r\n\r\n\t\t\t\tvar status = document.createElement(\"div\");\r\n\t\t\t\tstatus.id = \"asset-alert-acknowledge-status-\" + item.EventId;\r\n\t\t\t\tstatus.className = \"dialog-status alert toggle-content\";\r\n\r\n\t\t\t\tvar resolution = document.createElement(\"div\");\r\n\t\t\t\tresolution.className = \"alert-resolution form-group\";\r\n\t\t\t\tvar resolutionLabel = document.createElement(\"label\");\r\n\t\t\t\tresolutionLabel.setAttribute(\"for\", \"asset-alert-resolution-\" + item.EventId);\r\n\t\t\t\tresolutionLabel.textContent = strings.RESOLUTION;\r\n\t\t\t\tresolution.appendChild(resolutionLabel);\r\n\t\t\t\tvar resolutionText = document.createElement(\"textarea\");\r\n\t\t\t\tresolutionText.id = \"asset-alert-resolution-\" + item.EventId;\r\n\t\t\t\tresolutionText.className = \"form-control required\";\r\n\t\t\t\tresolution.appendChild(resolutionText);\r\n\r\n\t\t\t\tvar textAcknowledge = alert.LabelAcknowledge !== null ? alert.LabelAcknowledge : strings.ACKNOWLEDGE;\r\n\t\t\t\tvar textAcknowledgeAlt =\r\n\t\t\t\t\talert.LabelAcknowledgeAlt !== null ? alert.LabelAcknowledgeAlt : strings.ACKNOWLEDGE_ALT;\r\n\t\t\t\tvar acknowledge = document.createElement(\"div\");\r\n\t\t\t\tacknowledge.className = \"alert-acknowledge dialog-buttons\";\r\n\t\t\t\tvar ackButton = document.createElement(\"button\");\r\n\t\t\t\tackButton.className = \"btn btn-primary alert-acknowledge\";\r\n\t\t\t\tackButton.textContent = textAcknowledge;\r\n\t\t\t\tvar altAckButton = document.createElement(\"button\");\r\n\t\t\t\taltAckButton.className = \"btn btn-secondary alert-acknowledge-alt\";\r\n\t\t\t\taltAckButton.textContent = textAcknowledgeAlt;\r\n\t\t\t\tacknowledge.appendChild(ackButton);\r\n\t\t\t\tacknowledge.appendChild(altAckButton);\r\n\r\n\t\t\t\tform.appendChild(status);\r\n\t\t\t\tform.appendChild(resolution);\r\n\t\t\t\tform.appendChild(acknowledge);\r\n\t\t\t\tdetails.appendChild(form);\r\n\t\t\t} else {\r\n\t\t\t\t// include acknowledged by details\r\n\t\t\t\tvar resolution = document.createElement(\"div\");\r\n\t\t\t\tresolution.className = \"alert-resolution form-group\";\r\n\t\t\t\tvar resolutionLabel = document.createElement(\"label\");\r\n\t\t\t\tresolutionLabel.setAttribute(\"for\", \"asset-alert-resolution-\" + item.EventId);\r\n\t\t\t\tresolutionLabel.textContent = strings.RESOLUTION;\r\n\t\t\t\tresolution.appendChild(resolutionLabel);\r\n\t\t\t\tvar resolutionText = document.createElement(\"span\");\r\n\t\t\t\tresolutionText.id = \"asset-alert-resolution-\" + item.EventId;\r\n\t\t\t\tresolutionText.className = \"form-control-plaintext\";\r\n\t\t\t\tresolutionText.textContent = alert.AcknowledgedText;\r\n\t\t\t\tresolution.appendChild(resolutionText);\r\n\r\n\t\t\t\tvar status = document.createElement(\"div\");\r\n\t\t\t\tstatus.className = \"alert-status form-group\";\r\n\t\t\t\tvar statusLabel = document.createElement(\"label\");\r\n\t\t\t\tstatusLabel.setAttribute(\"for\", \"asset-alert-status-\" + item.EventId);\r\n\t\t\t\tstatusLabel.textContent = strings.STATUS;\r\n\t\t\t\tstatus.appendChild(statusLabel);\r\n\t\t\t\tvar statusText = document.createElement(\"span\");\r\n\t\t\t\tstatusText.id = \"asset-alert-status-\" + item.EventId;\r\n\t\t\t\tstatusText.className = \"form-control-plaintext\";\r\n\t\t\t\tstatusText.textContent = strings.ACKNOWLEDGE_STATUS.replace(\"{Status}\", alert.AcknowledgedStatus)\r\n\t\t\t\t\t.replace(\"{Time}\", alert.AcknowledgedOn)\r\n\t\t\t\t\t.replace(\"{User}\", alert.AcknowledgedBy);\r\n\t\t\t\tstatus.appendChild(statusText);\r\n\r\n\t\t\t\tdetails.appendChild(resolution);\r\n\t\t\t\tdetails.appendChild(status);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn details;\r\n}\r\n\r\nfunction renderListItemDetailsHeader(item, isGrouped) {\r\n\tvar alert = item.Alert;\r\n\tif (item.EventName !== undefined && (isGrouped || (alert !== undefined && alert !== null))) {\r\n\t\tvar hasDetails = item.Details !== undefined && item.Detials !== null && item.Details !== \"\";\r\n\t\tvar hasAlert = alert !== undefined && alert !== null;\r\n\r\n\t\tvar eventDetailsHeader = document.createElement(\"div\");\r\n\t\teventDetailsHeader.className = \"event-details-header\";\r\n\r\n\t\tvar isCollapse = hasDetails || hasAlert;\r\n\t\tif (isCollapse) {\r\n\t\t\t// for collapsible panels use buttons and data-toggle\r\n\t\t\tvar headerButton = document.createElement(\"button\");\r\n\t\t\theaderButton.className = \"btn btn-link\";\r\n\t\t\theaderButton.setAttribute(\"data-toggle\", \"collapse\");\r\n\t\t\theaderButton.setAttribute(\"data-target\", \"#event-details-\" + item.Id);\r\n\t\t\theaderButton.setAttribute(\"aria-expanded\", \"false\");\r\n\r\n\t\t\t// if grouped, include event type icon\r\n\t\t\tif (isGrouped) {\r\n\t\t\t\tvar itemType = getListItemGroupForEvent(item);\r\n\t\t\t\tvar typeIcon = renderListItemIcon(itemType);\r\n\t\t\t\tif (typeIcon !== undefined) {\r\n\t\t\t\t\t//typeIcon.className = 'list-item-icon';\r\n\t\t\t\t\ttypeIcon.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"class\", \"list-item-icon\");\r\n\t\t\t\t\theaderButton.appendChild(typeIcon);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tvar eventDetailsTitle = document.createElement(\"span\");\r\n\t\t\teventDetailsTitle.className = \"mr-auto\";\r\n\t\t\teventDetailsTitle.textContent = !isGrouped ? strings.DETAILS : item.EventName;\r\n\t\t\theaderButton.appendChild(eventDetailsTitle);\r\n\r\n\t\t\tif (item.Type === 14) {\r\n\t\t\t\t// alert triggered\r\n\t\t\t\tvar alertAcknowledgedIcon = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\r\n\t\t\t\talertAcknowledgedIcon.classList.add(\"list-item-action\");\r\n\t\t\t\talertAcknowledgedIcon.classList.add(\"alert-acknowledge-icon\");\r\n\t\t\t\tif (alert.Acknowledged === 0) {\r\n\t\t\t\t\tif (alert.RequiresAcknowledgement) {\r\n\t\t\t\t\t\talertAcknowledgedIcon.classList.add(\"requires-acknowledgement\");\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\talertAcknowledgedIcon.classList.add(\"pending-acknowledgement\");\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\talertAcknowledgedIcon.classList.add(\"is-acknowledged\");\r\n\t\t\t\t}\r\n\t\t\t\talertAcknowledgedIcon.setAttribute(\"data-event-id\", item.EventId);\r\n\t\t\t\tvar alertAcknowledgedTitle = document.createElementNS(\"http://www.w3.org/2000/svg\", \"title\");\r\n\t\t\t\talertAcknowledgedTitle.textContent = strings.ACKNOWLEDGE_ALERT;\r\n\t\t\t\talertAcknowledgedIcon.appendChild(alertAcknowledgedTitle);\r\n\r\n\t\t\t\tvar alertAcknowledgedIconType = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\r\n\t\t\t\tif (alert.Acknowledged === 0) {\r\n\t\t\t\t\talertAcknowledgedIconType.setAttributeNS(\r\n\t\t\t\t\t\t\"http://www.w3.org/1999/xlink\",\r\n\t\t\t\t\t\t\"href\",\r\n\t\t\t\t\t\t\"/content/svg/tracking.svg?v=15#times-circle-solid\"\r\n\t\t\t\t\t);\r\n\t\t\t\t} else {\r\n\t\t\t\t\talertAcknowledgedIconType.setAttributeNS(\r\n\t\t\t\t\t\t\"http://www.w3.org/1999/xlink\",\r\n\t\t\t\t\t\t\"href\",\r\n\t\t\t\t\t\t\"/content/svg/tracking.svg?v=15#check-circle-solid\"\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\r\n\t\t\t\talertAcknowledgedIcon.appendChild(alertAcknowledgedIconType);\r\n\t\t\t\theaderButton.appendChild(alertAcknowledgedIcon);\r\n\t\t\t}\r\n\r\n\t\t\tvar infoExpandIcon = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\r\n\t\t\tinfoExpandIcon.setAttribute(\"class\", \"list-item-action list-item-details\");\r\n\t\t\tvar infoExpandIconTitle = document.createElementNS(\"http://www.w3.org/2000/svg\", \"title\");\r\n\t\t\tinfoExpandIconTitle.textContent = strings.DETAILS;\r\n\t\t\tinfoExpandIcon.appendChild(infoExpandIconTitle);\r\n\t\t\tvar infoExpandIconContents = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\r\n\t\t\tinfoExpandIconContents.setAttributeNS(\r\n\t\t\t\t\"http://www.w3.org/1999/xlink\",\r\n\t\t\t\t\"href\",\r\n\t\t\t\t\"/content/svg/tracking.svg?v=15#expand\"\r\n\t\t\t);\r\n\t\t\tinfoExpandIcon.appendChild(infoExpandIconContents);\r\n\t\t\theaderButton.appendChild(infoExpandIcon);\r\n\r\n\t\t\teventDetailsHeader.appendChild(headerButton);\r\n\t\t} else {\r\n\t\t\t// if grouped, include event type icon\r\n\t\t\tif (isGrouped) {\r\n\t\t\t\tvar itemType = getListItemGroupForEvent(item);\r\n\t\t\t\tvar typeIcon = renderListItemIcon(itemType);\r\n\t\t\t\tif (typeIcon !== undefined) {\r\n\t\t\t\t\teventDetailsHeader.appendChild(typeIcon);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tvar eventDetailsTitle = document.createElement(\"span\");\r\n\t\t\teventDetailsTitle.textContent = item.EventName;\r\n\t\t\teventDetailsHeader.appendChild(eventDetailsTitle);\r\n\t\t}\r\n\t\treturn eventDetailsHeader;\r\n\t} else {\r\n\t\treturn undefined;\r\n\t}\r\n}\r\n\r\nfunction setListItemIndex(listItem, index) {\r\n\tvar indexDom = listItem.querySelector(\".item-index\");\r\n\tif (indexDom !== null) {\r\n\t\tindexDom.textContent = \"#\" + (index + 1);\r\n\t}\r\n}\r\n\r\nfunction getListItemGroupForEvent(item) {\r\n\t// TODO store this on the mapped item instead\r\n\tvar itemType = \"positions\";\r\n\tif (item.IsChat === true) {\r\n\t\titemType = \"chat\";\r\n\t} else if (item.MessageId !== undefined) {\r\n\t\titemType = \"messages\";\r\n\t} else if (item.EventId !== undefined) {\r\n\t\titemType = \"events\";\r\n\t\tif (EVENTS_STATUS.indexOf(item.Type) !== -1) {\r\n\t\t\titemType = \"status\";\r\n\t\t} else if (EVENTS_ALERT.indexOf(item.Type) !== -1) {\r\n\t\t\titemType = \"alerts\";\r\n\t\t} else if (EVENTS_EMERGENCY.indexOf(item.Type) !== -1) {\r\n\t\t\titemType = \"alerts\";\r\n\t\t} else {\r\n\t\t\titemType = \"events\";\r\n\t\t}\r\n\t}\r\n\treturn itemType;\r\n}\r\n\r\nfunction renderListItemIcon(type) {\r\n\tvar iconTypes = {\r\n\t\tpositions: \"map-marker-alt\",\r\n\t\tevents: \"exclamation-square\",\r\n\t\tstatus: \"exclamation-circle\",\r\n\t\talerts: \"exclamation-triangle\",\r\n\t\tchat: \"comments-alt\",\r\n\t\tmessages: \"code\",\r\n\t\tactivity: \"clock\",\r\n\t};\r\n\tvar typeIcon = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\r\n\tvar typeIconContents = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\r\n\ttypeIconContents.setAttributeNS(\r\n\t\t\"http://www.w3.org/1999/xlink\",\r\n\t\t\"href\",\r\n\t\t\"/content/svg/tracking.svg?v=15#\" + iconTypes[type]\r\n\t);\r\n\ttypeIcon.appendChild(typeIconContents);\r\n\treturn typeIcon;\r\n}\r\n\r\nfunction renderListItemPositionDetails(item) {\r\n\tif (item === undefined || item.Position === undefined) {\r\n\t\treturn undefined;\r\n\t}\r\n\r\n\tvar items = [\r\n\t\trenderDetailsItem(strings.SPEED, item.Position.Speed),\r\n\t\trenderDetailsItem(strings.ALTITUDE, item.Position.Altitude),\r\n\t\trenderDetailsItem(strings.HEADING, item.Position.Heading),\r\n\t\trenderDetailsItem(strings.ACCURACY, item.Position.Accuracy),\r\n\t\trenderDetailsItem(strings.DATA_SOURCE, item.Position.Source),\r\n\t\trenderDetailsItem(strings.STATUS, item.Position.Status),\r\n\t\trenderDetailsItem(strings.GEOFENCES, item.Position.InsideFences),\r\n\t\trenderDetailsItem(strings.ODOMETER, item.Position.Odometer),\r\n\t];\r\n\tvar actualItems = _.filter(items, function (row) {\r\n\t\treturn row !== undefined;\r\n\t});\r\n\tif (actualItems.length === 0) {\r\n\t\treturn undefined;\r\n\t}\r\n\r\n\tvar itemDetails = document.createDocumentFragment();\r\n\tvar header = document.createElement(\"div\");\r\n\theader.className = \"event-details-header\";\r\n\r\n\tvar headerButton = document.createElement(\"button\");\r\n\theaderButton.className = \"btn btn-link\";\r\n\theaderButton.setAttribute(\"data-toggle\", \"collapse\");\r\n\theaderButton.setAttribute(\"data-target\", \"#position-details-\" + item.Id);\r\n\theaderButton.setAttribute(\"aria-expanded\", \"false\");\r\n\r\n\theaderButton.appendChild(renderListItemIcon(\"positions\"));\r\n\r\n\tvar headerTitle = document.createElement(\"span\");\r\n\theaderTitle.className = \"mr-auto\";\r\n\theaderTitle.textContent = strings.DETAILS;\r\n\theaderButton.appendChild(headerTitle);\r\n\r\n\tvar infoExpandIcon = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\r\n\tinfoExpandIcon.setAttribute(\"class\", \"list-item-action list-item-details\");\r\n\tvar infoExpandIconTitle = document.createElementNS(\"http://www.w3.org/2000/svg\", \"title\");\r\n\tinfoExpandIconTitle.textContent = strings.DETAILS;\r\n\tinfoExpandIcon.appendChild(infoExpandIconTitle);\r\n\tvar infoExpandIconContents = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\r\n\tinfoExpandIconContents.setAttributeNS(\r\n\t\t\"http://www.w3.org/1999/xlink\",\r\n\t\t\"href\",\r\n\t\t\"/content/svg/tracking.svg?v=15#expand\"\r\n\t);\r\n\tinfoExpandIcon.appendChild(infoExpandIconContents);\r\n\theaderButton.appendChild(infoExpandIcon);\r\n\r\n\theader.appendChild(headerButton);\r\n\r\n\tvar details = document.createElement(\"div\");\r\n\tdetails.id = \"position-details-\" + item.Id;\r\n\tdetails.className = \"event-details break-text collapse\";\r\n\r\n\tvar meta = document.createElement(\"div\");\r\n\tmeta.className = \"item-metadata\";\r\n\r\n\t_.each(actualItems, function (rowItem) {\r\n\t\tmeta.appendChild(rowItem);\r\n\t});\r\n\r\n\tdetails.appendChild(meta);\r\n\r\n\titemDetails.appendChild(header);\r\n\titemDetails.appendChild(details);\r\n\treturn itemDetails;\r\n}\r\n\r\nfunction renderDetailsItem(label, text) {\r\n\tif (text === undefined || text === null || text === \"\") {\r\n\t\treturn undefined;\r\n\t}\r\n\tvar itemLine = document.createElement(\"div\");\r\n\r\n\tvar itemLabel = document.createElement(\"span\");\r\n\titemLabel.className = \"item-label\";\r\n\titemLabel.textContent = label + \": \";\r\n\r\n\tvar itemText = document.createElement(\"span\");\r\n\titemText.textContent = text;\r\n\titemLine.appendChild(itemLabel);\r\n\titemLine.appendChild(itemText);\r\n\treturn itemLine;\r\n}\r\n","import { createMarkerPath } from \"./marker-path.js\";\r\nimport strings from \"./strings.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport state from \"./state.js\";\r\nimport { viewModes } from \"./const.js\";\r\nimport FilteredList from \"./filtered-list.js\";\r\nimport trkData from \"./data.js\";\r\nimport { findAssetById } from \"./assets.js\";\r\nimport { createIconForAssetEvent } from \"./asset-state.js\";\r\nimport { formattedTextToDiv } from \"./dom-util.js\";\r\nimport { findPlaceByUniqueKey } from \"./place.js\";\r\nimport { findFenceById } from \"./fence.js\";\r\nimport {\r\n\tconvertToLatLngPreference,\r\n\tconvertSpeedToPreference,\r\n\tconvertFromMetresToUserDistancePreference,\r\n\tconvertAltitudeToPreference,\r\n} from \"./preferences.js\";\r\nimport { getStatusTextForLocation } from \"./location.js\";\r\nimport user from \"./user.js\";\r\nimport { switchMapMode } from \"./map-base.js\";\r\nimport { queryActiveAssets } from \"./assets-active.js\";\r\nimport options from \"./options.js\";\r\nimport { mapModes } from \"./const.js\";\r\nimport { querySharedViewData } from \"./shared-view.js\";\r\nimport { renderListItem } from \"./item-list-render.js\";\r\n\r\nimport _ from \"lodash\";\r\nimport { el, text } from \"redom\"; // https://redom.js.org/\r\nimport moment from \"moment\"; // https://www.npmjs.com/package/moment\r\n\r\nexport function updateItemListingIcon(itemId, color, isActive, iconType, nodeList) {\r\n\tvar alpha = isActive ? null : 50;\r\n\tvar forceAlpha = isActive ? false : true;\r\n\tvar iconPath = createMarkerPath(iconType, color, null, alpha, itemId, forceAlpha);\r\n\tvar items = nodeList[itemId];\r\n\tif (!_.isArray(items)) {\r\n\t\titems = [items];\r\n\t}\r\n\t_.each(items, function (itemNode) {\r\n\t\tif (isActive) {\r\n\t\t\titemNode.classList.remove(\"disabled\");\r\n\t\t\titemNode.classList.add(\"active\");\r\n\t\t} else {\r\n\t\t\titemNode.classList.add(\"disabled\");\r\n\t\t\titemNode.classList.remove(\"active\");\r\n\t\t}\r\n\t\tvar itemIcon = itemNode.querySelector(\".item-header\");\r\n\t\titemIcon.style[\"background-image\"] = \"url(\" + iconPath + \")\";\r\n\t});\r\n}\r\n\r\nexport function showResultLimitsIfApplicable(result, isDateFiltered) {\r\n\tconsole.log(\"showResultLimitsIfApplicable\", isDateFiltered);\r\n\t// first page may not be limited, need additional property to know that?\r\n\tif (result.IsLimited === undefined || result.IncludesLimitedData === undefined) {\r\n\t\treturn;\r\n\t}\r\n\t// only applies to history mode and shared views\r\n\tvar excess = domNodes.mapMode.excessData;\r\n\tvar cont = domNodes.mapMode.container;\r\n\tif (result.IsLimited || isDateFiltered) {\r\n\t\tif (isDateFiltered) {\r\n\t\t\tcont.classList.add(\"is-filtered\");\r\n\t\t} else {\r\n\t\t\tcont.classList.remove(\"is-filtered\");\r\n\t\t}\r\n\t\t//if (result.IsLimited) {\r\n\t\texcess.querySelector(\"p\").textContent = strings.ERROR_TOO_MANY_RESULTS.replace(\"{0}\", result.Limit);\r\n\t\t//}\r\n\r\n\t\tcont.classList.add(\"has-excess\");\r\n\t\tif (isDateFiltered || (result.IsLimited && result.IncludesLimitedData)) {\r\n\t\t\t// user agreed to view the limited data\r\n\t\t\tcont.classList.add(\"is-limited\");\r\n\t\t\tdocument.getElementById(\"map-mode-details-limited\").querySelector(\"div\").textContent =\r\n\t\t\t\tstrings.RESULTS_LIMITED.replace(\"{0}\", result.Limit);\r\n\t\t} else {\r\n\t\t\tcont.classList.remove(\"is-limited\");\r\n\t\t\t// show history form with notices\r\n\t\t\tdomNodes.mapMode.dateRange.classList.add(\"is-visible\");\r\n\t\t\tdocument.getElementById(\"history-custom\").classList.add(\"active\");\r\n\t\t}\r\n\t} else {\r\n\t\t// also when mode is changed\r\n\t\tcont.classList.remove(\"is-limited\");\r\n\t\tcont.classList.remove(\"has-excess\");\r\n\t\tcont.classList.remove(\"is-filtered\");\r\n\t}\r\n\r\n\tif (state.activeViewMode === viewModes.NORMAL) {\r\n\t} else if (state.activeViewMode === viewModes.SHARED_VIEW) {\r\n\t}\r\n}\r\n\r\nexport const notificationLists = {\r\n\tpositions: null,\r\n\tevents: null,\r\n\tchat: null,\r\n\tmessages: null,\r\n\talerts: null,\r\n\tstatus: null,\r\n\tactivity: null,\r\n\tpositionsList: null,\r\n\teventsList: null,\r\n\tchatList: null,\r\n\tmessagesList: null,\r\n\talertsList: null,\r\n\tstatusList: null,\r\n\tactivityList: null,\r\n};\r\n\r\nexport function createListing(items, grouping) {\r\n\tvar container = document.getElementById(\"asset-\" + grouping + \"-container\");\r\n\tvar mapped = _.map(items, function (item) {\r\n\t\treturn mapActivityItemToListItem(item);\r\n\t});\r\n\r\n\t// TODO pull filter from somewhere\r\n\tif (notificationLists[grouping + \"List\"] === null) {\r\n\t\tnotificationLists[grouping + \"List\"] = new FilteredList(mapped, container, renderListItem, {\r\n\t\t\tpaging: { currentPage: 1 },\r\n\t\t\tgroupBy: grouping === \"activity\" ? \"EpochGroup\" : null,\r\n\t\t});\r\n\t} else {\r\n\t\t// change data and re-render\r\n\t\tvar listing = notificationLists[grouping + \"List\"];\r\n\t\tlisting.data.items = mapped;\r\n\t\tlisting.reindex();\r\n\t\tlisting.redraw();\r\n\t}\r\n\r\n\t// TODO deciding which item should be in meta\r\n\tvar first = _.first(_.sortBy(mapped, \"Epoch\").reverse());\r\n\trenderMetaItem(first, grouping);\r\n}\r\n\r\nexport function defaultListItemSort() {\r\n\treturn function (item) {\r\n\t\treturn item.Epoch;\r\n\t};\r\n}\r\n\r\nfunction renderMetaItem(item, grouping) {\r\n\tvar meta = document.getElementById(\"panel-secondary-meta\").querySelector(\".meta-\" + grouping);\r\n\tvar metaDetails = meta.querySelector(\"table\");\r\n\tif (item !== undefined) {\r\n\t\tmetaDetails.classList.remove(\"toggle-content\");\r\n\t\tif (item.IsChat !== undefined || item.MessageId !== undefined) {\r\n\t\t\tvar itemType = meta.querySelector(\".recent-item-type\");\r\n\t\t\tif (itemType !== null) {\r\n\t\t\t\titemType.querySelector(\".meta-item\").textContent = item.EventName;\r\n\t\t\t}\r\n\t\t\tvar itemMessage = meta.querySelector(\".recent-item-message\");\r\n\t\t\tif (itemMessage !== null) {\r\n\t\t\t\titemMessage.querySelector(\".meta-item\").textContent = item.Text;\r\n\t\t\t}\r\n\t\t} else if (item.EventId !== undefined) {\r\n\t\t\tvar itemType = meta.querySelector(\".recent-item-type\");\r\n\t\t\titemType.querySelector(\".meta-item\").textContent = item.EventName;\r\n\t\t} else if (item.PositionId !== undefined) {\r\n\t\t}\r\n\r\n\t\t// common to all\r\n\t\tvar itemTime = meta.querySelector(\".recent-item-time\");\r\n\t\tif (itemTime !== null) {\r\n\t\t\titemTime.querySelector(\".meta-item\").textContent = item.Time;\r\n\t\t}\r\n\t\tvar itemName = meta.querySelector(\".recent-item-name\");\r\n\t\tif (itemName !== null) {\r\n\t\t\titemName.querySelector(\".meta-item\").textContent = item.AssetName;\r\n\t\t}\r\n\t\tvar itemAddress = meta.querySelector(\".recent-item-address\");\r\n\t\tif (itemAddress !== null) {\r\n\t\t\tif (item.Position !== undefined && item.Position !== null && item.Position.Address !== null) {\r\n\t\t\t\titemAddress.querySelector(\".meta-item\").textContent = item.Position.Address;\r\n\t\t\t\titemAddress.classList.remove(\"toggle-content\");\r\n\t\t\t} else {\r\n\t\t\t\titemAddress.classList.add(\"toggle-content\");\r\n\t\t\t}\r\n\t\t}\r\n\t\tvar itemLatLng = meta.querySelector(\".recent-item-latlng\");\r\n\t\tif (itemLatLng !== null) {\r\n\t\t\tif (item.Position !== undefined && item.Position !== null && item.Position.LatLng !== null) {\r\n\t\t\t\titemLatLng.querySelector(\".meta-item\").textContent = item.Position.LatLng;\r\n\t\t\t\titemLatLng.classList.remove(\"is-visible\");\r\n\t\t\t} else {\r\n\t\t\t\titemLatLng.classList.add(\"toggle-content\");\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tmetaDetails.classList.add(\"toggle-content\");\r\n\t}\r\n}\r\n\r\nfunction mapActivityItemToListItem(item) {\r\n\tif (item.Chat !== undefined) {\r\n\t\treturn mapMessageToListItem(item);\r\n\t} else if (item.Message !== undefined) {\r\n\t\treturn mapMessageToListItem(item);\r\n\t} else if (item.Event !== undefined) {\r\n\t\treturn mapEventToListItem(item);\r\n\t} else if (item.Position !== undefined) {\r\n\t\treturn mapPositionToListItem(item);\r\n\t}\r\n}\r\n\r\nfunction mapMessageToListItem(item) {\r\n\tif ((item.Message === undefined || item.Message === null) && (item.Chat === undefined || item.Chat === null)) {\r\n\t\treturn undefined;\r\n\t}\r\n\tvar dataSource = state.activeViewMode === viewModes.SHARED_VIEW ? trkData.sharedView : trkData;\r\n\tvar assetId = item.AssetId;\r\n\tvar position = item.Position;\r\n\tvar isChat = item.Message === undefined;\r\n\tvar item = !isChat ? item.Message : item.Chat;\r\n\r\n\tvar existing = dataSource.activityById[\"m-\" + item.Id];\r\n\tif (existing !== undefined) {\r\n\t\treturn existing;\r\n\t}\r\n\r\n\tvar asset = findAssetById(assetId);\r\n\tvar iconUrl = createMarkerPath(asset.Class, asset.Color, null, null, asset.Id, false);\r\n\tvar positionId = undefined;\r\n\tposition = mapPositionDetailsForListItem(asset, position);\r\n\tif (position !== undefined) {\r\n\t\tpositionId = position.Id;\r\n\t}\r\n\r\n\tvar mapped = {\r\n\t\tId: \"m-\" + item.Id,\r\n\t\tMessageId: item.Id,\r\n\t\tPositionId: positionId,\r\n\t\tAssetId: asset.Id,\r\n\t\tIsFromMobile: item.IsFromMobile,\r\n\t\tEpoch: item.CreatedEpoch,\r\n\t\tEpochGroup: item.CreatedEpoch + \"-\" + asset.Id,\r\n\t\tIsError: item.IsError,\r\n\t\tIsAcknowledged: item.IsAcknowledged,\r\n\t\tIconUrl: iconUrl,\r\n\t\tIsChat: isChat,\r\n\t\t// to index\r\n\t\tAssetName: asset.Name,\r\n\t\tMethod: item.IsFromMobile ? strings.FROM_MOBILE : strings.TO_MOBILE,\r\n\t\tEventName: item.Type,\r\n\t\tRawText: item.RawText,\r\n\t\tSource: item.Source,\r\n\t\tTime: item.CreatedOn,\r\n\t\tResponse: item.Response,\r\n\t\tDetails: text(item.Text),\r\n\t\tStatus: !item.IsError && !item.IsSent ? strings.PENDING : item.Status,\r\n\t\tPosition: position, //Position.Address, Position.LatLng\r\n\t};\r\n\tdataSource.activityById[\"m-\" + item.Id] = mapped;\r\n\treturn mapped;\r\n}\r\n\r\nfunction mapPositionToListItem(positionItem) {\r\n\tif (positionItem.Position === undefined || positionItem.Position === null) {\r\n\t\treturn undefined;\r\n\t}\r\n\r\n\tvar dataSource = state.activeViewMode === viewModes.SHARED_VIEW ? trkData.sharedView : trkData;\r\n\r\n\tvar existing = dataSource.activityById[\"p-\" + positionItem.Position.Id];\r\n\tif (existing !== undefined) {\r\n\t\treturn existing;\r\n\t}\r\n\r\n\tvar asset = findAssetById(positionItem.AssetId);\r\n\tvar item = positionItem.Position;\r\n\tvar position = mapPositionDetailsForListItem(asset, item);\r\n\tvar iconUrl = createMarkerPath(asset.Class, asset.Color, null, null, asset.Id, false);\r\n\r\n\t//var address = null;\r\n\t//if (!asset.HideAddress) {\r\n\t// address = item.Address;\r\n\t//}\r\n\r\n\t//var latLng = convertToLatLngPreference(item.DisplayLat, item.DisplayLng, item.Grid);\r\n\r\n\tvar eventTypes = _.uniq(_.map(item.Events, \"TypeName\")).join(\", \");\r\n\tvar mapped = {\r\n\t\tId: \"p-\" + item.Id,\r\n\t\tPositionId: item.Id,\r\n\t\tAssetId: asset.Id,\r\n\t\tIconUrl: iconUrl,\r\n\t\tEpoch: item.Epoch,\r\n\t\tEpochGroup: item.Epoch + \"-\" + asset.Id,\r\n\t\tIsHidden: item.IsHidden,\r\n\t\t// to index\r\n\t\tAssetName: asset.Name,\r\n\t\tTime: item.Time,\r\n\t\tEventTypes: eventTypes,\r\n\t\tPosition: position,\r\n\t};\r\n\tdataSource.activityById[\"p-\" + positionItem.Position.Id] = mapped;\r\n\treturn mapped;\r\n}\r\n\r\nfunction mapEventToListItem(eventItem) {\r\n\tif (eventItem.Event === undefined || eventItem.Event === null) {\r\n\t\treturn undefined;\r\n\t}\r\n\r\n\tvar dataSource = state.activeViewMode === viewModes.SHARED_VIEW ? trkData.sharedView : trkData;\r\n\r\n\tvar existing = dataSource.activityById[\"e-\" + eventItem.Event.Id];\r\n\tif (existing !== undefined) {\r\n\t\treturn existing;\r\n\t}\r\n\r\n\tvar asset = findAssetById(eventItem.AssetId);\r\n\tvar position = eventItem.Position;\r\n\tvar item = eventItem.Event;\r\n\r\n\tvar svgIcon = createIconForAssetEvent(asset, item.Type);\r\n\tvar iconUrl = createMarkerPath(asset.Class, asset.Color, null, null, asset.Id, false, item.Type);\r\n\tvar eventIcon = el(\"div.event-icon\", { style: { backgroundImage: \"url(\" + iconUrl + \")\" } });\r\n\tvar detailsElement = formattedTextToDiv(item.Details);\r\n\tswitch (item.Type) {\r\n\t\tcase 127: // garmin form submitted\r\n\t\t\tif (item.Details != null) {\r\n\t\t\t\tvar formDetails = item.Details.split(\"|\");\r\n\t\t\t\tvar formId = formDetails[0];\r\n\t\t\t\tvar formName = strings.VIEW;\r\n\t\t\t\tif (formDetails.length > 1) {\r\n\t\t\t\t\tformName = formDetails[1];\r\n\t\t\t\t}\r\n\t\t\t\tdetailsElement = el(\r\n\t\t\t\t\t\"button.ViewGarminSubmission.command.details.btn.btn-sm.btn-secondary\",\r\n\t\t\t\t\t{ dataset: { id: formId, assetId: asset.Id } },\r\n\t\t\t\t\tformName\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 270: // beacon read\r\n\t\t\tif (item.Details != null) {\r\n\t\t\t\tdetailsElement = null;\r\n\t\t\t\tvar detailsItems = [];\r\n\t\t\t\tvar beacons = item.Details.split(\"\\n\");\r\n\t\t\t\tfor (var k = 0; k < beacons.length; k++) {\r\n\t\t\t\t\tvar beacon = beacons[k].split(\"|\");\r\n\t\t\t\t\tif (beacon.length > 1) {\r\n\t\t\t\t\t\tvar beaconUniqueKey = beacon[0];\r\n\t\t\t\t\t\tvar beaconRSSI = beacon[1];\r\n\t\t\t\t\t\tvar beaconTxPower = beacon[2];\r\n\t\t\t\t\t\tif (beaconUniqueKey == null) {\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tvar beaconPlace = findPlaceByUniqueKey(beaconUniqueKey);\r\n\t\t\t\t\t\tif (beaconPlace != null) {\r\n\t\t\t\t\t\t\tdetailsItems.push(\r\n\t\t\t\t\t\t\t\tel(\"a.beacon-place\", { href: \"#\", dataset: { placeId: beaconPlace.Id } }, beaconPlace.Name)\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\tdetailsItems.push(text(\" @ \" + beaconRSSI + \" RSSI\"));\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tdetailsItems.push(text(beaconUniqueKey + \" @ \" + beaconRSSI + \" RSSI\"));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (beaconTxPower != \"\") {\r\n\t\t\t\t\t\t\tdetailsItems.push(text(\", \" + beaconTxPower + \" Tx\"));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tdetailsItems.push(el(\"br\"));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (detailsItems.length > 0) {\r\n\t\t\t\t\tdetailsElement = el(\"div\", detailsItems);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 272:\r\n\t\tcase 273:\r\n\t\tcase 274:\r\n\t\t\t// driver fatigue\r\n\t\t\tif (item.Details != null) {\r\n\t\t\t\tdetailsElement = el(\r\n\t\t\t\t\t\"button.ViewPhoto.command.details.btn.btn-sm.btn-secondary\",\r\n\t\t\t\t\t{ title: strings.VIEW_PHOTO, dataset: { photo: item.Details } },\r\n\t\t\t\t\tstrings.VIEW_PHOTO\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 275:\r\n\t\t\tif (item.Details != null) {\r\n\t\t\t\tvar parts = item.Details.split(\"|||\");\r\n\t\t\t\tdetailsElement = el(\r\n\t\t\t\t\t\"button.ViewPhoto.command.details.btn.btn-sm.btn-secondary\",\r\n\t\t\t\t\t{ title: strings.VIEW_PHOTO, dataset: { photo: parts[1] } },\r\n\t\t\t\t\tstrings.VIEW_PHOTO\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tvar fullName = item.TypeName;\r\n\tif (item.Alert !== undefined && item.Alert !== null) {\r\n\t\tvar alertName = item.Alert.Type;\r\n\t\tif (item.Alert.Name !== null) {\r\n\t\t\talertName = item.Alert.Name + \" [ \" + item.Alert.Type + \" ]\";\r\n\t\t}\r\n\t\tfullName += \", \" + alertName;\r\n\t}\r\n\r\n\tvar positionId = undefined;\r\n\tposition = mapPositionDetailsForListItem(asset, position);\r\n\tif (position !== undefined) {\r\n\t\tpositionId = position.Id;\r\n\t}\r\n\r\n\tvar mapped = {\r\n\t\tId: \"e-\" + item.Id,\r\n\t\tEventId: item.Id,\r\n\t\tPositionId: positionId,\r\n\t\tAssetId: asset.Id,\r\n\t\tIcon: eventIcon, // unused\r\n\t\tIconUrl: iconUrl,\r\n\t\tSvgIcon: svgIcon,\r\n\t\tIsAccurate: item.IsAcc,\r\n\t\tType: item.Type,\r\n\t\tEpoch: item.Epoch,\r\n\t\tEpochGroup: item.Epoch + \"-\" + asset.Id,\r\n\r\n\t\t// to index\r\n\t\tAssetName: asset.Name,\r\n\t\tEventName: fullName,\r\n\t\tPosition: position,\r\n\t\tDetails: detailsElement,\r\n\t\tTime: item.Time,\r\n\t\tAlert: item.Alert,\r\n\t};\r\n\tdataSource.activityById[\"e-\" + eventItem.Event.Id] = mapped;\r\n\treturn mapped;\r\n}\r\n\r\nfunction mapPositionDetailsForListItem(asset, item) {\r\n\tif (item == undefined || item === null) {\r\n\t\treturn undefined;\r\n\t}\r\n\tvar address = null;\r\n\tif (!asset.HideAddress) {\r\n\t\taddress = item.Address;\r\n\t}\r\n\tvar latLng = convertToLatLngPreference(item.DisplayLat, item.DisplayLng, item.Grid);\r\n\r\n\tvar course = undefined;\r\n\tif (!asset.HideCourse) {\r\n\t\tcourse = item.Course;\r\n\t}\r\n\r\n\tvar status = getStatusTextForLocation(item);\r\n\r\n\tvar altitude = null;\r\n\tif (!asset.HideAltitude && item.Altitude !== undefined && item.Altitude !== null) {\r\n\t\taltitude = convertAltitudeToPreference(item.Altitude);\r\n\t}\r\n\r\n\tvar fences = null;\r\n\tif (item.InsideFences !== undefined && item.InsideFences !== null) {\r\n\t\tvar fenceNames = [];\r\n\t\t_.each(item.InsideFences, function (fenceId) {\r\n\t\t\tvar fence = findFenceById(fenceId);\r\n\t\t\tif (fence !== null) {\r\n\t\t\t\tfenceNames.push(fence.Name);\r\n\t\t\t}\r\n\t\t});\r\n\t\tfences = fenceNames.join(\", \");\r\n\t}\r\n\r\n\tvar speed = null;\r\n\tif (!asset.HideSpeed) {\r\n\t\tspeed = convertSpeedToPreference(item.Speed);\r\n\t}\r\n\tvar accuracy = null;\r\n\tif (!asset.HideAccuracy) {\r\n\t\taccuracy = item.Accuracy;\r\n\t}\r\n\r\n\tvar odometer = null;\r\n\tif (item.Odometer !== undefined && item.Odometer !== null) {\r\n\t\todometer = convertFromMetresToUserDistancePreference(item.Odometer);\r\n\t}\r\n\r\n\t// core properties\r\n\tvar mapped = {\r\n\t\tId: item.Id,\r\n\t\tLatLng: latLng,\r\n\t\tAddress: address,\r\n\t\tTime: item.Time, // duplicated for consistency\r\n\t\tIsHidden: item.IsHidden,\r\n\t\t// extra details\r\n\t\tSource: item.Source,\r\n\t\tOdometer: odometer,\r\n\t\tHeading: course,\r\n\t\tStatus: status,\r\n\t\tAltitude: altitude,\r\n\t\tInsideFences: fences,\r\n\t\tSpeed: speed,\r\n\t\tIsSpeedEstimated: item.IsEst,\r\n\t\tIsTimeAccurate: item.IsAcc,\r\n\t\tAccuracy: accuracy,\r\n\t};\r\n\treturn mapped;\r\n}\r\n\r\nexport function filterDateClick(btn) {\r\n\t// TODO this is a mess and should be refactored\r\n\tvar range = btn.id.substring(8);\r\n\tvar fromDate = null;\r\n\tvar historyCustom = document.getElementById(\"history-custom\");\r\n\tvar historyDateForm = domNodes.mapMode.dateRange;\r\n\tvar doQuery = true;\r\n\tvar historyButtons = document.getElementById(\"filter-history-range\").querySelectorAll(\"button\");\r\n\t// clicking custom button should not change any others\r\n\tif (range !== \"custom\") {\r\n\t\t_.each(historyButtons, function (button) {\r\n\t\t\tif (button.id === \"history-live\") {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tbutton.classList.remove(\"active\");\r\n\t\t});\r\n\t}\r\n\tswitch (range) {\r\n\t\tcase \"live\":\r\n\t\t\thistoryDateForm.classList.remove(\"is-visible\");\r\n\t\t\tswitchMapMode(mapModes.LIVE);\r\n\t\t\treturn;\r\n\t\tcase \"1h\":\r\n\t\t\tfromDate = moment().subtract(user.tickOffset, \"ms\").subtract(1, \"hours\");\r\n\t\t\thistoryDateForm.classList.remove(\"is-visible\");\r\n\t\t\thistoryCustom.classList.remove(\"btn-primary\");\r\n\t\t\tbreak;\r\n\t\tcase \"24h\":\r\n\t\t\tfromDate = moment().subtract(user.tickOffset, \"ms\").subtract(24, \"hours\");\r\n\t\t\thistoryDateForm.classList.remove(\"is-visible\");\r\n\t\t\thistoryCustom.classList.remove(\"btn-primary\");\r\n\t\t\tbreak;\r\n\t\tcase \"7d\":\r\n\t\t\tfromDate = moment().subtract(user.tickOffset, \"ms\").subtract(7, \"days\");\r\n\t\t\thistoryDateForm.classList.remove(\"is-visible\");\r\n\t\t\thistoryCustom.classList.remove(\"btn-primary\");\r\n\t\t\tbreak;\r\n\t\tcase \"1m\":\r\n\t\t\tfromDate = moment().subtract(user.tickOffset, \"ms\").subtract(1, \"months\");\r\n\t\t\thistoryDateForm.classList.remove(\"is-visible\");\r\n\t\t\thistoryCustom.classList.remove(\"btn-primary\");\r\n\t\t\tbreak;\r\n\t\tcase \"custom\":\r\n\t\t\tif (historyDateForm.classList.contains(\"is-visible\")) {\r\n\t\t\t\thistoryDateForm.classList.remove(\"is-visible\");\r\n\t\t\t\tif (!btn.classList.contains(\"btn-primary\")) {\r\n\t\t\t\t\tbtn.classList.remove(\"active\");\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tif (!(state.isFirstLoad && options.isCompact)) {\r\n\t\t\t\t\thistoryDateForm.classList.add(\"is-visible\");\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tdoQuery = false;\r\n\t\t\tbreak;\r\n\t}\r\n\tif (fromDate !== null) {\r\n\t\tvar historyDateFrom = document.getElementById(\"txtDateFrom\");\r\n\t\thistoryDateFrom.value = fromDate.format(user.dateWithStandardTimeFormat);\r\n\t\tvar historyDateTo = document.getElementById(\"txtDateTo\");\r\n\t\thistoryDateTo.value = \"\";\r\n\t}\r\n\r\n\tif (doQuery) {\r\n\t\tif (state.activeViewMode === viewModes.NORMAL) {\r\n\t\t\tif (state.activeMapMode === mapModes.LIVE) {\r\n\t\t\t\tswitchMapMode(mapModes.HISTORY, null, true, true);\r\n\t\t\t} else {\r\n\t\t\t\tqueryActiveAssets(null, true);\r\n\t\t\t}\r\n\t\t} else if (state.activeViewMode === viewModes.SHARED_VIEW) {\r\n\t\t\t// requery shared view with dates entered in panel, limits apply\r\n\t\t\tvar dateFilter = {\r\n\t\t\t\tfrom: document.getElementById(\"txtDateFrom\").value,\r\n\t\t\t\tto: document.getElementById(\"txtDateTo\").value,\r\n\t\t\t};\r\n\t\t\tif (trkData.sharedView.temp !== null) {\r\n\t\t\t\tquerySharedViewData(trkData.sharedView.temp, dateFilter, false);\r\n\t\t\t} else if (trkData.sharedView.current !== null) {\r\n\t\t\t\tquerySharedViewData(trkData.sharedView.current, dateFilter, false);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t//if (range !== 'custom') {\r\n\tbtn.classList.add(\"active\");\r\n\t//}\r\n}\r\n","import trkData from \"./data.js\";\r\nimport { trkDataGroups } from \"./const.js\";\r\nimport { addItemToMap, removeItemFromMap } from \"./map-items.js\";\r\nimport { findAssetById, normalizeAssetData } from \"./assets.js\";\r\nimport preferences from \"./preferences.js\";\r\nimport { createListing } from \"./item-listing.js\";\r\nimport { getDisplayFilterForEventType } from \"./display-filter.js\";\r\nimport { createMarkerCluster } from \"./marker-cluster.js\";\r\nimport strings from \"./strings.js\";\r\nimport user, { displayPreferencesAdd, displayPreferencesRemove } from \"./user.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { addPositionMarkerToPoint } from \"./marker.js\";\r\nimport { openDialogPanel } from \"./panel-nav.js\";\r\nimport { findJourneyById } from \"./journey.js\";\r\nimport { isItemIncluded } from \"./polyfills.js\";\r\nimport { createPositionLinesForTrip } from \"./geometry-create.js\";\r\nimport { setMapBounds } from \"./map-bounds.js\";\r\nimport { updateItemListingIcon } from \"./item-listing.js\";\r\nimport { handleWebServiceError } from \"./ajax.js\";\r\nimport state from \"./state.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport { resizeApp } from \"./window-layout.js\";\r\nimport { updateGroupVisibilityStatus } from \"./asset-group.js\";\r\nimport { toggleLoadingMessage } from \"./ajax.js\";\r\nimport { updateGroupFunctionBadges, updateAssetFunctionBadges } from \"./badges.js\";\r\nimport { updateActiveAssetInformation } from \"./assets-active.js\";\r\nimport { createMarkerPath } from \"./marker-path.js\";\r\nimport options from \"./options.js\";\r\nimport templates from \"./templates.js\";\r\nimport { closeSecondaryPanel } from \"./panel.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport $j from \"jquery\";\r\nimport L from \"leaflet\";\r\nimport _ from \"lodash\";\r\nimport moment from \"moment\"; // https://www.npmjs.com/package/moment\r\n\r\nexport function findTripById(id) {\r\n\tvar tripId = parseInt(id);\r\n\tfor (var i = 0; i < trkData.journeys.length; i++) {\r\n\t\tfor (var j = 0; j < trkData.journeys[i].Trips.length; j++) {\r\n\t\t\tif (trkData.journeys[i].Trips[j].Id === tripId) {\r\n\t\t\t\treturn trkData.journeys[i].Trips[j];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn null;\r\n}\r\n\r\nfunction processTripData(journey, trip, data) {\r\n\tvar asset = findAssetById(journey.AssetId);\r\n\tif (asset === null) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t_.each(data.Positions, function (position) {\r\n\t\tif (trkData.positionsById[position.Id] === undefined) {\r\n\t\t\ttrkData.positionsById[position.Id] = normalizeAssetData(asset.Id, \"position\", position);\r\n\t\t}\r\n\t\t//trkData.trips.normalizedPositions.push(trkData.positionsById[position.Id]);\r\n\t\tif (trkData.trips.normalizedPositionsByTripId[trip.Id] === undefined) {\r\n\t\t\ttrkData.trips.normalizedPositionsByTripId[trip.Id] = [];\r\n\t\t}\r\n\t\ttrkData.trips.normalizedPositionsByTripId[trip.Id].push(trkData.positionsById[position.Id]);\r\n\t});\r\n\r\n\tif (data.ResultsForSearch) {\r\n\t\ttrkData.trips.tripIdsWithResults[trip.Id] = true;\r\n\t}\r\n\r\n\t// trkData.trips.positions.push(data); // needed?\r\n\ttrkData.trips.positionsByTripId[trip.Id] = data;\r\n\r\n\tif (data.MessageCounts !== null) {\r\n\t\t//trkData.trips.messageCounts.push(data.MessageCounts); // needed?\r\n\t\ttrkData.trips.messageCountsByTripId[trip.Id] = data.MessageCounts;\r\n\t}\r\n\r\n\tvar clusterTripMarkers = preferences.PREFERENCE_GROUP_POSITIONS && trip.IncludeAllPositions;\r\n\tvar visiblePositions = _.filter(data.Positions, function (item) {\r\n\t\treturn !item.IsHidden;\r\n\t});\r\n\tvar lastVisiblePositionId = null;\r\n\tvar firstVisiblePositionId = null;\r\n\tif (visiblePositions.length > 0) {\r\n\t\tlastVisiblePositionId = visiblePositions[0].Id;\r\n\t\tfirstVisiblePositionId = visiblePositions[visiblePositions.length - 1].Id;\r\n\t}\r\n\tif (visiblePositions.length > 0) {\r\n\t\tif (clusterTripMarkers && trkData.trips.markerClustersByTripId[trip.Id] === undefined) {\r\n\t\t\ttrkData.trips.markerClustersByTripId[trip.Id] = createMarkerCluster(asset, trip);\r\n\t\t}\r\n\r\n\t\tlet alpha = 255;\r\n\t\tconst alphaIncrement = preferences.PREFERENCE_ALPHA_POSITIONS\r\n\t\t\t? 185 / visiblePositions.length\r\n\t\t\t: 0;\r\n\t\t// positions are sorted from newest->last\r\n\t\tvar totalTripPositions = visiblePositions.length;\r\n\t\tvar clusterMarkers = [];\r\n\t\tfor (var j = 0; j < totalTripPositions; j++) {\r\n\t\t\t// add position to map and position filters\r\n\t\t\tvar position = visiblePositions[j];\r\n\t\t\tvar isFirst = totalTripPositions > 1 && position.Id === firstVisiblePositionId;\r\n\t\t\tvar isLast = totalTripPositions > 1 && position.Id === lastVisiblePositionId;\r\n\t\t\tif (!position.IsHidden && (trip.IncludeAllPositions || isFirst || isLast)) {\r\n\t\t\t\tvar marker = addPositionMarkerToPoint(\r\n\t\t\t\t\t[position.Lat, position.Lng],\r\n\t\t\t\t\tfalse,\r\n\t\t\t\t\tposition,\r\n\t\t\t\t\tasset,\r\n\t\t\t\t\talpha,\r\n\t\t\t\t\tclusterTripMarkers,\r\n\t\t\t\t\tisFirst,\r\n\t\t\t\t\tisLast,\r\n\t\t\t\t\ttrkDataGroups.JOURNEY_HISTORY,\r\n\t\t\t\t\ttrip\r\n\t\t\t\t);\r\n\t\t\t\tclusterMarkers.push(marker);\r\n\t\t\t\talpha -= alphaIncrement;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\ttrkData.trips.markersByTripId = _.groupBy(trkData.trips.markers, function (marker) {\r\n\t\t\treturn marker.data.tripId;\r\n\t\t});\r\n\r\n\t\tif (clusterTripMarkers && trkData.trips.markerClustersByTripId[trip.Id] !== undefined) {\r\n\t\t\ttrkData.trips.markerClustersByTripId[trip.Id].empty();\r\n\t\t\ttrkData.trips.markerClustersByTripId[trip.Id].multiAdd(clusterMarkers);\r\n\t\t\taddItemToMap(trkData.trips.markerClustersByTripId[trip.Id]);\r\n\t\t}\r\n\r\n\t\tcreatePositionLinesForTrip(trip, asset, visiblePositions);\r\n\t}\r\n}\r\n\r\nexport function openEventsForTrip(trip) {\r\n\tvar tripEvents = _.filter(trkData.trips.normalizedEventsByTripId[trip.Id], getDisplayFilterForEventType(\"events\"));\r\n\tcreateListing(tripEvents, \"events\");\r\n\topenDialogPanel(\r\n\t\tdomNodes.dialogs.assetEvents,\r\n\t\tstrings.EVENTS,\r\n\t\ttrip,\r\n\t\tfalse,\r\n\t\tundefined,\r\n\t\t\"trip\",\r\n\t\t\"trip-events\",\r\n\t\topenEventsForTrip\r\n\t);\r\n}\r\n\r\nexport function toggleTripActive(journeyId, tripId, makeTripActive, updateUI) {\r\n\tvar journey = findJourneyById(journeyId);\r\n\tif (journey === null) {\r\n\t\treturn false;\r\n\t}\r\n\tvar trip = null;\r\n\tfor (var i = 0; i < journey.Trips.length; i++) {\r\n\t\tif (journey.Trips[i].Id === tripId) {\r\n\t\t\ttrip = journey.Trips[i];\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif (trip === null) {\r\n\t\treturn false;\r\n\t}\r\n\tvar asset = findAssetById(journey.AssetId);\r\n\tif (asset === null) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tvar isCurrentlyActive = isItemIncluded(user.displayPreferences.visibleTrips, tripId);\r\n\tif (makeTripActive === null) {\r\n\t\tmakeTripActive = !isCurrentlyActive;\r\n\t}\r\n\r\n\tif (isCurrentlyActive === makeTripActive) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar tripPositions = null;\r\n\tif (trkData.trips.positionsByTripId !== null && trkData.trips.positionsByTripId[tripId] !== undefined) {\r\n\t\ttripPositions = trkData.trips.positionsByTripId[tripId];\r\n\t}\r\n\r\n\tvar setBounds = false;\r\n\tif (tripPositions !== null) {\r\n\t\tif (trkData.trips.mapLinesByTripId[trip.Id] !== undefined) {\r\n\t\t\tif (makeTripActive) {\r\n\t\t\t\taddItemToMap(trkData.trips.mapLinesByTripId[trip.Id]);\r\n\t\t\t} else {\r\n\t\t\t\tremoveItemFromMap(trkData.trips.mapLinesByTripId[trip.Id]);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (makeTripActive) {\r\n\t\t\tif (preferences.PREFERENCE_GROUP_POSITIONS) {\r\n\t\t\t\tif (trkData.trips.markerClustersByTripId[trip.Id] !== undefined) {\r\n\t\t\t\t\taddItemToMap(trkData.trips.markerClustersByTripId[trip.Id]);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t_.each(trkData.trips.markersByTripId[trip.Id], function (item) {\r\n\t\t\t\t\tif (!item.data.location.IsHidden) {\r\n\t\t\t\t\t\taddItemToMap(item);\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\t// remove marker cluster\r\n\t\t\tif (preferences.PREFERENCE_GROUP_POSITIONS) {\r\n\t\t\t\tif (trkData.trips.markerClustersByTripId[trip.Id] !== undefined) {\r\n\t\t\t\t\tremoveItemFromMap(trkData.trips.markerClustersByTripId[trip.Id]);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t_.each(trkData.trips.markersByTripId[trip.Id], function (item) {\r\n\t\t\t\t\tremoveItemFromMap(item);\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tsetBounds = true;\r\n\t}\r\n\r\n\tif (tripPositions === null && makeTripActive) {\r\n\t\tquerySingleTrip(journey, trip);\r\n\t}\r\n\r\n\tupdateTripVisibilityStatus(tripId, makeTripActive);\r\n\r\n\t// grey out / make active\r\n\tvar index = _.indexOf(trkData.visible.trips, tripId);\r\n\tif (makeTripActive) {\r\n\t\tupdateTripListingIcon(tripId, asset.Color, true, asset.Class);\r\n\t\tdisplayPreferencesAdd(\"visibleTrips\", tripId);\r\n\t\tif (index === -1) {\r\n\t\t\ttrkData.visible.trips.push(tripId);\r\n\t\t}\r\n\t} else {\r\n\t\tupdateTripListingIcon(tripId, asset.Color, false, asset.Class);\r\n\t\tdisplayPreferencesRemove(\"visibleTrips\", tripId);\r\n\t\tif (index !== -1) {\r\n\t\t\ttrkData.visible.trips.splice(index, 1);\r\n\t\t}\r\n\t}\r\n\r\n\t// these UI updates should really only happen after all assets have been toggled, so for group changes this is rough\r\n\tif (updateUI) {\r\n\t\tupdateGroupVisibilityStatus(\"journey-\" + journeyId);\r\n\t\tupdateActiveAssetInformation();\r\n\t}\r\n\tif (setBounds) {\r\n\t\tsetMapBounds();\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nexport function queryVisibleTrips() {\r\n\tvar deferreds = [];\r\n\t_.each(trkData.visible.trips, function (tripId) {\r\n\t\tvar trip = findTripById(tripId);\r\n\t\tif (trip === null) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tvar journey = findJourneyById(trip.JourneyId);\r\n\t\tif (journey === null) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tdeferreds.push(querySingleTrip(journey, trip));\r\n\t});\r\n\treturn deferreds;\r\n}\r\n\r\n//var throttledCompareSharedViews = _.throttle(compareSharedViews, 250, { leading: false });\r\n\r\nfunction querySingleTrip(journey, trip) {\r\n\tif (trip.IsQueried === true) {\r\n\t\treturn null;\r\n\t}\r\n\ttrip.IsQueried = true;\r\n\ttoggleLoadingMessage(true, \"trip\" + trip.Id);\r\n\tvar data = {\r\n\t\tjourneyId: journey.Id,\r\n\t\ttripId: trip.Id,\r\n\t\tzoomLevel: null,\r\n\t\tsensitivity: null,\r\n\t\tloadLimitedData: true,\r\n\t\tisMobile: state.isMobile,\r\n\t};\r\n\treturn $j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/GetTripData\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tif (msg.d) {\r\n\t\t\t\t//state.hasQueriedHistory = true;\r\n\t\t\t\tvar result = msg.d;\r\n\r\n\t\t\t\t_.each(result.Assets, function (assetResult) {\r\n\t\t\t\t\t// should only be a single asset returned\r\n\t\t\t\t\tprocessTripData(journey, trip, assetResult);\r\n\t\t\t\t});\r\n\t\t\t\t//var events = result.Events;\r\n\t\t\t\t//_.each(events, function (item) {\r\n\t\t\t\t// var existingTripEvent = _.find(trkData.trips.events, function (evt) { return evt.Id === item.Id; });\r\n\t\t\t\t// if (existingTripEvent !== undefined) {\r\n\t\t\t\t// return;\r\n\t\t\t\t// }\r\n\t\t\t\t// trkData.trips.events.push(item);\r\n\t\t\t\t//});\r\n\t\t\t\ttrkData.trips.eventsByTripId[trip.Id] = result.Events;\r\n\r\n\t\t\t\tvar normalizedTripEvents = [];\r\n\t\t\t\t_.each(result.Events, function (item) {\r\n\t\t\t\t\tif (trkData.eventsById[item.Id] === undefined) {\r\n\t\t\t\t\t\ttrkData.eventsById[item.Id] = normalizeAssetData(item.AssetId, \"event\", item);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tnormalizedTripEvents.push(trkData.eventsById[item.Id]);\r\n\t\t\t\t\ttrkData.trips.normalizedEvents.push(trkData.eventsById[item.Id]);\r\n\t\t\t\t\ttrkData.trips.normalizedEventIds[item.Id] = true;\r\n\t\t\t\t});\r\n\r\n\t\t\t\ttrkData.trips.normalizedEventsByTripId[trip.Id] = normalizedTripEvents;\r\n\r\n\t\t\t\tupdateAssetFunctionBadges(trkDataGroups.JOURNEY_HISTORY, trip.Id);\r\n\t\t\t\tupdateGroupFunctionBadges(trkDataGroups.JOURNEY_HISTORY, [trip.Id], \"trip\");\r\n\t\t\t\tresizeApp(true);\r\n\t\t\t\tsetMapBounds();\r\n\t\t\t}\r\n\t\t\ttoggleLoadingMessage(false, \"trip\" + trip.Id);\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\thandleWebServiceError(strings.MSG_SINGLE_ASSET_ERROR);\r\n\t\t\ttoggleLoadingMessage(false, \"trip\" + trip.Id);\r\n\t\t},\r\n\t});\r\n}\r\n\r\nfunction updateTripListingIcon(id, color, isActive, icon) {\r\n\tupdateItemListingIcon(id, color, isActive, icon, domNodes.trips);\r\n}\r\n\r\nfunction updateTripVisibilityStatus(tripId, makeActive) {\r\n\tupdateItemVisibilityStatus(tripId, makeActive, trkData.visible.trips, domNodes.trips);\r\n}\r\n\r\nfunction updateItemVisibilityStatus(itemId, makeActive, visibleList, domNodes) {\r\n\tvar index = _.indexOf(visibleList, itemId);\r\n\tif (makeActive) {\r\n\t\tif (index === -1) {\r\n\t\t\tvisibleList.push(itemId);\r\n\t\t}\r\n\t} else {\r\n\t\tif (index !== -1) {\r\n\t\t\tvisibleList.splice(index, 1);\r\n\t\t}\r\n\t}\r\n\tvar itemNodes = domNodes[itemId];\r\n\tif (!_.isArray(itemNodes)) {\r\n\t\titemNodes = [itemNodes];\r\n\t}\r\n\r\n\tconsole.log(itemId);\r\n\r\n\t_.each(itemNodes, function (itemNode) {\r\n\t\tvar visibilityIcon = itemNode.querySelector(\".showhide\");\r\n\t\tif (makeActive) {\r\n\t\t\tvisibilityIcon\r\n\t\t\t\t.querySelector(\"use\")\r\n\t\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#visible\");\r\n\t\t\tvisibilityIcon.classList.add(\"active\");\r\n\t\t} else {\r\n\t\t\tvisibilityIcon\r\n\t\t\t\t.querySelector(\"use\")\r\n\t\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#invisible\");\r\n\t\t\tvisibilityIcon.classList.remove(\"active\");\r\n\t\t}\r\n\t});\r\n}\r\n\r\nexport function createTripNode(journey, trip, asset) {\r\n\tif (trip === null || asset === null || journey === null) {\r\n\t\treturn null;\r\n\t}\r\n\tvar isActive = user.isAnonymous ? true : isItemIncluded(user.displayPreferences.visibleTrips, trip.Id);\r\n\tif (isActive) {\r\n\t\tif (_.indexOf(trkData.visible.trips, trip.Id) === -1) {\r\n\t\t\ttrkData.visible.trips.push(trip.Id);\r\n\t\t}\r\n\t}\r\n\tvar alpha = isActive ? null : 50;\r\n\tvar description = \"\";\r\n\tif (trip.FromEpoch !== undefined && trip.FromEpoch !== null) {\r\n\t\tdescription = moment(trip.FromEpoch).format(\"L\");\r\n\t}\r\n\tdescription += \" - \";\r\n\tif (trip.ToEpoch !== undefined && trip.ToEpoch !== null) {\r\n\t\tdescription += moment(trip.ToEpoch).format(\"L\");\r\n\t}\r\n\r\n\tvar tripDto = {\r\n\t\tid: trip.Id,\r\n\t\tname: trip.Name,\r\n\t\tdescription: description,\r\n\t\tjourneyId: journey.Id,\r\n\t\tcolor: asset.Color,\r\n\t\ticon: createMarkerPath(asset.Class, asset.Color, null, alpha, asset.Id, true),\r\n\t\tisVisible: isItemIncluded(user.displayPreferences.visibleTrips, trip.Id),\r\n\t\tvisibilityClass: isItemIncluded(user.displayPreferences.visibleTrips, trip.Id) ? \"active\" : \"disabled\",\r\n\t\tserviceClass: \"\",\r\n\t\tlocation: {\r\n\t\t\taddress: null,\r\n\t\t\tlatitude: null,\r\n\t\t\tlongitude: null,\r\n\t\t\ttime: null,\r\n\t\t\tspeed: null,\r\n\t\t},\r\n\t\tnotifications: {\r\n\t\t\tsymbol: user.isAnonymous\r\n\t\t\t\t? options.allowAnonymousMessaging\r\n\t\t\t\t\t? \"notifications-sh\"\r\n\t\t\t\t\t: \"notifications-sh-nc\"\r\n\t\t\t\t: \"notifications\",\r\n\t\t\talerts: 0,\r\n\t\t\tevents: 0,\r\n\t\t\tstatus: 0,\r\n\t\t\tmessages: 0,\r\n\t\t},\r\n\t};\r\n\r\n\tvar fragment = templates.trip(tripDto);\r\n\treturn fragment.childNodes[0];\r\n}\r\n\r\nexport function deleteTrip(trip) {\r\n\tdomNodes.trips[trip.Id].parentNode.removeChild(domNodes.trips[trip.Id]);\r\n\tvar panel = domNodes.panels.secondary;\r\n\tif (panel.getAttribute(\"data-group-for\") === \"trips\" && parseInt(panel.getAttribute(\"data-item-id\")) === trip.Id) {\r\n\t\tcloseSecondaryPanel();\r\n\t}\r\n\r\n\t_.each(trkData.trips.markersByTripId[trip.Id], function (marker) {\r\n\t\tremoveItemFromMap(marker);\r\n\t});\r\n\r\n\tdelete trkData.trips.markersByTripId[trip.Id];\r\n\tdelete trkData.trips.eventsByTripId[trip.Id];\r\n\tdelete trkData.trips.positionsByTripId[trip.Id];\r\n\tdelete trkData.trips.messagesByTripId[trip.Id];\r\n\tdelete trkData.trips.messageCountsByTripId[trip.Id];\r\n\r\n\tvar journey = findJourneyById(trip.JourneyId);\r\n\tif (journey != null) {\r\n\t\tfor (var i = 0; i < journey.Trips.length; i++) {\r\n\t\t\tif (journey.Trips[i].Id == trip.Id) {\r\n\t\t\t\tjourney.Trips.splice(i, 1);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tvar groupId = \"journey-\" + trip.JourneyId;\r\n\tupdateGroupVisibilityStatus(groupId);\r\n}\r\n","import { map } from \"./map-base.js\";\r\nimport trkData from \"./data.js\";\r\nimport state from \"./state.js\";\r\nimport options from \"./options.js\";\r\nimport { findAssetById } from \"./assets.js\";\r\nimport preferences from \"./preferences.js\";\r\nimport { viewModes, mapModes } from \"./const.js\";\r\nimport { findTripById } from \"./trips.js\";\r\n\r\nimport { normalGleoSymbols, sharedViewGleoSymbols } from \"./map-gleo.js\";\r\n\r\nimport RawGeometry from \"./gleo/src/geometry/RawGeometry.mjs\";\r\n\r\nimport _ from \"lodash\";\r\nimport L from \"leaflet\";\r\n\r\nexport function setMapBounds() {\r\n\tconsole.log(\"setMapBounds()\");\r\n\tif (map == null) {\r\n\t\treturn;\r\n\t}\r\n\t// recreate bounds based on visible positions\r\n\tclearBounds();\r\n\tif (state.activeViewMode === viewModes.NORMAL) {\r\n\t\tif (state.activeMapMode === mapModes.LIVE) {\r\n\t\t\tvar positionMarkers = _.keyBy(trkData.live.markers, function (item) {\r\n\t\t\t\treturn item.data.location.Id;\r\n\t\t\t});\r\n\t\t\t_.each(trkData.live.latestPositions, function (position) {\r\n\t\t\t\tvar asset = findAssetById(position.AssetId);\r\n\t\t\t\tif (asset == null) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tvar position = position.Position;\r\n\t\t\t\tvar positionMarker = positionMarkers[position.Id];\r\n\t\t\t\tif (positionMarker === undefined) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tif (!normalGleoSymbols.has(positionMarker)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\textendBounds(positionMarker.geometry.asLatLng());\r\n\t\t\t});\r\n\t\t} else if (state.activeMapMode === mapModes.HISTORY) {\r\n\t\t\tif (preferences.PREFERENCE_GROUP_POSITIONS) {\r\n\t\t\t\t// set bounds based on markercluster\r\n\t\t\t\tfor (var i = 0; i < trkData.assets.length; i++) {\r\n\t\t\t\t\tvar cluster = trkData.history.markerClustersByAssetId[trkData.assets[i].Id];\r\n\t\t\t\t\tif (cluster == undefined) {\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (!normalGleoSymbols.has(cluster)) {\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif (!cluster.platina) {\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tconst bbox = new RawGeometry(cluster.platina.crs, cluster.bbox).asLatLng();\r\n\t\t\t\t\tif (bbox.every(n=>isFinite(n))) {\r\n\r\n\t\t\t\t\t\tconst clusterBounds = L.latLngBounds([\r\n\t\t\t\t\t\t\t[bbox[0],bbox[1]],\r\n\t\t\t\t\t\t\t[bbox[2],bbox[3]],\r\n\t\t\t\t\t\t]);\r\n\r\n\t\t\t\t\t\tif (clusterBounds.isValid()) {\r\n\t\t\t\t\t\t\textendBounds(clusterBounds);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t_.each(trkData.history.markers, function (positionMarker) {\r\n\t\t\t\t\tif (!normalGleoSymbols.has(positionMarker)) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\textendBounds(positionMarker.getLatLng());\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// active trip bounds\r\n\t\t_.each(trkData.visible.trips, function (tripId) {\r\n\t\t\tvar trip = findTripById(tripId);\r\n\t\t\tif (trip !== null && trkData.trips.positionsByTripId[tripId] !== undefined) {\r\n\t\t\t\tvar visiblePositions = _.filter(trkData.trips.positionsByTripId[tripId].Positions, function (item) {\r\n\t\t\t\t\treturn !item.IsHidden;\r\n\t\t\t\t});\r\n\t\t\t\t_.each(visiblePositions, function (position) {\r\n\t\t\t\t\textendBounds(L.latLng(position.Lat, position.Lng));\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t});\r\n\t} else if (state.activeViewMode === viewModes.SHARED_VIEW) {\r\n\t\tif (\r\n\t\t\t(trkData.sharedView.temp !== null && trkData.sharedView.temp.Preferences.PositionConsolidation) ||\r\n\t\t\t(trkData.sharedView.temp === null &&\r\n\t\t\t\ttrkData.sharedView.current !== null &&\r\n\t\t\t\ttrkData.sharedView.current.Preferences.PositionConsolidation)\r\n\t\t) {\r\n\t\t\t// set bounds based on markercluster\r\n\t\t\t_.each(trkData.sharedView.markerClustersByAssetId, function (cluster) {\r\n\t\t\t\tif (!sharedViewGleoSymbols.has(cluster)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst clusterBounds = L.latLngBounds(new RawGeometry(cluster.platina.crs, cluster.bbox).asLatLng());\r\n\t\t\t\tif (clusterBounds.isValid()) {\r\n\t\t\t\t\textendBounds(clusterBounds);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t} else {\r\n\t\t\t_.each(trkData.sharedView.markers, function (positionMarker) {\r\n\t\t\t\tif (!sharedViewGleoSymbols.has(positionMarker)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\textendBounds(positionMarker.getLatLng());\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\tif (state.bounds == null || !state.bounds.isValid()) {\r\n\t\t// set the map center to be global center\r\n\t\tmap.setView(L.latLng(0, 0), 2);\r\n\t} else {\r\n\t\tmap.fitBounds(state.bounds, { padding: [10, 10], maxZoom: options.maximumZoom });\r\n\t}\r\n}\r\n\r\nexport function clearBounds() {\r\n\tstate.bounds = L.latLngBounds();\r\n\tstate.boundsItems = [];\r\n}\r\n\r\nexport function extendBounds(location) {\r\n\tif (state.bounds === null) {\r\n\t\treturn;\r\n\t}\r\n\tstate.boundsItems.push(location);\r\n\tif (state.bounds.isValid()) {\r\n\t\tif (state.bounds.contains(location)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tstate.bounds.extend(location);\r\n}\r\n","import trkData from \"./data.js\";\r\nimport { mapModes } from \"./const.js\";\r\nimport state from \"./state.js\";\r\nimport preferences from \"./preferences.js\";\r\nimport { addItemToMap, removeItemFromMap } from \"./map-items.js\";\r\nimport { findAssetById } from \"./assets.js\";\r\nimport { setMapBounds } from \"./map-bounds.js\";\r\nimport { isItemIncluded } from \"./polyfills.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport { toggleLoadingMessage } from \"./ajax.js\";\r\nimport { resizeApp } from \"./window-layout.js\";\r\nimport { handleWebServiceError } from \"./ajax.js\";\r\nimport strings from \"./strings.js\";\r\nimport { updateItemListingIcon, showResultLimitsIfApplicable } from \"./item-listing.js\";\r\nimport { addAssetEvents } from \"./asset-events.js\";\r\nimport user, { displayPreferencesAdd, displayPreferencesRemove } from \"./user.js\";\r\nimport { createHistoryPositionResults, processAssetHistoryPositionsResult } from \"./position-history.js\";\r\nimport { updateGroupVisibilityStatus } from \"./asset-group.js\";\r\nimport { updateActiveAssetInformation } from \"./assets-active.js\";\r\n\r\nimport _ from \"lodash\";\r\n\r\n// Will dispatch an event whenever an asset is selected or deselected from the list.\r\nexport const assetActiveNotifier = new EventTarget();\r\n\r\n\r\n/// NOTE: Even though the function name is about an \"active\" asset, the\r\n/// contept of \"active assets\" is different - see assets-active.js\r\n\r\nexport function toggleAssetActive(assetId, makeAssetActive, updateUI) {\r\n\tvar asset = findAssetById(assetId);\r\n\tif (asset === null) {\r\n\t\treturn Promise.resolve(true);\r\n\t}\r\n\r\n\tvar isCurrentlyActive = !isItemIncluded(user.displayPreferences.hiddenAssets, assetId);\r\n\tif (makeAssetActive === null) {\r\n\t\t// assuming toggling active/inactive if not specified\r\n\t\tmakeAssetActive = !isCurrentlyActive;\r\n\t}\r\n\r\n\tif (isCurrentlyActive === makeAssetActive) {\r\n\t\treturn Promise.resolve(true);\r\n\t}\r\n\r\n\tconst ev = new CustomEvent(\r\n\t\tmakeAssetActive ? \"select\" : \"deselect\",\r\n\t\t{detail: asset}\r\n\t);\r\n\tassetActiveNotifier.dispatchEvent(ev);\r\n\r\n\tconst promises = [];\r\n\r\n\t// show/hide waypoints (if any)\r\n\t// todo: should waypoints be hidden altogether in history mode?\r\n\tvar waypoints = _.filter(trkData.waypoints, { AssetId: asset.Id });\r\n\twaypoints.forEach((waypoint) => {\r\n\t\tif (makeAssetActive) {\r\n\t\t\taddItemToMap(waypoint.Location.marker);\r\n\t\t} else {\r\n\t\t\tremoveItemFromMap(waypoint.Location.marker);\r\n\t\t}\r\n\t});\r\n\r\n\tif (state.activeMapMode !== mapModes.LIVE) {\r\n\t\tvar isAssetFound = trkData.history.positionsByAssetId[assetId] !== undefined;\r\n\r\n\t\t// toggle any map items for the asset\r\n\t\tif (isAssetFound) {\r\n\t\t\t// show/hide positions connecting line\r\n\t\t\tif (trkData.history.mapLinesByAssetId[asset.Id] !== undefined) {\r\n\t\t\t\tif (makeAssetActive) {\r\n\t\t\t\t\taddItemToMap(trkData.history.mapLinesByAssetId[asset.Id]);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tremoveItemFromMap(trkData.history.mapLinesByAssetId[asset.Id]);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// show/hide markers\r\n\t\t\tif (makeAssetActive) {\r\n\t\t\t\tif (preferences.PREFERENCE_GROUP_POSITIONS) {\r\n\t\t\t\t\tif (trkData.history.markerClustersByAssetId[asset.Id] !== undefined) {\r\n\t\t\t\t\t\taddItemToMap(trkData.history.markerClustersByAssetId[asset.Id]);\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\t_.each(trkData.history.markersByAssetId[assetId], function (item) {\r\n\t\t\t\t\t\tif (!item.data.location.IsHidden) {\r\n\t\t\t\t\t\t\taddItemToMap(item);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t// remove marker cluster\r\n\t\t\t\tif (preferences.PREFERENCE_GROUP_POSITIONS) {\r\n\t\t\t\t\tif (trkData.history.markerClustersByAssetId[asset.Id] !== undefined) {\r\n\t\t\t\t\t\tremoveItemFromMap(trkData.history.markerClustersByAssetId[asset.Id]);\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\t_.each(trkData.history.markersByAssetId[assetId], function (item) {\r\n\t\t\t\t\t\tremoveItemFromMap(item);\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tsetMapBounds();\r\n\t\t}\r\n\r\n\t\tif (!isAssetFound && makeAssetActive && state.hasQueriedHistory) {\r\n\t\t\t// query for this specific asset's results to add to existing\r\n\t\t\tpromises.push(querySingleAsset(assetId));\r\n\t\t}\r\n\t} else {\r\n\t\t// show/hide latest position from map and from history\r\n\t\t_.each(trkData.live.markersByAssetId[assetId], function (marker) {\r\n\t\t\tif (makeAssetActive && marker.data.hide !== true) {\r\n\t\t\t\t// data.hide is for markers only temporarily visible, loaded outside of active view\r\n\t\t\t\taddItemToMap(marker);\r\n\t\t\t} else {\r\n\t\t\t\tremoveItemFromMap(marker);\r\n\t\t\t}\r\n\t\t});\r\n\t\tif (trkData.live.mapLinesByAssetId[asset.Id] !== undefined) {\r\n\t\t\tif (makeAssetActive) {\r\n\t\t\t\taddItemToMap(trkData.live.mapLinesByAssetId[asset.Id]);\r\n\t\t\t} else {\r\n\t\t\t\tremoveItemFromMap(trkData.live.mapLinesByAssetId[asset.Id]);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tupdateItemVisibilityStatus(assetId, \"assets\", makeAssetActive);\r\n\r\n\t// grey out / make active\r\n\tvar index = _.indexOf(trkData.visible.assets, assetId);\r\n\tif (makeAssetActive) {\r\n\t\tupdateAssetListingIcon(assetId, asset.Color, true, asset.Class);\r\n\t\tdisplayPreferencesRemove(\"hiddenAssets\", assetId);\r\n\t\tif (index === -1) {\r\n\t\t\ttrkData.visible.assets.push(assetId);\r\n\t\t}\r\n\t} else {\r\n\t\tupdateAssetListingIcon(assetId, asset.Color, false, asset.Class);\r\n\t\tdisplayPreferencesAdd(\"hiddenAssets\", assetId);\r\n\t\tif (index !== -1) {\r\n\t\t\ttrkData.visible.assets.splice(index, 1);\r\n\t\t}\r\n\t}\r\n\r\n\t// these UI updates should really only happen after all assets have been toggled, so for group changes this is rough\r\n\tif (updateUI) {\r\n\t\t// update group visibility statuses\r\n\t\t_.each(asset.GroupIds, function (assetGroupId) {\r\n\t\t\tupdateGroupVisibilityStatus(assetGroupId);\r\n\t\t});\r\n\t\tupdateGroupVisibilityStatus(\"all-assets\");\r\n\r\n\t\tupdateActiveAssetInformation();\r\n\t}\r\n\r\n\treturn Promise.all(promises);\r\n}\r\n\r\nexport async function querySingleAsset(assetId) {\r\n\t// add a single asset's positions to the existing query results\r\n\tvar fromDate = trkData.history.fromDate;\r\n\tvar toDate = trkData.history.toDate;\r\n\t// disable show button and show loading message\r\n\tdomNodes.mapMode.show.disabled = true;\r\n\ttoggleLoadingMessage(true, assetId);\r\n\tvar data = {\r\n\t\tfromDate: fromDate,\r\n\t\ttoDate: toDate,\r\n\t\tassetIds: assetId,\r\n\t\tzoomLevel: null,\r\n\t\tsensitivity: null,\r\n\t\tformat: user.dateFormat,\r\n\t\tlang: user.dateCulture,\r\n\t\tloadLimitedData: false,\r\n\t\tisMobile: state.isMobile,\r\n\t};\r\n\r\n\treturn fetch(wrapUrl(\"/services/GPSService.asmx/GetAssetPositionsForDateRange\"), {\r\n\t\tmethod: \"POST\",\r\n\t\tbody: JSON.stringify(data),\r\n\t\theaders: new Headers({\r\n\t\t\t\"Content-Type\": \"application/json; charset=utf-8\",\r\n\t\t}),\r\n\t})\r\n\t\t.then((res) => res.json())\r\n\t\t.then(function (msg) {\r\n\t\t\tdomNodes.mapMode.show.disabled = false;\r\n\t\t\ttoggleLoadingMessage(false, assetId);\r\n\t\t\tif (msg.d) {\r\n\t\t\t\tvar result = msg.d;\r\n\t\t\t\tif (result.IsLimited === true && result.IncludesLimitedData === false) {\r\n\t\t\t\t\tshowResultLimitsIfApplicable(result, false);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tstate.hasQueriedHistory = true;\r\n\t\t\t\t_.each(result.Assets, function (assetResult) {\r\n\t\t\t\t\tprocessAssetHistoryPositionsResult(assetResult);\r\n\t\t\t\t});\r\n\t\t\t\tif (result.Events !== null) {\r\n\t\t\t\t\taddAssetEvents(result.Events, mapModes.HISTORY);\r\n\t\t\t\t}\r\n\t\t\t\tcreateHistoryPositionResults();\r\n\t\t\t\tif (state.activeMapMode === mapModes.HISTORY) {\r\n\t\t\t\t\tresizeApp(true);\r\n\t\t\t\t\tsetMapBounds();\r\n\t\t\t\t}\r\n\t\t\t\tshowResultLimitsIfApplicable(result, false);\r\n\t\t\t\ttrkData.history.isLimited = result.IsLimited;\r\n\t\t\t\ttrkData.history.isLoadedLimitedData = result.IncludesLimitedData;\r\n\t\t\t}\r\n\t\t})\r\n\t\t.catch(function (error) {\r\n\t\t\thandleWebServiceError(strings.MSG_SINGLE_ASSET_ERROR);\r\n\t\t\t// re-enable show button and clear loading message\r\n\t\t\tdomNodes.mapMode.show.disabled = false;\r\n\t\t\ttoggleLoadingMessage(false, assetId);\r\n\t\t});\r\n}\r\n\r\nexport function updateAssetListingIcon(id, color, isActive, icon) {\r\n\tupdateItemListingIcon(id, color, isActive, icon, domNodes.assets);\r\n}\r\n\r\nexport function updateItemVisibilityStatus(itemId, forItems, makeActive) {\r\n\tvar index = _.indexOf(trkData.visible[forItems], itemId);\r\n\tif (makeActive) {\r\n\t\tif (index === -1) {\r\n\t\t\ttrkData.visible[forItems].push(itemId);\r\n\t\t}\r\n\t} else {\r\n\t\tif (index !== -1) {\r\n\t\t\ttrkData.visible[forItems].splice(index, 1);\r\n\t\t}\r\n\t}\r\n\t_.each(domNodes[forItems][itemId], function (itemNode) {\r\n\t\tvar visibilityIcon = itemNode.querySelector(\".showhide\");\r\n\t\tif (makeActive) {\r\n\t\t\tvisibilityIcon\r\n\t\t\t\t.querySelector(\"use\")\r\n\t\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#visible\");\r\n\t\t\tvisibilityIcon.classList.add(\"active\");\r\n\t\t} else {\r\n\t\t\tvisibilityIcon\r\n\t\t\t\t.querySelector(\"use\")\r\n\t\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#invisible\");\r\n\t\t\tvisibilityIcon.classList.remove(\"active\");\r\n\t\t}\r\n\t});\r\n}\r\n\r\nexport function hideAllAssetsExcept(assetId) {\r\n\t_.each(trkData.assets, function (asset) {\r\n\t\tvar makeActive = asset.Id === assetId;\r\n\t\ttoggleAssetActive(asset.Id, makeActive, false);\r\n\t});\r\n\r\n\t_.each(trkData.groups, function (group) {\r\n\t\tupdateGroupVisibilityStatus(group.Id);\r\n\t});\r\n\tupdateGroupVisibilityStatus(\"all-assets\");\r\n\tupdateActiveAssetInformation();\r\n}\r\n","import strings from \"./strings.js\";\r\nimport trkData from \"./data.js\";\r\nimport state from \"./state.js\";\r\nimport { viewModes, mapModes } from \"./const.js\";\r\nimport { intervals } from \"./timers.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { findAssetById } from \"./assets.js\";\r\nimport { toggleAssetActive } from \"./asset-select.js\";\r\nimport { getPositionInHistoryRelative } from \"./position-history.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport _ from \"lodash\";\r\nimport { el, svg } from \"redom\"; // https://redom.js.org/\r\n\r\nexport function initPlayback() {\r\n\t$(domNodes.infoDialogs.mapItemInformation).on(\"click\", \"#playback-first\", function (e) {\r\n\t\te.preventDefault();\r\n\t\tplaybackFirstPosition();\r\n\t});\r\n\t$(domNodes.infoDialogs.mapItemInformation).on(\"click\", \"#playback-prev\", function (e) {\r\n\t\te.preventDefault();\r\n\t\tplaybackPrevPosition();\r\n\t});\r\n\t$(domNodes.infoDialogs.mapItemInformation).on(\"click\", \"#playback-next\", function (e) {\r\n\t\te.preventDefault();\r\n\t\tplaybackNextPosition();\r\n\t});\r\n\t$(domNodes.infoDialogs.mapItemInformation).on(\"click\", \"#playback-last\", function (e) {\r\n\t\te.preventDefault();\r\n\t\tplaybackLastPosition();\r\n\t});\r\n\t$(domNodes.infoDialogs.mapItemInformation).on(\"click\", \"#playback\", function (e) {\r\n\t\te.preventDefault();\r\n\t\tplaybackClick();\r\n\t});\r\n}\r\n\r\nexport function createPositionPlaybackForAsset(asset, marker) {\r\n\tvar location = marker.data.location;\r\n\tvar tripId = marker.data.tripId;\r\n\tvar isForTrip = tripId !== undefined && tripId !== null;\r\n\tif (\r\n\t\tstate.activeMapMode === mapModes.LIVE &&\r\n\t\tstate.activeViewMode === viewModes.NORMAL &&\r\n\t\t(tripId === undefined || tripId === null)\r\n\t) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// include position history playback buttons in history mode\r\n\tvar playbackTextElements;\r\n\tvar total = null;\r\n\tvar current = null;\r\n\r\n\tvar linkOptions = {\r\n\t\tdataset: { assetId: asset.Id, positionId: location.Id },\r\n\t\thref: \"#\",\r\n\t\ttitle: strings.PLAYBACK_PLAY,\r\n\t};\r\n\tif (isForTrip) {\r\n\t\tlinkOptions.dataset.tripId = tripId;\r\n\t}\r\n\r\n\tif (state.isInPlaybackMode) {\r\n\t\ttotal = trkData.playback.positions.length;\r\n\t\tcurrent = trkData.playback.positions.length - trkData.playback.index;\r\n\t\tplaybackTextElements = [svg(\"svg\", svg(\"use\", { xlink: { href: \"/content/svg/tracking.svg?v=15#pause-solid\" } }))]; // text(strings.PLAYBACK_STOP)\r\n\t\tlinkOptions.title = strings.PLAYBACK_STOP;\r\n\t} else {\r\n\t\t// todo: doesn't work with trips\r\n\t\t// determine current position in history through calculation\r\n\t\ttotal = null;\r\n\t\tcurrent = null;\r\n\t\tvar assetPositions = [];\r\n\t\tif (isForTrip) {\r\n\t\t\tassetPositions = trkData.trips.positionsByTripId[tripId];\r\n\t\t} else if (state.activeViewMode === viewModes.NORMAL) {\r\n\t\t\tassetPositions = trkData.history.positionsByAssetId[asset.Id];\r\n\t\t} else if (state.activeViewMode === viewModes.SHARED_VIEW) {\r\n\t\t\tassetPositions = trkData.sharedView.positionsByAssetId[asset.Id];\r\n\t\t}\r\n\r\n\t\tif (assetPositions !== undefined) {\r\n\t\t\tassetPositions = assetPositions.Positions;\r\n\t\t\tfor (var j = 0; j < assetPositions.length; j++) {\r\n\t\t\t\tif (assetPositions[j].Id === location.Id) {\r\n\t\t\t\t\ttotal = assetPositions.length;\r\n\t\t\t\t\tcurrent = assetPositions.length - j;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tplaybackTextElements = [svg(\"svg\", svg(\"use\", { xlink: { href: \"/content/svg/tracking.svg?v=15#play-solid\" } }))]; // text(strings.PLAYBACK_PLAY)\r\n\t\tlinkOptions.title = strings.PLAYBACK_PLAY;\r\n\t}\r\n\r\n\tvar playbackStatus = strings.POSITION_INDEX.replace(\"{0}\", current).replace(\"{1}\", total) + \" \";\r\n\tvar disablePrev = current === 1;\r\n\tvar disableNext = current >= total;\r\n\r\n\tvar playback = [\r\n\t\tel(\r\n\t\t\t\"a#playback-first.btn.btn-secondary.btn-sm.playback-link\" + (disablePrev ? \".disabled\" : \"\"),\r\n\t\t\t{ href: \"#\", title: strings.FIRST },\r\n\t\t\t[svg(\"svg\", svg(\"use\", { xlink: { href: \"/content/svg/tracking.svg?v=15#fast-backward-solid\" } }))]\r\n\t\t), // , el('span', strings.FIRST)\r\n\t\tel(\r\n\t\t\t\"a#playback-prev.btn.btn-secondary.btn-sm.playback-link\" + (disablePrev ? \".disabled\" : \"\"),\r\n\t\t\t{ href: \"#\", title: strings.POSITION_PREV },\r\n\t\t\t[svg(\"svg\", svg(\"use\", { xlink: { href: \"/content/svg/tracking.svg?v=15#backward-solid\" } }))]\r\n\t\t), //, el('span', strings.POSITION_PREV)\r\n\t\tel(\"span#playback-status.btn.btn-secondary.btn-sm.disabled.w-100\", playbackStatus),\r\n\t\tel(\r\n\t\t\t\"a#playback-next.btn.btn-secondary.btn-sm.playback-link\" + (disableNext ? \".disabled\" : \"\"),\r\n\t\t\t{ href: \"#\", title: strings.POSITION_NEXT },\r\n\t\t\t[svg(\"svg\", svg(\"use\", { xlink: { href: \"/content/svg/tracking.svg?v=15#forward-solid\" } }))]\r\n\t\t), //el('span', strings.POSITION_NEXT),\r\n\t\tel(\r\n\t\t\t\"a#playback-last.btn.btn-secondary.btn-sm.playback-link\" + (disableNext ? \".disabled\" : \"\"),\r\n\t\t\t{ href: \"#\", title: strings.LAST },\r\n\t\t\t[svg(\"svg\", svg(\"use\", { xlink: { href: \"/content/svg/tracking.svg?v=15#fast-forward-solid\" } }))]\r\n\t\t), // el('span', strings.LAST),\r\n\t\tel(\r\n\t\t\t\"a#playback.btn.btn-secondary.btn-sm.playback-link\" + (disableNext ? \".disabled\" : \"\"),\r\n\t\t\tlinkOptions,\r\n\t\t\tplaybackTextElements\r\n\t\t),\r\n\t];\r\n\treturn el(\"div.btn-group.w-100.my-1.playback-container\", playback);\r\n}\r\n\r\nexport function playbackPrevPosition() {\r\n\tvar link = document.getElementById(\"playback\");\r\n\tvar assetId = parseInt(link.getAttribute(\"data-asset-id\"));\r\n\tvar positionId = link.getAttribute(\"data-position-id\");\r\n\tvar tripId = link.getAttribute(\"data-trip-id\");\r\n\tif (tripId !== null) {\r\n\t\ttripId = parseInt(tripId);\r\n\t}\r\n\r\n\tif (state.activeMapMode === mapModes.LIVE && state.activeViewMode === viewModes.NORMAL && tripId === null) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// get previous position id\r\n\tvar relativePosition = getPositionInHistoryRelative(assetId, positionId, tripId, 1);\r\n\tif (relativePosition == null) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// reset the playback interval if in playback mode\r\n\tif (state.isInPlaybackMode) {\r\n\t\tif (intervals.playbackInterval != null) {\r\n\t\t\tclearInterval(intervals.playbackInterval);\r\n\t\t}\r\n\t\tintervals.playbackInterval = setInterval(playbackNext, 5000);\r\n\t\ttrkData.playback.index++;\r\n\t}\r\n\r\n\t// open its marker\r\n\topenMarkerForPosition(relativePosition.Id, tripId);\r\n}\r\n\r\nfunction playbackLastPosition() {\r\n\tvar link = document.getElementById(\"playback\");\r\n\tvar assetId = parseInt(link.getAttribute(\"data-asset-id\"));\r\n\tvar tripId = link.getAttribute(\"data-trip-id\");\r\n\tif (tripId !== null) {\r\n\t\ttripId = parseInt(tripId);\r\n\t}\r\n\r\n\t// doesn't have to be in live mode if playing back a trip\r\n\tif (state.activeMapMode === mapModes.LIVE && state.activeViewMode === viewModes.NORMAL && tripId === null) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar relativePosition = null;\r\n\tvar assetPositions = [];\r\n\tif (tripId !== null) {\r\n\t\tassetPositions = trkData.trips.positionsByTripId[tripId].Positions;\r\n\t} else if (state.activeViewMode === viewModes.NORMAL) {\r\n\t\tassetPositions = trkData.history.positionsByAssetId[assetId].Positions;\r\n\t} else if (state.activeViewMode === viewModes.SHARED_VIEW) {\r\n\t\tassetPositions = trkData.sharedView.positionsByAssetId[assetId].Positions;\r\n\t}\r\n\tif (assetPositions.length === 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\trelativePosition = assetPositions[0];\r\n\r\n\t// reset the playback interval if in playback mode\r\n\tif (state.isInPlaybackMode) {\r\n\t\tif (intervals.playbackInterval != null) {\r\n\t\t\tclearInterval(intervals.playbackInterval);\r\n\t\t}\r\n\t\tintervals.playbackInterval = setInterval(playbackNext, 5000);\r\n\t\ttrkData.playback.index = 0;\r\n\t}\r\n\r\n\t// open its marker\r\n\topenMarkerForPosition(relativePosition.Id, tripId);\r\n}\r\n\r\nfunction playbackFirstPosition() {\r\n\tvar link = document.getElementById(\"playback\");\r\n\tvar assetId = parseInt(link.getAttribute(\"data-asset-id\"));\r\n\tvar tripId = link.getAttribute(\"data-trip-id\");\r\n\tif (tripId !== null) {\r\n\t\ttripId = parseInt(tripId);\r\n\t}\r\n\r\n\tif (state.activeMapMode === mapModes.LIVE && state.activeViewMode === viewModes.NORMAL && tripId === null) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar relativePosition = null;\r\n\tvar assetPositions = [];\r\n\tif (tripId !== null) {\r\n\t\tassetPositions = trkData.trips.positionsByTripId[tripId].Positions;\r\n\t} else if (state.activeViewMode === viewModes.NORMAL) {\r\n\t\tassetPositions = trkData.history.positionsByAssetId[assetId].Positions;\r\n\t} else if (state.activeViewMode === viewModes.SHARED_VIEW) {\r\n\t\tassetPositions = trkData.sharedView.positionsByAssetId[assetId].Positions;\r\n\t}\r\n\tif (assetPositions.length === 0) {\r\n\t\treturn;\r\n\t}\r\n\trelativePosition = assetPositions[assetPositions.length - 1];\r\n\r\n\tif (relativePosition == null) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// reset the playback interval if in playback mode\r\n\tif (state.isInPlaybackMode) {\r\n\t\tif (intervals.playbackInterval != null) {\r\n\t\t\tclearInterval(intervals.playbackInterval);\r\n\t\t}\r\n\t\tintervals.playbackInterval = setInterval(playbackNext, 5000);\r\n\t\ttrkData.playback.index = assetPositions.length - 1;\r\n\t}\r\n\r\n\t// open its marker\r\n\topenMarkerForPosition(relativePosition.Id, tripId);\r\n}\r\n\r\nexport function playbackNextPosition() {\r\n\tvar link = document.getElementById(\"playback\");\r\n\tvar assetId = parseInt(link.getAttribute(\"data-asset-id\"));\r\n\tvar positionId = link.getAttribute(\"data-position-id\");\r\n\tvar tripId = link.getAttribute(\"data-trip-id\");\r\n\tif (tripId !== null) {\r\n\t\ttripId = parseInt(tripId);\r\n\t}\r\n\r\n\tif (state.activeMapMode === mapModes.LIVE && state.activeViewMode === viewModes.NORMAL && tripId === null) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar relativePosition = getPositionInHistoryRelative(assetId, positionId, tripId, -1);\r\n\tif (relativePosition == null) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// reset the playback interval if in playback mode\r\n\tif (state.isInPlaybackMode) {\r\n\t\tif (intervals.playbackInterval != null) {\r\n\t\t\tclearInterval(intervals.playbackInterval);\r\n\t\t}\r\n\t\tintervals.playbackInterval = setInterval(playbackNext, 5000);\r\n\t\ttrkData.playback.index--;\r\n\t}\r\n\r\n\t// open its marker\r\n\topenMarkerForPosition(relativePosition.Id, tripId);\r\n}\r\n\r\nfunction playbackNext() {\r\n\tif (\r\n\t\tstate.activeMapMode === mapModes.LIVE &&\r\n\t\tstate.activeViewMode === viewModes.NORMAL &&\r\n\t\ttrkData.playback.tripId === null\r\n\t) {\r\n\t\tplaybackEnd();\r\n\t}\r\n\tif (trkData.playback.positions == null) {\r\n\t\tplaybackEnd();\r\n\t}\r\n\r\n\t// move to the next position in playback index\r\n\ttrkData.playback.index--;\r\n\tif (trkData.playback.positions.length > trkData.playback.index && trkData.playback.index >= 0) {\r\n\t\tvar position = trkData.playback.positions[trkData.playback.index];\r\n\t\topenMarkerForPosition(position.Id, trkData.playback.tripId);\r\n\t\tif (trkData.playback.index == 0) {\r\n\t\t\tplaybackEnd();\r\n\t\t}\r\n\t} else {\r\n\t\t// reached the last position\r\n\t\tplaybackEnd();\r\n\t}\r\n}\r\n\r\nexport function playbackStart(assetId, positionId, tripId) {\r\n\tconsole.log(\"playback: \" + assetId + \",\" + positionId + \",\" + tripId);\r\n\tvar asset = findAssetById(assetId);\r\n\tif (asset == null) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar playbackPositions = [];\r\n\ttrkData.playback.assetId = assetId;\r\n\ttrkData.playback.tripId = tripId;\r\n\tif (tripId === null && state.activeViewMode === viewModes.NORMAL) {\r\n\t\tplaybackPositions = trkData.history.positionsByAssetId[assetId];\r\n\t} else if (tripId !== undefined && tripId !== null) {\r\n\t\tplaybackPositions = trkData.trips.positionsByTripId[tripId];\r\n\t} else if (state.activeViewMode === viewModes.SHARED_VIEW) {\r\n\t\tplaybackPositions = trkData.sharedView.positionsByTripId[tripId];\r\n\t}\r\n\tif (playbackPositions !== undefined && playbackPositions !== null) {\r\n\t\ttrkData.playback.positions = playbackPositions.Positions;\r\n\t\t// find current position\r\n\t\tfor (var j = 0; j < trkData.playback.positions.length; j++) {\r\n\t\t\tif (trkData.playback.positions[j].Id == positionId) {\r\n\t\t\t\ttrkData.playback.index = j;\r\n\t\t\t\tif (intervals.playbackInterval != null) {\r\n\t\t\t\t\tclearInterval(intervals.playbackInterval);\r\n\t\t\t\t}\r\n\t\t\t\tintervals.playbackInterval = setInterval(playbackNext, 5000);\r\n\t\t\t\tvar total = trkData.playback.positions.length;\r\n\t\t\t\tvar current = trkData.playback.positions.length - trkData.playback.index;\r\n\t\t\t\tvar positionStatus = strings.POSITION_INDEX.replace(\"{0}\", current).replace(\"{1}\", total) + \" \";\r\n\t\t\t\t$(\"#playback-status\").text(positionStatus);\r\n\t\t\t\tvar playback = document.getElementById(\"playback\");\r\n\t\t\t\tplayback.title = strings.PLAYBACK_STOP;\r\n\t\t\t\tplayback\r\n\t\t\t\t\t.querySelector(\"use\")\r\n\t\t\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#pause-solid\");\r\n\t\t\t\tstate.isInPlaybackMode = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction playbackClick() {\r\n\t// start playback from this position if not already running\r\n\tif (state.isInPlaybackMode) {\r\n\t\tplaybackEnd();\r\n\t} else {\r\n\t\tvar link = document.getElementById(\"playback\");\r\n\t\tif (link === null) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tvar assetId = parseInt(link.getAttribute(\"data-asset-id\"));\r\n\t\tvar positionId = link.getAttribute(\"data-position-id\");\r\n\t\tvar tripId = link.getAttribute(\"data-trip-id\");\r\n\t\tif (tripId !== null) {\r\n\t\t\ttripId = parseInt(tripId);\r\n\t\t}\r\n\t\tif (state.activeMapMode === mapModes.LIVE && state.activeViewMode === viewModes.NORMAL && tripId === null) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tplaybackStart(assetId, positionId, tripId);\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nexport function playbackEnd() {\r\n\tclearInterval(intervals.playbackInterval);\r\n\ttrkData.playback.assetId = null;\r\n\ttrkData.playback.tripId = null;\r\n\tstate.isInPlaybackMode = false;\r\n\ttrkData.playback.positions = [];\r\n\ttrkData.playback.index = 0;\r\n\tvar playback = document.getElementById(\"playback\");\r\n\tif (playback !== null) {\r\n\t\tplayback.title = strings.PLAYBACK_PLAY;\r\n\t\tplayback\r\n\t\t\t.querySelector(\"use\")\r\n\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#play-solid\");\r\n\t}\r\n}\r\n\r\nexport function openMarkerForPosition(positionId, tripId) {\r\n\tvar marker = null;\r\n\tif (tripId !== null) {\r\n\t\tmarker = _.find(trkData.trips.markersByTripId[tripId], function (item) {\r\n\t\t\treturn item.data.location.Id === positionId;\r\n\t\t});\r\n\t} else if (state.activeViewMode === viewModes.NORMAL) {\r\n\t\tmarker = _.find(trkData.history.markers, function (item) {\r\n\t\t\treturn item.data.location.Id === positionId;\r\n\t\t});\r\n\t} else if (state.activeViewMode === viewModes.SHARED_VIEW) {\r\n\t\tmarker = _.find(trkData.sharedView.markers, function (item) {\r\n\t\t\treturn item.data.location.Id === positionId;\r\n\t\t});\r\n\t}\r\n\tif (marker !== undefined) {\r\n\t\t// if the asset for this location is not active, make it active\r\n\t\tif (tripId === null) {\r\n\t\t\ttoggleAssetActive(marker.data.assetId, true, true);\r\n\t\t}\r\n\t\tmarker.fire(\"click\");\r\n\t}\r\n}\r\n","import strings from \"./strings.js\";\r\n\r\nimport _ from \"lodash\";\r\nimport $ from \"jquery\";\r\n\r\n//loadDialogButtons(domNodes.dialogs.placeRouting, placeRouteButtons);\r\n\r\nexport const closeButton = {\r\n\ticons: { primary: \"ui-icon-close\" },\r\n\ttext: strings.CANCEL,\r\n\tclick: function () {\r\n\t\tdocument.getElementById(\"panel-dialog-back\").click();\r\n\t},\r\n\tbuttonType: \"secondary\",\r\n};\r\n\r\nexport function loadDialogButtons(dialog, buttons) {\r\n\tif (buttons === null || buttons.length === 0) {\r\n\t\treturn;\r\n\t}\r\n\tif (dialog === null) {\r\n\t\treturn;\r\n\t}\r\n\tvar buttonPane = dialog.querySelector(\".dialog-buttons\");\r\n\tif (buttonPane === null) {\r\n\t\treturn;\r\n\t}\r\n\tbuttons.forEach(function (button, index, list) {\r\n\t\tvar btn = document.createElement(\"button\");\r\n\t\tbtn.className = \"btn\";\r\n\t\tif (button.class !== undefined) {\r\n\t\t\tbtn.className += \" \" + button.class;\r\n\t\t}\r\n\t\tbtn.type = \"button\";\r\n\t\tif (button.id !== undefined) {\r\n\t\t\tbtn.id = button.id;\r\n\t\t}\r\n\t\tif (button.svgIcon !== undefined) {\r\n\t\t\tvar svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\r\n\t\t\tvar use = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\r\n\t\t\tsvg.appendChild(use);\r\n\t\t\tuse.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#\" + button.svgIcon);\r\n\t\t\tbtn.appendChild(svg);\r\n\t\t\tbtn.appendChild(document.createTextNode(\"\\u00A0\"));\r\n\t\t}\r\n\t\tif (button.buttonType !== undefined) {\r\n\t\t\tbtn.classList.add(\"btn-\" + button.buttonType);\r\n\t\t} else {\r\n\t\t\t// default to primary if left unspecified\r\n\t\t\tbtn.classList.add(\"btn-primary\");\r\n\t\t}\r\n\t\tif (button.disabled !== undefined && button.disabled === true) {\r\n\t\t\tbtn.disabled = true;\r\n\t\t}\r\n\t\tvar label = document.createElement(\"span\");\r\n\t\tlabel.textContent = button.text;\r\n\t\tbtn.appendChild(label);\r\n\r\n\t\tif (button.click !== undefined) {\r\n\t\t\t$(btn).on(\"click\", button.click);\r\n\t\t}\r\n\t\tif (buttonPane.hasChildNodes()) {\r\n\t\t\tbuttonPane.appendChild(document.createTextNode(\"\\u00A0\"));\r\n\t\t}\r\n\t\tbuttonPane.appendChild(btn);\r\n\t});\r\n}\r\n","import strings from \"./strings.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { closeRuler } from \"./ruler.js\";\r\nimport state from \"./state.js\";\r\nimport { mapModes } from \"./const.js\";\r\nimport { initializeSharedViewInformationDialog, deselectSharedView } from \"./shared-view.js\";\r\nimport { svgPath } from \"./dom-util.js\";\r\nimport { playbackPrevPosition, playbackNextPosition } from \"./playback.js\";\r\nimport { closeButton } from \"./modal-dialog-buttons.js\";\r\nimport { findAssetById } from \"./assets.js\";\r\nimport { findTripById } from \"./trips.js\";\r\nimport { createPositionHistorySummary } from \"./position-history.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport $j from \"jquery\";\r\nimport _ from \"lodash\";\r\nimport { el, svg, setChildren } from \"redom\"; // https://redom.js.org/\r\n\r\nexport function initDialogs() {\r\n\t// Update the strings for the generic dialog buttons, now that the strings\r\n\t// have been loaded.\r\n\tcloseButton.text = strings.CANCEL;\r\n\r\n\t$j(domNodes.infoDialogs.eventDetails).dialog({\r\n\t\tautoOpen: false,\r\n\t\tresizable: true,\r\n\t\tmodal: false,\r\n\t\twidth: 400,\r\n\t\tcreate: function () {\r\n\t\t\tcreateDialogTitlebar(this);\r\n\t\t\treplaceDialogButtons(this, $(this).dialog(\"option\", \"buttons\"));\r\n\t\t},\r\n\t});\r\n\r\n\t//domNodes.infoDialogs.placeInformation = document.getElementById('place-information-dialog');\r\n\t//$(domNodes.infoDialogs.placeInformation).dialog({\r\n\t// autoOpen: false,\r\n\t// resizable: false,\r\n\t// modal: false,\r\n\t// maxWidth: 375,\r\n\t// create: function (event, ui) {\r\n\t// createDialogTitlebar(this);\r\n\t// replaceDialogButtons(this, $(this).dialog('option', 'buttons'));\r\n\t// $(this).closest('.ui-dialog')\r\n\t// .draggable('option', 'containment', '#base-content')\r\n\t// .attr('id', 'dialog-place-information');\r\n\t// }\r\n\t//});\r\n\t//domNodes.infoDialogs.geofenceInformation = document.getElementById('geofence-information-dialog');\r\n\t//$(domNodes.infoDialogs.geofenceInformation).dialog({\r\n\t// autoOpen: false,\r\n\t// resizable: false,\r\n\t// modal: false,\r\n\t// maxWidth: 375,\r\n\t// create: function (event, ui) {\r\n\t// createDialogTitlebar(this);\r\n\t// replaceDialogButtons(this, $(this).dialog('option', 'buttons'));\r\n\t// $(this).closest('.ui-dialog')\r\n\t// .draggable('option', 'containment', '#base-content')\r\n\t// .attr('id', 'dialog-geofence-information');\r\n\t// }\r\n\t//});\r\n\r\n\tdomNodes.infoDialogs.sharedViewInformation.manualCloseCallback = function () {\r\n\t\tdeselectSharedView();\r\n\t};\r\n\t$(domNodes.infoDialogs.sharedViewInformation).dialog({\r\n\t\tautoOpen: false,\r\n\t\tresizable: false,\r\n\t\tmodal: false,\r\n\t\twidth: 350,\r\n\t\tmaxWidth: 400,\r\n\t\tminHeight: 0,\r\n\t\tcreate: function (event, ui) {\r\n\t\t\t// undocumented call to allow html in title (for icon) - can't be shared for some reason\r\n\t\t\t$(domNodes.infoDialogs.sharedViewInformation).data(\"uiDialog\")._title = function (title) {\r\n\t\t\t\tsetChildren(title[0], this.options.title);\r\n\t\t\t};\r\n\r\n\t\t\tcreateDialogTitlebar(this);\r\n\t\t\treplaceDialogButtons(this, $(this).dialog(\"option\", \"buttons\"));\r\n\t\t\t$(this)\r\n\t\t\t\t.closest(\".ui-dialog\")\r\n\t\t\t\t.draggable(\"option\", \"containment\", \"#base-content\")\r\n\t\t\t\t.attr(\"id\", \"dialog-shared-view-information\");\r\n\t\t\tinitializeSharedViewInformationDialog();\r\n\t\t},\r\n\t\tclose: function (event, ui) {\r\n\t\t\t//if (trkData.sharedView.current !== null && !state.openPanels.secondary) {\r\n\t\t\t// deselectSharedView();\r\n\t\t\t//}\r\n\t\t},\r\n\t\topen: function (event, ui) {\r\n\t\t\t//if (this.getAttribute('data-has-collapse')) {\r\n\t\t\t// if (this.getAttribute('data-collapsed') === 'true') {\r\n\t\t\t// }\r\n\t\t\t//}\r\n\t\t},\r\n\t});\r\n\r\n\t$(domNodes.infoDialogs.positionHistory).dialog({\r\n\t\tautoOpen: false,\r\n\t\tresizable: false,\r\n\t\tmodal: false,\r\n\t\tmaxWidth: 375,\r\n\t\tcreate: function (event, ui) {\r\n\t\t\t// undocumented call to allow html in title (for icon) - can't be shared for some reason\r\n\t\t\t$(domNodes.infoDialogs.positionHistory).data(\"uiDialog\")._title = function (title) {\r\n\t\t\t\tsetChildren(title[0], this.options.title);\r\n\t\t\t};\r\n\r\n\t\t\tcreateDialogTitlebar(this);\r\n\t\t\treplaceDialogButtons(this, $(this).dialog(\"option\", \"buttons\"));\r\n\t\t\t$(this)\r\n\t\t\t\t.closest(\".ui-dialog\")\r\n\t\t\t\t.draggable(\"option\", \"containment\", \"#base-content\")\r\n\t\t\t\t.attr(\"id\", \"dialog-position-history\");\r\n\t\t},\r\n\t});\r\n\r\n\t$(domNodes.infoDialogs.positionHistory).on(\"change\", \"select.time-picker\", function (e) {\r\n\t\tvar dialog = $(domNodes.infoDialogs.positionHistory);\r\n\t\tvar asset = findAssetById(dialog.data(\"assetId\"));\r\n\t\tvar trip = findTripById(dialog.data(\"tripId\"));\r\n\t\tvar fromId = $(\"#positions-begin-header .time-picker\").val();\r\n\t\tvar toId = $(\"#positions-end-header .time-picker\").val();\r\n\t\tcreatePositionHistorySummary(asset, trip, fromId, toId);\r\n\t});\r\n\r\n\t$(domNodes.infoDialogs.mapItemInformation).dialog({\r\n\t\tautoOpen: false,\r\n\t\tresizable: false,\r\n\t\tmodal: false,\r\n\t\t//width: 375,\r\n\t\tmaxWidth: 375,\r\n\t\tminHeight: 0,\r\n\t\topen: function (event, ui) {\r\n\t\t\t// start listening for left/right key presses\r\n\t\t\tif (state.activeMapMode !== mapModes.LIVE) {\r\n\t\t\t\t// todo: check if mapInformation is for an asset\r\n\t\t\t\t$(document)\r\n\t\t\t\t\t.off(\"keydown.map-item-information-dialog\")\r\n\t\t\t\t\t.on(\"keydown.map-item-information-dialog\", function (e) {\r\n\t\t\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\t\t\tcase 37: // left\r\n\t\t\t\t\t\t\t\tplaybackPrevPosition();\r\n\t\t\t\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\t\t\t\te.stopPropagation();\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\tcase 39: // right\r\n\t\t\t\t\t\t\t\tplaybackNextPosition();\r\n\t\t\t\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\t\t\t\te.stopPropagation();\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t});\r\n\t\t\t}\r\n\t\t},\r\n\t\tcreate: function (event, ui) {\r\n\t\t\t// undocumented call to allow html in title (for icon) - can't be shared for some reason\r\n\t\t\t$(domNodes.infoDialogs.mapItemInformation).data(\"uiDialog\")._title = function (title) {\r\n\t\t\t\tsetChildren(title[0], this.options.title);\r\n\t\t\t};\r\n\r\n\t\t\tcreateDialogTitlebar(this);\r\n\t\t\treplaceDialogButtons(this, $(this).dialog(\"option\", \"buttons\"));\r\n\t\t\t$(this)\r\n\t\t\t\t.closest(\".ui-dialog\")\r\n\t\t\t\t.draggable(\"option\", \"containment\", \"#base-content\")\r\n\t\t\t\t.attr(\"id\", \"dialog-map-item-information\"); // give it an id for styling\r\n\t\t\t$(domNodes.infoDialogs.mapItemInformation).bsTooltip({ selector: \".estimated\", placement: \"top\" });\r\n\t\t},\r\n\t});\r\n\r\n\t$j(domNodes.infoDialogs.ruler).dialog({\r\n\t\tautoOpen: false,\r\n\t\tmodal: false,\r\n\t\tmaxWidth: 350,\r\n\t\tresizable: false,\r\n\t\tclose: function () {\r\n\t\t\tcloseRuler();\r\n\t\t},\r\n\t\tcreate: function () {\r\n\t\t\tcreateDialogTitlebar(this);\r\n\t\t\treplaceDialogButtons(this, $(this).dialog(\"option\", \"buttons\"));\r\n\t\t},\r\n\t});\r\n\r\n\t$j(domNodes.infoDialogs.garminSubmission).dialog({\r\n\t\tautoOpen: false,\r\n\t\tmodal: false,\r\n\t\twidth: 400,\r\n\t\tclose: function () {},\r\n\t\tcreate: function () {\r\n\t\t\tcreateDialogTitlebar(this);\r\n\t\t\treplaceDialogButtons(this, $(this).dialog(\"option\", \"buttons\"));\r\n\t\t},\r\n\t});\r\n}\r\n\r\nexport function moveOrOpenDialogRelativeTo($dialog, referencePoint, relativePlacement) {\r\n\tif (!$dialog.dialog(\"isOpen\")) {\r\n\t\tif (window.screen.width > 768) {\r\n\t\t\t$dialog.dialog(\"option\", \"position\", {\r\n\t\t\t\tmy: \"left center\",\r\n\t\t\t\tat: relativePlacement,\r\n\t\t\t\tof: referencePoint,\r\n\t\t\t\tcollision: \"flipfit\",\r\n\t\t\t\twithin: domNodes.map,\r\n\t\t\t\tusing: function (param1, param2) {\r\n\t\t\t\t\t$(this).css(param1);\r\n\t\t\t\t},\r\n\t\t\t});\r\n\t\t}\r\n\t\t$dialog.dialog(\"open\"); // dialog must be opened away from the marker so it can be moved without triggering\r\n\t} else {\r\n\t\t// dialog was already open but may have been resized due to content changes\r\n\t\tvar parent = $dialog.closest(\".ui-dialog\");\r\n\t\tparent.position({\r\n\t\t\tmy: \"left center\",\r\n\t\t\tat: relativePlacement,\r\n\t\t\tof: referencePoint,\r\n\t\t\tcollision: \"flipfit\",\r\n\t\t\twithin: domNodes.map,\r\n\t\t\tusing: function (param1, param2) {\r\n\t\t\t\t// if the dialog is currently in the same horizontal position as before\r\n\t\t\t\t// then we will assume the user has not manually moved it and it can be\r\n\t\t\t\t// repositioned programmatically to fit centered vertically\r\n\t\t\t\tif ($dialog.closest(\".ui-dialog\").position().left == param1.left) {\r\n\t\t\t\t\t// just move the dialog vertically\r\n\t\t\t\t\t$(this).css(param1);\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t});\r\n\t}\r\n\t$dialog.dialog(\"moveToTop\");\r\n}\r\n\r\nfunction replaceDialogButtons(dialog, buttons) {\r\n\tif (buttons === undefined || buttons.length === 0) {\r\n\t\treturn;\r\n\t}\r\n\tvar ui = dialog.parentNode;\r\n\tvar pane = ui.querySelector(\".ui-dialog-buttonset\");\r\n\tvar uiButtons = pane.querySelectorAll(\"button\");\r\n\t_.each(uiButtons, function (uiButton, index, list) {\r\n\t\tvar buttonType = buttons[index].buttonType === undefined ? \"primary\" : buttons[index].buttonType;\r\n\t\tvar buttonIcon =\r\n\t\t\tbuttons[index].svgIcon === undefined\r\n\t\t\t\t? null\r\n\t\t\t\t: svg(\"svg\", svg(\"use\", { xlink: { href: \"/content/svg/tracking.svg?v=15#\" + buttons[index].svgIcon } }));\r\n\t\tuiButton.className = \"btn btn-\" + buttonType;\r\n\t\tsetChildren(uiButton, _.compact(buttonIcon, el(\"span\", buttons[index].text)));\r\n\t});\r\n}\r\n\r\nfunction createDialogTitlebar(dialog) {\r\n\tvar panel = $(dialog).parent();\r\n\tvar title = $(\"div.ui-dialog-titlebar\", panel).addClass(\"w-100\");\r\n\t$(\".ui-dialog-titlebar-close\", title).remove();\r\n\r\n\tvar bar = $('');\r\n\t// svg icon for those that support it\r\n\tvar svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\r\n\tvar use = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\r\n\tsvg.appendChild(use);\r\n\tuse.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", svgPath(\"info-circle\"));\r\n\ttitle[0].insertBefore(svg, title[0].firstChild);\r\n\t//title[0].appendChild(svg);\r\n\r\n\ttitle.appendTo(bar); // move title to new flex-row for button support\r\n\tvar $quickActions = $(\".dialog-quick-actions\", dialog);\r\n\tif ($quickActions.length > 0) {\r\n\t\t//// quick actions select list should be pre-defined somewhere?\r\n\t\t//var action = $('
')\r\n\t\t//action.appendTo(bar);\r\n\t\t$quickActions.appendTo(bar);\r\n\t}\r\n\tif (dialog.getAttribute(\"data-has-collapse\") !== null) {\r\n\t\tvar collapse = document.createElement(\"button\");\r\n\t\tcollapse.setAttribute(\"data-for-dialog\", dialog.id);\r\n\t\tcollapse.className = \"btn item-collapse panel-options\";\r\n\t\tvar collapseSvg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\r\n\t\tvar collapseUse = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\r\n\t\tcollapseSvg.appendChild(collapseUse);\r\n\t\tcollapseUse.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", svgPath(\"angle-up\"));\r\n\t\tcollapse.appendChild(collapseSvg);\r\n\t\tbar[0].appendChild(collapse);\r\n\t}\r\n\r\n\tvar close = document.createElement(\"button\");\r\n\tclose.setAttribute(\"data-for-dialog\", dialog.id);\r\n\tclose.className = \"btn item-close\";\r\n\tvar closeSvg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\r\n\tvar closeUse = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\r\n\tcloseSvg.appendChild(closeUse);\r\n\tcloseUse.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", svgPath(\"times\"));\r\n\tclose.appendChild(closeSvg);\r\n\tbar[0].appendChild(close);\r\n\r\n\t//var close = $('
');\r\n\t//close.appendTo(bar);\r\n\tbar.prependTo(panel);\r\n}\r\n","import trkData from \"./data.js\";\r\nimport strings from \"./strings.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport { toggleLoadingMessage } from \"./ajax.js\";\r\nimport { handleWebServiceError } from \"./ajax.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { openDialogPanel } from \"./panel-nav.js\";\r\nimport { renderDomElement } from \"./datatables.js\";\r\nimport { handleAjaxFormSubmission, formShowErrorMessage, formShowSuccessMessage } from \"./ajax.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport $j from \"jquery\";\r\nimport _ from \"lodash\";\r\nimport { el } from \"redom\"; // https://redom.js.org/\r\n\r\nexport function getDescriptionForDriver(driver) {\r\n\tvar description = \"\";\r\n\tif (driver == null) {\r\n\t\treturn description;\r\n\t}\r\n\tif (driver.IButtonId !== undefined && driver.IButtonId !== null && driver.IButtonId !== '') {\r\n\t\tdescription = driver.IButtonId;\r\n\t}\r\n\tif (driver.GarminId !== null && driver.GarminId !== undefined) {\r\n\t\tif (description !== \"\") {\r\n\t\t\tdescription += \" / \";\r\n\t\t}\r\n\t\tdescription += driver.GarminId;\r\n\t}\r\n\treturn description;\r\n}\r\n\r\nexport function addDriverToAsset(driverId, assetId) {\r\n\tif (trkData.assetDrivers == null) return;\r\n\tfor (var i = 0; i < trkData.assetDrivers.length; i++) {\r\n\t\tif (trkData.assetDrivers[i].AssetId == assetId) {\r\n\t\t\ttrkData.assetDrivers[i].DriverIds.push(driverId);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport function findAssetDriverGroupIdsByAssetId(id) {\r\n\tvar item = _.find(trkData.assetDriverGroups, { AssetId: parseInt(id) });\r\n\treturn item === undefined ? null : item.DriverGroupIds;\r\n}\r\n\r\nexport function findAssetDriversByAssetId(id) {\r\n\tvar item = _.find(trkData.assetDrivers, { AssetId: parseInt(id) });\r\n\treturn item === undefined ? null : item.DriverIds;\r\n}\r\n\r\nfunction calculateGroupDriverIdsForAsset(assetId) {\r\n\tvar assetDriverGroup = _.find(trkData.assetDriverGroups, { AssetId: parseInt(assetId) });\r\n\tif (assetDriverGroup === undefined) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar groupDriverIds = [];\r\n\t_.each(assetDriverGroup.DriverGroupIds, function (groupId) {\r\n\t\tvar driverGroup = _.find(trkData.driverGroups, { Id: groupId });\r\n\t\tif (driverGroup === undefined) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tgroupDriverIds = groupDriverIds.concat(driverGroup.ItemIds);\r\n\t});\r\n\r\n\tvar assetDrivers = _.find(trkData.assetDrivers, { AssetId: parseInt(assetId) });\r\n\tif (assetDrivers === undefined) {\r\n\t\ttrkData.assetDrivers.push({ AssetId: parseInt(assetId), DriverIds: [], GroupDriverIds: groupDriverIds });\r\n\t} else {\r\n\t\tassetDrivers.GroupDriverIds = groupDriverIds;\r\n\t}\r\n}\r\n\r\nexport function addDriverGroupToAsset(driverGroupId, assetId) {\r\n\tvar assetDriverGroup = _.find(trkData.assetDriverGroups, { AssetId: parseInt(assetId) });\r\n\tif (assetDriverGroup === undefined) {\r\n\t\ttrkData.assetDriverGroups.push({ AssetId: parseInt(assetId), DriverGroupIds: [driverGroupId] });\r\n\t} else {\r\n\t\tif (_.indexOf(assetDriverGroup.DriverGroupIds, driverGroupId) === -1) {\r\n\t\t\tassetDriverGroup.DriverGroupIds.push(driverGroupId);\r\n\t\t}\r\n\t}\r\n\r\n\t// recalculate GroupDriverIds for the asset\r\n\tcalculateGroupDriverIdsForAsset(assetId);\r\n}\r\n\r\nexport function removeDriverGroupFromAsset(driverGroupId, assetId) {\r\n\tvar assetDriverGroup = _.find(trkData.assetDriverGroups, { AssetId: parseInt(assetId) });\r\n\tif (assetDriverGroup === undefined) {\r\n\t\treturn;\r\n\t}\r\n\tvar groupIndex = _.indexOf(assetDriverGroup.DriverGroupIds, driverGroupId);\r\n\tif (groupIndex !== -1) {\r\n\t\t// remove group\r\n\t\tassetDriverGroup.DriverGroupIds.splice(groupIndex, 1);\r\n\t}\r\n\r\n\t// recalculate GroupDriverIds for the asset based on remaining group(s) assigned\r\n\tcalculateGroupDriverIdsForAsset(assetId);\r\n}\r\n\r\nexport function removeDriverFromAsset(driverId, assetId) {\r\n\tif (trkData.assetDrivers == null) return;\r\n\tfor (var i = 0; i < trkData.assetDrivers.length; i++) {\r\n\t\tif (trkData.assetDrivers[i].AssetId == assetId) {\r\n\t\t\tfor (var j = 0; j < trkData.assetDrivers[i].DriverIds.length; j++) {\r\n\t\t\t\tif (driverId == trkData.assetDrivers[i].DriverIds[j]) {\r\n\t\t\t\t\ttrkData.assetDrivers[i].DriverIds.splice(j, 1);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport function findDriverById(id) {\r\n\tvar item = _.find(trkData.drivers, { Id: parseInt(id) });\r\n\treturn item === undefined ? null : item;\r\n}\r\n\r\nexport function findAssetDriverIdsByAssetIdSorted(id) {\r\n\t// trkData.drivers is sorted\r\n\tif (trkData.assetDrivers == null) {\r\n\t\treturn null;\r\n\t}\r\n\tvar ids = null;\r\n\tvar assetDrivers = _.find(trkData.assetDrivers, { AssetId: parseInt(id) });\r\n\tif (assetDrivers !== undefined) {\r\n\t\tids = assetDrivers.DriverIds.concat(assetDrivers.GroupDriverIds);\r\n\t}\r\n\tif (ids != null) {\r\n\t\tvar sortedIds = [];\r\n\t\tfor (var i = 0, len = trkData.drivers.length; i < len; i++) {\r\n\t\t\tvar driverId = trkData.drivers[i].Id;\r\n\t\t\tfor (var j = 0; j < ids.length; j++) {\r\n\t\t\t\tvar includedId = ids[j];\r\n\t\t\t\tif (driverId == includedId) {\r\n\t\t\t\t\tsortedIds.push(includedId);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn sortedIds;\r\n\t}\r\n\r\n\treturn null;\r\n}\r\n\r\nexport function updateAssetDriverStatus(asset, driverId, statusId, btn, notes) {\r\n\tvar status = document.getElementById(\"current-drivers-status\");\r\n\tvar data = { assetId: asset.Id, driverId: driverId, statusId: statusId, notes: notes };\r\n\thandleAjaxFormSubmission(\r\n\t\t\"AssetDriverUpdateStatus\",\r\n\t\tdata,\r\n\t\tbtn,\r\n\t\tstatus,\r\n\t\tstrings.MSG_UPDATE_DRIVER_SUCCESS,\r\n\t\tstrings.MSG_UPDATE_DRIVER_ERROR,\r\n\t\tfunction () {\r\n\t\t\tloadAssetDrivers(asset);\r\n\t\t}\r\n\t);\r\n\r\n\t// if(btn != null)\r\n\t// btn.prop('disabled', true);\r\n\t//toggleLoadingMessage(true, 'asset-driver-update');\r\n\t//$j.ajax({\r\n\t// type: 'POST',\r\n\t// url: wrapUrl('/services/GPSService.asmx/AssetDriverUpdateStatus'),\r\n\t// data: JSON.stringify(data),\r\n\t// contentType: 'application/json; charset=utf-8',\r\n\t// dataType: 'json',\r\n\t// success: function (msg) {\r\n\t// if (btn != null)\r\n\t// btn.prop('disabled', false);\r\n\t// if (msg.d) {\r\n\t// var result = msg.d;\r\n\t// if (result.Success == true) {\r\n\t// loadAssetDrivers(asset);\r\n\t// trkData.validation.currentDriver.resetForm();\r\n\t// trkData.validation.currentDriver.currentForm.reset();\r\n\t// } else {\r\n\t// handleWebServiceError(strings.MSG_UPDATE_DRIVER_ERROR);\r\n\t// }\r\n\t// }\r\n\t// toggleLoadingMessage(false, 'asset-driver-update');\r\n\t// },\r\n\t// error: function (xhr, status, error) {\r\n\t// handleWebServiceError(strings.MSG_UPDATE_DRIVER_ERROR);\r\n\t// toggleLoadingMessage(false, 'asset-driver-update');\r\n\t// if (btn != null)\r\n\t// btn.prop('disabled', false);\r\n\t// }\r\n\t//});\r\n}\r\n\r\nexport function loginAssetDriver(asset, driverId, notes, btn, statusId) {\r\n\tvar status = document.getElementById(\"current-drivers-status\");\r\n\tvar data = { assetId: asset.Id, driverId: driverId, notes: notes, statusId: statusId };\r\n\thandleAjaxFormSubmission(\r\n\t\t\"AssetDriverLogin\",\r\n\t\tdata,\r\n\t\tbtn,\r\n\t\tstatus,\r\n\t\tstrings.MSG_LOGIN_DRIVER_SUCCESS,\r\n\t\tstrings.MSG_LOGIN_DRIVER_ERROR,\r\n\t\tfunction () {\r\n\t\t\ttrkData.validation.currentDriver.resetForm();\r\n\t\t\ttrkData.validation.currentDriver.currentForm.reset();\r\n\r\n\t\t\tloadAssetDrivers(asset);\r\n\t\t}\r\n\t);\r\n\r\n\t//var btn = $j('#LoginDriver')[0];\r\n\r\n\t// btn.disabled = true;\r\n\t//toggleLoadingMessage(true, 'asset-driver-login');\r\n\t//$j.ajax({\r\n\t// type: 'POST',\r\n\t// url: wrapUrl('/services/GPSService.asmx/AssetDriverLogin'),\r\n\t// data: JSON.stringify(data),\r\n\t// contentType: 'application/json; charset=utf-8',\r\n\t// dataType: 'json',\r\n\t// success: function (msg) {\r\n\t// btn.disabled = false;\r\n\t// if (msg.d) {\r\n\t// var result = msg.d;\r\n\t// if (result.Success == true) {\r\n\t// loadAssetDrivers(asset);\r\n\t// } else {\r\n\t// handleWebServiceError(strings.MSG_LOGIN_DRIVER_ERROR);\r\n\t// }\r\n\t// }\r\n\t// toggleLoadingMessage(false, 'asset-driver-login');\r\n\t// },\r\n\t// error: function (xhr, status, error) {\r\n\t// handleWebServiceError(strings.MSG_LOGIN_DRIVER_ERROR);\r\n\t// toggleLoadingMessage(false, 'asset-driver-login');\r\n\t// btn.disabled = false;\r\n\t// }\r\n\t//});\r\n}\r\n\r\nexport function loadAssetDrivers(asset) {\r\n\tvar btn = $j(\"#RefreshAssetDrivers\");\r\n\tvar data = { assetId: asset.Id };\r\n\tbtn.prop(\"disabled\", true);\r\n\ttoggleLoadingMessage(true, \"asset-drivers\");\r\n\t$j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/GetAssetDriverInformation\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tbtn.prop(\"disabled\", false);\r\n\t\t\tif (msg.d) {\r\n\t\t\t\tvar result = msg.d;\r\n\t\t\t\tif (result.Success == true) {\r\n\t\t\t\t\tvar statuses = $j(\"#AssetStatuses\").empty();\r\n\t\t\t\t\tstatuses.append($j(\"
\"));\r\n\t\t\t\t\tvar logoffStatus = $j(\" \").val(-1).text(strings.LOGOUT);\r\n\t\t\t\t\tvar loginStatus = $j(\" \").val(0).text(strings.LOGIN);\r\n\r\n\t\t\t\t\tif (result.Statuses != null) {\r\n\t\t\t\t\t\t// statuses defined for this asset\r\n\t\t\t\t\t\tfor (var i = 0; i < result.Statuses.length; i++) {\r\n\t\t\t\t\t\t\tvar status = result.Statuses[i];\r\n\t\t\t\t\t\t\tif (status.IsLogOff) logoffStatus = $j(\" \").val(-1).text(status.Status);\r\n\t\t\t\t\t\t\telse statuses.append($j(\" \").val(status.Id).text(status.Status));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tstatuses.append(logoffStatus);\r\n\r\n\t\t\t\t\t// clear current drivers listing\r\n\t\t\t\t\tvar drivers = $j(\"#AssetDrivers tbody\").empty();\r\n\t\t\t\t\tvar driverIds = [];\r\n\t\t\t\t\tif (result.Drivers != null) {\r\n\t\t\t\t\t\tfor (var i = 0; i < result.Drivers.length; i++) {\r\n\t\t\t\t\t\t\tvar driver = result.Drivers[i];\r\n\t\t\t\t\t\t\tvar status = driver.Status;\r\n\t\t\t\t\t\t\tlet statusId;\r\n\t\t\t\t\t\t\tif (status == null) {\r\n\t\t\t\t\t\t\t\tstatusId = \"\";\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tstatusId = status.Id;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tvar statusOptions = statuses\r\n\t\t\t\t\t\t\t\t.clone(false)\r\n\t\t\t\t\t\t\t\t.removeAttr(\"id\")\r\n\t\t\t\t\t\t\t\t.val(statusId)\r\n\t\t\t\t\t\t\t\t.data(\"driverId\", driver.Driver.Id)\r\n\t\t\t\t\t\t\t\t.show();\r\n\t\t\t\t\t\t\tvar driverDescription = getDescriptionForDriver(driver.Driver);\r\n\t\t\t\t\t\t\tif (driverDescription !== \"\") {\r\n\t\t\t\t\t\t\t\tdriverDescription = \" (\" + driverDescription + \")\";\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tdrivers.append(\r\n\t\t\t\t\t\t\t\t$j(\"\")\r\n\t\t\t\t\t\t\t\t\t.append($j(\"\").text(driver.Driver.DriverId + driverDescription))\r\n\t\t\t\t\t\t\t\t\t.append($j(\" \").append(statusOptions))\r\n\t\t\t\t\t\t\t\t\t.append(\r\n\t\t\t\t\t\t\t\t\t\t$j(\" \").append(\r\n\t\t\t\t\t\t\t\t\t\t\t$j(\"\").addClass(\"update-driver btn btn-primary\").text(strings.UPDATE_STATUS)\r\n\t\t\t\t\t\t\t\t\t\t)\r\n\t\t\t\t\t\t\t\t\t)\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\tdriverIds.push(driver.Driver.Id);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tvar login = $j(\"#LoginDrivers\").empty();\r\n\t\t\t\t\tvar assetDrivers = findAssetDriverIdsByAssetIdSorted(asset.Id);\r\n\r\n\t\t\t\t\tif (assetDrivers != null) {\r\n\t\t\t\t\t\tfor (var i = 0; i < assetDrivers.length; i++) {\r\n\t\t\t\t\t\t\tvar driverId = assetDrivers[i];\r\n\t\t\t\t\t\t\tif ($j.inArray(driverId, driverIds) == -1) {\r\n\t\t\t\t\t\t\t\tvar driver = findDriverById(driverId);\r\n\t\t\t\t\t\t\t\tif (driver == null) continue;\r\n\t\t\t\t\t\t\t\tvar driverDescription = getDescriptionForDriver(driver);\r\n\t\t\t\t\t\t\t\tif (driverDescription !== \"\") {\r\n\t\t\t\t\t\t\t\t\tdriverDescription = \" (\" + driverDescription + \")\";\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\tlogin.append(\r\n\t\t\t\t\t\t\t\t\t$j(\"\")\r\n\t\t\t\t\t\t\t\t\t\t.val(driverId)\r\n\t\t\t\t\t\t\t\t\t\t.text(driver.DriverId + driverDescription)\r\n\t\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tvar stats = $j(\"#LoginDriversStatus\").empty();\r\n\t\t\t\t\tif (result.Statuses == null || result.Statuses.length == 0) {\r\n\t\t\t\t\t\tstats.append(loginStatus);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\t// statuses defined for this asset\r\n\t\t\t\t\t\tfor (var i = 0; i < result.Statuses.length; i++) {\r\n\t\t\t\t\t\t\tvar status = result.Statuses[i];\r\n\t\t\t\t\t\t\tif (!status.IsLogOff) stats.append($j(\" \").val(status.Id).text(status.Status));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\thandleWebServiceError(strings.MSG_GET_DRIVERS_ERROR);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ttoggleLoadingMessage(false, \"asset-drivers\");\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\thandleWebServiceError(strings.MSG_GET_DRIVERS_ERROR);\r\n\t\t\ttoggleLoadingMessage(false, \"asset-drivers\");\r\n\t\t\tbtn.prop(\"disabled\", false);\r\n\t\t},\r\n\t});\r\n}\r\n\r\nexport function openCurrentDriversDialog(asset) {\r\n\ttrkData.validation.currentDriver.resetForm();\r\n\ttrkData.validation.currentDriver.currentForm.reset();\r\n\r\n\ttrkData.validation.addPosition.resetForm();\r\n\ttrkData.validation.addPosition.currentForm.reset();\r\n\topenDialogPanel(\r\n\t\tdomNodes.dialogs.currentDrivers,\r\n\t\tstrings.SET_DRIVER_STATUS,\r\n\t\tasset,\r\n\t\tfalse,\r\n\t\tnull,\r\n\t\t\"asset\",\r\n\t\t\"set-driver\",\r\n\t\topenCurrentDriversDialog\r\n\t);\r\n\tloadAssetDrivers(asset);\r\n\r\n\t$(domNodes.dialogs.currentDrivers).data(\"assetId\", asset.Id);\r\n}\r\n\r\nexport function loadDriverHistoryDialog(asset) {\r\n\t$(domNodes.dialogs.driverHistory).data(\"assetId\", asset.Id);\r\n\topenDialogPanel(\r\n\t\tdomNodes.dialogs.driverHistory,\r\n\t\tstrings.DRIVER_LOG,\r\n\t\tasset,\r\n\t\ttrue,\r\n\t\tnull,\r\n\t\t\"asset\",\r\n\t\t\"view-logs-driver\",\r\n\t\tloadDriverHistoryDialog\r\n\t);\r\n\r\n\tloadDriverHistory(asset);\r\n}\r\n\r\nexport function loadDriverHistory(asset) {\r\n\tvar btn = document.getElementById(\"RefreshDrivers\");\r\n\tvar status = document.getElementById(\"drivers-status\");\r\n\tvar data = { assetId: asset.Id };\r\n\thandleAjaxFormSubmission(\r\n\t\t\"GetDriverHistoryForAsset\",\r\n\t\tdata,\r\n\t\tbtn,\r\n\t\tstatus,\r\n\t\tnull,\r\n\t\tstrings.MSG_DRIVER_HISTORY_ERROR,\r\n\t\tfunction (result) {\r\n\t\t\tif (result.Success == true) {\r\n\t\t\t\tvar itemData = [];\r\n\t\t\t\tif (result.Items != null) {\r\n\t\t\t\t\tfor (var i = 0; i < result.Items.length; i++) {\r\n\t\t\t\t\t\tvar item = result.Items[i];\r\n\t\t\t\t\t\tvar source = item.Source;\r\n\t\t\t\t\t\tif (item.CreatedBy != null) {\r\n\t\t\t\t\t\t\tsource = item.CreatedBy;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tvar history = el(\r\n\t\t\t\t\t\t\t\"a.history\",\r\n\t\t\t\t\t\t\t{ href: \"#\", dataset: { from: item.LoginOn, to: item.LogoutOn } },\r\n\t\t\t\t\t\t\tstrings.REPLAY_TRIP\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t\titemData.push([\r\n\t\t\t\t\t\t\t//item.Id,\r\n\t\t\t\t\t\t\titem.Driver.DriverId,\r\n\t\t\t\t\t\t\titem.LoginStatus,\r\n\t\t\t\t\t\t\titem.LoginOn,\r\n\t\t\t\t\t\t\titem.LogoutStatus,\r\n\t\t\t\t\t\t\titem.LogoutOn,\r\n\t\t\t\t\t\t\titem.Duration,\r\n\t\t\t\t\t\t\thistory,\r\n\t\t\t\t\t\t\titem.Notes,\r\n\t\t\t\t\t\t\tsource,\r\n\t\t\t\t\t\t\t//status,\r\n\t\t\t\t\t\t\t//position,\r\n\t\t\t\t\t\t\t//item.Source,\r\n\t\t\t\t\t\t\t//item.CreatedOn\r\n\t\t\t\t\t\t]);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t$(\"#DriverLogs\").dataTable({\r\n\t\t\t\t\tdata: itemData,\r\n\t\t\t\t\tdestroy: true,\r\n\t\t\t\t\tfilter: false,\r\n\t\t\t\t\tinfo: false,\r\n\t\t\t\t\tjQueryUI: false,\r\n\t\t\t\t\tautoWidth: false,\r\n\t\t\t\t\tlengthChange: false,\r\n\t\t\t\t\tpaging: true,\r\n\t\t\t\t\tpageLength: 10,\r\n\t\t\t\t\tdeferRender: true,\r\n\t\t\t\t\torder: [[2, \"desc\"]],\r\n\t\t\t\t\tcolumnDefs: [\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttargets: \"_all\",\r\n\t\t\t\t\t\t\trender: $.fn.dataTable.render.text(),\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t],\r\n\t\t\t\t\tcolumns: [\r\n\t\t\t\t\t\t{}, // driver\r\n\t\t\t\t\t\t{}, // login\r\n\t\t\t\t\t\t{ width: \"75px\" }, // login on\r\n\t\t\t\t\t\t{}, // logoff\r\n\t\t\t\t\t\t{ width: \"75px\" }, // logoff on\r\n\t\t\t\t\t\t{}, // duration\r\n\t\t\t\t\t\t{ render: renderDomElement }, // history replay\r\n\t\t\t\t\t\t{}, // notes\r\n\t\t\t\t\t\t{}, // source\r\n\t\t\t\t\t],\r\n\t\t\t\t\tlanguage: strings.DATATABLE,\r\n\t\t\t\t});\r\n\r\n\t\t\t\t$j(\"#DriverLogs\").removeAttr(\"style\");\r\n\t\t\t} else {\r\n\t\t\t\tformShowErrorMessage(status, strings.MSG_DRIVER_HISTORY_ERROR);\r\n\t\t\t}\r\n\t\t},\r\n\t\tnull\r\n\t);\r\n}\r\n\r\nexport function getGroupNamesForDriver(driver) {\r\n\tvar groupNames = [];\r\n\t_.each(trkData.driverGroups, function (driverGroup) {\r\n\t\tif (_.indexOf(driverGroup.ItemIds, driver.Id) !== -1) {\r\n\t\t\tgroupNames.push(driverGroup.Name);\r\n\t\t}\r\n\t});\r\n\treturn groupNames.join(', ');\r\n}","import strings from \"./strings.js\";\r\nimport trkData from \"./data.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport state from \"./state.js\";\r\nimport user from \"./user.js\";\r\nimport options from \"./options.js\";\r\nimport { populateCheckboxList, svgPath } from \"./dom-util.js\";\r\nimport preferences from \"./preferences.js\";\r\nimport { clearSharedViewData, cloneSharedView, querySharedViewData } from \"./shared-view.js\";\r\nimport { openDialogPanel } from \"./panel-nav.js\";\r\nimport { moveSecondaryPanelToPrimary } from \"./panel.js\";\r\nimport { getDescriptionForDriver } from \"./driver.js\";\r\nimport { sortAssetGroups } from \"./item-sorting.js\";\r\nimport { checkForShareViewChange } from \"./shared-view.js\";\r\nimport { restrictAllChildren } from \"./dom-util.js\";\r\nimport { changePrimaryButtonLabel } from \"./modal.js\";\r\nimport { addGroupToGroupListWithName } from \"./group-list.js\";\r\nimport { querySharedViewInvites } from \"./shared-view.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport _ from \"lodash\";\r\nimport moment from \"moment\"; // https://www.npmjs.com/package/moment\r\n\r\nexport function initSharedViewDialog() {\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \".next-step,.prev-step\", function (e) {\r\n\t\tconsole.log(\"next/prev step\");\r\n\t\tvar isNext = this.classList.contains(\"next-step\");\r\n\t\tvar currentStep = domNodes.dialogs.sharedView.querySelector(\".wizard-step.is-active\");\r\n\t\tvar currentStepId = currentStep.getAttribute(\"data-step-id\");\r\n\t\tvar currentStepStep = parseInt(currentStep.getAttribute(\"data-step-step\"));\r\n\t\tconsole.log(currentStepId, isNext);\r\n\t\tif (isNext) {\r\n\t\t\tgoToWizardStep(trkData.wizards.sharedView, null, ++currentStepStep);\r\n\t\t} else {\r\n\t\t\tgoToWizardStep(trkData.wizards.sharedView, null, --currentStepStep);\r\n\t\t}\r\n\t});\r\n}\r\n\r\nexport function openSharedViewDialog(sharedView, step) {\r\n\tif (user.isAnonymous) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (sharedView === undefined) {\r\n\t\tsharedView = null;\r\n\t}\r\n\r\n\t// only reset the current step?\r\n\t_.each(trkData.wizards.sharedView.steps, function (step) {\r\n\t\tif (step.form !== undefined) {\r\n\t\t\tstep.form.resetForm();\r\n\t\t\tstep.form.currentForm.reset();\r\n\t\t}\r\n\t});\r\n\r\n\t// hide shared view information dialog\r\n\r\n\tvar dialog = domNodes.dialogs.sharedView;\r\n\tvar wizard = dialog.querySelector(\".step-wizard\");\r\n\twizard.currentStep = null;\r\n\tvar wizardHeader = wizard.querySelector(\".wizard-header\");\r\n\r\n\t// dialog title based on section when editing\r\n\tvar dialogTitle = sharedView !== null ? strings.EDIT_SHARED_VIEW : strings.ADD_SHARED_VIEW;\r\n\r\n\tvar chosenStep = goToWizardStep(wizard, step);\r\n\r\n\tvar editSharedView = null;\r\n\tif (sharedView === null) {\r\n\t\ttrkData.sharedView.current = null;\r\n\t\tclearSharedViewData(true);\r\n\t\t$(domNodes.infoDialogs.sharedViewInformation).dialog(\"close\");\r\n\r\n\t\teditSharedView = {\r\n\t\t\tAssetGroupIds: [],\r\n\t\t\tAssetIds: [],\r\n\t\t\tPlaceIds: [],\r\n\t\t\tFenceIds: [],\r\n\r\n\t\t\tColor: \"#bbbbbb\",\r\n\t\t\tDescription: \"\",\r\n\t\t\tDriverIds: [],\r\n\t\t\tName: \"\",\r\n\r\n\t\t\tExpiresOnEpoch: null,\r\n\t\t\tFromDateEpoch: null,\r\n\t\t\tToDateEpoch: null,\r\n\t\t\tIsAvailable: true,\r\n\t\t\tIsEnabled: true,\r\n\t\t\tIsTimeframeRelative: true,\r\n\t\t\tRelativeTimeframeNumber: 7,\r\n\t\t\tRelativeTimeframeType: \"d\",\r\n\t\t\tIsMessagingEnabled: false,\r\n\t\t\tIsPublic: true,\r\n\t\t\tPassword: \"\",\r\n\t\t\tPreferences: {\r\n\t\t\t\tDefaultMode: \"\",\r\n\t\t\t\tEmergencyAudio: false,\r\n\t\t\t\tFuel: preferences.PREFERENCE_FUEL_UNIT,\r\n\t\t\t\tHistoryViewNumber: \"7\",\r\n\t\t\t\tHistoryViewType: \"d\",\r\n\t\t\t\tLanguage: preferences.PREFERENCE_LANGUAGE,\r\n\t\t\t\tLatLng: preferences.PREFERENCE_LAT_LNG,\r\n\t\t\t\tMapType: trkData.MAP_TYPES[state.currentMapType],\r\n\t\t\t\tPositionAlpha: preferences.PREFERENCE_ALPHA_POSITIONS,\r\n\t\t\t\tPositionConsolidation: preferences.PREFERENCE_GROUP_POSITIONS,\r\n\t\t\t\tRemoveRoads: preferences.PREFERENCE_REMOVE_ROADS,\r\n\t\t\t\tSpeed: preferences.PREFERENCE_SPEED,\r\n\t\t\t\tTimezone: preferences.PREFERENCE_TIMEZONE,\r\n\t\t\t},\r\n\t\t};\r\n\r\n\t\t// new shared view, show wizard, have it be placed in the \"primary\" panel\r\n\t\twizardHeader.classList.add(\"is-visible\");\r\n\t\tdialog.classList.add(\"is-wizard\");\r\n\t} else {\r\n\t\t// editing an existing sharedView\r\n\t\tvar deferreds = [];\r\n\t\tif (trkData.sharedView.current !== sharedView) {\r\n\t\t\t// load and display data\r\n\t\t\tdeferreds.push(querySharedViewData(sharedView, null, false));\r\n\t\t}\r\n\r\n\t\ttrkData.sharedView.current = sharedView;\r\n\t\teditSharedView = sharedView;\r\n\t\t//editSharedView = cloneSharedView(trkData.sharedView.current);\r\n\r\n\t\t// existing shared view, hide wizard\r\n\t\twizardHeader.classList.remove(\"is-visible\");\r\n\t\tdialog.classList.remove(\"is-wizard\");\r\n\r\n\t\tdialogTitle = chosenStep.title;\r\n\t}\r\n\r\n\t// populate from existing saved values\r\n\r\n\tdocument.getElementById(\"SharedViewId\").value = editSharedView.Id;\r\n\r\n\t// details\r\n\tvar name = document.getElementById(\"SharedViewName\");\r\n\tname.value = editSharedView.Name;\r\n\r\n\tvar description = document.getElementById(\"SharedViewDescription\");\r\n\tdescription.value = editSharedView.Description;\r\n\r\n\tvar $color = $(document.getElementById(\"SharedViewColor\"));\r\n\t$color.val(editSharedView.Color);\r\n\t$color.css(\"background-color\", editSharedView.Color);\r\n\t$color.next(\"span\").css(\"background-color\", editSharedView.Color);\r\n\r\n\t// access controls\r\n\tif (editSharedView.IsEnabled) {\r\n\t\tdocument.getElementById(\"SharedViewIsEnabledYes\").checked = true;\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewIsEnabledNo\").checked = true;\r\n\t}\r\n\r\n\tif (editSharedView.IsPublic) {\r\n\t\tdocument.getElementById(\"SharedViewIsPublicYes\").checked = true;\r\n\t\tdocument.getElementById(\"SharedViewPrivatePassword\").classList.remove(\"is-visible\");\r\n\t\tdocument.getElementById(\"SharedViewPassword\").classList.remove(\"required\");\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewIsPublicNo\").checked = true;\r\n\t\tdocument.getElementById(\"SharedViewPrivatePassword\").classList.add(\"is-visible\");\r\n\t\tdocument.getElementById(\"SharedViewPassword\").classList.add(\"required\");\r\n\t}\r\n\tif (editSharedView.Password === undefined || editSharedView.Password === null) {\r\n\t\tdocument.getElementById(\"SharedViewPassword\").value = \"\";\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewPassword\").value = editSharedView.Password;\r\n\t}\r\n\r\n\tif (editSharedView.ExpiresOnEpoch !== null) {\r\n\t\tdocument.getElementById(\"SharedViewDoesExpireYes\").checked = true;\r\n\t\tdocument.getElementById(\"SharedViewExpireDate\").classList.add(\"is-visible\");\r\n\t\tdocument.getElementById(\"SharedViewExpiresOn\").classList.add(\"required\");\r\n\t\t$(\"#SharedViewExpiresOn\").datetimepicker(\"setDate\", moment(editSharedView.ExpiresOnEpoch).toDate());\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewDoesExpireNo\").checked = true;\r\n\t\tdocument.getElementById(\"SharedViewExpireDate\").classList.remove(\"is-visible\");\r\n\t\tdocument.getElementById(\"SharedViewExpiresOn\").value = \"\";\r\n\t\tdocument.getElementById(\"SharedViewExpiresOn\").classList.remove(\"required\");\r\n\t}\r\n\r\n\tif (editSharedView.IsTimeframeRelative) {\r\n\t\tdocument.getElementById(\"SharedViewDataTimeframeRelative\").checked = true;\r\n\t\tdocument.getElementById(\"SharedViewRelativeDateRange\").classList.add(\"is-visible\");\r\n\t\tdocument.getElementById(\"SharedViewDataTimeframeRelativeNumber\").disabled = false;\r\n\t\tdocument.getElementById(\"SharedViewDataTimeframeRelativeType\").disabled = false;\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewDataTimeframeRelativeNumber\").disabled = true;\r\n\t\tdocument.getElementById(\"SharedViewDataTimeframeRelativeType\").disabled = true;\r\n\t\tif (editSharedView.FromDateEpoch !== null || editSharedView.ToDateEpoch !== null) {\r\n\t\t\tdocument.getElementById(\"SharedViewDataTimeframeCustom\").checked = true;\r\n\t\t\tdocument.getElementById(\"SharedViewDateRange\").classList.add(\"is-visible\");\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"SharedViewDataTimeframeAll\").checked = true;\r\n\t\t\tdocument.getElementById(\"SharedViewDateRange\").classList.remove(\"is-visible\");\r\n\t\t}\r\n\t}\r\n\r\n\tif (editSharedView.RelativeTimeframeNumber === null) {\r\n\t\tdocument.getElementById(\"SharedViewDataTimeframeRelativeNumber\").value = \"7\";\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewDataTimeframeRelativeNumber\").value = editSharedView.RelativeTimeframeNumber;\r\n\t}\r\n\tif (editSharedView.RelativeTimeframeType === null) {\r\n\t\tdocument.getElementById(\"SharedViewDataTimeframeRelativeType\").value = \"d\";\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewDataTimeframeRelativeType\").value = editSharedView.RelativeTimeframeType;\r\n\t}\r\n\r\n\tif (editSharedView.FromDateEpoch !== null) {\r\n\t\t$(\"#SharedViewFrom\").datetimepicker(\"setDate\", moment(editSharedView.FromDateEpoch).toDate());\r\n\t\t$(\"#SharedViewTo\").datetimepicker(\"option\", \"minDate\", moment(editSharedView.FromDateEpoch).toDate());\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewFrom\").value = \"\";\r\n\t\t$(\"#SharedViewTo\").datetimepicker(\r\n\t\t\t\"option\",\r\n\t\t\t\"maxDate\",\r\n\t\t\toptions.dateRangeMin === null ? null : new Date(options.dateRangeMin)\r\n\t\t);\r\n\t}\r\n\tif (editSharedView.ToDateEpoch !== null) {\r\n\t\t$(\"#SharedViewTo\").datetimepicker(\"setDate\", moment(editSharedView.ToDateEpoch).toDate());\r\n\t\t$(\"#SharedViewFrom\").datetimepicker(\"option\", \"maxDate\", moment(editSharedView.ToDateEpoch).toDate());\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewTo\").value = \"\";\r\n\t\t$(\"#SharedViewFrom\").datetimepicker(\r\n\t\t\t\"option\",\r\n\t\t\t\"maxDate\",\r\n\t\t\toptions.dateRangeMax === null ? null : new Date(options.dateRangeMax)\r\n\t\t);\r\n\t}\r\n\r\n\tif (editSharedView.IsMessagingEnabled) {\r\n\t\tdocument.getElementById(\"SharedViewIsMessagingEnabledYes\").checked = true;\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewIsMessagingEnabledNo\").checked = true;\r\n\t}\r\n\r\n\t// data visualization\r\n\tdocument.getElementById(\"SharedViewDefaultMode\").value = editSharedView.Preferences.DefaultMode;\r\n\t//document.getElementById('SharedViewHistoryViewNumber').value = editSharedView.Preferences.HistoryViewNumber;\r\n\t//document.getElementById('SharedViewHistoryViewType').value = editSharedView.Preferences.HistoryViewType;\r\n\r\n\t//if (editSharedView.Preferences.DefaultMode === mapModes.HISTORY) {\r\n\t// document.getElementById('SharedViewModeHistory').classList.add('is-visible');\r\n\t//} else {\r\n\t// document.getElementById('SharedViewModeHistory').classList.remove('is-visible');\r\n\t//}\r\n\r\n\t// map settings\r\n\tdocument.getElementById(\"SharedViewMapType\").value = editSharedView.Preferences.MapType;\r\n\tif (editSharedView.Preferences.PositionConsolidation) {\r\n\t\tdocument.getElementById(\"SharedViewPositionConsolidationYes\").checked = true;\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewPositionConsolidationNo\").checked = true;\r\n\t}\r\n\tif (editSharedView.Preferences.PositionAlpha) {\r\n\t\tdocument.getElementById(\"SharedViewPositionAlphaYes\").checked = true;\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewPositionAlphaNo\").checked = true;\r\n\t}\r\n\tif (editSharedView.Preferences.RemoveRoads) {\r\n\t\tdocument.getElementById(\"SharedViewRemoveRoadsYes\").checked = true;\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewRemoveRoadsNo\").checked = true;\r\n\t}\r\n\t//if (editSharedView.Preferences.EmergencyAudio) {\r\n\t// document.getElementById('SharedViewEmergencyAudioYes').checked = true;\r\n\t//} else {\r\n\t// document.getElementById('SharedViewEmergencyAudioNo').checked = true;\r\n\t//}\r\n\r\n\t// permissions\r\n\r\n\t// preferences\r\n\tif (editSharedView.Preferences.Language === null) {\r\n\t\tdocument.getElementById(\"SharedViewLanguage\").value = \"\";\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewLanguage\").value = editSharedView.Preferences.Language;\r\n\t}\r\n\tdocument.getElementById(\"SharedViewTimezone\").value = editSharedView.Preferences.Timezone;\r\n\tdocument.getElementById(\"SharedViewLatLngFormat\").value = editSharedView.Preferences.LatLng;\r\n\tdocument.getElementById(\"SharedViewSpeedFormat\").value = editSharedView.Preferences.Speed;\r\n\tdocument.getElementById(\"SharedViewFuelFormat\").value = editSharedView.Preferences.Fuel;\r\n\r\n\t// permissions\r\n\tif (editSharedView.AssetIds.length > 0) {\r\n\t\tdocument.getElementById(\"SharedViewPermissionsAssets\").checked = true;\r\n\t\tdocument.getElementById(\"accordion-shared-view-assets-content\").classList.add(\"show\");\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewPermissionsAssets\").checked = false;\r\n\t\tdocument.getElementById(\"accordion-shared-view-assets-content\").classList.remove(\"show\");\r\n\t}\r\n\r\n\t// groups\r\n\tif (editSharedView.AssetGroupIds.length > 0) {\r\n\t\tdocument.getElementById(\"SharedViewPermissionsGroups\").checked = true;\r\n\t\tdocument.getElementById(\"accordion-shared-view-groups-content\").classList.add(\"show\");\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewPermissionsGroups\").checked = false;\r\n\t\tdocument.getElementById(\"accordion-shared-view-groups-content\").classList.remove(\"show\");\r\n\t}\r\n\r\n\t// geofences\r\n\tif (editSharedView.FenceIds.length > 0) {\r\n\t\tdocument.getElementById(\"SharedViewPermissionsGeofences\").checked = true;\r\n\t\tdocument.getElementById(\"accordion-shared-view-geofences-content\").classList.add(\"show\");\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewPermissionsGeofences\").checked = false;\r\n\t\tdocument.getElementById(\"accordion-shared-view-geofences-content\").classList.remove(\"show\");\r\n\t}\r\n\r\n\t// places\r\n\tif (editSharedView.PlaceIds.length > 0) {\r\n\t\tdocument.getElementById(\"SharedViewPermissionsPlaces\").checked = true;\r\n\t\tdocument.getElementById(\"accordion-shared-view-places-content\").classList.add(\"show\");\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewPermissionsPlaces\").checked = false;\r\n\t\tdocument.getElementById(\"accordion-shared-view-places-content\").classList.remove(\"show\");\r\n\t}\r\n\r\n\t// drivers\r\n\tif (editSharedView.DriverIds.length > 0) {\r\n\t\tdocument.getElementById(\"SharedViewPermissionsDrivers\").checked = true;\r\n\t\tdocument.getElementById(\"accordion-shared-view-drivers-content\").classList.add(\"show\");\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewPermissionsDrivers\").checked = false;\r\n\t\tdocument.getElementById(\"accordion-shared-view-drivers-content\").classList.remove(\"show\");\r\n\t}\r\n\r\n\t//}\r\n\t// groups\r\n\t// TODO use checkbox list for groups\r\n\tvar cont = document.getElementById(\"shared-view-groups-list\");\r\n\tcont.innerHTML = \"\";\r\n\tvar fragment = document.createDocumentFragment();\r\n\tvar sortedGroups = sortAssetGroups();\r\n\tfor (var i = 0; i < sortedGroups.length; i++) {\r\n\t\tvar group = sortedGroups[i];\r\n\t\taddGroupToGroupListWithName(group, 0, fragment, \"SharedViewAssetGroupIds\", null, true);\r\n\t}\r\n\tcont.appendChild(fragment);\r\n\tif (sharedView !== null) {\r\n\t\t// select groups if chosen\r\n\t\t_.each(sharedView.AssetGroupIds, function (assetGroupId) {\r\n\t\t\tvar group = document.getElementById(\"SharedViewAssetGroupIds\" + assetGroupId);\r\n\t\t\tif (group !== undefined) {\r\n\t\t\t\tgroup.checked = true;\r\n\t\t\t\trestrictAllChildren(group, cont);\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\t// assets\r\n\tvar sharedViewAssets = _.filter(trkData.assets, function (item) {\r\n\t\treturn true;\r\n\t});\r\n\tpopulateCheckboxList(\r\n\t\t\"shared-view-assets-list\",\r\n\t\tsharedViewAssets,\r\n\t\t\"SharedViewAssetIds\",\r\n\t\tfunction (item) {\r\n\t\t\tif (sharedView === null) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\treturn _.indexOf(sharedView.AssetIds, item.Id) !== -1;\r\n\t\t},\r\n\t\tfunction (item) {\r\n\t\t\treturn item.Name;\r\n\t\t},\r\n\t\t\"assets\",\r\n\t\tfunction (item) {\r\n\t\t\treturn item.UniqueId;\r\n\t\t}\r\n\t);\r\n\tvar sharedViewGeofences = _.filter(trkData.fences, function (item) {\r\n\t\treturn true;\r\n\t});\r\n\tpopulateCheckboxList(\r\n\t\t\"shared-view-geofences-list\",\r\n\t\tsharedViewGeofences,\r\n\t\t\"SharedViewFenceIds\",\r\n\t\tfunction (item) {\r\n\t\t\tif (sharedView === null) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\treturn _.indexOf(sharedView.FenceIds, item.Id) !== -1;\r\n\t\t},\r\n\t\tfunction (item) {\r\n\t\t\treturn item.Name;\r\n\t\t},\r\n\t\t\"fences\",\r\n\t\tfunction (item) {\r\n\t\t\treturn item.Description;\r\n\t\t}\r\n\t);\r\n\tvar sharedViewPlaces = _.filter(trkData.places, function (item) {\r\n\t\treturn true;\r\n\t});\r\n\tpopulateCheckboxList(\r\n\t\t\"shared-view-places-list\",\r\n\t\tsharedViewPlaces,\r\n\t\t\"SharedViewPlaceIds\",\r\n\t\tfunction (item) {\r\n\t\t\tif (sharedView === null) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\treturn _.indexOf(sharedView.PlaceIds, item.Id) !== -1;\r\n\t\t},\r\n\t\tfunction (item) {\r\n\t\t\treturn item.Name;\r\n\t\t},\r\n\t\t\"places\",\r\n\t\tfunction (item) {\r\n\t\t\treturn item.Description;\r\n\t\t}\r\n\t);\r\n\tvar sharedViewDrivers = _.filter(trkData.drivers, function (item) {\r\n\t\treturn true;\r\n\t});\r\n\tpopulateCheckboxList(\r\n\t\t\"shared-view-drivers-list\",\r\n\t\tsharedViewDrivers,\r\n\t\t\"SharedViewDriverIds\",\r\n\t\tfunction (item) {\r\n\t\t\tif (sharedView === null) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\treturn _.indexOf(sharedView.DriverIds, item.Id) !== -1;\r\n\t\t},\r\n\t\tfunction (item) {\r\n\t\t\treturn item.DriverId;\r\n\t\t},\r\n\t\t\"drivers\",\r\n\t\tgetDescriptionForDriver\r\n\t);\r\n\r\n\t// disable groupings if they have no options available\r\n\tvar assetsOption = document.getElementById(\"SharedViewPermissionsAssets\");\r\n\tif (trkData.assets.length === 0) {\r\n\t\tassetsOption.disabled = true;\r\n\t} else if (!assetsOption.classList.contains(\"disabled\")) {\r\n\t\tassetsOption.disabled = false;\r\n\t}\r\n\tvar fencesOption = document.getElementById(\"SharedViewPermissionsGeofences\");\r\n\tif (trkData.fences.length === 0) {\r\n\t\tfencesOption.disabled = true;\r\n\t} else if (!fencesOption.classList.contains(\"disabled\")) {\r\n\t\tfencesOption.disabled = false;\r\n\t}\r\n\tvar placesOption = document.getElementById(\"SharedViewPermissionsPlaces\");\r\n\tif (trkData.places.length === 0) {\r\n\t\tplacesOption.disabled = true;\r\n\t} else if (!placesOption.classList.contains(\"disabled\")) {\r\n\t\tplacesOption.disabled = false;\r\n\t}\r\n\tvar assetGroupsOption = document.getElementById(\"SharedViewPermissionsGroups\");\r\n\tif (trkData.groups.length === 1) {\r\n\t\tassetGroupsOption.disabled = true;\r\n\t} else if (!assetGroupsOption.classList.contains(\"disabled\")) {\r\n\t\tassetGroupsOption.disabled = false;\r\n\t}\r\n\tvar driversOption = document.getElementById(\"SharedViewPermissionsDrivers\");\r\n\tif (trkData.drivers.length === 0) {\r\n\t\tdriversOption.disabled = true;\r\n\t} else if (!driversOption.classList.contains(\"disabled\")) {\r\n\t\tdriversOption.disabled = false;\r\n\t}\r\n\r\n\ttrkData.sharedView.temp = cloneSharedView(editSharedView);\r\n\r\n\tvar buttonText = sharedView !== null ? strings.SAVE_CHANGES : strings.CREATE_SHARED_VIEW;\r\n\tchangePrimaryButtonLabel(domNodes.dialogs.sharedView, buttonText);\r\n\tvar callback = function (item) {\r\n\t\topenSharedViewDialog(item, step);\r\n\t};\r\n\topenDialogPanel(\r\n\t\tdialog,\r\n\t\tdialogTitle,\r\n\t\tsharedView,\r\n\t\tfalse,\r\n\t\tcheckForShareViewChange(sharedView, true),\r\n\t\t\"shared-view\",\r\n\t\tsharedView !== null ? \"edit-shared-view\" : null,\r\n\t\tsharedView !== null ? callback : null\r\n\t);\r\n\t$(domNodes.infoDialogs.sharedViewInformation).dialog(\"close\");\r\n\tif (sharedView === null) {\r\n\t\tmoveSecondaryPanelToPrimary();\r\n\t}\r\n}\r\n\r\n// // TODO reusable wizard component (see Shared Views)\r\n// var ItemWizard = function (steps, container, options) {\r\n// \tthis.initialized = false;\r\n//\r\n// \tthis.options = {};\r\n// \tthis.data = {\r\n// \t\tsteps: [],\r\n// \t};\r\n// \tthis.domNodes = {\r\n// \t\twizardContainer: container,\r\n// \t};\r\n//\r\n// \tvar self = this;\r\n// \tfunction init(steps, options) {\r\n// \t\t$.extend(true, self.options, options);\r\n// \t\tself.initialized = true;\r\n// \t\tself.data.steps = steps;\r\n//\r\n// \t\tvar container = self.domNodes.wizardContainer;\r\n// \t}\r\n//\r\n// \tfunction validateStep(step) {}\r\n//\r\n// \tthis.changeStep = function (step) {};\r\n//\r\n// \tinit(steps, options);\r\n// };\r\n\r\nexport function goToWizardStep(wizard, stepId, stepNum) {\r\n\tvar SUCCESS_STEP_ID = \"success\";\r\n\tvar steps = wizard.steps;\r\n\tvar stepsById = _.keyBy(steps, \"id\");\r\n\tvar chosenStep = null;\r\n\tif (stepId !== undefined && stepId !== null) {\r\n\t\tchosenStep = stepsById[stepId];\r\n\t} else if (stepNum !== undefined && stepNum !== null) {\r\n\t\tchosenStep = _.find(steps, { step: stepNum });\r\n\t}\r\n\tif (chosenStep === undefined || chosenStep === null) {\r\n\t\tchosenStep = _.find(steps, { step: 1 });\r\n\t}\r\n\tconsole.log(\"chosen step\", chosenStep);\r\n\r\n\tif (wizard.currentStep !== undefined && wizard.currentStep !== null) {\r\n\t\t// only validate if moving forward\r\n\t\tif (chosenStep.step > wizard.currentStep.step) {\r\n\t\t\tif (wizard.currentStep.form !== undefined) {\r\n\t\t\t\tvar isValid = $(wizard.currentStep.form.currentForm).valid();\r\n\t\t\t\tconsole.log(\"check form validity\", isValid, wizard.currentStep.form);\r\n\t\t\t\tif (!isValid) {\r\n\t\t\t\t\twizard.currentStep.form.focusInvalid();\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\twizard\r\n\t\t.querySelector(\".step-title use\")\r\n\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", svgPath(chosenStep.icon));\r\n\twizard.querySelector(\".step-title span\").textContent = chosenStep.title;\r\n\tvar allSteps = wizard.querySelectorAll(\".wizard-step\");\r\n\t_.each(allSteps, function (wizardStep) {\r\n\t\tif (wizardStep.getAttribute(\"data-step-id\") === chosenStep.id) {\r\n\t\t\twizardStep.classList.add(\"is-active\");\r\n\t\t} else {\r\n\t\t\twizardStep.classList.remove(\"is-active\");\r\n\t\t}\r\n\t});\r\n\r\n\tvar navigableSteps = _.reject(steps, function (step) {\r\n\t\treturn step.id === SUCCESS_STEP_ID;\r\n\t});\r\n\tvar lastStepNum = _.last(navigableSteps).step;\r\n\r\n\tvar isFirstStep = chosenStep.step === 1;\r\n\tvar isLastStep = chosenStep.step === lastStepNum;\r\n\twizard.querySelector(\".wizard-buttons .prev-step\").disabled = isFirstStep;\r\n\twizard.querySelector(\".wizard-buttons .next-step\").disabled = isLastStep;\r\n\tif (isLastStep) {\r\n\t\twizard.querySelector(\".wizard-buttons .next-step\").classList.remove(\"is-visible\");\r\n\t\twizard.querySelector(\".wizard-buttons .final-step\").classList.add(\"is-visible\");\r\n\t} else {\r\n\t\twizard.querySelector(\".wizard-buttons .next-step\").classList.add(\"is-visible\");\r\n\t\twizard.querySelector(\".wizard-buttons .final-step\").classList.remove(\"is-visible\");\r\n\t}\r\n\twizard.currentStep = chosenStep;\r\n\r\n\tif (chosenStep.id === SUCCESS_STEP_ID) {\r\n\t\twizard.querySelector(\".wizard-buttons\").classList.add(\"toggle-content\");\r\n\t} else {\r\n\t\twizard.querySelector(\".wizard-buttons\").classList.remove(\"toggle-content\");\r\n\t}\r\n\r\n\t// set progress meter\r\n\tvar totalSteps = lastStepNum;\r\n\tvar width = ((chosenStep.step - 1) * (100 / totalSteps)).toFixed(0) + \"%\";\r\n\tvar progressBar = wizard.querySelector(\".progress-bar\");\r\n\tprogressBar.style.width = width;\r\n\tprogressBar.textContent = width;\r\n\r\n\treturn chosenStep;\r\n}\r\n\r\nexport function openSharedViewShareDialog(sharedView) {\r\n\tif (sharedView === undefined || sharedView === null) {\r\n\t\treturn;\r\n\t}\r\n\ttrkData.sharedView.current = sharedView;\r\n\r\n\tdocument.getElementById(\"SharedViewShareLink\").textContent = sharedView.Link;\r\n\r\n\tif (!sharedView.IsPublic) {\r\n\t\tdocument.getElementById(\"SharedViewSharePrivate\").classList.add(\"is-visible\");\r\n\t} else {\r\n\t\tdocument.getElementById(\"SharedViewSharePrivate\").classList.remove(\"is-visible\");\r\n\t}\r\n\r\n\tquerySharedViewInvites(sharedView);\r\n\tvar dialog = domNodes.dialogs.sharedViewShare;\r\n\topenDialogPanel(\r\n\t\tdialog,\r\n\t\tstrings.SHARE,\r\n\t\tsharedView,\r\n\t\tfalse,\r\n\t\tcheckForShareViewChange(sharedView),\r\n\t\t\"shared-view\",\r\n\t\t\"share\",\r\n\t\topenSharedViewShareDialog\r\n\t);\r\n\t$(domNodes.infoDialogs.sharedViewInformation).dialog(\"close\");\r\n}\r\n","import strings from \"./strings.js\";\r\nimport user from \"./user.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { mapModes } from \"./const.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport _ from \"lodash\";\r\nimport moment from \"moment\"; // https://www.npmjs.com/package/moment\r\nimport { el } from \"redom\"; // https://redom.js.org/\r\n\r\nexport function populateSharedViewInformation(sharedView) {\r\n\tvar frag = document.createDocumentFragment();\r\n\r\n\tvar cont = document.createElement(\"div\");\r\n\tcont.className = \"container-fluid\";\r\n\tvar row = document.createElement(\"div\");\r\n\trow.className = \"section-meta row\";\r\n\tvar leftCol = document.createElement(\"div\");\r\n\tleftCol.className = \"col-7\";\r\n\tvar list = document.createElement(\"ul\");\r\n\r\n\tvar name = populateSharedViewListItem(\r\n\t\tstrings.DEFAULT_MODE,\r\n\t\tsharedView.Preferences.DefaultMode === mapModes.LIVE ? strings.MODE_LIVE : strings.MODE_HISTORY\r\n\t);\r\n\tlist.appendChild(name);\r\n\r\n\tif (sharedView.Description !== null && sharedView.Description !== \"\") {\r\n\t\tvar description = populateSharedViewListItem(strings.DESCRIPTION, sharedView.Description);\r\n\t\tdescription.className = \"pt-2\";\r\n\t\tlist.appendChild(description);\r\n\t}\r\n\r\n\tleftCol.appendChild(list);\r\n\r\n\tvar shareCont = document.createElement(\"div\");\r\n\tshareCont.className = \"pt-3\";\r\n\tvar shareButton = document.createElement(\"a\");\r\n\tshareButton.href = \"#\";\r\n\tshareButton.className = \"btn btn-primary\";\r\n\tshareButton.id = \"SharedViewMapInformationShare\";\r\n\r\n\tvar shareIcon = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\r\n\tvar shareIconTitle = document.createElementNS(\"http://www.w3.org/2000/svg\", \"title\");\r\n\tshareIconTitle.textContent = strings.SHARE_THIS_VIEW;\r\n\tshareIcon.appendChild(shareIconTitle);\r\n\tvar shareIconType = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\r\n\tshareIconType.setAttributeNS(\r\n\t\t\"http://www.w3.org/1999/xlink\",\r\n\t\t\"href\",\r\n\t\t\"/content/svg/tracking.svg?v=15#share-alt-solid\"\r\n\t);\r\n\tshareIcon.appendChild(shareIconType);\r\n\tshareButton.appendChild(shareIcon);\r\n\r\n\tvar shareLabel = document.createElement(\"span\");\r\n\tshareLabel.textContent = strings.SHARE_THIS_VIEW;\r\n\tshareButton.appendChild(shareLabel);\r\n\tshareCont.appendChild(shareButton);\r\n\tleftCol.appendChild(shareCont);\r\n\r\n\trow.appendChild(leftCol);\r\n\r\n\t// right column\r\n\tvar rightCol = document.createElement(\"div\");\r\n\trightCol.className = \"col-5 info-right\";\r\n\tvar rightList = document.createElement(\"ul\");\r\n\trightCol.appendChild(rightList);\r\n\r\n\tvar status = populateSharedViewListItem(strings.STATUS, sharedView.IsEnabled ? strings.ENABLED : strings.DISABLED);\r\n\trightList.appendChild(status);\r\n\tvar expires = populateSharedViewListItem(\r\n\t\tstrings.EXPIRES,\r\n\t\tsharedView.ExpiresOnEpoch === null ? strings.NEVER : moment.utc(sharedView.ExpiresOnEpoch).format(user.dateFormat)\r\n\t);\r\n\trightList.appendChild(expires);\r\n\tvar availability = populateSharedViewListItem(\r\n\t\tstrings.AVAILABILITY,\r\n\t\tsharedView.IsPublic ? strings.PUBLIC : strings.PRIVATE\r\n\t);\r\n\trightList.appendChild(availability);\r\n\tvar messaging = populateSharedViewListItem(\r\n\t\tstrings.TWO_WAY_MESSAGING,\r\n\t\tsharedView.IsMessagingEnabled ? strings.ENABLED : strings.DISABLED\r\n\t);\r\n\trightList.appendChild(messaging);\r\n\tvar created = populateSharedViewListItem(\r\n\t\tstrings.CREATED_ON,\r\n\t\tmoment.utc(sharedView.CreatedOnEpoch).format(user.dateFormat)\r\n\t);\r\n\trightList.appendChild(created);\r\n\tvar updated = populateSharedViewListItem(\r\n\t\tstrings.UPDATED_ON,\r\n\t\tsharedView.UpdatedOnEpoch === null ? strings.NEVER : moment.utc(sharedView.UpdatedOnEpoch).format(user.dateFormat)\r\n\t);\r\n\trightList.appendChild(updated);\r\n\trow.appendChild(rightCol);\r\n\r\n\tcont.appendChild(row);\r\n\tfrag.appendChild(cont);\r\n\treturn frag;\r\n}\r\n\r\nexport function populateSharedViewSubmissionFromForm() {\r\n\tvar id = parseInt(document.getElementById(\"SharedViewId\").value);\r\n\tvar name = document.getElementById(\"SharedViewName\").value;\r\n\tvar description = document.getElementById(\"SharedViewDescription\").value;\r\n\tvar color = document.getElementById(\"SharedViewColor\").value;\r\n\r\n\tvar permissions = getSharedViewSelectionOptions();\r\n\tvar assetGroupIds = permissions.assetGroupIds;\r\n\tvar assetIds = permissions.assetIds;\r\n\tvar fenceIds = permissions.fenceIds;\r\n\tvar placeIds = permissions.placeIds;\r\n\tvar driverIds = permissions.driverIds;\r\n\r\n\tvar isEnabled = document.getElementById(\"SharedViewIsEnabledYes\").checked;\r\n\tvar isPublic = document.getElementById(\"SharedViewIsPublicYes\").checked;\r\n\tvar password = document.getElementById(\"SharedViewPassword\").value;\r\n\tvar doesExpire = document.getElementById(\"SharedViewDoesExpireYes\").checked;\r\n\tvar expiresOn = $(document.getElementById(\"SharedViewExpiresOn\")).datetimepicker(\"getDate\"); // user's local date\r\n\tif (expiresOn !== null) {\r\n\t\texpiresOn = moment(expiresOn).format(user.dateFormat);\r\n\t}\r\n\tvar isMessagingEnabled = document.getElementById(\"SharedViewIsMessagingEnabledYes\").checked;\r\n\tvar isTimeframeRelative = document.getElementById(\"SharedViewDataTimeframeRelative\").checked;\r\n\tvar relativeTimeframeNumber = null;\r\n\tvar relativeTimeframeType = null;\r\n\tvar isDataLimited = false;\r\n\tvar from = null;\r\n\tvar to = null;\r\n\tif (isTimeframeRelative) {\r\n\t\trelativeTimeframeNumber = document.getElementById(\"SharedViewDataTimeframeRelativeNumber\").value;\r\n\t\trelativeTimeframeType = document.getElementById(\"SharedViewDataTimeframeRelativeType\").value;\r\n\t} else {\r\n\t\tisDataLimited = document.getElementById(\"SharedViewDataTimeframeCustom\").checked;\r\n\t\tfrom = $(document.getElementById(\"SharedViewFrom\")).datetimepicker(\"getDate\");\r\n\t\tif (from !== null) {\r\n\t\t\tfrom = moment(from).format(user.dateFormat);\r\n\t\t}\r\n\t\tto = $(document.getElementById(\"SharedViewTo\")).datetimepicker(\"getDate\");\r\n\t\tif (to !== null) {\r\n\t\t\tto = moment(to).format(user.dateFormat);\r\n\t\t}\r\n\t}\r\n\r\n\tvar preferenceLanguage = document.getElementById(\"SharedViewLanguage\").value;\r\n\tvar preferenceTimezone = document.getElementById(\"SharedViewTimezone\").value;\r\n\tvar preferenceLatLng = parseInt(document.getElementById(\"SharedViewLatLngFormat\").value);\r\n\tvar preferenceSpeed = parseInt(document.getElementById(\"SharedViewSpeedFormat\").value);\r\n\tvar preferenceFuel = parseInt(document.getElementById(\"SharedViewFuelFormat\").value);\r\n\r\n\tvar preferenceRemoveRoads = document.getElementById(\"SharedViewRemoveRoadsYes\").checked;\r\n\tvar preferencePositionConsolidation = document.getElementById(\"SharedViewPositionConsolidationYes\").checked;\r\n\tvar preferencePositionAlpha = document.getElementById(\"SharedViewPositionAlphaYes\").checked;\r\n\tvar preferenceHistoryViewNumber = 7; //parseInt(document.getElementById('SharedViewHistoryViewNumber').value);\r\n\tvar preferenceHistoryViewType = \"d\"; //document.getElementById('SharedViewHistoryViewType').value;\r\n\tvar preferenceMapType = parseInt(document.getElementById(\"SharedViewMapType\").value);\r\n\tvar preferenceDefaultMode = parseInt(document.getElementById(\"SharedViewDefaultMode\").value);\r\n\r\n\tvar data = {\r\n\t\tid: id,\r\n\t\tname: name,\r\n\t\tdescription: description,\r\n\t\tcolor: color,\r\n\t\tassetGroupIds: assetGroupIds,\r\n\t\tassetIds: assetIds,\r\n\t\tfenceIds: fenceIds,\r\n\t\tplaceIds: placeIds,\r\n\t\tdriverIds: driverIds,\r\n\t\tisEnabled: isEnabled,\r\n\t\tisPublic: isPublic,\r\n\t\tpassword: password,\r\n\t\tdoesExpire: doesExpire,\r\n\t\texpiresOn: expiresOn,\r\n\t\t//expiresOnUtc: expiresOn,\r\n\t\tisTimeframeRelative: isTimeframeRelative,\r\n\t\trelativeTimeframeNumber: relativeTimeframeNumber,\r\n\t\trelativeTimeframeType: relativeTimeframeType,\r\n\t\tisDataLimited: isDataLimited,\r\n\t\tisMessagingEnabled: isMessagingEnabled,\r\n\t\t//fromUtc: from,\r\n\t\tfrom: from,\r\n\t\tto: to,\r\n\t\t//toUtc: to,\r\n\t\tpreferences: {\r\n\t\t\tpreferenceSpeed: preferenceSpeed,\r\n\t\t\tpreferenceFuel: preferenceFuel,\r\n\t\t\tpreferenceTimezone: preferenceTimezone,\r\n\t\t\tpreferenceLanguage: preferenceLanguage,\r\n\t\t\tpreferenceRemoveRoads: preferenceRemoveRoads,\r\n\t\t\tpreferencePositionConsolidation: preferencePositionConsolidation,\r\n\t\t\tpreferencePositionAlpha: preferencePositionAlpha,\r\n\t\t\tpreferenceHistoryViewNumber: preferenceHistoryViewNumber,\r\n\t\t\tpreferenceHistoryViewType: preferenceHistoryViewType,\r\n\t\t\tpreferenceLatLng: preferenceLatLng,\r\n\t\t\tpreferenceMapType: preferenceMapType,\r\n\t\t\tpreferenceDefaultMode: preferenceDefaultMode,\r\n\t\t},\r\n\t};\r\n\treturn data;\r\n}\r\n\r\nfunction populateSharedViewListItem(label, text) {\r\n\treturn el(\"li\", [el(\"div.meta-header\", label + \":\"), el(\"div.meta-item\", text)]);\r\n}\r\n\r\nexport function getSharedViewSelectionOptions() {\r\n\tvar dialog = domNodes.dialogs.sharedView;\r\n\tvar assetGroupIds = [];\r\n\tvar assetIds = [];\r\n\tvar fenceIds = [];\r\n\tvar placeIds = [];\r\n\tvar driverIds = [];\r\n\tif (document.getElementById(\"SharedViewPermissionsGroups\").checked) {\r\n\t\tassetGroupIds = _.map(dialog.querySelectorAll('input[name=\"SharedViewAssetGroupIds\"]:checked'), \"value\");\r\n\t}\r\n\tif (document.getElementById(\"SharedViewPermissionsAssets\").checked) {\r\n\t\tassetIds = _.map(dialog.querySelectorAll('input[name=\"SharedViewAssetIds\"]:checked'), function (item) {\r\n\t\t\treturn parseInt(item.value);\r\n\t\t});\r\n\t}\r\n\tif (document.getElementById(\"SharedViewPermissionsGeofences\").checked) {\r\n\t\tfenceIds = _.map(dialog.querySelectorAll('input[name=\"SharedViewFenceIds\"]:checked'), \"value\");\r\n\t}\r\n\tif (document.getElementById(\"SharedViewPermissionsPlaces\").checked) {\r\n\t\tplaceIds = _.map(dialog.querySelectorAll('input[name=\"SharedViewPlaceIds\"]:checked'), function (item) {\r\n\t\t\treturn parseInt(item.value);\r\n\t\t});\r\n\t}\r\n\tif (document.getElementById(\"SharedViewPermissionsDrivers\").checked) {\r\n\t\tdriverIds = _.map(dialog.querySelectorAll('input[name=\"SharedViewDriverIds\"]:checked'), function (item) {\r\n\t\t\treturn parseInt(item.value);\r\n\t\t});\r\n\t}\r\n\treturn {\r\n\t\tassetIds: assetIds,\r\n\t\tfenceIds: fenceIds,\r\n\t\tplaceIds: placeIds,\r\n\t\tdriverIds: driverIds,\r\n\t\tassetGroupIds: assetGroupIds,\r\n\t};\r\n}\r\n","import strings from \"./strings.js\";\r\nimport trkData from \"./data.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport state from \"./state.js\";\r\nimport { map } from \"./map-base.js\";\r\nimport { addItemToMap, removeItemFromMap } from \"./map-items.js\";\r\nimport user from \"./user.js\";\r\nimport { viewModes, trkDataGroups } from \"./const.js\";\r\nimport { resizeApp } from \"./window-layout.js\";\r\nimport { findAssetById, normalizeAssetData, findAssetIdsUnderGroup } from \"./assets.js\";\r\nimport options from \"./options.js\";\r\nimport { sortModes } from \"./const.js\";\r\nimport { moveOrOpenDialogRelativeTo } from \"./modal-dialog.js\";\r\nimport { loadDialogButtons, closeButton } from \"./modal-dialog-buttons.js\";\r\nimport { setMapBounds } from \"./map-bounds.js\";\r\nimport { convertHexToSortable, convertNamedColorToHex, getItemHexColor } from \"./color.js\";\r\nimport { createMarkerPath } from \"./marker-path.js\";\r\nimport { sortItemsByMode, resortItemGroup, toggleItemSorting } from \"./item-sorting.js\";\r\nimport { closeSecondaryPanel } from \"./panel.js\";\r\nimport { handleLimitedDataResult } from \"./limited-data.js\";\r\nimport { changeMapType } from \"./map-maptype.js\";\r\nimport { updateAssetFunctionBadges } from \"./badges.js\";\r\nimport { createMarkerCluster } from \"./marker-cluster.js\";\r\nimport { initSharedViewDialog, openSharedViewShareDialog } from \"./shared-view-dialog.js\";\r\nimport { handleAjaxFormSubmission } from \"./ajax.js\";\r\nimport { addPositionMarkerToPoint } from \"./marker.js\";\r\nimport { restrictAllChildren, unrestrictDirectChildren } from \"./dom-util.js\";\r\nimport { productTitle } from \"./entry_point.js\";\r\nimport { showResultLimitsIfApplicable } from \"./item-listing.js\";\r\nimport { findGroupById, updateGroupVisibilityStatus } from \"./asset-group.js\";\r\nimport { updateActiveAssetInformation } from \"./assets-active.js\";\r\nimport { createPositionLinesForAsset } from \"./geometry-create.js\";\r\nimport { getSvgIconForItemType, createDialogTitleFragment } from \"./dom-util.js\";\r\nimport { updateMapModeDateRange } from \"./map-ui.js\";\r\nimport { highlightActiveItemInPrimaryPanel } from \"./panel.js\";\r\nimport { openSharedViewSettingsPanel } from \"./panel-settings.js\";\r\nimport templates from \"./templates.js\";\r\nimport { goToWizardStep } from \"./shared-view-dialog.js\";\r\nimport {\r\n\tpopulateSharedViewInformation,\r\n\tpopulateSharedViewSubmissionFromForm,\r\n\tgetSharedViewSelectionOptions,\r\n} from \"./shared-view-populate.js\";\r\nimport { createQuickActionsForSharedView } from \"./quick-actions.js\";\r\nimport { updateMapModePanel } from \"./map-ui.js\";\r\nimport log from \"./log.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport _ from \"lodash\";\r\nimport L from \"leaflet\";\r\nimport moment from \"moment\"; // https://www.npmjs.com/package/moment\r\n\r\n/*global JsSearch, MapToolbar */\r\n// import JsSearch from '../js-search.js';\r\n\r\nexport function initSharedView() {\r\n\tvar sharedViewShareButtons = [\r\n\t\t{\r\n\t\t\tbuttonType: \"primary\",\r\n\t\t\tsvgIcon: \"envelope-solid\",\r\n\t\t\ttext: strings.SEND_INVITE,\r\n\t\t\tid: \"SharedViewShareButton\",\r\n\t\t\tclick: function () {\r\n\t\t\t\tvar isValid = $(trkData.validation.sharedViewShare.currentForm).valid();\r\n\t\t\t\tif (!isValid) {\r\n\t\t\t\t\ttrkData.validation.sharedViewShare.focusInvalid();\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar dialog = domNodes.dialogs.sharedViewShare;\r\n\t\t\t\tvar status = dialog.querySelector(\".dialog-status\");\r\n\t\t\t\tvar btn = this;\r\n\r\n\t\t\t\tvar id = parseInt(domNodes.panels.secondary.getAttribute(\"data-item-id\"));\r\n\t\t\t\tvar email = document.getElementById(\"SharedViewShareEmail\").value;\r\n\t\t\t\tvar subject = document.getElementById(\"SharedViewShareSubject\").value;\r\n\t\t\t\tvar body = document.getElementById(\"SharedViewShareBody\").value;\r\n\t\t\t\tvar includePassword = document.getElementById(\"SharedViewShareIncludePasswordYes\").checked;\r\n\r\n\t\t\t\tvar data = {\r\n\t\t\t\t\tid: id,\r\n\t\t\t\t\temail: email,\r\n\t\t\t\t\tsubject: subject,\r\n\t\t\t\t\tbody: body,\r\n\t\t\t\t\tincludePassword: includePassword,\r\n\t\t\t\t};\r\n\r\n\t\t\t\thandleAjaxFormSubmission(\r\n\t\t\t\t\t\"SendSharedViewInvites\",\r\n\t\t\t\t\tdata,\r\n\t\t\t\t\tbtn,\r\n\t\t\t\t\tstatus,\r\n\t\t\t\t\tstrings.MSG_SHARE_SHARED_VIEW_SUCCESS,\r\n\t\t\t\t\tstrings.MSG_SHARE_SHARED_VIEW_ERROR,\r\n\t\t\t\t\tfunction (result) {\r\n\t\t\t\t\t\t// reload form defaults\r\n\t\t\t\t\t\ttrkData.validation.sharedViewShare.resetForm();\r\n\t\t\t\t\t\ttrkData.validation.sharedViewShare.currentForm.reset();\r\n\r\n\t\t\t\t\t\tvar sharedView = findSharedViewById(id);\r\n\t\t\t\t\t\tif (sharedView !== null) {\r\n\t\t\t\t\t\t\tquerySharedViewInvites(sharedView);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t},\r\n\t\t},\r\n\t\tcloseButton,\r\n\t];\r\n\r\n\tloadDialogButtons(domNodes.dialogs.sharedViewShare, sharedViewShareButtons);\r\n\r\n\tloadDialogButtons(domNodes.dialogs.sharedViewStatistics, [closeButton]);\r\n\t$(\"#shared-view-visitor-activity\").dataTable({\r\n\t\tdestroy: true,\r\n\t\tfilter: false,\r\n\t\tinfo: false,\r\n\t\tjQueryUI: false,\r\n\t\tautoWidth: false,\r\n\t\tlengthChange: false,\r\n\t\tpaging: false,\r\n\t\tpageLength: 3,\r\n\t\tdeferRender: true,\r\n\t\torder: [[2, \"desc\"]],\r\n\t\tcolumnDefs: [\r\n\t\t\t{\r\n\t\t\t\ttargets: \"_all\",\r\n\t\t\t\trender: $.fn.dataTable.render.text(),\r\n\t\t\t},\r\n\t\t],\r\n\t\tcolumns: [\r\n\t\t\t{}, // name\r\n\t\t\t{}, // visits\r\n\t\t\t{}, // last visit\r\n\t\t],\r\n\t\tlanguage: strings.DATATABLE,\r\n\t\tdrawCallback: function (oSettings) {},\r\n\t\tinitComplete: function (oSettings, json) {\r\n\t\t\t$(\"#shared-view-visitor-activity\").DataTable().clear();\r\n\t\t},\r\n\t});\r\n\r\n\tvar sharedViewButtons = [\r\n\t\t{\r\n\t\t\tbuttonType: \"primary\",\r\n\t\t\ttext: strings.CREATE_SHARED_VIEW,\r\n\t\t\tid: \"UpdateSharedViewButton\",\r\n\t\t\tclick: function () {},\r\n\t\t},\r\n\t\tcloseButton,\r\n\t];\r\n\r\n\ttrkData.wizards.sharedView = domNodes.dialogs.sharedView.querySelector(\".step-wizard\");\r\n\ttrkData.wizards.sharedView.steps = [];\r\n\t_.each(trkData.wizards.sharedView.querySelectorAll(\".wizard-step\"), function (item) {\r\n\t\ttrkData.wizards.sharedView.steps.push({\r\n\t\t\tid: item.getAttribute(\"data-step-id\"),\r\n\t\t\tstep: parseInt(item.getAttribute(\"data-step-step\")),\r\n\t\t\ttitle: item.getAttribute(\"data-step-title\"),\r\n\t\t\ticon: item.getAttribute(\"data-step-icon\"),\r\n\t\t\tform: $(item.querySelector(\"form\")).validate({\r\n\t\t\t\tignore: \":hidden:not(#SharedViewShareOne)\",\r\n\t\t\t\tshowErrors: function (errorMap, errorList) {\r\n\t\t\t\t\tif (errorMap.SharedViewShareOne !== undefined) {\r\n\t\t\t\t\t\t// turn it red\r\n\t\t\t\t\t\tdocument.getElementById(\"SharedViewShareOneHint\").classList.add(\"invalid-feedback\");\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthis.defaultShowErrors();\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\terrorPlacement: function (error, element) {\r\n\t\t\t\t\t// error = error element\r\n\t\t\t\t\tif (element.id !== \"SharedViewShareOne\" && element.id !== \"SharedViewDataTimeframeRelativeNumber\") {\r\n\t\t\t\t\t\terror.addClass(\"invalid-feedback\");\r\n\t\t\t\t\t\terror.insertAfter(element);\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\tunhighlight: function (element, errorClass, validClass) {\r\n\t\t\t\t\tconsole.log(\"unhighlight\", element, errorClass, validClass);\r\n\t\t\t\t\tif (element.id === \"SharedViewShareOne\") {\r\n\t\t\t\t\t\tdocument.getElementById(\"SharedViewShareOneHint\").classList.remove(\"invalid-feedback\");\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\t$(element).removeClass(errorClass).addClass(validClass);\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t}), // this should happen after jquery validation initialization\r\n\t\t});\r\n\t});\r\n\ttrkData.wizards.sharedView.steps = _.sortBy(trkData.wizards.sharedView.steps, \"step\");\r\n\r\n\tloadDialogButtons(domNodes.dialogs.sharedView, sharedViewButtons);\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \"input[name=SharedViewIsPublic]\", function (e) {\r\n\t\tvar isPrivate = document.getElementById(\"SharedViewIsPublicNo\").checked;\r\n\t\tif (isPrivate) {\r\n\t\t\tdocument.getElementById(\"SharedViewPrivatePassword\").classList.add(\"is-visible\");\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"SharedViewPrivatePassword\").classList.remove(\"is-visible\");\r\n\t\t}\r\n\t});\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \"#ShareViewShowAll\", function (e) {\r\n\t\te.preventDefault();\r\n\t\tcloseSecondaryPanel();\r\n\t});\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \"#ShareViewEdit\", function (e) {\r\n\t\te.preventDefault();\r\n\t\tif (trkData.sharedView.current !== null) {\r\n\t\t\topenSharedViewSettingsPanel(trkData.sharedView.current);\r\n\t\t}\r\n\t});\r\n\t$(domNodes.infoDialogs.sharedViewInformation).on(\"click\", \"#SharedViewMapInformationShare\", function (e) {\r\n\t\te.preventDefault();\r\n\t\tif (trkData.sharedView.current !== null) {\r\n\t\t\topenSharedViewSettingsPanel(findSharedViewById(trkData.sharedView.current.Id));\r\n\t\t}\r\n\t});\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \"#ShareViewCompleteEmail\", function (e) {\r\n\t\te.preventDefault();\r\n\t\tif (trkData.sharedView.current !== null) {\r\n\t\t\topenSharedViewShareDialog(findSharedViewById(trkData.sharedView.current.Id));\r\n\t\t}\r\n\t});\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \"input[name=SharedViewDoesExpire]\", function (e) {\r\n\t\tvar doesExpire = document.getElementById(\"SharedViewDoesExpireYes\").checked;\r\n\t\tif (doesExpire) {\r\n\t\t\tdocument.getElementById(\"SharedViewExpireDate\").classList.add(\"is-visible\");\r\n\t\t\tdocument.getElementById(\"SharedViewExpiresOn\").disabled = false;\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"SharedViewExpireDate\").classList.remove(\"is-visible\");\r\n\t\t\tdocument.getElementById(\"SharedViewExpiresOn\").disabled = true;\r\n\t\t}\r\n\t});\r\n\t$(domNodes.dialogs.sharedView).on(\"change\", \"#SharedViewMapType\", function (e) {\r\n\t\tvar editing = trkData.sharedView.temp;\r\n\t\tif (editing !== null) {\r\n\t\t\tvar prior = cloneSharedView(editing);\r\n\t\t\tediting.Preferences.MapType = parseInt(this.value);\r\n\t\t\tcompareSharedViews(editing, prior);\r\n\t\t}\r\n\t});\r\n\r\n\t//$(domNodes.dialogs.sharedView).on('change', '#SharedViewDefaultMode', function(e) {\r\n\t// if (parseInt(this.value) === mapModes.HISTORY) {\r\n\t// document.getElementById('SharedViewModeHistory').classList.add('is-visible');\r\n\t// } else {\r\n\t// document.getElementById('SharedViewModeHistory').classList.remove('is-visible');\r\n\t// }\r\n\t//});\r\n\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \"input[name=SharedViewPositionConsolidation]\", function (e) {\r\n\t\tvar isPositionsConsolidated = document.getElementById(\"SharedViewPositionConsolidationYes\").checked;\r\n\t\tvar editing = trkData.sharedView.temp;\r\n\t\tif (editing !== null) {\r\n\t\t\tvar prior = cloneSharedView(editing);\r\n\t\t\tediting.Preferences.PositionConsolidation = isPositionsConsolidated;\r\n\t\t\tcompareSharedViews(editing, prior);\r\n\t\t}\r\n\t});\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \"input[name=SharedViewRemoveRoads]\", function (e) {\r\n\t\tvar isRemoveRoads = document.getElementById(\"SharedViewRemoveRoadsYes\").checked;\r\n\t\tvar editing = trkData.sharedView.temp;\r\n\t\tif (editing !== null) {\r\n\t\t\tvar prior = cloneSharedView(editing);\r\n\t\t\tediting.Preferences.RemoveRoads = isRemoveRoads;\r\n\t\t\tcompareSharedViews(editing, prior);\r\n\t\t}\r\n\t});\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \"input[name=SharedViewIsMessagingEnabled]\", function (e) {\r\n\t\tvar isMessagingEnabled = document.getElementById(\"SharedViewIsMessagingEnabledYes\").checked;\r\n\t\tvar editing = trkData.sharedView.temp;\r\n\t\tif (editing !== null) {\r\n\t\t\tvar prior = cloneSharedView(editing);\r\n\t\t\tediting.IsMessagingEnabled = isMessagingEnabled;\r\n\t\t\tcompareSharedViews(editing, prior);\r\n\t\t}\r\n\t});\r\n\r\n\tfunction sharedViewDateChange() {\r\n\t\tconsole.log(\"sharedViewDateChange\");\r\n\t\tvar editing = trkData.sharedView.temp;\r\n\t\tif (editing === null) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar prior = cloneSharedView(editing);\r\n\t\tvar isRelative = document.getElementById(\"SharedViewDataTimeframeRelative\").checked;\r\n\t\tvar isDataLimited = document.getElementById(\"SharedViewDataTimeframeCustom\").checked;\r\n\r\n\t\tif (isRelative) {\r\n\t\t\tediting.IsTimeframeRelative = true;\r\n\t\t\tediting.RelativeTimeframeNumber = document.getElementById(\"SharedViewDataTimeframeRelativeNumber\").value;\r\n\t\t\tediting.RelativeTimeframeType = document.getElementById(\"SharedViewDataTimeframeRelativeType\").value;\r\n\t\t\tediting.FromDateEpoch = null;\r\n\t\t\tediting.ToDateEpoch = null;\r\n\t\t} else {\r\n\t\t\tediting.IsTimeframeRelative = false;\r\n\t\t\tediting.RelativeTimeframeNumber = null;\r\n\t\t\tediting.RelativeTimeframeType = null;\r\n\t\t\tif (isDataLimited) {\r\n\t\t\t\tvar from = $(document.getElementById(\"SharedViewFrom\")).datetimepicker(\"getDate\");\r\n\t\t\t\tif (from !== null) {\r\n\t\t\t\t\tfrom = from.getTime();\r\n\t\t\t\t}\r\n\t\t\t\tvar to = $(document.getElementById(\"SharedViewTo\")).datetimepicker(\"getDate\");\r\n\t\t\t\tif (to !== null) {\r\n\t\t\t\t\tto = to.getTime();\r\n\t\t\t\t}\r\n\t\t\t\tediting.FromDateEpoch = from;\r\n\t\t\t\tediting.ToDateEpoch = to;\r\n\t\t\t} else {\r\n\t\t\t\tediting.FromDateEpoch = null;\r\n\t\t\t\tediting.ToDateEpoch = null;\r\n\t\t\t}\r\n\t\t}\r\n\t\tcompareSharedViews(editing, prior);\r\n\t}\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \"input[name=SharedViewDataTimeframe]\", function (e) {\r\n\t\t// enable/disable inputs based on which radio is selected\r\n\t\tvar isRelative = document.getElementById(\"SharedViewDataTimeframeRelative\").checked;\r\n\t\tif (isRelative) {\r\n\t\t\tdocument.getElementById(\"SharedViewRelativeDateRange\").classList.add(\"is-visible\");\r\n\t\t\tdocument.getElementById(\"SharedViewDataTimeframeRelativeNumber\").disabled = false;\r\n\t\t\tdocument.getElementById(\"SharedViewDataTimeframeRelativeType\").disabled = false;\r\n\t\t\tdocument.getElementById(\"SharedViewDateRange\").classList.remove(\"is-visible\");\r\n\t\t\tdocument.getElementById(\"SharedViewFrom\").disabled = true;\r\n\t\t\tdocument.getElementById(\"SharedViewTo\").disabled = true;\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"SharedViewRelativeDateRange\").classList.remove(\"is-visible\");\r\n\t\t\tdocument.getElementById(\"SharedViewDataTimeframeRelativeNumber\").disabled = true;\r\n\t\t\tdocument.getElementById(\"SharedViewDataTimeframeRelativeType\").disabled = true;\r\n\t\t\tvar isLimited = document.getElementById(\"SharedViewDataTimeframeCustom\").checked;\r\n\t\t\tif (isLimited) {\r\n\t\t\t\tdocument.getElementById(\"SharedViewDateRange\").classList.add(\"is-visible\");\r\n\t\t\t\tdocument.getElementById(\"SharedViewFrom\").disabled = false;\r\n\t\t\t\tdocument.getElementById(\"SharedViewTo\").disabled = false;\r\n\t\t\t} else {\r\n\t\t\t\tdocument.getElementById(\"SharedViewDateRange\").classList.remove(\"is-visible\");\r\n\t\t\t\tdocument.getElementById(\"SharedViewFrom\").disabled = true;\r\n\t\t\t\tdocument.getElementById(\"SharedViewTo\").disabled = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tsharedViewDateChange();\r\n\t});\r\n\t$(domNodes.dialogs.sharedView).on(\r\n\t\t\"change\",\r\n\t\t\"#SharedViewFrom,#SharedViewTo,#SharedViewDataTimeframeRelativeNumber,#SharedViewDataTimeframeRelativeType\",\r\n\t\tsharedViewDateChange\r\n\t);\r\n\t$(domNodes.dialogs.sharedView).on(\r\n\t\t\"change\",\r\n\t\t\"#SharedViewPermissionsGroups,#SharedViewPermissionsAssets,#SharedViewPermissionsGeofences,#SharedViewPermissionsPlaces,#SharedViewPermissionsDrivers\",\r\n\t\tfunction (e) {\r\n\t\t\tvar collapse = document.getElementById(this.getAttribute(\"aria-controls\"));\r\n\t\t\tif (this.checked) {\r\n\t\t\t\t$(collapse).collapse(\"show\");\r\n\t\t\t} else {\r\n\t\t\t\t$(collapse).collapse(\"hide\");\r\n\t\t\t}\r\n\t\t\tvar editing = trkData.sharedView.temp;\r\n\t\t\tif (editing !== null) {\r\n\t\t\t\tvar permissions = getSharedViewSelectionOptions();\r\n\t\t\t\tvar prior = cloneSharedView(editing);\r\n\t\t\t\tediting.AssetIds = permissions.assetIds;\r\n\t\t\t\tediting.FenceIds = permissions.fenceIds;\r\n\t\t\t\tediting.AssetGroupIds = permissions.assetGroupIds;\r\n\t\t\t\tediting.PlaceIds = permissions.placeIds;\r\n\t\t\t\tediting.DriverIds = permissions.driverIds;\r\n\t\t\t\tcompareSharedViews(editing, prior);\r\n\t\t\t}\r\n\t\t}\r\n\t);\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \"input[name=SharedViewAssetGroupIds]\", function (e) {\r\n\t\tvar cont = document.getElementById(\"shared-view-groups-list\");\r\n\t\tif (this.checked) {\r\n\t\t\trestrictAllChildren(this, cont);\r\n\t\t} else {\r\n\t\t\tunrestrictDirectChildren(this, cont);\r\n\t\t}\r\n\t});\r\n\t$(domNodes.dialogs.sharedView).on(\r\n\t\t\"change\",\r\n\t\t\"input[name=SharedViewAssetGroupIds],input[name=SharedViewAssetIds],input[name=SharedViewPlaceIds],input[name=SharedViewFenceIds],input[name=SharedViewDriverIds]\",\r\n\t\tfunction (e) {\r\n\t\t\t// this is happening before the input checkbox is checked\r\n\t\t\t//\r\n\t\t\tconsole.log(\"permissions item click\");\r\n\t\t\tvar editing = trkData.sharedView.temp;\r\n\t\t\tif (editing !== null) {\r\n\t\t\t\tvar permissions = getSharedViewSelectionOptions();\r\n\t\t\t\tvar prior = cloneSharedView(trkData.sharedView.temp);\r\n\t\t\t\tediting.AssetIds = permissions.assetIds;\r\n\t\t\t\tediting.FenceIds = permissions.fenceIds;\r\n\t\t\t\tediting.AssetGroupIds = permissions.assetGroupIds;\r\n\t\t\t\tediting.PlaceIds = permissions.placeIds;\r\n\t\t\t\tediting.DriverIds = permissions.driverIds;\r\n\t\t\t\tcompareSharedViews(editing, prior);\r\n\t\t\t}\r\n\t\t}\r\n\t);\r\n\r\n\tinitSharedViewDialog();\r\n\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \".wizard-buttons .cancel\", function (e) {\r\n\t\te.preventDefault();\r\n\t\t_.each(trkData.wizards.sharedView.steps, function (step) {\r\n\t\t\tif (step.form !== undefined) {\r\n\t\t\t\tstep.form.resetForm();\r\n\t\t\t\tstep.form.currentForm.reset();\r\n\t\t\t}\r\n\t\t});\r\n\t\tcloseSecondaryPanel();\r\n\t});\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \".cancel\", function (e) {\r\n\t\te.preventDefault();\r\n\r\n\t\t_.each(trkData.wizards.sharedView.steps, function (step) {\r\n\t\t\tif (step.form !== undefined) {\r\n\t\t\t\tstep.form.resetForm();\r\n\t\t\t\tstep.form.currentForm.reset();\r\n\t\t\t}\r\n\t\t});\r\n\t\tdocument.getElementById(\"panel-dialog-back\").click();\r\n\t});\r\n\t$(\"#SharedViewExpiresOn\").datetimepicker({\r\n\t\tdateFormat: user.shortDateFormat,\r\n\t\thour: 0,\r\n\t\tminute: 0,\r\n\t\tminDate: options.dateRangeMin === null ? null : new Date(options.dateRangeMin),\r\n\t\tmaxDate: options.dateRangeMax === null ? null : new Date(options.dateRangeMax),\r\n\t});\r\n\t$(\"#SharedViewFrom\").datetimepicker({\r\n\t\tdateFormat: user.shortDateFormat,\r\n\t\thour: 0,\r\n\t\tminute: 0,\r\n\t\tminDate: options.dateRangeMin === null ? null : new Date(options.dateRangeMin),\r\n\t\tmaxDate: options.dateRangeMax === null ? null : new Date(options.dateRangeMax),\r\n\t\tonSelect: function (selectedDate) {\r\n\t\t\t// when a date is selected here, set the min date for the to picker\r\n\t\t\tvar current = $(\"#SharedViewTo\").val();\r\n\t\t\t$(\"#SharedViewTo\").datetimepicker(\"option\", \"minDate\", $(this).datetimepicker(\"getDate\"));\r\n\t\t\t$(\"#SharedViewTo\").val(current);\r\n\t\t},\r\n\t});\r\n\t$(\"#SharedViewTo\").datetimepicker({\r\n\t\tdateFormat: user.shortDateFormat,\r\n\t\thour: 23,\r\n\t\tminute: 59,\r\n\t\tminDate: options.dateRangeMin === null ? null : new Date(options.dateRangeMin),\r\n\t\tmaxDate: options.dateRangeMax === null ? null : new Date(options.dateRangeMax),\r\n\t\tonSelect: function (selectedDate) {\r\n\t\t\t// when a date is selected here, set the max date for the from picker\r\n\t\t\tvar current = $(\"#SharedViewFrom\").val();\r\n\t\t\t$(\"#SharedViewFrom\").datetimepicker(\"option\", \"maxDate\", $(this).datetimepicker(\"getDate\"));\r\n\t\t\t$(\"#SharedViewFrom\").val(current);\r\n\t\t},\r\n\t});\r\n\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \"#UpdateSharedViewButton\", function (e) {\r\n\t\tvar step = trkData.wizards.sharedView.currentStep;\r\n\t\tvar isValid = $(step.form.currentForm).valid();\r\n\t\tif (!isValid) {\r\n\t\t\tstep.form.focusInvalid();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar dialog = domNodes.dialogs.sharedView;\r\n\t\tvar status = dialog.querySelector(\".dialog-status\");\r\n\t\tvar btn = this;\r\n\r\n\t\t// really should just be updating the current step, but probably ok to do it all\r\n\t\tvar data = populateSharedViewSubmissionFromForm();\r\n\r\n\t\thandleAjaxFormSubmission(\r\n\t\t\t\"UpdateSharedView\",\r\n\t\t\tdata,\r\n\t\t\tbtn,\r\n\t\t\tstatus,\r\n\t\t\tstrings.MSG_EDIT_SHARED_VIEW_SUCCESS,\r\n\t\t\tstrings.MSG_EDIT_SHARED_VIEW_ERROR,\r\n\t\t\tfunction (result) {\r\n\t\t\t\tupdateSharedView(result.SharedView);\r\n\r\n\t\t\t\ttrkData.sharedView.temp = result.SharedView;\r\n\t\t\t\ttrkData.sharedView.current = result.SharedView;\r\n\t\t\t\tshowSharedViewInformationOnMap(result.SharedView, false);\r\n\t\t\t}\r\n\t\t);\r\n\t});\r\n\r\n\t$(domNodes.dialogs.sharedView).on(\"click\", \"#SharedViewWizardSave\", function (e) {\r\n\t\te.preventDefault();\r\n\r\n\t\tvar isFormValid = true;\r\n\t\tvar invalidStep = null;\r\n\t\t_.each(trkData.wizards.sharedView.steps, function (step) {\r\n\t\t\tif (step.form !== undefined) {\r\n\t\t\t\tvar isValid = $(step.form.currentForm).valid();\r\n\t\t\t\tif (!isValid) {\r\n\t\t\t\t\tisFormValid = false;\r\n\t\t\t\t\tinvalidStep = step;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t});\r\n\r\n\t\tif (!isFormValid) {\r\n\t\t\tinvalidStep.form.focusInvalid();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar dialog = domNodes.dialogs.sharedView;\r\n\t\tvar status = dialog.querySelector(\".dialog-status\");\r\n\t\tvar btn = this;\r\n\t\tvar data = populateSharedViewSubmissionFromForm();\r\n\t\tdelete data.id;\r\n\t\thandleAjaxFormSubmission(\r\n\t\t\t\"AddSharedView\",\r\n\t\t\tdata,\r\n\t\t\tbtn,\r\n\t\t\tstatus,\r\n\t\t\tnull,\r\n\t\t\tstrings.MSG_CREATE_SHARED_VIEW_ERROR,\r\n\t\t\tfunction (result) {\r\n\t\t\t\tvar sharedView = result.SharedView;\r\n\t\t\t\taddSharedView(sharedView);\r\n\r\n\t\t\t\ttrkData.sharedView.current = sharedView;\r\n\t\t\t\thighlightActiveItemInPrimaryPanel(\"shared-views\", sharedView.Id);\r\n\r\n\t\t\t\t// show success step\r\n\t\t\t\tgoToWizardStep(trkData.wizards.sharedView, \"success\");\r\n\r\n\t\t\t\t// populate share links\r\n\t\t\t\tdialog.querySelector(\".share-view-share.email\").setAttribute(\"data-share-view-id\", sharedView.Id);\r\n\t\t\t\tdialog\r\n\t\t\t\t\t.querySelector(\".share-view-share.twitter\")\r\n\t\t\t\t\t.setAttribute(\r\n\t\t\t\t\t\t\"href\",\r\n\t\t\t\t\t\t\"https://twitter.com/intent/tweet?url=\" +\r\n\t\t\t\t\t\t\tencodeURIComponent(sharedView.Link) +\r\n\t\t\t\t\t\t\t\"&text=\" +\r\n\t\t\t\t\t\t\tencodeURIComponent(sharedView.Name) +\r\n\t\t\t\t\t\t\t\". \" +\r\n\t\t\t\t\t\t\tencodeURIComponent(sharedView.Description)\r\n\t\t\t\t\t);\r\n\t\t\t\tdialog\r\n\t\t\t\t\t.querySelector(\".share-view-share.linkedin\")\r\n\t\t\t\t\t.setAttribute(\r\n\t\t\t\t\t\t\"href\",\r\n\t\t\t\t\t\t\"https://www.linkedin.com/shareArticle?mini=true&url=\" +\r\n\t\t\t\t\t\t\tencodeURIComponent(sharedView.Link) +\r\n\t\t\t\t\t\t\t\"&title=\" +\r\n\t\t\t\t\t\t\tencodeURIComponent(sharedView.Name) +\r\n\t\t\t\t\t\t\t\"&summary=\" +\r\n\t\t\t\t\t\t\tencodeURIComponent(sharedView.Description) +\r\n\t\t\t\t\t\t\t\"&source=\" +\r\n\t\t\t\t\t\t\tencodeURIComponent(productTitle)\r\n\t\t\t\t\t);\r\n\t\t\t\tdialog\r\n\t\t\t\t\t.querySelector(\".share-view-share.facebook\")\r\n\t\t\t\t\t.setAttribute(\"href\", \"https://www.facebook.com/sharer.php?u=\" + encodeURIComponent(sharedView.Link));\r\n\t\t\t\tdialog.querySelector(\"#ShareViewCopyLink\").setAttribute(\"data-share-view-id\", sharedView.Id);\r\n\t\t\t\tdialog.querySelector(\"#ShareViewCopyLink\").setAttribute(\"data-link\", sharedView.Link);\r\n\t\t\t\tdocument.getElementById(\"ShareViewCopyLinkLink\").textContent = sharedView.Link;\r\n\t\t\t\tdocument.getElementById(\"ShareViewCopyLinkLink\").href = sharedView.Link;\r\n\t\t\t}\r\n\t\t);\r\n\t});\r\n}\r\n\r\nexport function findSharedViewById(id) {\r\n\tvar item = _.find(trkData.sharedViews, { Id: parseInt(id) });\r\n\treturn item === undefined ? null : item;\r\n}\r\n\r\nexport function initializeSharedViewInformationDialog() {\r\n\tdomNodes.infoDialogs.sharedViewInformation.parentNode.classList.add(\"default-state\");\r\n\tlet $dialog = $(domNodes.infoDialogs.sharedViewInformation);\r\n\t$dialog.dialog(\"option\", \"title\", createDialogTitleFragment(strings.EDIT_MODE + \" - \" + strings.SHARED_VIEWS));\r\n\tvar dialogPanel = document.getElementById(\"dialog-shared-view-information\");\r\n\tvar dialogTitleName = dialogPanel.querySelector(\"div.ui-dialog-titlebar\");\r\n\r\n\tdialogTitleName.classList.add(\"has-svg-icon\");\r\n\tdialogTitleName.style.backgroundImage = null;\r\n\r\n\tdialogTitleName\r\n\t\t.querySelector(\"use\")\r\n\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", getSvgIconForItemType(\"shared-views\"));\r\n\tdialogTitleName\r\n\t\t.querySelector(\"svg\")\r\n\t\t.setAttribute(\"style\", \"color: #bbbbbb; --color-primary: #bbbbbb; --color-secondary: #bbbbbb\");\r\n}\r\n\r\nexport function deselectSharedView() {\r\n\tconsole.log(\"shared view de-selected. none active.\");\r\n\t_.each(domNodes.sharedViews, clearSettingsNode);\r\n\tdomNodes.panels.secondary.removeAttribute(\"data-chat-enabled\");\r\n\tclearSharedViewData(true);\r\n\ttrkData.sharedView.current = null;\r\n\ttrkData.sharedView.temp = null;\r\n\r\n\tinitializeSharedViewInformationDialog();\r\n\r\n\tvar $dialog = $(domNodes.infoDialogs.sharedViewInformation);\r\n\tif (!$dialog.dialog(\"isOpen\")) {\r\n\t\tmoveOrOpenDialogRelativeTo($dialog, map._container, \"center center\");\r\n\t\t$dialog.off(\"dialogclose\");\r\n\t}\r\n\r\n\t//$(domNodes.infoDialogs.sharedViewInformation).dialog('close');\r\n\t// resetting map type to prior\r\n\ttrkData.isSatelliteLabelOverlayEnabled = trkData.sharedView.priorIsSatelliteLabelOverlayEnabled;\r\n\tchangeMapType(trkData.sharedView.priorMapType);\r\n}\r\n\r\nexport function selectSharedView(sharedView) {\r\n\tif (sharedView === null) {\r\n\t\tdeselectSharedView();\r\n\t\treturn;\r\n\t}\r\n\r\n\tdomNodes.infoDialogs.sharedViewInformation.parentNode.classList.remove(\"default-state\");\r\n\r\n\tif (trkData.sharedView.current !== null) {\r\n\t\t// clear out previous shared view\r\n\t\tconsole.log(\"selected shared view changed?\"); // handled by other close callback?\r\n\t}\r\n\r\n\tif (trkData.sharedView.current === sharedView) {\r\n\t\t// nothing's changed\r\n\t\tconsole.log(\"selected shared view did not change.\");\r\n\t\treturn;\r\n\t}\r\n\r\n\t// deselect previous\r\n\t_.each(domNodes.sharedViews, clearSettingsNode);\r\n\tconsole.log(\"selected shared view changed\");\r\n\thighlightActiveItemInPrimaryPanel(\"shared-views\", sharedView.Id);\r\n\ttrkData.sharedView.current = sharedView;\r\n\tclearSharedViewData(true);\r\n\tquerySharedViewData(sharedView, null, false);\r\n\r\n\t// if secondary panel is opened, hide the sharedviewinformation dialog\r\n\tshowSharedViewInformationOnMap(sharedView, !state.openPanels.secondary);\r\n}\r\n\r\nfunction showSharedViewInformationOnMap(sharedView, doOpen) {\r\n\tif (sharedView === undefined || sharedView === null) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tdomNodes.infoDialogs.sharedViewInformation.parentNode.classList.remove(\"default-state\");\r\n\tvar dialog = domNodes.infoDialogs.sharedViewInformation;\r\n\tvar $dialog = $(dialog);\r\n\tvar content = populateSharedViewInformation(sharedView);\r\n\tcreateQuickActionsForSharedView(sharedView);\r\n\tdialog.setAttribute(\"data-shared-view-id\", sharedView.Id);\r\n\t$dialog.data.sharedViewId = sharedView.Id;\r\n\r\n\tvar contentArea = dialog.querySelector(\".content-selected\");\r\n\r\n\twhile (contentArea.firstChild) {\r\n\t\tcontentArea.removeChild(contentArea.firstChild);\r\n\t}\r\n\tcontentArea.appendChild(content);\r\n\r\n\t$dialog.dialog(\"option\", \"title\", createDialogTitleFragment(sharedView.Name, strings.SHARED_VIEWS));\r\n\tvar dialogPanel = document.getElementById(\"dialog-shared-view-information\");\r\n\tvar dialogTitleName = dialogPanel.querySelector(\"div.ui-dialog-titlebar\");\r\n\r\n\tdialogTitleName.classList.add(\"has-svg-icon\");\r\n\tdialogTitleName.style.backgroundImage = null;\r\n\r\n\tdialogTitleName\r\n\t\t.querySelector(\"use\")\r\n\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", getSvgIconForItemType(\"shared-views\", sharedView));\r\n\tdialogTitleName\r\n\t\t.querySelector(\"svg\")\r\n\t\t.setAttribute(\r\n\t\t\t\"style\",\r\n\t\t\t\"color: \" +\r\n\t\t\t\tsharedView.Color +\r\n\t\t\t\t\"; --color-primary: \" +\r\n\t\t\t\tsharedView.Color +\r\n\t\t\t\t\"; --color-secondary: \" +\r\n\t\t\t\tsharedView.Color\r\n\t\t);\r\n\r\n\tif (doOpen) {\r\n\t\tmoveOrOpenDialogRelativeTo($dialog, map._container, \"center center\");\r\n\t\t$dialog.unbind(\"dialogclose\");\r\n\t}\r\n}\r\n\r\nexport function clearSettingsNode(node) {\r\n\tif (node.classList.contains(\"settings-active\")) {\r\n\t\tnode.classList.remove(\"settings-active\");\r\n\t\tvar settingsIcon = node.querySelector(\".item-settings\");\r\n\t\tif (settingsIcon !== null) {\r\n\t\t\tvar use = settingsIcon.querySelector(\"use\");\r\n\t\t\tuse.setAttributeNS(\r\n\t\t\t\t\"http://www.w3.org/1999/xlink\",\r\n\t\t\t\t\"href\",\r\n\t\t\t\tuse.getAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\").replace(\"-solid\", \"\")\r\n\t\t\t);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport function clearSharedViewData(clearLimitedData) {\r\n\tconsole.log(\"clearSharedViewData\");\r\n\t_.each(trkData.sharedView.markers, function (item) {\r\n\t\tremoveItemFromMap(item, null, viewModes.SHARED_VIEW);\r\n\t});\r\n\t_.each(trkData.sharedView.mapLinesByAssetId, function (item) {\r\n\t\tremoveItemFromMap(item, null, viewModes.SHARED_VIEW);\r\n\t});\r\n\t_.each(trkData.sharedView.markerClustersByAssetId, function (item) {\r\n\t\tremoveItemFromMap(item, null, viewModes.SHARED_VIEW);\r\n\t});\r\n\t_.each(trkData.sharedView.fenceMarkers, function (item) {\r\n\t\tremoveItemFromMap(item, null, viewModes.SHARED_VIEW);\r\n\t});\r\n\t_.each(trkData.sharedView.placeMarkers, function (item) {\r\n\t\tremoveItemFromMap(item, null, viewModes.SHARED_VIEW);\r\n\t});\r\n\r\n\ttrkData.sharedView.markers = [];\r\n\ttrkData.sharedView.fenceMarkers = [];\r\n\ttrkData.sharedView.placeMarkers = [];\r\n\ttrkData.sharedView.events = [];\r\n\ttrkData.sharedView.normalizedEvents = [];\r\n\ttrkData.sharedView.isMessagesLoaded = false;\r\n\ttrkData.sharedView.normalizedMessages = [];\r\n\ttrkData.sharedView.normalizedEventIds = {};\r\n\ttrkData.sharedView.markerClustersByAssetId = {};\r\n\ttrkData.sharedView.mapLinesByAssetId = {};\r\n\ttrkData.sharedView.positionsByAssetId = {};\r\n\ttrkData.sharedView.markersByAssetId = {};\r\n\ttrkData.sharedView.normalizedPositions = [];\r\n\ttrkData.sharedView.normalizedPositionsByAssetId = {};\r\n\ttrkData.sharedView.messageCountsByAssetId = {};\r\n\ttrkData.sharedView.fromDate = null;\r\n\ttrkData.sharedView.toDate = null;\r\n\ttrkData.sharedView.isDateFiltered = false;\r\n\ttrkData.sharedView.isLimited = false;\r\n\ttrkData.sharedView.isLoadedLimitedData = false;\r\n\ttrkData.sharedView.messageCounts = {\r\n\t\tFromMobile: 0,\r\n\t\tToMobile: 0,\r\n\t\tFromMobileChats: 0,\r\n\t\tToMobileChats: 0,\r\n\t\tFromMobileDevice: 0,\r\n\t\tToMobileDevice: 0,\r\n\t};\r\n\tif (clearLimitedData) {\r\n\t\ttrkData.sharedView.limitedData = null;\r\n\t\tupdateMapModePanel();\r\n\t\tupdateActiveAssetInformation(viewModes.SHARED_VIEW);\r\n\t} else {\r\n\t\tshowResultLimitsIfApplicable({ IsLimited: false, IncludesLimitedData: false }, false);\r\n\t}\r\n}\r\n\r\nexport function querySharedViewData(sharedView, dateFilter, loadLimitedData) {\r\n\tconsole.log(\"query shared view\", sharedView);\r\n\tvar fromUtc = null;\r\n\tvar fromUtcEpoch = null;\r\n\tvar toUtc = null;\r\n\tvar toUtcEpoch = null;\r\n\r\n\t// override shared view's date ranges to show data that otherwise would exceed display limits\r\n\tvar isDateFiltered = false;\r\n\tif (dateFilter !== undefined && dateFilter !== null) {\r\n\t\tfromUtc = dateFilter.fromUtc;\r\n\t\ttoUtc = dateFilter.toUtc;\r\n\t\tisDateFiltered = true;\r\n\t} else {\r\n\t\tif (sharedView.IsTimeframeRelative) {\r\n\t\t\tvar momentType = sharedView.RelativeTimeframeType === \"m\" ? \"M\" : sharedView.RelativeTimeframeType;\r\n\t\t\tvar fromLocal = moment().subtract(sharedView.RelativeTimeframeNumber, momentType).subtract(user.tickOffset, \"ms\");\r\n\t\t\t//fromUtcEpoch = moment.utc()\r\n\t\t\tfromUtc = moment.utc().subtract(sharedView.RelativeTimeframeNumber, momentType).format(user.dateFormat);\r\n\t\t\tdocument.getElementById(\"txtDateFrom\").value = fromLocal.format(user.dateFormat); // utc to local\r\n\t\t\tdocument.getElementById(\"txtDateTo\").value = \"\";\r\n\t\t} else {\r\n\t\t\tif (sharedView.FromDateEpoch !== null) {\r\n\t\t\t\tvar fromLocal = moment(sharedView.FromDateEpoch);\r\n\t\t\t\tfromUtc = moment.utc(sharedView.FromDateEpoch).format(user.dateFormat);\r\n\t\t\t\tdocument.getElementById(\"txtDateFrom\").value = fromLocal\r\n\t\t\t\t\t.subtract(user.tickOffset, \"ms\")\r\n\t\t\t\t\t.format(user.dateFormat); // utc to local\r\n\t\t\t} else {\r\n\t\t\t\tdocument.getElementById(\"txtDateFrom\").value = \"\";\r\n\t\t\t}\r\n\t\t\tif (sharedView.ToDateEpoch !== null) {\r\n\t\t\t\tvar toLocal = moment(sharedView.ToDateEpoch);\r\n\t\t\t\ttoUtc = moment.utc(sharedView.ToDateEpoch).format(user.dateFormat);\r\n\t\t\t\tdocument.getElementById(\"txtDateTo\").value = toLocal.subtract(user.tickOffset, \"ms\").format(user.dateFormat); // utc to local\r\n\t\t\t} else {\r\n\t\t\t\tdocument.getElementById(\"txtDateTo\").value = \"\";\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tvar assetIds = sharedView.AssetIds.slice(0);\r\n\tvar assetGroupIds = sharedView.AssetGroupIds;\r\n\t_.each(assetGroupIds, function (assetGroupId) {\r\n\t\tvar group = findGroupById(assetGroupId);\r\n\t\tif (group !== null) {\r\n\t\t\tvar groupAssetIds = findAssetIdsUnderGroup(group);\r\n\t\t\tassetIds = assetIds.concat(groupAssetIds);\r\n\t\t}\r\n\t});\r\n\tvar sharedViewId = null;\r\n\tif (sharedView !== null) {\r\n\t\tsharedViewId = sharedView.Id;\r\n\t}\r\n\r\n\tvar data = {\r\n\t\tsharedViewId: sharedViewId,\r\n\t\tfromDate: fromUtc, // UTC\r\n\t\ttoDate: toUtc, // UTC\r\n\t\tisMessagingEnabled: sharedView.IsMessagingEnabled,\r\n\t\tassetIds: _.uniq(assetIds),\r\n\t\tloadLimitedData: loadLimitedData,\r\n\t\tisMobile: state.isMobile,\r\n\t\tformat: user.dateFormat,\r\n\t\tlang: user.dateCulture,\r\n\t};\r\n\r\n\t// set some dates in the map mode panel\r\n\ttrkData.sharedView.fromDate = fromUtc;\r\n\ttrkData.sharedView.toDate = toUtc;\r\n\r\n\treturn handleAjaxFormSubmission(\r\n\t\t\"GetSharedViewData\",\r\n\t\tdata,\r\n\t\tnull,\r\n\t\tnull,\r\n\t\tnull,\r\n\t\tstrings.MSG_QUERY_SHARED_VIEW_ERROR,\r\n\t\tfunction (result) {\r\n\t\t\tif (trkData.sharedView.current !== sharedView && trkData.sharedView.temp !== sharedView) {\r\n\t\t\t\t// if the results came back after the shared view has changed, discard them\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tif (result.IsLimited === true && result.IncludesLimitedData === false) {\r\n\t\t\t\tdocument.getElementById(\"txtDateFrom\").value = fromUtc; // isn't this utc?\r\n\t\t\t\tdocument.getElementById(\"txtDateTo\").value = toUtc; // isn't this utc?\r\n\t\t\t\tshowResultLimitsIfApplicable(result, false);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// clear previous results\r\n\t\t\tclearSharedViewData(!isDateFiltered); // TODO clear limitedData here under specific circumstances?\r\n\r\n\t\t\ttrkData.sharedView.isDateFiltered = isDateFiltered;\r\n\t\t\ttrkData.sharedView.isLimited = result.IsLimited;\r\n\t\t\ttrkData.sharedView.isLoadedLimitedData = result.IncludesLimitedData;\r\n\r\n\t\t\t_.each(result.Assets, function (assetResult) {\r\n\t\t\t\tprocessSharedViewData(sharedView.Id, assetResult, sharedView.Preferences.PositionConsolidation);\r\n\t\t\t});\r\n\r\n\t\t\ttrkData.sharedView.events = result.Events;\r\n\t\t\ttrkData.sharedView.messageCounts = {\r\n\t\t\t\tFromMobile: 0,\r\n\t\t\t\tFromMobileChats: 0,\r\n\t\t\t\tFromMobileDevice: 0,\r\n\t\t\t\tToMobile: 0,\r\n\t\t\t\tToMobileChats: 0,\r\n\t\t\t\tToMobileDevice: 0,\r\n\t\t\t};\r\n\r\n\t\t\t_.each(trkData.sharedView.messageCountsByAssetId, function (item) {\r\n\t\t\t\ttrkData.sharedView.messageCounts.FromMobile += item.FromMobile;\r\n\t\t\t\ttrkData.sharedView.messageCounts.FromMobileChats += item.FromMobileChats;\r\n\t\t\t\ttrkData.sharedView.messageCounts.FromMobileDevice += item.FromMobileDevice;\r\n\t\t\t\ttrkData.sharedView.messageCounts.ToMobile += item.ToMobile;\r\n\t\t\t\ttrkData.sharedView.messageCounts.ToMobileChats += item.ToMobileChats;\r\n\t\t\t\ttrkData.sharedView.messageCounts.ToMobileDevice += item.ToMobileDevice;\r\n\t\t\t});\r\n\r\n\t\t\tvar normalizedSharedViewEvents = [];\r\n\t\t\t_.each(result.Events, function (item) {\r\n\t\t\t\tif (trkData.sharedView.eventsById[item.Id] === undefined) {\r\n\t\t\t\t\ttrkData.sharedView.eventsById[item.Id] = normalizeAssetData(item.AssetId, \"event\", item);\r\n\t\t\t\t}\r\n\t\t\t\tnormalizedSharedViewEvents.push(trkData.sharedView.eventsById[item.Id]);\r\n\t\t\t\ttrkData.sharedView.normalizedEvents.push(trkData.sharedView.eventsById[item.Id]);\r\n\t\t\t\ttrkData.sharedView.normalizedEventIds[item.Id] = true;\r\n\t\t\t});\r\n\r\n\t\t\ttrkData.sharedView.normalizedEvents = normalizedSharedViewEvents;\r\n\r\n\t\t\t// data manipulation/loading completed by this step\r\n\r\n\t\t\t// add geofences and places\r\n\t\t\taddFenceAndPlaceMarkersToSharedView(sharedView.PlaceIds, sharedView.FenceIds);\r\n\r\n\t\t\t// map type\r\n\t\t\ttrkData.isSatelliteLabelOverlayEnabled = !sharedView.Preferences.RemoveRoads;\r\n\t\t\tchangeMapType(\r\n\t\t\t\t_.findKey(trkData.MAP_TYPES, function (item) {\r\n\t\t\t\t\treturn item === sharedView.Preferences.MapType;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tupdateAssetFunctionBadges(trkDataGroups.SHARED_VIEW_HISTORY, sharedView.Id);\r\n\t\t\tshowResultLimitsIfApplicable(result, isDateFiltered);\r\n\r\n\t\t\tif (\r\n\t\t\t\t(trkData.sharedView.isLimited && trkData.sharedView.isLoadedLimitedData) ||\r\n\t\t\t\ttrkData.sharedView.limitedData !== null\r\n\t\t\t) {\r\n\t\t\t\thandleLimitedDataResult(viewModes.SHARED_VIEW, fromUtc, toUtc, result.Counts, result.Limit);\r\n\t\t\t} else {\r\n\t\t\t\ttrkData.sharedView.limitedData = null;\r\n\t\t\t}\r\n\t\t\tupdateActiveAssetInformation(viewModes.SHARED_VIEW);\r\n\t\t\tupdateMapModeDateRange();\r\n\r\n\t\t\tresizeApp(true);\r\n\t\t\tsetMapBounds();\r\n\t\t}\r\n\t);\r\n}\r\n\r\nexport const throttledQuerySharedViewData = _.throttle(querySharedViewData, 250, { leading: false });\r\n\r\nfunction processSharedViewData(sharedViewId, data, clusterMarkers) {\r\n\t//console.log('processSharedViewData ' + sharedViewId + ', cluster? ' + clusterMarkers);\r\n\tvar asset = findAssetById(data.Id);\r\n\tif (asset === null) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar sharedView = findSharedViewById(sharedViewId);\r\n\r\n\t_.each(data.Positions, function (position) {\r\n\t\t// we probably shouldn't check data.positions\r\n\t\tif (trkData.sharedView.positionsById[position.Id] === undefined) {\r\n\t\t\ttrkData.sharedView.positionsById[position.Id] = normalizeAssetData(asset.Id, \"position\", position);\r\n\t\t}\r\n\r\n\t\tif (trkData.sharedView.normalizedPositionsByAssetId[asset.Id] === undefined) {\r\n\t\t\ttrkData.sharedView.normalizedPositionsByAssetId[asset.Id] = [];\r\n\t\t}\r\n\t\ttrkData.sharedView.normalizedPositionsByAssetId[asset.Id].push(trkData.sharedView.positionsById[position.Id]);\r\n\t\ttrkData.sharedView.normalizedPositions.push(trkData.sharedView.positionsById[position.Id]);\r\n\t});\r\n\r\n\ttrkData.sharedView.positionsByAssetId[asset.Id] = data;\r\n\r\n\tif (data.MessageCounts !== null) {\r\n\t\ttrkData.sharedView.messageCountsByAssetId[asset.Id] = data.MessageCounts;\r\n\t}\r\n\r\n\tvar visiblePositions = _.filter(data.Positions, function (item) {\r\n\t\treturn !item.IsHidden;\r\n\t});\r\n\tvar lastVisiblePositionId = null;\r\n\tvar firstVisiblePositionId = null;\r\n\tif (visiblePositions.length > 0) {\r\n\t\tlastVisiblePositionId = visiblePositions[0].Id;\r\n\t\tfirstVisiblePositionId = visiblePositions[visiblePositions.length - 1].Id;\r\n\t}\r\n\t//console.log('Asset ' + asset.Id + ' visible positions: ' + visiblePositions.length);\r\n\tif (data.Positions.length > 0) {\r\n\t\tif (clusterMarkers && trkData.sharedView.markerClustersByAssetId[asset.Id] === undefined) {\r\n\t\t\ttrkData.sharedView.markerClustersByAssetId[asset.Id] = createMarkerCluster(asset, null, sharedViewId);\r\n\t\t}\r\n\r\n\t\tlet alpha = 255;\r\n\t\tconst alphaIncrement = sharedView.Preferences.PositionAlpha\r\n\t\t\t? 185 / visiblePositions.length\r\n\t\t\t: 0;\r\n\t\t// positions are sorted from newest->last\r\n\t\tvar totalAssetPositions = visiblePositions.length;\r\n\t\tvar markersForCluster = [];\r\n\t\tfor (var j = 0; j < data.Positions.length; j++) {\r\n\t\t\t// add position to map and position filters\r\n\t\t\tvar position = data.Positions[j];\r\n\t\t\tvar isFirst = totalAssetPositions > 1 && position.Id === firstVisiblePositionId;\r\n\t\t\tvar isLast = totalAssetPositions > 1 && position.Id === lastVisiblePositionId;\r\n\t\t\tvar marker = addPositionMarkerToPoint(\r\n\t\t\t\t[position.Lat, position.Lng],\r\n\t\t\t\tfalse,\r\n\t\t\t\tposition,\r\n\t\t\t\tasset,\r\n\t\t\t\talpha,\r\n\t\t\t\tclusterMarkers,\r\n\t\t\t\tisFirst,\r\n\t\t\t\tisLast,\r\n\t\t\t\ttrkDataGroups.SHARED_VIEW_HISTORY,\r\n\t\t\t\tnull,\r\n\t\t\t\tsharedViewId\r\n\t\t\t);\r\n\t\t\tif (!position.IsHidden) {\r\n\t\t\t\tmarkersForCluster.push(marker);\r\n\t\t\t}\r\n\t\t\talpha -= alphaIncrement;\r\n\t\t}\r\n\r\n\t\ttrkData.sharedView.markersByAssetId = _.groupBy(trkData.sharedView.markers, function (marker) {\r\n\t\t\treturn marker.data.assetId;\r\n\t\t});\r\n\r\n\t\tif (clusterMarkers && trkData.sharedView.markerClustersByAssetId[asset.Id] !== undefined) {\r\n\t\t\ttrkData.sharedView.markerClustersByAssetId[asset.Id].empty();\r\n\t\t\ttrkData.sharedView.markerClustersByAssetId[asset.Id].multiAdd(markersForCluster);\r\n\t\t\taddItemToMap(trkData.sharedView.markerClustersByAssetId[asset.Id], null, viewModes.SHARED_VIEW);\r\n\t\t}\r\n\r\n\t\tcreatePositionLinesForAsset(asset, visiblePositions, viewModes.SHARED_VIEW);\r\n\t}\r\n}\r\n\r\nfunction addFenceAndPlaceMarkersToSharedView(placeIds, fenceIds) {\r\n\tvar fenceIdLookup = _.keyBy(fenceIds);\r\n\tvar placeIdLookup = _.keyBy(placeIds);\r\n\tvar fenceMarkers = _.filter(trkData.fenceMarkers, function (item) {\r\n\t\treturn fenceIdLookup[item.data.fenceId] !== undefined;\r\n\t});\r\n\tvar placeMarkers = _.filter(trkData.placeMarkers, function (item) {\r\n\t\treturn placeIdLookup[item.data.placeId] !== undefined;\r\n\t});\r\n\ttrkData.sharedView.fenceMarkers = fenceMarkers;\r\n\ttrkData.sharedView.placeMarkers = placeMarkers;\r\n\t_.each(fenceMarkers, function (item) {\r\n\t\taddItemToMap(item, null, viewModes.SHARED_VIEW);\r\n\t});\r\n\t_.each(placeMarkers, function (item) {\r\n\t\taddItemToMap(item, null, viewModes.SHARED_VIEW);\r\n\t});\r\n}\r\n\r\nexport function cloneSharedView(sharedView) {\r\n\tvar clonedPreferences = _.clone(sharedView.Preferences);\r\n\tvar cloned = _.clone(sharedView);\r\n\tcloned.Preferences = clonedPreferences;\r\n\treturn cloned;\r\n}\r\n\r\nfunction compareSharedViews(newView, oldView) {\r\n\tconsole.log(\"compareSharedViews\", newView, oldView);\r\n\t// first check all properties that would require a re-processing\r\n\tvar isReprocessing = false;\r\n\tvar changeMade = false;\r\n\tif (\r\n\t\tnewView.IsMessagingEnabled !== oldView.IsMessagingEnabled ||\r\n\t\tnewView.FromDateEpoch !== oldView.FromDateEpoch ||\r\n\t\tnewView.ToDateEpoch !== oldView.ToDateEpoch ||\r\n\t\t!_.isEqual(newView.AssetIds, oldView.AssetIds) ||\r\n\t\t!_.isEqual(newView.AssetGroupIds, oldView.AssetGroupIds) ||\r\n\t\tnewView.IsTimeframeRelative !== oldView.IsTimeframeRelative ||\r\n\t\tnewView.RelativeTimeframeNumber !== oldView.RelativeTimeframeNumber ||\r\n\t\tnewView.RelativeTimeframeType !== oldView.RelativeTimeframeType\r\n\t) {\r\n\t\tisReprocessing = true;\r\n\t\t//querySharedViewData(newView, null, false);\r\n\t\tthrottledQuerySharedViewData(newView, null, false);\r\n\t\tconsole.log(\"change made\");\r\n\t\treturn;\r\n\t}\r\n\r\n\t// add/remove fences/places\r\n\tif (!_.isEqual(newView.FenceIds, oldView.FenceIds) || !_.isEqual(newView.PlaceIds, oldView.PlaceIds)) {\r\n\t\t_.each(trkData.sharedView.fenceMarkers, function (item) {\r\n\t\t\tremoveItemFromMap(item, null, viewModes.SHARED_VIEW);\r\n\t\t});\r\n\t\t_.each(trkData.sharedView.placeMarkers, function (item) {\r\n\t\t\tremoveItemFromMap(item, null, viewModes.SHARED_VIEW);\r\n\t\t});\r\n\t\taddFenceAndPlaceMarkersToSharedView(newView.PlaceIds, newView.FenceIds);\r\n\t\tchangeMade = true;\r\n\t}\r\n\r\n\t// all properties that can just be modified on the view go here\r\n\tif (\r\n\t\tnewView.Preferences.MapType !== oldView.Preferences.MapType ||\r\n\t\tnewView.Preferences.RemoveRoads !== oldView.Preferences.RemoveRoads\r\n\t) {\r\n\t\ttrkData.isSatelliteLabelOverlayEnabled = !newView.Preferences.RemoveRoads;\r\n\t\tchangeMapType(\r\n\t\t\t_.findKey(trkData.MAP_TYPES, function (item) {\r\n\t\t\t\treturn item === newView.Preferences.MapType;\r\n\t\t\t})\r\n\t\t);\r\n\t\tchangeMade = true;\r\n\t}\r\n\r\n\tif (newView.Preferences.PositionConsolidation !== oldView.Preferences.PositionConsolidation) {\r\n\t\tif (!newView.Preferences.PositionConsolidation) {\r\n\t\t\t// remove clusters and show visible markers\r\n\t\t\t_.each(trkData.sharedView.markerClustersByAssetId, function (item) {\r\n\t\t\t\titem.empty();\r\n\t\t\t});\r\n\t\t\t_.each(trkData.sharedView.markers, function (item) {\r\n\t\t\t\tif (!item.data.isHidden) {\r\n\t\t\t\t\taddItemToMap(item, null, viewModes.SHARED_VIEW);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t} else {\r\n\t\t\t// remove visible markers, adding them to appropriate clusters (were they ever created?)\r\n\t\t\t_.each(trkData.sharedView.markersByAssetId, function (item, assetId) {\r\n\t\t\t\t_.each(item, function (marker) {\r\n\t\t\t\t\tremoveItemFromMap(marker, null, viewModes.SHARED_VIEW);\r\n\t\t\t\t});\r\n\r\n\t\t\t\tif (trkData.sharedView.markerClustersByAssetId[assetId] === undefined) {\r\n\t\t\t\t\tvar asset = findAssetById(assetId);\r\n\t\t\t\t\ttrkData.sharedView.markerClustersByAssetId[assetId] = createMarkerCluster(asset, null, newView.Id);\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttrkData.sharedView.markerClustersByAssetId[assetId].empty();\r\n\t\t\t\ttrkData.sharedView.markerClustersByAssetId[assetId].multiAdd(item);\r\n\t\t\t\taddItemToMap(trkData.sharedView.markerClustersByAssetId[assetId], null, viewModes.SHARED_VIEW);\r\n\t\t\t});\r\n\t\t}\r\n\t\tchangeMade = true;\r\n\t}\r\n\r\n\tif (changeMade) {\r\n\t\tconsole.log(\"changes made\");\r\n\t}\r\n}\r\n\r\nexport function getSharedViewLink(sharedView) {\r\n\t// TODO remove this method\r\n\treturn window.location.protocol + \"//\" + window.location.host + \"/s/\" + sharedView.UniqueKey;\r\n}\r\n\r\nfunction updateSharedView(sharedView) {\r\n\tvar oldSharedView = findSharedViewById(sharedView.Id);\r\n\tfor (var i = 0; i < trkData.sharedViews.length; i++) {\r\n\t\tif (trkData.sharedViews[i].Id == sharedView.Id) {\r\n\t\t\ttrkData.sharedViews.splice(i, 1, sharedView);\r\n\t\t}\r\n\t}\r\n\r\n\tvar li = domNodes.sharedViews[sharedView.Id];\r\n\tif (li !== undefined) {\r\n\t\tvar name = li.querySelector(\".shared-view-name\");\r\n\t\tname.textContent = sharedView.Name;\r\n\t\tvar description = li.querySelector(\".shared-view-description\");\r\n\t\tdescription.textContent = getSharedViewNodeDescription(sharedView);\r\n\t}\r\n\r\n\tsharedView.ColorSorted = convertHexToSortable(convertNamedColorToHex(sharedView.Color));\r\n\tsharedView.Link = getSharedViewLink(sharedView); // TODO remove this\r\n\tif (oldSharedView.Color !== sharedView.Color || oldSharedView.IsEnabled !== sharedView.IsEnabled) {\r\n\t\tupdateSharedViewListingIcon(sharedView);\r\n\t}\r\n\t// TODO title and icon of secondary panel, if open, applies to all item types too\r\n\r\n\t// update options panel if opened\r\n\tif (\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-group-for\") === \"shared-views\" &&\r\n\t\tparseInt(domNodes.panels.secondary.getAttribute(\"data-item-id\")) === sharedView.Id\r\n\t) {\r\n\t\topenSharedViewSettingsPanel(sharedView);\r\n\t}\r\n\r\n\tresortItemGroup(\"all-shared-views\");\r\n\tindexSharedViewsForSearch();\r\n}\r\n\r\nfunction getSharedViewNodeDescription(sharedView) {\r\n\tvar description = strings.ALL_TIME;\r\n\tif (sharedView.FromDateEpoch !== null || sharedView.ToDateEpoch !== null) {\r\n\t\tvar from = moment(sharedView.FromDateEpoch);\r\n\t\tvar to = moment(sharedView.ToDateEpoch);\r\n\t\tif (from.isValid() && to.isValid()) {\r\n\t\t\tdescription = from.format(user.shortDateFormat) + \" - \" + to.format(user.shortDateFormat);\r\n\t\t} else if (from.isValid()) {\r\n\t\t\tdescription = from.format(user.shortDateFormat) + \" - \";\r\n\t\t} else if (to.isValid()) {\r\n\t\t\tdescription = \" - \" + to.format(user.shortDateFormat);\r\n\t\t}\r\n\t} else if (sharedView.IsTimeframeRelative === true) {\r\n\t\tvar timeFrames = {\r\n\t\t\t\"h\": strings.HOURS,\r\n\t\t\t\"m\": strings.MONTHS,\r\n\t\t\t\"d\": strings.DAYS,\r\n\t\t\t\"w\": strings.WEEKS,\r\n\t\t};\r\n\t\tdescription = sharedView.RelativeTimeframeNumber + \" \" + timeFrames[sharedView.RelativeTimeframeType];\r\n\t}\r\n\treturn description;\r\n}\r\n\r\nexport function createSharedViewNode(sharedView) {\r\n\tif (sharedView === undefined || sharedView === null) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tvar color = getItemHexColor(sharedView);\r\n\tvar description = getSharedViewNodeDescription(sharedView);\r\n\tvar imagePath = createMarkerPath(\"SharedView\", color, null, null, null, false);\r\n\tvar sharedViewDto = {\r\n\t\tid: sharedView.Id,\r\n\t\tname: sharedView.Name,\r\n\t\tcolor: sharedView.Color,\r\n\t\tdescription: description,\r\n\t\ticon: imagePath,\r\n\t\tvisibilityClass: sharedView.IsEnabled ? \"active\" : \"disabled\",\r\n\t};\r\n\tvar fragment = templates.sharedView(sharedViewDto);\r\n\treturn fragment.childNodes[0];\r\n}\r\n\r\nexport function checkForShareViewChange(sharedView, wasEditing) {\r\n\treturn function () {\r\n\t\tconsole.log(\"checkForShareViewChange - dialog closed\", wasEditing, sharedView);\r\n\t\tvar currentSharedViewId = domNodes.panels.secondary.getAttribute(\"data-item-id\");\r\n\t\tif (wasEditing === true && trkData.sharedView.temp !== null && trkData.sharedView.current !== null) {\r\n\t\t\t// closed out of editing\r\n\t\t\tconsole.log(\"- canceled shared view temp edit\");\r\n\t\t\tcompareSharedViews(trkData.sharedView.current, trkData.sharedView.temp);\r\n\t\t\ttrkData.sharedView.temp = null;\r\n\t\t\t// may have also closed secondary panel\r\n\t\t} else if (wasEditing === true && trkData.sharedView.temp !== null) {\r\n\t\t\tconsole.log(\"- canceled out of new shared view\");\r\n\t\t\tdeselectSharedView();\r\n\t\t} else if (currentSharedViewId !== null) {\r\n\t\t\tvar newSharedViewId = parseInt(currentSharedViewId);\r\n\t\t\tif (\r\n\t\t\t\t(sharedView === null && currentSharedViewId === null) ||\r\n\t\t\t\t(sharedView !== null && newSharedViewId !== sharedView.Id)\r\n\t\t\t) {\r\n\t\t\t\tconsole.log(\"- change in shared view\", newSharedViewId, sharedView.Id);\r\n\t\t\t\tclearSharedViewData(true);\r\n\t\t\t\ttrkData.sharedView.current = null;\r\n\t\t\t\t$(domNodes.infoDialogs.sharedViewInformation).dialog(\"close\");\r\n\t\t\t\tif (newSharedViewId === null) {\r\n\t\t\t\t\t// resetting map type to prior\r\n\t\t\t\t\ttrkData.isSatelliteLabelOverlayEnabled = trkData.sharedView.priorIsSatelliteLabelOverlayEnabled;\r\n\t\t\t\t\tchangeMapType(trkData.sharedView.priorMapType);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tconsole.log(\"- no change in shared view\");\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (currentSharedViewId === null) {\r\n\t\t\t// user has closed secondary panel.. re-show shared view information\r\n\t\t\tconsole.log(\"- reshow shared view info\");\r\n\t\t\tshowSharedViewInformationOnMap(trkData.sharedView.current, true);\r\n\t\t}\r\n\t};\r\n}\r\n\r\nfunction addSharedView(sharedView, groupId) {\r\n\tsharedView.ColorSorted = convertHexToSortable(sharedView.Color);\r\n\tsharedView.Link = getSharedViewLink(sharedView); // TODO remove this\r\n\ttrkData.sharedViews.push(sharedView);\r\n\r\n\tvar group = findGroupById(groupId);\r\n\tif (group === null) {\r\n\t\tgroupId = \"all-shared-views\";\r\n\t}\r\n\r\n\tvar itemNode = createSharedViewNode(sharedView);\r\n\tdomNodes.sharedViews[sharedView.Id] = itemNode;\r\n\tvar groupContentsNode = domNodes.groupContents[groupId].querySelector(\"ul.group-list-list\");\r\n\r\n\tvar groupItems = sortItemsByMode(\"shared-views\", trkData.sharedViews, groupId, \"shared-views\");\r\n\r\n\t// add it where it belongs instead of at the end\r\n\tif (groupItems.length > 1) {\r\n\t\tvar itemIndex = _.indexOf(groupItems, sharedView);\r\n\t\tvar subgroups = group !== null ? group.GroupIds.length : 0;\r\n\t\tgroupContentsNode.insertBefore(itemNode, groupContentsNode.children[itemIndex + subgroups + 1]); // +1 due to the no-items first node\r\n\t} else {\r\n\t\tgroupContentsNode.appendChild(itemNode);\r\n\t}\r\n\r\n\tupdateGroupVisibilityStatus(groupId);\r\n\ttoggleItemSorting(\"shared-views\", user.displayPreferences.sortMode[\"shared-views\"] === sortModes.CUSTOM);\r\n\tdocument.getElementById(\"no-shared-views\").classList.remove(\"is-visible\");\r\n\tdocument.getElementById(\"shared-views-all\").classList.add(\"is-visible\");\r\n\tdocument.getElementById(\"filter-shared-views\").querySelector(\".filter-box\").classList.add(\"is-visible\");\r\n\tgroupContentsNode.querySelector(\".no-items\").classList.remove(\"is-visible\");\r\n}\r\n\r\nexport function querySharedViewInvites(sharedView) {\r\n\t// get existing invites list\r\n\t// maybe only if not already loaded?\r\n\tvar data = {\r\n\t\tid: sharedView.Id,\r\n\t};\r\n\r\n\tvar itemList = document.getElementById(\"shared-with-items\");\r\n\titemList.setAttribute(\"data-shared-view-id\", sharedView.Id);\r\n\t// clear previous data\r\n\twhile (itemList.firstChild) {\r\n\t\titemList.removeChild(itemList.firstChild);\r\n\t}\r\n\treturn handleAjaxFormSubmission(\r\n\t\t\"GetSharedViewInvites\",\r\n\t\tdata,\r\n\t\tnull,\r\n\t\tnull,\r\n\t\tnull,\r\n\t\tstrings.MSG_GET_SHARED_VIEW_INVITES_ERROR,\r\n\t\tfunction (result) {\r\n\t\t\tif (parseInt(itemList.getAttribute(\"data-shared-view-id\")) !== sharedView.Id) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tvar items = document.createDocumentFragment();\r\n\t\t\tif (result.Invites.length === 0) {\r\n\t\t\t\tdocument.getElementById(\"shared-with-none\").classList.add(\"is-visible\");\r\n\t\t\t} else {\r\n\t\t\t\tdocument.getElementById(\"shared-with-none\").classList.remove(\"is-visible\");\r\n\t\t\t}\r\n\t\t\t_.each(result.Invites, function (invite) {\r\n\t\t\t\tvar li = document.createElement(\"li\");\r\n\t\t\t\tli.className = \"list-group-item\";\r\n\t\t\t\tvar head = document.createElement(\"div\");\r\n\t\t\t\thead.className = \"list-group-item-header\";\r\n\t\t\t\tvar email = document.createElement(\"a\");\r\n\t\t\t\temail.href = \"mailto:\" + invite.Email;\r\n\t\t\t\temail.textContent = invite.Email;\r\n\t\t\t\tvar time = document.createElement(\"span\");\r\n\t\t\t\ttime.textContent = invite.SharedOn;\r\n\r\n\t\t\t\thead.appendChild(email);\r\n\t\t\t\thead.appendChild(time);\r\n\t\t\t\tli.appendChild(head);\r\n\r\n\t\t\t\tvar link = document.createElement(\"a\");\r\n\t\t\t\tlink.href = sharedView.Link + \"/\" + invite.UniqueKey;\r\n\t\t\t\tlink.textContent = sharedView.Link + \"/\" + invite.UniqueKey;\r\n\t\t\t\tlink.setAttribute(\"target\", \"_blank\");\r\n\t\t\t\tlink.setAttribute(\"rel\", \"nofollow\");\r\n\t\t\t\tli.appendChild(link);\r\n\t\t\t\titems.appendChild(li);\r\n\t\t\t});\r\n\t\t\titemList.appendChild(items);\r\n\t\t}\r\n\t);\r\n}\r\n\r\nfunction updateSharedViewListingIcon(sharedView) {\r\n\tvar color = getItemHexColor(sharedView);\r\n\tvar isActive = sharedView.IsEnabled;\r\n\tvar svgIcon = getSvgIconForItemType(\"shared-views\", sharedView);\r\n\tvar items = domNodes.sharedViews[sharedView.Id];\r\n\tif (!_.isArray(items)) {\r\n\t\titems = [items];\r\n\t}\r\n\t_.each(items, function (itemNode) {\r\n\t\tif (isActive) {\r\n\t\t\titemNode.classList.remove(\"disabled\");\r\n\t\t\titemNode.classList.add(\"active\");\r\n\t\t} else {\r\n\t\t\titemNode.classList.add(\"disabled\");\r\n\t\t\titemNode.classList.remove(\"active\");\r\n\t\t}\r\n\t\tvar itemIcon = itemNode.querySelector(\".list-item-icon\");\r\n\t\titemIcon.querySelector(\"use\").setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", svgIcon);\r\n\t\titemIcon.style[\"color\"] = color;\r\n\t});\r\n}\r\n\r\nexport function indexSharedViewsForSearch() {\r\n\ttrkData.search.sharedViews = new JsSearch.Search(\"Id\");\r\n\ttrkData.search.sharedViews.indexStrategy = new JsSearch.AllSubstringsIndexStrategy();\r\n\tvar attributes = [\"Name\", \"Description\", \"UniqueKey\"];\r\n\t// todo: asset or group names?\r\n\t_.each(attributes, function (attribute) {\r\n\t\ttrkData.search.sharedViews.addIndex(attribute);\r\n\t});\r\n\ttrkData.search.sharedViews.addDocuments(trkData.sharedViews);\r\n\tlog(\"Shared Views indexed for search filtering.\");\r\n}\r\n\r\nexport function changeSharedViewStatus(sharedView) {\r\n\tvar data = {\r\n\t\tid: sharedView.Id,\r\n\t\tisEnabled: !sharedView.IsEnabled,\r\n\t};\r\n\r\n\thandleAjaxFormSubmission(\r\n\t\t\"ChangeSharedViewStatus\",\r\n\t\tdata,\r\n\t\tnull,\r\n\t\tnull,\r\n\t\tstrings.MSG_EDIT_SHARED_VIEW_SUCCESS,\r\n\t\tstrings.MSG_EDIT_SHARED_VIEW_ERROR,\r\n\t\tfunction (result) {\r\n\t\t\tupdateSharedView(result.SharedView);\r\n\t\t\tshowSharedViewInformationOnMap(result.SharedView, !state.openPanels.secondary);\r\n\t\t}\r\n\t);\r\n}\r\n","// Sorts DOM structures.\r\n// Applies to list of assets, places or fences.\r\n\r\nimport user, { saveDisplayPreferences } from \"./user.js\";\r\nimport { language, sortModes, sortDirections } from \"./const.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport trkData from \"./data.js\";\r\nimport { findDeviceById } from \"./devices.js\";\r\nimport { findSharedViewById } from \"./shared-view.js\";\r\nimport { findGroupById } from \"./asset-group.js\";\r\nimport { findAssetById } from \"./assets.js\";\r\nimport { findFenceById } from \"./fence.js\";\r\nimport { findPlaceById } from \"./place.js\";\r\n\r\nimport _ from \"lodash\";\r\n\r\nexport function sortByName(a, b) {\r\n\t// if .localeCompare is not available?\r\n\treturn a.Name.localeCompare(b.Name, language);\r\n}\r\n\r\nfunction sortByColorAndName(a, b) {\r\n\t// color\r\n\tif (a.ColorSorted !== undefined && b.ColorSorted !== undefined) {\r\n\t\tif (a.ColorSorted.h < b.ColorSorted.h) {\r\n\t\t\treturn -1;\r\n\t\t} else if (a.ColorSorted.h > b.ColorSorted.h) {\r\n\t\t\treturn 1;\r\n\t\t} else if (a.ColorSorted.lum < b.ColorSorted.lum) {\r\n\t\t\treturn -1;\r\n\t\t} else if (a.ColorSorted.lum > b.ColorSorted.lum) {\r\n\t\t\treturn 1;\r\n\t\t} else if (a.ColorSorted.l < b.ColorSorted.l) {\r\n\t\t\treturn -1;\r\n\t\t} else if (a.ColorSorted.l > b.ColorSorted.l) {\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t}\r\n\r\n\t// name\r\n\treturn sortByName(a, b);\r\n}\r\n\r\nfunction sortBySortOrderAndName(items, sortOrders) {\r\n\treturn items.sort(function (a, b) {\r\n\t\tvar aIndex = sortOrders.indexOf(a.Id);\r\n\t\tif (aIndex === -1) {\r\n\t\t\taIndex = 99999;\r\n\t\t}\r\n\t\tvar bIndex = sortOrders.indexOf(b.Id);\r\n\t\tif (bIndex === -1) {\r\n\t\t\tbIndex = 99999;\r\n\t\t}\r\n\t\tif (aIndex < bIndex) {\r\n\t\t\treturn -1;\r\n\t\t} else if (aIndex > bIndex) {\r\n\t\t\treturn 1;\r\n\t\t}\r\n\r\n\t\treturn sortByName(a, b);\r\n\t});\r\n}\r\n\r\nfunction sortItemsWithDirection(items, sortFunction, sortDirection) {\r\n\tif (sortDirection === undefined || sortDirection === sortDirections.ASC) {\r\n\t\treturn items.sort(function (a, b) {\r\n\t\t\treturn sortFunction(a, b);\r\n\t\t});\r\n\t} else {\r\n\t\treturn items.sort(function (a, b) {\r\n\t\t\treturn sortFunction(b, a);\r\n\t\t});\r\n\t}\r\n}\r\n\r\nfunction sortByManufacturer(a, b) {\r\n\tvar aDevice = findDeviceById(a.DeviceId);\r\n\tvar bDevice = findDeviceById(b.DeviceId);\r\n\tvar manufacturerSort = aDevice.Manufacturer.localeCompare(bDevice.Manufacturer, language);\r\n\tif (manufacturerSort === 0) {\r\n\t\treturn sortByName(a, b);\r\n\t}\r\n\treturn manufacturerSort;\r\n}\r\n\r\nfunction sortByDeviceType(a, b) {\r\n\tvar aDevice = findDeviceById(a.DeviceId);\r\n\tvar bDevice = findDeviceById(b.DeviceId);\r\n\tvar deviceSort = aDevice.Name.localeCompare(bDevice.Name, language);\r\n\tif (deviceSort === 0) {\r\n\t\treturn sortByName(a, b);\r\n\t}\r\n\treturn deviceSort;\r\n}\r\n\r\nexport function sortItemsByMode(modeType, items, parentGroupId, itemType) {\r\n\tvar mode = user.displayPreferences.sortMode[modeType];\r\n\tvar direction = user.displayPreferences.sortDirection[modeType];\r\n\tswitch (mode) {\r\n\t\tcase sortModes.COLOR:\r\n\t\t\treturn sortItemsWithDirection(items, sortByColorAndName, direction);\r\n\t\tcase sortModes.CUSTOM:\r\n\t\t\tvar itemSortOrders = user.displayPreferences.customSort[parentGroupId + \"-\" + itemType];\r\n\t\t\tif (itemSortOrders !== undefined) {\r\n\t\t\t\treturn sortBySortOrderAndName(items, itemSortOrders);\r\n\t\t\t} else {\r\n\t\t\t\treturn items.sort(sortByName);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase sortModes.MANUFACTURER:\r\n\t\t\tif (itemType === \"assets\") {\r\n\t\t\t\treturn sortItemsWithDirection(items, sortByManufacturer, direction);\r\n\t\t\t} else {\r\n\t\t\t\treturn sortItemsWithDirection(items, sortByName, direction);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase sortModes.DEVICE_TYPE:\r\n\t\t\tif (itemType === \"assets\") {\r\n\t\t\t\treturn sortItemsWithDirection(items, sortByDeviceType, direction);\r\n\t\t\t} else {\r\n\t\t\t\treturn sortItemsWithDirection(items, sortByName, direction);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase sortModes.ALPHABETICAL:\r\n\t\tdefault:\r\n\t\t\treturn sortItemsWithDirection(items, sortByName, direction);\r\n\t}\r\n}\r\n\r\nexport function saveItemCustomSortOrder() {\r\n\tvar customSortOrder = {};\r\n\r\n\tvar groupIds = _.map(trkData.groups, \"Id\");\r\n\r\n\tvar panelTypes = [\"assets\", \"places\", \"fences\"];\r\n\t_.each(panelTypes, function (panelType) {\r\n\t\tcustomSortOrder[panelType + \"-root-groups\"] = [];\r\n\t\tvar rootNode = document.getElementById(panelType + \"-all\");\r\n\t\tfor (var i = 0; i < rootNode.childNodes.length; i++) {\r\n\t\t\tvar groupId = rootNode.childNodes[i].id.substring(6);\r\n\t\t\tcustomSortOrder[panelType + \"-root-groups\"].push(groupId);\r\n\t\t}\r\n\t\tgroupIds.push(\"all-\" + panelType);\r\n\t});\r\n\r\n\t_.each(groupIds, function (groupId) {\r\n\t\tvar groupContents = domNodes.groupContents[groupId];\r\n\t\tcustomSortOrder[groupId + \"-groups\"] = [];\r\n\t\tcustomSortOrder[groupId + \"-assets\"] = [];\r\n\t\tcustomSortOrder[groupId + \"-places\"] = [];\r\n\t\tcustomSortOrder[groupId + \"-fences\"] = [];\r\n\t\tvar groupList = _.find(groupContents.childNodes, function (node) {\r\n\t\t\treturn node.classList !== undefined && node.classList.contains(\"group-list-list\");\r\n\t\t});\r\n\t\tif (groupList === undefined) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tvar groupNodes = _.filter(groupList.childNodes, function (node) {\r\n\t\t\treturn node.classList !== undefined && node.classList.contains(\"group\");\r\n\t\t});\r\n\t\tvar assetNodes = _.filter(groupList.childNodes, function (node) {\r\n\t\t\treturn node.classList !== undefined && node.classList.contains(\"assets-item\");\r\n\t\t});\r\n\t\tvar placeNodes = _.filter(groupList.childNodes, function (node) {\r\n\t\t\treturn node.classList !== undefined && node.classList.contains(\"places-item\");\r\n\t\t});\r\n\t\tvar fenceNodes = _.filter(groupList.childNodes, function (node) {\r\n\t\t\treturn node.classList !== undefined && node.classList.contains(\"fences-item\");\r\n\t\t});\r\n\r\n\t\t_.each(groupNodes, function (node, index) {\r\n\t\t\tvar id = node.getAttribute(\"data-group-id\");\r\n\t\t\tcustomSortOrder[groupId + \"-groups\"].splice(index, 0, id);\r\n\t\t});\r\n\r\n\t\t_.each(assetNodes, function (node, index) {\r\n\t\t\tvar id = parseInt(node.getAttribute(\"data-asset-id\"));\r\n\t\t\tcustomSortOrder[groupId + \"-assets\"].splice(index, 0, id);\r\n\t\t});\r\n\r\n\t\t_.each(placeNodes, function (node, index) {\r\n\t\t\tvar id = parseInt(node.getAttribute(\"data-place-id\"));\r\n\t\t\tcustomSortOrder[groupId + \"-places\"].splice(index, 0, id);\r\n\t\t});\r\n\r\n\t\t_.each(fenceNodes, function (node, index) {\r\n\t\t\tvar id = node.getAttribute(\"data-fence-id\");\r\n\t\t\tcustomSortOrder[groupId + \"-fences\"].splice(index, 0, id);\r\n\t\t});\r\n\t});\r\n\r\n\tuser.displayPreferences.customSort = customSortOrder;\r\n\tsaveDisplayPreferences();\r\n}\r\n\r\nexport function toggleItemSorting(type, isEnabled) {\r\n\t// enable/disable custom item sorting for the passed item type\r\n\t// todo: lookup the current state of sorting enabled\r\n\t// and do nothing if it has not changed\r\n\r\n\t_.each(domNodes.groups, function (itemNode) {\r\n\t\tif (itemNode.dataset.groupFor !== type) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tvar dragNode = itemNode.querySelector(\".group-drag\");\r\n\t\tif (isEnabled) {\r\n\t\t\tdragNode.classList.remove(\"disabled\");\r\n\t\t\tdragNode.parentNode.classList.add(\"drag-enabled\");\r\n\t\t} else {\r\n\t\t\tdragNode.classList.add(\"disabled\");\r\n\t\t\tdragNode.parentNode.classList.remove(\"drag-enabled\");\r\n\t\t}\r\n\t});\r\n\r\n\t_.each(domNodes[type], function (typeNodes) {\r\n\t\t// assets, places and fences are arrays since they can be in multiple groups\r\n\t\tif (!_.isArray(typeNodes)) {\r\n\t\t\ttypeNodes = [typeNodes];\r\n\t\t}\r\n\t\t_.each(typeNodes, function (itemNode) {\r\n\t\t\tvar dragNode = itemNode.querySelector(\".item-drag\");\r\n\t\t\tif (isEnabled) {\r\n\t\t\t\tdragNode.classList.remove(\"disabled\");\r\n\t\t\t\tdragNode.parentNode.classList.add(\"drag-enabled\");\r\n\t\t\t} else {\r\n\t\t\t\tdragNode.classList.add(\"disabled\");\r\n\t\t\t\tdragNode.parentNode.classList.remove(\"drag-enabled\");\r\n\t\t\t}\r\n\t\t});\r\n\t});\r\n}\r\n\r\nexport function sortModeUpdated(typeUpdated) {\r\n\tvar types = [\"assets\", \"places\", \"fences\"];\r\n\tif (typeUpdated !== undefined) {\r\n\t\ttypes = [typeUpdated];\r\n\t}\r\n\r\n\t_.each(types, function (itemType) {\r\n\t\tvar list = document.getElementById(itemType + \"-filter-options-list\");\r\n\t\tvar listOptions = list.querySelectorAll('.dropdown-item[data-option-type=\"sorting\"]');\r\n\t\t_.each(listOptions, function (option) {\r\n\t\t\tvar sortMode = parseInt(option.getAttribute(\"data-sort\"));\r\n\t\t\tif (sortMode !== user.displayPreferences.sortMode[itemType]) {\r\n\t\t\t\toption.classList.remove(\"active\");\r\n\t\t\t\toption.classList.remove(\"sort-asc\");\r\n\t\t\t\toption.classList.remove(\"sort-desc\");\r\n\t\t\t} else {\r\n\t\t\t\toption.classList.add(\"active\");\r\n\t\t\t\toption.classList.remove(\"sort-asc\");\r\n\t\t\t\toption.classList.remove(\"sort-desc\");\r\n\t\t\t\tif (user.displayPreferences.sortDirection[itemType] === sortDirections.ASC) {\r\n\t\t\t\t\toption.classList.add(\"sort-asc\");\r\n\t\t\t\t} else {\r\n\t\t\t\t\toption.classList.add(\"sort-desc\");\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\t//var isSortingEnabled = user.displayPreferences.sortMode.assets === sortModes.ALPHABETICAL\r\n\t\t// || user.displayPreferences.sortMode.assets === sortModes.CUSTOM;\r\n\t\tvar isSortingEnabled = user.displayPreferences.sortMode[itemType] === sortModes.CUSTOM;\r\n\t\ttoggleItemSorting(itemType, isSortingEnabled);\r\n\t});\r\n}\r\n\r\nexport function changeItemSort(type, newMode) {\r\n\tvar currentMode = user.displayPreferences.sortMode[type];\r\n\tvar currentDirection = user.displayPreferences.sortDirection[type];\r\n\tif (newMode === currentMode) {\r\n\t\t// toggle the sort direction, if possible (currently everything except custom)\r\n\t\tif (currentMode === sortModes.CUSTOM) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (currentDirection === sortDirections.ASC) {\r\n\t\t\tuser.displayPreferences.sortDirection[type] = sortDirections.DESC;\r\n\t\t} else {\r\n\t\t\tuser.displayPreferences.sortDirection[type] = sortDirections.ASC;\r\n\t\t}\r\n\t} else {\r\n\t\t// always start ascending in new mode\r\n\t\tuser.displayPreferences.sortDirection[type] = sortDirections.ASC;\r\n\t}\r\n\tuser.displayPreferences.sortMode[type] = newMode;\r\n\tsortModeUpdated(type);\r\n\r\n\tresortItemGroup(\"all-\" + type);\r\n\r\n\tvar allGroups = type === \"assets\" ? trkData.groups :\r\n\t\ttype === \"places\" ? trkData.placeGroups :\r\n\t\ttype === \"fences\" ? trkData.fenceGroups : null;\r\n\r\n\tif (allGroups) {\r\n\t\t// sort items in groups - currently asset specific\r\n\t\t_.each(allGroups, function (group) {\r\n\t\t\tresortItemGroup(group.Id);\r\n\t\t});\r\n\r\n\t\t// sort root groups - currently asset specific\r\n\t\tvar rootGroups = _.filter(allGroups, function (group) {\r\n\t\t\treturn !group.ParentGroupId;\r\n\t\t});\r\n\t\tvar sortedRootGroups = sortItemsByMode(type, rootGroups, type + \"-root\", \"groups\");\r\n\t\t_.each(sortedRootGroups, function (group) {\r\n\t\t\t// root group should always be attached to parent node for this to work\r\n\t\t\tdomNodes.groups[group.Id].parentNode.appendChild(domNodes.groups[group.Id]);\r\n\t\t});\r\n\t}\r\n\tsaveDisplayPreferences();\r\n}\r\n\r\nexport function resortItemGroup(groupId) {\r\n\tvar groupContents = domNodes.groupContents[groupId];\r\n\tif (groupContents === undefined) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar groupList = _.find(groupContents.childNodes, function (node) {\r\n\t\treturn node.classList !== undefined && node.classList.contains(\"group-list-list\");\r\n\t});\r\n\tvar groupNodes = {};\r\n\tvar assetNodes = {};\r\n\tvar fenceNodes = {};\r\n\tvar placeNodes = {};\r\n\tvar sharedViewNodes = {};\r\n\tvar groups = [];\r\n\tvar assets = [];\r\n\tvar fences = [];\r\n\tvar places = [];\r\n\tvar sharedViews = [];\r\n\tif (groupList !== undefined) {\r\n\t\t_.each(groupList.childNodes, function (node) {\r\n\t\t\tif (node.classList !== undefined && node.classList.contains(\"group\")) {\r\n\t\t\t\t// subgroup\r\n\t\t\t\tvar id = node.getAttribute(\"data-group-id\");\r\n\t\t\t\tgroupNodes[id] = node;\r\n\t\t\t\tvar group = findGroupById(id);\r\n\t\t\t\tif (group !== null) {\r\n\t\t\t\t\tgroups.push(group);\r\n\t\t\t\t}\r\n\t\t\t} else if (node.classList !== undefined && node.classList.contains(\"assets-item\")) {\r\n\t\t\t\t// asset\r\n\t\t\t\tvar id = parseInt(node.getAttribute(\"data-asset-id\"));\r\n\t\t\t\tassetNodes[id] = node;\r\n\t\t\t\tvar asset = findAssetById(id);\r\n\t\t\t\tif (asset !== null) {\r\n\t\t\t\t\tassets.push(asset);\r\n\t\t\t\t}\r\n\t\t\t} else if (node.classList !== undefined && node.classList.contains(\"fences-item\")) {\r\n\t\t\t\tvar id = node.getAttribute(\"data-fence-id\");\r\n\t\t\t\tfenceNodes[id] = node;\r\n\t\t\t\tvar fence = findFenceById(id);\r\n\t\t\t\tif (fence !== null) {\r\n\t\t\t\t\tfences.push(fence);\r\n\t\t\t\t}\r\n\t\t\t} else if (node.classList !== undefined && node.classList.contains(\"places-item\")) {\r\n\t\t\t\tvar id = parseInt(node.getAttribute(\"data-place-id\"));\r\n\t\t\t\tplaceNodes[id] = node;\r\n\t\t\t\tvar place = findPlaceById(id);\r\n\t\t\t\tif (place !== null) {\r\n\t\t\t\t\tplaces.push(place);\r\n\t\t\t\t}\r\n\t\t\t} else if (node.classList !== undefined && node.classList.contains(\"shared-views-item\")) {\r\n\t\t\t\tvar id = parseInt(node.getAttribute(\"data-shared-view-id\"));\r\n\t\t\t\tsharedViewNodes[id] = node;\r\n\t\t\t\tvar sharedView = findSharedViewById(id);\r\n\t\t\t\tif (sharedView !== null) {\r\n\t\t\t\t\tsharedViews.push(sharedView);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\t// the reordering could be improved upon\r\n\t// by only moving nodes whose order change\r\n\tvar groupsSorted = sortItemsByMode(\"assets\", groups, groupId, \"groups\");\r\n\t_.each(groupsSorted, function (group) {\r\n\t\t// move node to the bottom\r\n\t\tgroupList.appendChild(groupNodes[group.Id]);\r\n\t});\r\n\r\n\tvar assetsSorted = sortItemsByMode(\"assets\", assets, groupId, \"assets\");\r\n\t_.each(assetsSorted, function (asset) {\r\n\t\tgroupList.appendChild(assetNodes[asset.Id]);\r\n\t});\r\n\r\n\tvar fencesSorted = sortItemsByMode(\"fences\", fences, groupId, \"fences\");\r\n\t_.each(fencesSorted, function (fence) {\r\n\t\tgroupList.appendChild(fenceNodes[fence.Id]);\r\n\t});\r\n\r\n\tvar placesSorted = sortItemsByMode(\"places\", places, groupId, \"places\");\r\n\t_.each(placesSorted, function (place) {\r\n\t\tgroupList.appendChild(placeNodes[place.Id]);\r\n\t});\r\n\r\n\tvar sharedViewsSorted = sortItemsByMode(\"shared-views\", sharedViews, groupId, \"shared-views\");\r\n\t_.each(sharedViewsSorted, function (sharedView) {\r\n\t\tgroupList.appendChild(sharedViewNodes[sharedView.Id]);\r\n\t});\r\n}\r\n\r\nexport function sortItemGroups(groups) {\r\n\t// reset groups\r\n\tvar groupsById = _.keyBy(groups, \"Id\");\r\n\tfor (var i = 0; i < groups.length; i++) {\r\n\t\tgroups[i].Groups = [];\r\n\t}\r\n\r\n\tvar sortedGroups = groups.sort(function (a, b) {\r\n\t\treturn a.Name.localeCompare(b.Name);\r\n\t});\r\n\tvar rootGroups = { Groups: [] };\r\n\tfor (var i = 0; i < sortedGroups.length; i++) {\r\n\t\tvar group = sortedGroups[i];\r\n\t\tif (group.ParentGroupId == null || groupsById[group.ParentGroupId] === undefined) {\r\n\t\t\tsortItemGroup(groups, group, rootGroups);\r\n\t\t}\r\n\t}\r\n\treturn rootGroups.Groups;\r\n}\r\n\r\nfunction sortItemGroup(groups, group, parent) {\r\n\tparent.Groups.push(group);\r\n\r\n\tfor (var i = 0; i < groups.length; i++) {\r\n\t\tvar otherGroup = groups[i];\r\n\t\tif (otherGroup.ParentGroupId == group.Id) {\r\n\t\t\tsortItemGroup(groups, otherGroup, group);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport function sortAssetGroups() {\r\n\treturn sortGroups(trkData.groups);\r\n}\r\n\r\nexport function sortGroups(groups) {\r\n\t// reset groups\r\n\tfor (var i = 0; i < groups.length; i++) {\r\n\t\tgroups[i].Groups = [];\r\n\t}\r\n\r\n\tvar sortedGroups = groups.sort(function (a, b) {\r\n\t\treturn a.Name.localeCompare(b.Name);\r\n\t});\r\n\tvar rootGroups = { Groups: [] };\r\n\tfor (var i = 0; i < sortedGroups.length; i++) {\r\n\t\tvar group = sortedGroups[i];\r\n\t\tif (group.ParentGroupId == null || !groups.find(g => g.Id === group.ParentGroupId)) {\r\n\t\t\tsortGroup(groups, group, rootGroups);\r\n\t\t}\r\n\t}\r\n\treturn rootGroups.Groups;\r\n}\r\n\r\nfunction sortGroup(groups, group, parent) {\r\n\tparent.Groups.push(group);\r\n\r\n\tfor (var i = 0; i < groups.length; i++) {\r\n\t\tvar otherGroup = groups[i];\r\n\t\tif (otherGroup.ParentGroupId == group.Id) sortGroup(groups, otherGroup, group);\r\n\t}\r\n}\r\n","import { getSvgIconForItemType } from \"./dom-util.js\";\r\nimport strings from \"./strings.js\";\r\nimport { findGroupById } from \"./asset-group.js\";\r\nimport { sortAssetGroups } from \"./item-sorting.js\";\r\nimport trkData from \"./data.js\";\r\n\r\nimport _ from \"lodash\";\r\nimport { el, text, mount, setChildren } from \"redom\"; // https://redom.js.org/\r\n\r\nexport function populateGroupList(sortedGroups = sortAssetGroups()) {\r\n\t// populate group parent list\r\n\tvar cont = document.getElementById(\"ddlGroupParent\");\r\n\tvar defaultOption = el(\"option\", { selected: true, value: \"\" }, strings.GROUP_NONE);\r\n\tdefaultOption.setAttribute(\"selected\", \"selected\");\r\n\tconst options = [defaultOption];\r\n\r\n\tfor (var i = 0; i < sortedGroups.length; i++) {\r\n\t\tvar group = sortedGroups[i];\r\n\t\taddGroupToGroupListInAddGroupDialog(group, 0, options);\r\n\t}\r\n\tsetChildren(cont, options);\r\n}\r\n\r\nfunction addGroupToGroupListInAddGroupDialog(group, level, options) {\r\n\tif (group.IsDefault) {\r\n\t\treturn;\r\n\t}\r\n\tvar prepend = \"\";\r\n\tfor (var i = 0; i < level; i++) {\r\n\t\tprepend += \"--\";\r\n\t}\r\n\tif (prepend != \"\") {\r\n\t\tprepend += \" \";\r\n\t}\r\n\toptions.push(el(\"option\", { value: group.Id }, prepend + group.Name));\r\n\tlevel++;\r\n\tif (group.Groups != null) {\r\n\t\tfor (let g of group.Groups) {\r\n\t\t\taddGroupToGroupListInAddGroupDialog(g, level, options);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport function addGroupToGroupListInItemEditDialog(group, level, cont, item) {\r\n\tif (group.IsDefault) {\r\n\t\treturn;\r\n\t}\r\n\tvar isChecked = false;\r\n\tif (item != null) {\r\n\t\tfor (var j = 0; j < item.GroupIds.length; j++) {\r\n\t\t\tif (item.GroupIds[j] == group.Id) {\r\n\t\t\t\tisChecked = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tvar checkbox = el(\"input.custom-control-input\", {\r\n\t\ttype: \"checkbox\",\r\n\t\tid: \"EditGroup\" + group.Id,\r\n\t\tname: \"EditGroupIds\",\r\n\t\tvalue: group.Id,\r\n\t\tchecked: isChecked,\r\n\t});\r\n\tif (isChecked) {\r\n\t\tcheckbox.setAttribute(\"checked\", \"checked\");\r\n\t}\r\n\tvar input = el(\"div.custom-control.custom-checkbox\", { style: { marginLeft: level * 15 + \"px\" } }, [\r\n\t\tcheckbox,\r\n\t\ttext(\" \"),\r\n\t\tel(\"label.custom-control-label\", { for: \"EditGroup\" + group.Id }, group.Name),\r\n\t]);\r\n\tmount(cont, input);\r\n\tlevel++;\r\n\tif (group.GroupIds != null) {\r\n\t\tfor (var k = 0; k < group.GroupIds.length; k++) {\r\n\t\t\tvar subGroup = findGroupById(group.GroupIds[k], group.Type);\r\n\t\t\taddGroupToGroupListInItemEditDialog(subGroup, level, cont, item);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport function addItemGroupToItemGroupListInAssetEditDialog(group, level, cont, selectedGroupIds) {\r\n\tif (group.IsDefault) {\r\n\t\treturn;\r\n\t}\r\n\tvar isChecked = _.indexOf(selectedGroupIds, group.Id) !== -1;\r\n\tvar checkbox = el(\"input.custom-control-input\", {\r\n\t\ttype: \"checkbox\",\r\n\t\tid: \"EditAssetDriverGroup\" + group.Id,\r\n\t\tname: \"EditAssetDriverGroupIds\",\r\n\t\tvalue: group.Id,\r\n\t\tchecked: isChecked,\r\n\t});\r\n\tif (isChecked) {\r\n\t\tcheckbox.setAttribute(\"checked\", \"checked\");\r\n\t}\r\n\tvar input = el(\"div.custom-control.custom-checkbox\", { style: { marginLeft: level * 15 + \"px\" } }, [\r\n\t\tcheckbox,\r\n\t\ttext(\" \"),\r\n\t\tel(\"label.custom-control-label\", { for: \"EditAssetDriverGroup\" + group.Id }, group.Name),\r\n\t]);\r\n\tmount(cont, input);\r\n\tlevel++;\r\n\tif (group.GroupIds != null) {\r\n\t\tfor (var k = 0; k < group.GroupIds.length; k++) {\r\n\t\t\tvar subGroup = _.find(trkData.driverGroups, { Id: group.GroupIds[k] });\r\n\t\t\taddItemGroupToItemGroupListInAssetEditDialog(subGroup, level, cont, selectedGroupIds);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport function addGroupToGroupListWithName(group, level, cont, name, parent, includeIcon) {\r\n\tif (group.IsDefault) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar control = document.createElement(\"div\");\r\n\tcontrol.className = \"custom-control custom-checkbox\";\r\n\tif (level > 0) {\r\n\t\tcontrol.style.marginLeft = level * 15 + \"px\";\r\n\t}\r\n\r\n\tvar input = document.createElement(\"input\");\r\n\tinput.className = \"custom-control-input\";\r\n\tinput.type = \"checkbox\";\r\n\tinput.id = name + group.Id;\r\n\tinput.name = name;\r\n\tinput.value = group.Id;\r\n\tif (parent !== undefined && parent !== null) {\r\n\t\tinput.setAttribute(\"data-parent\", parent.Id);\r\n\t}\r\n\r\n\tvar label = document.createElement(\"label\");\r\n\tlabel.className = \"custom-control-label\";\r\n\tlabel.setAttribute(\"for\", name + group.Id);\r\n\r\n\tvar span = document.createElement(\"span\");\r\n\tspan.textContent = group.Name;\r\n\r\n\tif (includeIcon === true) {\r\n\t\tvar svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\r\n\t\tvar iconType = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\r\n\t\ticonType.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", getSvgIconForItemType(\"groups\", group));\r\n\t\tsvg.setAttribute(\"style\", \"color: \" + group.Color);\r\n\t\tsvg.appendChild(iconType);\r\n\t\tlabel.appendChild(svg);\r\n\t\tlabel.classList.add(\"has-svg-icon\");\r\n\t}\r\n\r\n\tlabel.appendChild(span);\r\n\tcontrol.appendChild(input);\r\n\tcontrol.appendChild(label);\r\n\tcont.appendChild(control);\r\n\tlevel++;\r\n\tif (group.GroupIds != null) {\r\n\t\tfor (var k = 0; k < group.GroupIds.length; k++) {\r\n\t\t\tvar subGroup = findGroupById(group.GroupIds[k]);\r\n\t\t\taddGroupToGroupListWithName(subGroup, level, cont, name, group, includeIcon);\r\n\t\t}\r\n\t}\r\n}\r\n","import trkData from \"./data.js\";\r\nimport { addGroupToGroupListWithName } from \"./group-list.js\";\r\nimport { sortAssetGroups } from \"./item-sorting.js\";\r\nimport { devices } from \"./devices.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { findAssetById } from \"./assets.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport _ from \"lodash\";\r\nimport { el, setChildren } from \"redom\"; // https://redom.js.org/\r\n\r\nexport function openActionDialog(\r\n\tbuttonLabel,\r\n\tdialogTitle,\r\n\tcallback,\r\n\tidOverride,\r\n\tshowGroupSelection,\r\n\tsatelliteOnly,\r\n\tforDeviceIds\r\n) {\r\n\tvar modal = document.getElementById(\"message-action-modal\");\r\n\tvar btn = document.getElementById(\"message-action-button\");\r\n\tbtn.textContent = buttonLabel;\r\n\tvar title = document.getElementById(\"message-action-modal-title\");\r\n\ttitle.textContent = dialogTitle;\r\n\t$(modal).data(\"message-action-callback\", callback);\r\n\r\n\t$(\"input[name=IDPGateway]\", modal).prop(\"disabled\", false);\r\n\tif (satelliteOnly === true) {\r\n\t\t$(\"input[name=IDPGateway]\", modal).prop(\"checked\", false).prop(\"disabled\", true);\r\n\t\t$(\"#IDPGatewaySatellite\").prop(\"checked\", true).prop(\"disabled\", false);\r\n\t}\r\n\r\n\t// populate groups and assets\r\n\tvar cont = $(\".GroupsContainer\", modal).empty();\r\n\tif (cont.length > 0) {\r\n\t\tvar sortedGroups = sortAssetGroups();\r\n\t\tfor (var i = 0; i < sortedGroups.length; i++) {\r\n\t\t\tvar group = sortedGroups[i];\r\n\t\t\taddGroupToGroupListWithName(group, 0, cont[0], \"IDPGatewayParametersGroups\", null, false);\r\n\t\t}\r\n\t}\r\n\r\n\t// this seems obscure/fragile\r\n\tvar assetId = $(domNodes.dialogs.idpSendCommand).data(\"assetId\");\r\n\tif (idOverride != null) {\r\n\t\tassetId = idOverride;\r\n\t}\r\n\r\n\tvar showGroups = true;\r\n\tif (showGroupSelection != null) {\r\n\t\tshowGroups = showGroupSelection;\r\n\t}\r\n\r\n\tif (showGroups) {\r\n\t\t$(\"#message-action-additional\").show();\r\n\t} else {\r\n\t\t$(\"#message-action-additional\").hide();\r\n\t}\r\n\r\n\tif (forDeviceIds === undefined) {\r\n\t\tforDeviceIds = null;\r\n\t}\r\n\r\n\t// assets - filter on Configuration version or AVL config (ARC?)\r\n\tvar primaryAsset = findAssetById(assetId);\r\n\tif (!satelliteOnly) {\r\n\t\tvar defaultGateway = 3;\r\n\t\tif (_.indexOf(devices.SKYWAVE_IDP_CELL_ONLY, primaryAsset.DeviceId) !== -1) {\r\n\t\t\tdefaultGateway = 2;\r\n\t\t} else if (primaryAsset.DefaultIDPGateway != null) {\r\n\t\t\tvar defaultGateway = primaryAsset.DefaultIDPGateway;\r\n\t\t}\r\n\t\t$(\"input[name=IDPGateway][value=\" + defaultGateway + \"]\").prop(\"checked\", true);\r\n\t}\r\n\t$(\"select.AssetsIncluded\", modal).empty();\r\n\tvar notIncludedContainer = modal.querySelector(\"select.AssetsNotIncluded\");\r\n\tvar optionCount = 0;\r\n\tconst options = [];\r\n\tfor (var i = 0; i < trkData.assets.length; i++) {\r\n\t\tvar asset = trkData.assets[i];\r\n\t\tif (asset.Id == assetId) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (asset.IsOutOfService) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (forDeviceIds != null) {\r\n\t\t\tif (_.indexOf(forDeviceIds, asset.DeviceId) === -1) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\toptions.push(el(\"option\", { value: asset.Id }, asset.Name + \" (\" + asset.UniqueId + \")\"));\r\n\t\t\toptionCount++;\r\n\t\t} else {\r\n\t\t\tif (primaryAsset != null) {\r\n\t\t\t\tif (asset.Configuration == primaryAsset.Configuration) {\r\n\t\t\t\t\toptions.push(el(\"option\", { value: asset.Id }, asset.Name + \" (\" + asset.UniqueId + \")\"));\r\n\t\t\t\t\toptionCount++;\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tif (_.indexOf(trkData.avlConfigurations, asset.Configuration) !== -1) {\r\n\t\t\t\t\toptions.push(el(\"option\", { value: asset.Id }, asset.Name + \" (\" + asset.UniqueId + \")\"));\r\n\t\t\t\t\toptionCount++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tsetChildren(notIncludedContainer, options);\r\n\t$(\"#ActionAssetsNotIncludedCount\").text(optionCount);\r\n\t$(\"#ActionAssetsIncludedCount\").text(\"0\");\r\n\r\n\t$(modal).data(\"assetId\", assetId);\r\n\t$(modal).modal(\"show\");\r\n}\r\n\r\nexport function changePrimaryButtonLabel(dialog, text) {\r\n\tvar id = null;\r\n\tvar btn =\r\n\t\tid !== null\r\n\t\t\t? document.getElementById(id)\r\n\t\t\t: dialog !== null\r\n\t\t\t? dialog.querySelector(\".dialog-buttons .btn-primary\")\r\n\t\t\t: null;\r\n\tif (btn === null) {\r\n\t\treturn;\r\n\t}\r\n\tvar span = btn.querySelector(\"span\");\r\n\tif (span !== null) {\r\n\t\tspan.textContent = text;\r\n\t} else {\r\n\t\tbtn.textContent = text;\r\n\t}\r\n\r\n\t//var icn = btn.querySelector('use');\r\n\t//if (icn !== null && icon !== undefined && icon !== null) {\r\n\t// icn.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '/content/svg/tracking.svg?v=15#' + icon);\r\n\t//}\r\n}\r\n","import { wrapUrl } from \"./wrapurl.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { openActionDialog } from \"./modal.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport $j from \"jquery\";\r\nimport _ from \"lodash\";\r\nimport { el, svg } from \"redom\";\r\n\r\nexport async function handleAjaxFormSubmission(\r\n\tendpoint,\r\n\tdata,\r\n\tbutton,\r\n\tstatusAlert,\r\n\tmsgSuccess,\r\n\tmsgError,\r\n\tcallbackSuccess,\r\n\tcallbackFailure\r\n) {\r\n\ttoggleLoadingMessage(true, endpoint);\r\n\tvar buttons = [];\r\n\tif (button !== null) {\r\n\t\tif (Array.isArray(button)) {\r\n\t\t\tbuttons = button;\r\n\t\t} else {\r\n\t\t\tbuttons = [button];\r\n\t\t}\r\n\t}\r\n\tbuttons.forEach(b => b.disabled = true);\r\n\tif (statusAlert !== undefined && statusAlert !== null) {\r\n\t\tstatusAlert.classList.remove(\"is-visible\");\r\n\t\tstatusAlert.textContent = \"\";\r\n\t}\r\n\ttry {\r\n\t\tconst req = await fetch(wrapUrl(\"/services/GPSService.asmx/\" + endpoint), {\r\n\t\t\tmethod: \"POST\",\r\n\t\t\tbody: JSON.stringify(data),\r\n\t\t\theaders: new Headers({\r\n\t\t\t\t\"Content-Type\": \"application/json; charset=utf-8\",\r\n\t\t\t}),\r\n\t\t});\r\n\r\n\t\tif (!req.ok) {\r\n\t\t\t// TODO: 400, 401 and 404 are api errors... 400 may have modelstate\r\n\t\t\t// information leave this generic error for the 500\r\n\t\t\t// test with invalid assetid or similar\r\n\t\t\tif (msgError && statusAlert) {\r\n\t\t\t\tbuttons.forEach(b => b.disabled = false);\r\n\t\t\t\ttoggleLoadingMessage(false, endpoint);\r\n\t\t\t\tformShowErrorMessage(statusAlert, msgError);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst msg = await req.json();\r\n\r\n\t\tbuttons.forEach(b => b.disabled = false);\r\n\r\n\t\ttoggleLoadingMessage(false, endpoint);\r\n\t\tvar result = msg.d;\r\n\t\tif (result) {\r\n\t\t\tif (result.Success == true) {\r\n\t\t\t\tif (msgSuccess !== null && statusAlert !== undefined && statusAlert !== null) {\r\n\t\t\t\t\tformShowSuccessMessage(statusAlert, msgSuccess);\r\n\t\t\t\t}\r\n\t\t\t\tif (callbackSuccess !== undefined && callbackSuccess !== null) {\r\n\t\t\t\t\tcallbackSuccess(result);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tif (msgError !== null && statusAlert !== undefined && statusAlert !== null) {\r\n\t\t\t\t\tformShowErrorMessage(statusAlert, msgError);\r\n\t\t\t\t\tif (result.ErrorMessage != null && result.ErrorMessage !== \"\") {\r\n\t\t\t\t\t\tformShowErrorMessage(statusAlert, statusAlert.textContent + \" \" + result.ErrorMessage);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (callbackFailure !== undefined && callbackFailure !== null) {\r\n\t\t\t\t\tcallbackFailure(result);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t} catch (ex) {\r\n\t\tbuttons.forEach(b => b.disabled = false);\r\n\t\ttoggleLoadingMessage(false, endpoint);\r\n\t\thandleWebServiceError(ex);\r\n\t}\r\n}\r\n\r\nexport function handleAjaxFormSubmissionWithGatewaySelection(\r\n\tendpoint,\r\n\tdata,\r\n\tbutton,\r\n\tstatusAlert,\r\n\tmsgSuccess,\r\n\tmsgError,\r\n\tcallbackSuccess,\r\n\tcallbackFailure,\r\n\tcallbackDone,\r\n\tbuttonLabel,\r\n\tdialogTitle\r\n) {\r\n\tvar actiondialog = $(domNodes.modals.messageAction);\r\n\tvar callback = function (id, groupIds, assetIds, gateway, gatewayTimeout, gatewayRetries) {\r\n\t\tvar coreData = {\r\n\t\t\tassetId: id,\r\n\t\t\tgroupIds: groupIds,\r\n\t\t\tassetIds: assetIds,\r\n\t\t\tgateway: gateway,\r\n\t\t\tgatewayTimeout: gatewayTimeout,\r\n\t\t\tgatewayRetries: gatewayRetries,\r\n\t\t};\r\n\r\n\t\tvar mergedData = _.extend(coreData, data);\r\n\r\n\t\thandleAjaxFormSubmission(\r\n\t\t\tendpoint,\r\n\t\t\tmergedData,\r\n\t\t\tbutton,\r\n\t\t\tstatusAlert,\r\n\t\t\tmsgSuccess,\r\n\t\t\tmsgError,\r\n\t\t\tcallbackSuccess,\r\n\t\t\tcallbackFailure\r\n\t\t).then(function () {\r\n\t\t\tactiondialog.modal(\"hide\");\r\n\t\t});\r\n\t};\r\n\r\n\topenActionDialog(buttonLabel, dialogTitle, callback);\r\n}\r\n\r\n/// TODO: Most functions calling either/both formShowSuccessMessage / formShowErrorMessage\r\n/// should be refactored into a handleAjaxFormSubmission call.\r\n\r\nexport function formShowSuccessMessage(elem, message, noScroll) {\r\n\telem.textContent = message;\r\n\telem.classList.add(\"alert-success\");\r\n\telem.classList.add(\"is-visible\");\r\n\telem.classList.remove(\"alert-danger\");\r\n\tif (noScroll === undefined) {\r\n\t\telem.scrollIntoView(false);\r\n\t}\r\n\t//elem.text(message).addClass('alert-success is-visible').removeClass('alert-danger');\r\n}\r\n\r\nexport function formShowErrorMessage(elem, message, noScroll) {\r\n\telem.textContent = message;\r\n\telem.classList.add(\"alert-danger\");\r\n\telem.classList.add(\"is-visible\");\r\n\telem.classList.remove(\"alert-success\");\r\n\tif (noScroll === undefined) {\r\n\t\telem.scrollIntoView(false);\r\n\t}\r\n\t//elem.text(message).addClass('alert-danger is-visible').removeClass('alert-success');\r\n}\r\n\r\nconst loading = [];\r\n\r\nexport function toggleLoadingMessage(show, key) {\r\n\t// if key is supplied, tie the show/hide to that key\r\n\tif (key != null) {\r\n\t\tif (show) {\r\n\t\t\tloading.push(key);\r\n\t\t} else {\r\n\t\t\tfor (var i = 0; i < loading.length; i++) {\r\n\t\t\t\tif (loading[i] == key) {\r\n\t\t\t\t\tloading.splice(i, 1);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (show) {\r\n\t\t$j(\"#loading\").show();\r\n\t} else {\r\n\t\t// don't hide until all keys are done loading\r\n\t\tif (loading.length == 0) $j(\"#loading\").hide();\r\n\t}\r\n}\r\n\r\nexport function uploadFile(id, url, data, callback) {\r\n\tvar file = document.getElementById(id).files[0];\r\n\tif (file === undefined) {\r\n\t\treturn false;\r\n\t}\r\n\tvar formData = new FormData();\r\n\tformData.append(id, file);\r\n\t_.each(data, function (value, key, obj) {\r\n\t\tformData.append(key, value);\r\n\t});\r\n\r\n\t$.ajax({\r\n\t\turl: wrapUrl(url),\r\n\t\ttype: \"POST\",\r\n\t\tdata: formData,\r\n\t\tcache: false,\r\n\t\tcontentType: false,\r\n\t\tprocessData: false,\r\n\t\tsuccess: callback,\r\n\t});\r\n\treturn true;\r\n}\r\n\r\n// The global `utilityStrings` is defined elsewhere by the C# code.\r\n/*global utilityStrings */\r\n\r\n/// NOTE: This function is duplicated from `../utility.js'.\r\n/// Ideally it should be de-duplicated.\r\nexport function handleWebServiceError(msg) {\r\n\tvar items = [\r\n\t\tsvg(\r\n\t\t\t\"svg\",\r\n\t\t\tsvg(\"use\", {\r\n\t\t\t\txlink: { href: \"/content/svg/tracking.svg?v=15#exclamation-circle\" },\r\n\t\t\t})\r\n\t\t),\r\n\t];\r\n\tif (msg && msg.length > 0) {\r\n\t\titems.push(el(\"span\", msg));\r\n\t\t$.jGrowl(items, {\r\n\t\t\theader: utilityStrings.MSG_ERROR,\r\n\t\t\tlife: 10000,\r\n\t\t\ttheme: \"growl-error\",\r\n\t\t});\r\n\t} else {\r\n\t\titems.push(el(\"span\", utilityStrings.MSG_ERROR_OCURRED));\r\n\t\t$.jGrowl(items, {\r\n\t\t\theader: utilityStrings.MSG_ERROR,\r\n\t\t\tlife: 10000,\r\n\t\t\ttheme: \"growl-error\",\r\n\t\t});\r\n\t}\r\n}","import trkData from \"./data.js\";\r\nimport strings from \"./strings.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { handleAjaxFormSubmission, formShowErrorMessage } from \"./ajax.js\";\r\nimport { renderIDPCommandLog } from \"./datatables.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport state from \"./state.js\";\r\nimport { toggleLoadingMessage } from \"./ajax.js\";\r\nimport { requestAVLInformation } from \"./avl.js\";\r\nimport { handleWebServiceError } from \"./ajax.js\";\r\nimport { openActionDialog } from \"./modal.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport $j from \"jquery\";\r\nimport _ from \"lodash\";\r\n\r\nexport function requestIDPCommandLog(assetId, scrollTo) {\r\n\tvar data = {\r\n\t\tassetId: assetId,\r\n\t};\r\n\r\n\tvar btn = document.getElementById(\"RefreshIDPCommandLog\");\r\n\thandleAjaxFormSubmission(\"IDPGetExecuteCommandResponses\", data, btn, null, null, null, function (result) {\r\n\t\trenderIDPCommandLog(result.Commands);\r\n\t\tif (scrollTo) {\r\n\t\t\tdocument.getElementById(\"IDPCommand\").scrollIntoView(false);\r\n\t\t}\r\n\t});\r\n}\r\n\r\nexport function idpSendCommand() {\r\n\tvar isFormValid = $(trkData.validation.idpCommandLog.currentForm).valid();\r\n\tif (!isFormValid) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar cmd = document.getElementById(\"IDPCommand\");\r\n\tcmd.focus();\r\n\tvar command = cmd.value;\r\n\tvar type = document.getElementById(\"IDPCommandType\").value;\r\n\tvar isLua = false;\r\n\tvar isJson = false;\r\n\tif (type === \"lua\") {\r\n\t\tisLua = true;\r\n\t} else if (type === \"json\") {\r\n\t\tisJson = true;\r\n\t}\r\n\r\n\tvar status = document.getElementById(\"idp-query-status\");\r\n\tvar btn = this;\r\n\r\n\tvar callback = function (id, groupIds, assetIds, gateway, gatewayTimeout, gatewayRetries) {\r\n\t\tvar data = {\r\n\t\t\tassetId: id,\r\n\t\t\tassetIds: assetIds,\r\n\t\t\tgroupIds: groupIds,\r\n\t\t\tcommand: command,\r\n\t\t\tisLua: isLua,\r\n\t\t\tisJson: isJson,\r\n\t\t\tgateway: gateway,\r\n\t\t\tgatewayTimeout: gatewayTimeout,\r\n\t\t\tgatewayRetries: gatewayRetries,\r\n\t\t};\r\n\r\n\t\t$.when(\r\n\t\t\thandleAjaxFormSubmission(\"IDPSendExecuteCommandRequest\", data, btn, status, null, strings.MSG_COMMAND_ERROR)\r\n\t\t).done(function () {\r\n\t\t\trequestIDPCommandLog(id, true);\r\n\t\t\tvar cmd = document.getElementById(\"IDPCommand\");\r\n\t\t\tcmd.value = \"\";\r\n\t\t\tstate.nextFocus = cmd;\r\n\r\n\t\t\t$(domNodes.modals.messageAction).modal(\"hide\");\r\n\t\t});\r\n\t};\r\n\r\n\topenActionDialog(strings.SEND_COMMAND, strings.SEND_COMMAND, callback);\r\n}\r\n\r\nexport function populateIDPCryptoInformation(crypto) {\r\n\t//crypto.IsServiceEnabled\r\n\t//crypto.IsEnforced\r\n\t//crypto.CipherSuite\r\n\t//crypto.IsKeyDefault\r\n\tvar serviceInfo = document.getElementById(\"idp-crypto-enabled\");\r\n\tvar enforced = document.getElementById(\"idp-crypto-required\");\r\n\tvar disableButton = document.getElementById(\"IDPCryptoDisableRequirement\");\r\n\tvar enableButton = document.getElementById(\"IDPCryptoEnableRequirement\");\r\n\tvar cipher = document.getElementById(\"idp-crypto-cipher\");\r\n\tvar key = document.getElementById(\"idp-crypto-key\");\r\n\tvar rekeyButton = document.getElementById(\"IDPCryptoRekey\");\r\n\r\n\tserviceInfo.textContent =\r\n\t\tcrypto.IsServiceEnabled === true ? strings.YES : crypto.IsServiceEnabled === false ? strings.NO : strings.UNKNOWN;\r\n\tenforced.textContent = crypto.IsEnforced === true ? strings.YES : strings.NO;\r\n\r\n\tif (crypto.IsEnforced === true) {\r\n\t\tdisableButton.classList.remove(\"disabled\");\r\n\t\tdisableButton.classList.remove(\"toggle-content\");\r\n\t\tdisableButton.disabled = false;\r\n\r\n\t\tenableButton.classList.add(\"disabled\");\r\n\t\tenableButton.classList.add(\"toggle-content\");\r\n\t\tenableButton.disabled = true;\r\n\t} else {\r\n\t\tdisableButton.classList.add(\"disabled\");\r\n\t\tdisableButton.classList.add(\"toggle-content\");\r\n\t\tdisableButton.disabled = true;\r\n\r\n\t\tenableButton.classList.remove(\"disabled\");\r\n\t\tenableButton.classList.remove(\"toggle-content\");\r\n\t\tenableButton.disabled = false;\r\n\t}\r\n\r\n\tcipher.textContent = crypto.CipherSuite !== null ? crypto.CipherSuite : strings.UNKNOWN;\r\n\tkey.textContent = crypto.IsKeyDefault === true ? strings.DEFAULT : strings.CUSTOM;\r\n\r\n\tif (crypto.IsServiceEnabled === false) {\r\n\t\trekeyButton.classList.add(\"disabled\");\r\n\t\trekeyButton.disabled = true;\r\n\t} else {\r\n\t\trekeyButton.classList.remove(\"disabled\");\r\n\t\trekeyButton.disabled = false;\r\n\t}\r\n}\r\n\r\nexport function populateIDPUpdaterInformation(updater) {\r\n\t// terminal info\r\n\tvar terminalInfo = updater.TerminalInfos;\r\n\tvar terminalInfoData = [];\r\n\tfor (var i = 0; i < terminalInfo.length; i++) {\r\n\t\tvar item = terminalInfo[i];\r\n\t\tif (item.Info !== null) {\r\n\t\t\tterminalInfoData.push([\r\n\t\t\t\titem.Info.FirmwarePackage,\r\n\t\t\t\titem.Info.FirmwareVersion,\r\n\t\t\t\titem.Info.FreeFilespaceBytes,\r\n\t\t\t\titem.Info.FreeRamBytes,\r\n\t\t\t\titem.Info.TerminalKind,\r\n\t\t\t\titem.CreatedOn,\r\n\t\t\t]);\r\n\t\t}\r\n\t}\r\n\t$(\"#IDPUpdaterVersionHistory\").dataTable({\r\n\t\tdata: terminalInfoData,\r\n\t\tdestroy: true,\r\n\t\tfilter: false,\r\n\t\tinfo: false,\r\n\t\tjQueryUI: true,\r\n\t\tautoWidth: false,\r\n\t\tlengthChange: false,\r\n\t\tpaging: false,\r\n\t\tpageLength: 3,\r\n\t\tdeferRender: true,\r\n\t\torder: [[5, \"desc\"]],\r\n\t\tcolumnDefs: [\r\n\t\t\t{\r\n\t\t\t\ttargets: \"_all\",\r\n\t\t\t\trender: $.fn.dataTable.render.text(),\r\n\t\t\t},\r\n\t\t],\r\n\t\tcolumns: [{}, {}, {}, {}, {}, {}],\r\n\t\tlanguage: strings.DATATABLE,\r\n\t});\r\n\r\n\t// update states\r\n\tvar stateInfo = updater.States;\r\n\tvar terminalStateData = [];\r\n\tfor (var i = 0; i < stateInfo.length; i++) {\r\n\t\tvar item = stateInfo[i];\r\n\t\tterminalStateData.push([item.State, item.CreatedOn]);\r\n\t}\r\n\t$(\"#IDPUpdaterStatus\").dataTable({\r\n\t\tdata: terminalStateData,\r\n\t\tdestroy: true,\r\n\t\tfilter: false,\r\n\t\tinfo: false,\r\n\t\tjQueryUI: true,\r\n\t\tautoWidth: false,\r\n\t\tlengthChange: false,\r\n\t\tpaging: true,\r\n\t\tpageLength: 5,\r\n\t\tdeferRender: true,\r\n\t\torder: [[1, \"desc\"]],\r\n\t\tcolumnDefs: [\r\n\t\t\t{\r\n\t\t\t\ttargets: \"_all\",\r\n\t\t\t\trender: $.fn.dataTable.render.text(),\r\n\t\t\t},\r\n\t\t],\r\n\t\tcolumns: [{}, {}],\r\n\t\tlanguage: strings.DATATABLE,\r\n\t});\r\n}\r\n\r\nexport function requestIDPUpdaterInformation(assetId) {\r\n\ttoggleLoadingMessage(true, \"idp-updater\");\r\n\tvar data = {\r\n\t\tassetId: assetId,\r\n\t};\r\n\treturn $j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/IDPUpdaterGetInformation\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tif (msg !== null && msg.d !== null && msg.d.Success === true) {\r\n\t\t\t\tpopulateIDPUpdaterInformation(msg.d);\r\n\t\t\t}\r\n\t\t\ttoggleLoadingMessage(false, \"idp-updater\");\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\thandleWebServiceError(strings.MSG_IDP_INFORMATION_ERROR);\r\n\t\t\ttoggleLoadingMessage(false, \"idp-updater\");\r\n\t\t},\r\n\t});\r\n}\r\n\r\nexport function requestIDPCryptoInformation(assetId) {\r\n\ttoggleLoadingMessage(true, \"idp-crypto\");\r\n\tvar data = {\r\n\t\tassetId: assetId,\r\n\t};\r\n\treturn $j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/IDPCryptoGetInformation\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tif (msg !== null && msg.d !== null && msg.d.Success === true) {\r\n\t\t\t\tpopulateIDPCryptoInformation(msg.d);\r\n\t\t\t}\r\n\t\t\ttoggleLoadingMessage(false, \"idp-crypto\");\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\thandleWebServiceError(strings.MSG_IDP_INFORMATION_ERROR);\r\n\t\t\ttoggleLoadingMessage(false, \"idp-crypto\");\r\n\t\t},\r\n\t});\r\n}\r\n\r\nexport function resetIDPCounters(assetId) {\r\n\tvar data = {\r\n\t\tassetId: assetId,\r\n\t};\r\n\tvar status = document.getElementById(\"idp-query-status\");\r\n\ttoggleLoadingMessage(true, \"idp-counters-reset\");\r\n\treturn $j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/ResetAssetCounters\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tvar result = msg.d;\r\n\t\t\tif (result) {\r\n\t\t\t\tif (result.Success == true) {\r\n\t\t\t\t\trequestAVLInformation(assetId);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// message failure, keep text field to allow retry\r\n\t\t\t\t\tformShowErrorMessage(status, strings.MSG_SKYWAVE_COUNTERS_RESET_ERROR);\r\n\t\t\t\t\tif (result.ErrorMessage != null && result.ErrorMessage != \"\") {\r\n\t\t\t\t\t\tformShowErrorMessage(status, status.textContent + \" \" + result.ErrorMessage);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ttoggleLoadingMessage(false, \"idp-counters-reset\");\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\thandleWebServiceError(strings.MSG_SKYWAVE_COUNTERS_RESET_ERROR);\r\n\t\t\ttoggleLoadingMessage(false, \"idp-counters-reset\");\r\n\t\t},\r\n\t});\r\n}\r\n","import strings from \"./strings.js\";\r\nimport trkData from \"./data.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport { findAssetById } from \"./assets.js\";\r\nimport { disabledCheckboxEl } from \"./dom-util.js\";\r\nimport { renderDomElement } from \"./datatables.js\";\r\nimport { renderIDPCommandLog } from \"./datatables.js\";\r\nimport { devices } from \"./devices.js\";\r\nimport { handleWebServiceError } from \"./ajax.js\";\r\nimport { toggleLoadingMessage, formShowErrorMessage } from \"./ajax.js\";\r\nimport { populateIDPCryptoInformation, populateIDPUpdaterInformation } from \"./idp-command.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport $j from \"jquery\";\r\nimport _ from \"lodash\";\r\nimport { el, setChildren } from \"redom\"; // https://redom.js.org/\r\n\r\nexport function hasAVLAssets() {\r\n\tfor (var i = 0; i < trkData.assets.length; i++) {\r\n\t\tif ($j.inArray(trkData.assets[i].Configuration, trkData.avlConfigurations) !== -1) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nexport function requestAVLInformation(assetId) {\r\n\tvar data = {\r\n\t\tassetId: assetId,\r\n\t};\r\n\tvar status = document.getElementById(\"idp-query-status\");\r\n\ttoggleLoadingMessage(true, \"idp-information\");\r\n\treturn $j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/GetAVLInformationForAsset\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tvar result = msg.d;\r\n\t\t\tif (result) {\r\n\t\t\t\tif (result.Success == true) {\r\n\t\t\t\t\tonAVLInformation(result, assetId);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t// message failure, keep text field to allow retry\r\n\t\t\t\tformShowErrorMessage(status, strings.MSG_IDP_INFORMATION_ERROR);\r\n\t\t\t\tif (result.ErrorMessage != null && result.ErrorMessage != \"\") {\r\n\t\t\t\t\tformShowErrorMessage(status, status.textContent + \" \" + result.ErrorMessage);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ttoggleLoadingMessage(false, \"idp-information\");\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\thandleWebServiceError(strings.MSG_IDP_INFORMATION_ERROR);\r\n\t\t\ttoggleLoadingMessage(false, \"idp-information\");\r\n\t\t},\r\n\t});\r\n}\r\n\r\nfunction onAVLInformation(result, assetId) {\r\n\tvar asset = findAssetById(assetId);\r\n\tif (result.IDP != null) {\r\n\t\tasset.IDP = result.IDP;\r\n\t}\r\n\r\n\t// service meter\r\n\tvar meter = result.ServiceMeter;\r\n\tif (meter.LastRetrievedOn == null) {\r\n\t\t$j(\"#IDPServiceMetersLastRetrieved\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\"#IDPServiceMetersLastRetrieved\").text(meter.LastRetrievedOn);\r\n\t}\r\n\tif (meter.LastQueriedOn == null) {\r\n\t\t$j(\"#IDPServiceMetersLastQueried\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\"#IDPServiceMetersLastQueried\").text(meter.LastQueriedOn);\r\n\t}\r\n\tvar props = meter.ServiceMeter;\r\n\tif (props != null) {\r\n\t\t$j(\"#txtIDPAVLSM0Time\").val(props.SM0Time);\r\n\t\t$j(\"#txtIDPAVLSM0Distance\").val(props.SM0Distance);\r\n\t\t$j(\"#txtIDPAVLSM1Time\").val(props.SM1Time);\r\n\t\t$j(\"#txtIDPAVLSM1Distance\").val(props.SM1Distance);\r\n\t\t$j(\"#txtIDPAVLSM2Time\").val(props.SM2Time);\r\n\t\t$j(\"#txtIDPAVLSM2Distance\").val(props.SM2Distance);\r\n\t\t$j(\"#txtIDPAVLSM3Time\").val(props.SM3Time);\r\n\t\t$j(\"#txtIDPAVLSM3Distance\").val(props.SM3Distance);\r\n\t\t$j(\"#txtIDPAVLSM4Time\").val(props.SM4Time);\r\n\t\t$j(\"#txtIDPAVLSM4Distance\").val(props.SM4Distance);\r\n\t\t$j(\"#txtIDPServiceMeterOdometer\").val(props.Odometer);\r\n\t}\r\n\r\n\t// core parameters\r\n\tvar core = result.CoreProperties;\r\n\tvar props = core.CoreProperties;\r\n\r\n\tif (core.LastRetrievedOn == null) {\r\n\t\t$j(\".CoreParametersLastRetrieved\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\".CoreParametersLastRetrieved\").text(core.LastRetrievedOn);\r\n\t}\r\n\tif (core.LastQueriedOn == null) {\r\n\t\t$j(\".CoreParametersLastQueried\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\".CoreParametersLastQueried\").text(core.LastQueriedOn);\r\n\t}\r\n\tif (props != null) {\r\n\t\t// apply updated asset IDP information\r\n\r\n\t\tif (props.System != null) {\r\n\t\t\t$j(\"#txtIDPSystemExecutionWatchdogTimeout\").val(props.System.ExecutionWatchdogTimeout);\r\n\t\t\t$j(\"#txtIDPSystemAutoGCMemThreshold\").val(props.System.AutoGCMemThreshold);\r\n\t\t\t$j(\"#ddlIDPSystemLedControl\").val(props.System.LedControl);\r\n\t\t}\r\n\t\tif (props.Power != null) {\r\n\t\t\t$j(\"#ddlIDPPowerExtPowerPresentStateDetect\").val(props.Power.ExtPowerPresentStateDetect);\r\n\t\t}\r\n\t\tif (props.Report != null) {\r\n\t\t\t$j(\"input:radio[name=rbIDPReport1Enabled][value=\" + props.Report.Report1Enabled + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"#ddlIDPReport1ReportType\").val(props.Report.Report1MIN);\r\n\t\t\t$j(\"#txtIDPReport1TimeInterval\").val(props.Report.Report1Interval);\r\n\t\t}\r\n\t\tif (props.Message != null) {\r\n\t\t\t$j(\"input:radio[name=rbIDPMessageRetry][value=\" + props.Message.Retry + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"#txtIDPMessageTransport1\").val(props.Message.Transport1);\r\n\t\t\t$j(\"#txtIDPMessageTransport2\").val(props.Message.Transport2);\r\n\t\t\t$j(\"#txtIDPMessageTimeout1\").val(props.Message.Timeout1);\r\n\t\t\t$j(\"#txtIDPMessageTimeout2\").val(props.Message.Timeout2);\r\n\t\t\t$j(\"#txtIDPMessageRetrvInterval\").val(props.Message.RetrvInterval);\r\n\t\t\t$j(\"#txtIDPMessageRetrvMultiplier\").val(props.Message.RetrvMultiplier);\r\n\t\t}\r\n\t\tif (props.Position != null) {\r\n\t\t\t$j(\"#txtIDPPositionContinuous\").val(props.Position.Continuous);\r\n\t\t}\r\n\t\tif (props.Log != null) {\r\n\t\t\t$j(\"input:radio[name=rbIDPLogDataLogEnabled][value=\" + props.Log.DataLogEnabled + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"#txtIDPLogMaxDataLogSize\").val(props.Log.MaxDataLogSize);\r\n\t\t\t$j(\"#txtIDPLogMaxDataLogFiles\").val(props.Log.MaxDataLogFiles);\r\n\t\t\t$j(\"input:radio[name=rbIDPLogDebugLogEnabled][value=\" + props.Log.DebugLogEnabled + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"#txtIDPLogMaxDebugLogSize\").val(props.Log.MaxDebugLogSize);\r\n\t\t}\r\n\t\tif (props.EIO != null) {\r\n\t\t\t$j(\"#ddlIDPEIOPort1Config\").val(props.EIO.Port1Config);\r\n\t\t\t//$j('input[name=rbIDPEIOPort1AlarmMsg]:checked').val(props.EIO.Port1AlarmMsg);\r\n\t\t\t//$j('input[name=rbIDPEIOPort1AlarmLog]:checked').val(props.EIO.Port1AlarmLog);\r\n\t\t\t$j(\"input:radio[name=rbIDPEIOPort1AlarmMsg][value=\" + props.EIO.Port1AlarmMsg + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"input:radio[name=rbIDPEIOPort1AlarmLog][value=\" + props.EIO.Port1AlarmLog + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"#ddlIDPEIOPort1EdgeDetect\").val(props.EIO.Port1EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEIOPort1EdgeSampleCount\").val(props.EIO.Port1EdgeSampleCount);\r\n\t\t\t$j(\"#txtIDPEIOPort1EdgeSampleError\").val(props.EIO.Port1EdgeSampleError);\r\n\t\t\t$j(\"#txtIDPEIOPort1AnalogSampleRate\").val(props.EIO.Port1AnalogSampleRate);\r\n\t\t\t$j(\"#txtIDPEIOPort1AnalogSampleFilter\").val(props.EIO.Port1AnalogSampleFilter);\r\n\t\t\t$j(\"#txtIDPEIOPort1AnalogLowThreshold\").val(props.EIO.Port1AnalogLowThreshold);\r\n\t\t\t$j(\"#txtIDPEIOPort1AnalogHighThreshold\").val(props.EIO.Port1AnalogHighThreshold);\r\n\t\t\t$j(\"#ddlIDPEIOPort2Config\").val(props.EIO.Port2Config);\r\n\t\t\t$j(\"input:radio[name=rbIDPEIOPort2AlarmMsg][value=\" + props.EIO.Port2AlarmMsg + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"input:radio[name=rbIDPEIOPort2AlarmLog][value=\" + props.EIO.Port2AlarmLog + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"#ddlIDPEIOPort2EdgeDetect\").val(props.EIO.Port2EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEIOPort2EdgeSampleCount\").val(props.EIO.Port2EdgeSampleCount);\r\n\t\t\t$j(\"#txtIDPEIOPort2EdgeSampleError\").val(props.EIO.Port2EdgeSampleError);\r\n\t\t\t$j(\"#txtIDPEIOPort2AnalogSampleRate\").val(props.EIO.Port2AnalogSampleRate);\r\n\t\t\t$j(\"#txtIDPEIOPort2AnalogSampleFilter\").val(props.EIO.Port2AnalogSampleFilter);\r\n\t\t\t$j(\"#txtIDPEIOPort2AnalogLowThreshold\").val(props.EIO.Port2AnalogLowThreshold);\r\n\t\t\t$j(\"#txtIDPEIOPort2AnalogHighThreshold\").val(props.EIO.Port2AnalogHighThreshold);\r\n\t\t\t$j(\"#ddlIDPEIOPort3Config\").val(props.EIO.Port3Config);\r\n\t\t\t$j(\"input:radio[name=rbIDPEIOPort3AlarmMsg][value=\" + props.EIO.Port3AlarmMsg + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"input:radio[name=rbIDPEIOPort3AlarmLog][value=\" + props.EIO.Port3AlarmLog + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"#ddlIDPEIOPort3EdgeDetect\").val(props.EIO.Port3EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEIOPort3EdgeSampleCount\").val(props.EIO.Port3EdgeSampleCount);\r\n\t\t\t$j(\"#txtIDPEIOPort3EdgeSampleError\").val(props.EIO.Port3EdgeSampleError);\r\n\t\t\t$j(\"#txtIDPEIOPort3AnalogSampleRate\").val(props.EIO.Port3AnalogSampleRate);\r\n\t\t\t$j(\"#txtIDPEIOPort3AnalogSampleFilter\").val(props.EIO.Port3AnalogSampleFilter);\r\n\t\t\t$j(\"#txtIDPEIOPort3AnalogLowThreshold\").val(props.EIO.Port3AnalogLowThreshold);\r\n\t\t\t$j(\"#txtIDPEIOPort3AnalogHighThreshold\").val(props.EIO.Port3AnalogHighThreshold);\r\n\t\t\t$j(\"#ddlIDPEIOPort4Config\").val(props.EIO.Port4Config);\r\n\t\t\t$j(\"input:radio[name=rbIDPEIOPort4AlarmMsg][value=\" + props.EIO.Port4AlarmMsg + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"input:radio[name=rbIDPEIOPort4AlarmLog][value=\" + props.EIO.Port4AlarmLog + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"#ddlIDPEIOPort4EdgeDetect\").val(props.EIO.Port4EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEIOPort4EdgeSampleCount\").val(props.EIO.Port4EdgeSampleCount);\r\n\t\t\t$j(\"#txtIDPEIOPort4EdgeSampleError\").val(props.EIO.Port4EdgeSampleError);\r\n\t\t\t$j(\"#txtIDPEIOPort4AnalogSampleRate\").val(props.EIO.Port4AnalogSampleRate);\r\n\t\t\t$j(\"#txtIDPEIOPort4AnalogSampleFilter\").val(props.EIO.Port4AnalogSampleFilter);\r\n\t\t\t$j(\"#txtIDPEIOPort4AnalogLowThreshold\").val(props.EIO.Port4AnalogLowThreshold);\r\n\t\t\t$j(\"#txtIDPEIOPort4AnalogHighThreshold\").val(props.EIO.Port4AnalogHighThreshold);\r\n\t\t\t$j(\"input:radio[name=rbIDPEIOTemperatureAlarmMsg][value=\" + props.EIO.TemperatureAlarmMsg + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPEIOTemperatureAlarmLog][value=\" + props.EIO.TemperatureAlarmLog + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"#txtIDPEIOTemperatureSampleRate\").val(props.EIO.TemperatureSampleRate);\r\n\t\t\t$j(\"#txtIDPEIOTemperatureSampleFilter\").val(props.EIO.TemperatureSampleFilter);\r\n\t\t\t$j(\"#txtIDPEIOTemperatureLowThreshold\").val(props.EIO.TemperatureLowThreshold);\r\n\t\t\t$j(\"#txtIDPEIOTemperatureHighThreshold\").val(props.EIO.TemperatureHighThreshold);\r\n\t\t\t$j(\"input:radio[name=rbIDPEIOPowerAlarmMsg][value=\" + props.EIO.PowerAlarmMsg + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"input:radio[name=rbIDPEIOPowerAlarmLog][value=\" + props.EIO.PowerAlarmLog + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"#txtIDPEIOPowerSampleRate\").val(props.EIO.PowerSampleRate);\r\n\t\t\t$j(\"#txtIDPEIOPowerSampleFilter\").val(props.EIO.PowerSampleFilter);\r\n\t\t\t$j(\"#txtIDPEIOPowerLowThreshold\").val(props.EIO.PowerLowThreshold);\r\n\t\t\t$j(\"#txtIDPEIOPowerHighThreshold\").val(props.EIO.PowerHighThreshold);\r\n\t\t\t$j(\"#ddlIDPEIOOutputSink5Default\").val(props.EIO.OutputSink5Default);\r\n\t\t\t$j(\"#ddlIDPEIOOutputSink6Default\").val(props.EIO.OutputSink6Default);\r\n\t\t}\r\n\t\tif (props.GPRS != null) {\r\n\t\t\t$j(\"#txtIDPGPRSSIM1PIN\").val(props.GPRS.SIM1PIN);\r\n\t\t\t$j(\"#txtIDPGPRSSIM1APN\").val(props.GPRS.SIM1APN);\r\n\t\t\t$j(\"#txtIDPGPRSSIM1Username\").val(props.GPRS.SIM1Username);\r\n\t\t\t$j(\"#txtIDPGPRSSIM1Password\").val(props.GPRS.SIM1Password);\r\n\t\t\t$j(\"#txtIDPGPRSSIM1DNS1\").val(props.GPRS.SIM1DNS1);\r\n\t\t\t$j(\"#txtIDPGPRSSIM1DNS2\").val(props.GPRS.SIM1DNS2);\r\n\t\t\t$j(\"#txtIDPGPRSSIM2PIN\").val(props.GPRS.SIM2PIN);\r\n\t\t\t$j(\"#txtIDPGPRSSIM2APN\").val(props.GPRS.SIM2APN);\r\n\t\t\t$j(\"#txtIDPGPRSSIM2Username\").val(props.GPRS.SIM2Username);\r\n\t\t\t$j(\"#txtIDPGPRSSIM2Password\").val(props.GPRS.SIM2Password);\r\n\t\t\t$j(\"#txtIDPGPRSSIM2DNS1\").val(props.GPRS.SIM2DNS1);\r\n\t\t\t$j(\"#txtIDPGPRSSIM2DNS2\").val(props.GPRS.SIM2DNS2);\r\n\t\t\t$j(\"#txtIDPGPRSServer1\").val(props.GPRS.Server1);\r\n\t\t\t$j(\"#txtIDPGPRSPort1\").val(props.GPRS.Port1);\r\n\t\t\t$j(\"#txtIDPGPRSPollingInterval\").val(props.GPRS.PollingInterval);\r\n\t\t\t$j(\"#ddlIDPGPRSActiveSIM\").val(props.GPRS.ActiveSIM);\r\n\t\t\t$j(\"#ddlIDPGPRSTargetMode\").val(props.GPRS.TargetMode);\r\n\t\t}\r\n\t\tif (props.EEIO != null) {\r\n\t\t\t$j(\"#ddlIDPEEIOInput1Config\").val(props.EEIO.Input1Config);\r\n\t\t\t$j(\"#ddlIDPEEIOInput1EdgeDetect\").val(props.EEIO.Input1EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEEIOInput1EdgeFilterCount\").val(props.EEIO.Input1EdgeFilterCount);\r\n\t\t\t$j(\"#txtIDPEEIOInput1AnalogSampleRate\").val(props.EEIO.Input1AnalogSampleRate);\r\n\t\t\t$j(\"#txtIDPEEIOInput1AnalogFilterCount\").val(props.EEIO.Input1AnalogFilterCount);\r\n\t\t\t$j(\"#txtIDPEEIOInput1AnalogLowThreshold\").val(props.EEIO.Input1AnalogLowThreshold);\r\n\t\t\t$j(\"#txtIDPEEIOInput1AnalogHighThreshold\").val(props.EEIO.Input1AnalogHighThreshold);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInput1AlarmMsg][value=\" + props.EEIO.Input1AlarmMsg + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInput1AlarmLog][value=\" + props.EEIO.Input1AlarmLog + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"#ddlIDPEEIOInput2Config\").val(props.EEIO.Input2Config);\r\n\t\t\t$j(\"#ddlIDPEEIOInput2EdgeDetect\").val(props.EEIO.Input2EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEEIOInput2EdgeFilterCount\").val(props.EEIO.Input2EdgeFilterCount);\r\n\t\t\t$j(\"#txtIDPEEIOInput2AnalogSampleRate\").val(props.EEIO.Input2AnalogSampleRate);\r\n\t\t\t$j(\"#txtIDPEEIOInput2AnalogFilterCount\").val(props.EEIO.Input2AnalogFilterCount);\r\n\t\t\t$j(\"#txtIDPEEIOInput2AnalogLowThreshold\").val(props.EEIO.Input2AnalogLowThreshold);\r\n\t\t\t$j(\"#txtIDPEEIOInput2AnalogHighThreshold\").val(props.EEIO.Input2AnalogHighThreshold);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInput2AlarmMsg][value=\" + props.EEIO.Input2AlarmMsg + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInput2AlarmLog][value=\" + props.EEIO.Input2AlarmLog + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"#ddlIDPEEIOInput3Config\").val(props.EEIO.Input3Config);\r\n\t\t\t$j(\"#ddlIDPEEIOInput3EdgeDetect\").val(props.EEIO.Input3EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEEIOInput3EdgeFilterCount\").val(props.EEIO.Input3EdgeFilterCount);\r\n\t\t\t$j(\"#txtIDPEEIOInput3AnalogSampleRate\").val(props.EEIO.Input3AnalogSampleRate);\r\n\t\t\t$j(\"#txtIDPEEIOInput3AnalogFilterCount\").val(props.EEIO.Input3AnalogFilterCount);\r\n\t\t\t$j(\"#txtIDPEEIOInput3AnalogLowThreshold\").val(props.EEIO.Input3AnalogLowThreshold);\r\n\t\t\t$j(\"#txtIDPEEIOInput3AnalogHighThreshold\").val(props.EEIO.Input3AnalogHighThreshold);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInput3AlarmMsg][value=\" + props.EEIO.Input3AlarmMsg + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInput3AlarmLog][value=\" + props.EEIO.Input3AlarmLog + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"#ddlIDPEEIOInput4Config\").val(props.EEIO.Input4Config);\r\n\t\t\t$j(\"#ddlIDPEEIOInput4EdgeDetect\").val(props.EEIO.Input4EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEEIOInput4EdgeFilterCount\").val(props.EEIO.Input4EdgeFilterCount);\r\n\t\t\t$j(\"#txtIDPEEIOInput4AnalogSampleRate\").val(props.EEIO.Input4AnalogSampleRate);\r\n\t\t\t$j(\"#txtIDPEEIOInput4AnalogFilterCount\").val(props.EEIO.Input4AnalogFilterCount);\r\n\t\t\t$j(\"#txtIDPEEIOInput4AnalogLowThreshold\").val(props.EEIO.Input4AnalogLowThreshold);\r\n\t\t\t$j(\"#txtIDPEEIOInput4AnalogHighThreshold\").val(props.EEIO.Input4AnalogHighThreshold);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInput4AlarmMsg][value=\" + props.EEIO.Input4AlarmMsg + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInput4AlarmLog][value=\" + props.EEIO.Input4AlarmLog + \"]\").prop(\"checked\", true);\r\n\t\t\t$j(\"#ddlIDPEEIOInputDigital5EdgeDetect\").val(props.EEIO.InputDigital5EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEEIOInputDigital5EdgeFilterCount\").val(props.EEIO.InputDigital5EdgeFilterCount);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital5AlarmMsg][value=\" + props.EEIO.InputDigital5AlarmMsg + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital5AlarmLog][value=\" + props.EEIO.InputDigital5AlarmLog + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"#ddlIDPEEIOInputDigital6EdgeDetect\").val(props.EEIO.InputDigital6EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEEIOInputDigital6EdgeFilterCount\").val(props.EEIO.InputDigital6EdgeFilterCount);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital6AlarmMsg][value=\" + props.EEIO.InputDigital6AlarmMsg + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital6AlarmLog][value=\" + props.EEIO.InputDigital6AlarmLog + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"#ddlIDPEEIOInputDigital7EdgeDetect\").val(props.EEIO.InputDigital7EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEEIOInputDigital7EdgeFilterCount\").val(props.EEIO.InputDigital7EdgeFilterCount);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital7AlarmMsg][value=\" + props.EEIO.InputDigital7AlarmMsg + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital7AlarmLog][value=\" + props.EEIO.InputDigital7AlarmLog + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"#ddlIDPEEIOInputDigital8EdgeDetect\").val(props.EEIO.InputDigital8EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEEIOInputDigital8EdgeFilterCount\").val(props.EEIO.InputDigital8EdgeFilterCount);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital8AlarmMsg][value=\" + props.EEIO.InputDigital8AlarmMsg + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital8AlarmLog][value=\" + props.EEIO.InputDigital8AlarmLog + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"#ddlIDPEEIOInputDigital9EdgeDetect\").val(props.EEIO.InputDigital9EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEEIOInputDigital9EdgeFilterCount\").val(props.EEIO.InputDigital9EdgeFilterCount);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital9AlarmMsg][value=\" + props.EEIO.InputDigital9AlarmMsg + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital9AlarmLog][value=\" + props.EEIO.InputDigital9AlarmLog + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"#ddlIDPEEIOInputDigital10EdgeDetect\").val(props.EEIO.InputDigital10EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEEIOInputDigital10EdgeFilterCount\").val(props.EEIO.InputDigital10EdgeFilterCount);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital10AlarmMsg][value=\" + props.EEIO.InputDigital10AlarmMsg + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital10AlarmLog][value=\" + props.EEIO.InputDigital10AlarmLog + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"#ddlIDPEEIOInputDigital11EdgeDetect\").val(props.EEIO.InputDigital11EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEEIOInputDigital11EdgeFilterCount\").val(props.EEIO.InputDigital11EdgeFilterCount);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital11AlarmMsg][value=\" + props.EEIO.InputDigital11AlarmMsg + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputDigital11AlarmLog][value=\" + props.EEIO.InputDigital11AlarmLog + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"#ddlIDPEEIOInputIgnition12EdgeDetect\").val(props.EEIO.InputIgnition12EdgeDetect);\r\n\t\t\t$j(\"#txtIDPEEIOInputIgnition12EdgeFilterCount\").val(props.EEIO.InputIgnition12EdgeFilterCount);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputIgnition12AlarmMsg][value=\" + props.EEIO.InputIgnition12AlarmMsg + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOInputIgnition12AlarmLog][value=\" + props.EEIO.InputIgnition12AlarmLog + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"#ddlIDPEEIOutputSink14Default\").val(props.EEIO.OutputSink14Default);\r\n\t\t\t$j(\"#ddlIDPEEIOutputSink15Default\").val(props.EEIO.OutputSink15Default);\r\n\t\t\t$j(\"#ddlIDPEEIOutputSink16Default\").val(props.EEIO.OutputSink16Default);\r\n\t\t\t$j(\"#ddlIDPEEIOutputSink17Default\").val(props.EEIO.OutputSink17Default);\r\n\t\t\t$j(\"#ddlIDPEEIOutputSink18Default\").val(props.EEIO.OutputSink18Default);\r\n\t\t\t$j(\"#txtIDPEEIOTemperatureSampleRate\").val(props.EEIO.TemperatureSampleRate);\r\n\t\t\t$j(\"#txtIDPEEIOTemperatureFilterCount\").val(props.EEIO.TemperatureFilterCount);\r\n\t\t\t$j(\"#txtIDPEEIOTemperatureLowThreshold\").val(props.EEIO.TemperatureLowThreshold);\r\n\t\t\t$j(\"#txtIDPEEIOTemperatureHighThreshold\").val(props.EEIO.TemperatureHighThreshold);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOTemperatureAlarmMsg][value=\" + props.EEIO.TemperatureAlarmMsg + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOTemperatureAlarmLog][value=\" + props.EEIO.TemperatureAlarmLog + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"#txtIDPEEIOExternalPowerSampleRate\").val(props.EEIO.ExternalPowerSampleRate);\r\n\t\t\t$j(\"#txtIDPEEIOExternalPowerFilterCount\").val(props.EEIO.ExternalPowerFilterCount);\r\n\t\t\t$j(\"#txtIDPEEIOExternalPowerLowThreshold\").val(props.EEIO.ExternalPowerLowThreshold);\r\n\t\t\t$j(\"#txtIDPEEIOExternalPowerHighThreshold\").val(props.EEIO.ExternalPowerHighThreshold);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOExternalPowerAlarmMsg][value=\" + props.EEIO.ExternalPowerAlarmMsg + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPEEIOExternalPowerAlarmLog][value=\" + props.EEIO.ExternalPowerAlarmLog + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t}\r\n\t\tif (props.Accel != null) {\r\n\t\t\t$j(\"#txtIDPAccelSleepInterval\").val(props.Accel.SleepInterval);\r\n\t\t\t$j(\"#txtIDPAccelGRange\").val(props.Accel.GRange);\r\n\t\t\t$j(\"#txtIDPAccelMotionEventThreshold\").val(props.Accel.MotionEventThreshold);\r\n\t\t\t$j(\"input:radio[name=rbIDPAccelMotionEventXAxisEn][value=\" + props.Accel.MotionEventXAxisEn + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPAccelMotionEventYAxisEn][value=\" + props.Accel.MotionEventYAxisEn + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPAccelMotionEventZAxisEn][value=\" + props.Accel.MotionEventZAxisEn + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t}\r\n\t}\r\n\r\n\t// geofence parameters\r\n\tvar geofence = result.GeofenceParameters;\r\n\tvar props = geofence.GeofenceParameters;\r\n\r\n\tif (geofence.LastRetrievedOn == null) {\r\n\t\t$j(\"#AVLGeofenceParametersLastRetrieved\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\"#AVLGeofenceParametersLastRetrieved\").text(geofence.LastRetrievedOn);\r\n\t}\r\n\tif (geofence.LastQueriedOn == null) {\r\n\t\t$j(\"#AVLGeofenceParametersLastQueried\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\"#AVLGeofenceParametersLastQueried\").text(geofence.LastQueriedOn);\r\n\t}\r\n\tif (props != null) {\r\n\t\t$j(\"input:radio[name=rbIDPAVLGeofenceEnabled][value=\" + props.Enabled + \"]\").prop(\"checked\", true);\r\n\t\t$j(\"#txtIDPAVLGeofenceInterval\").val(props.Interval);\r\n\t\t$j(\"#txtIDPAVLGeofenceHysteresis\").val(props.Hysteresis);\r\n\t\t$j(\"input:radio[name=rbIDPAVLGeofenceSendAlarm][value=\" + props.SendAlarm + \"]\").prop(\"checked\", true);\r\n\t}\r\n\r\n\t// avl parameters\r\n\tvar avl = result.AVLParameters;\r\n\tvar props = avl.ServiceProperties;\r\n\tif (avl.LastRetrievedOn == null) {\r\n\t\t$j(\".AVLParametersLastRetrieved\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\".AVLParametersLastRetrieved\").text(avl.LastRetrievedOn);\r\n\t}\r\n\tif (avl.LastQueriedOn == null) {\r\n\t\t$j(\".AVLParametersLastQueried\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\".AVLParametersLastQueried\").text(avl.LastQueriedOn);\r\n\t}\r\n\tif (props != null) {\r\n\t\t// populate\r\n\t\t$j(\"#txtIDPAVLStationarySpeedThld\").val(props.StationarySpeedThreshold);\r\n\t\t$j(\"#txtIDPAVLStationaryDebounceTime\").val(props.StationaryDebounceTime);\r\n\t\t$j(\"#txtIDPAVLMovingDebounceTime\").val(props.MovingDebounceTime);\r\n\t\t$j(\"#txtIDPAVLMovingDistanceThld\").val(props.MovingDistanceThreshold);\r\n\t\t$j(\"#txtIDPAVLDefaultSpeedLimit\").val(props.DefaultSpeedLimit);\r\n\t\t$j(\"#txtIDPAVLSpeedingTimeOver\").val(props.SpeedingTimeOver);\r\n\t\t$j(\"#txtIDPAVLSpeedingTimeUnder\").val(props.SpeedingTimeUnder);\r\n\t\t$j(\"#txtIDPAVLLoggingPositionsInterval\").val(props.LoggingPositionsInterval);\r\n\t\t$j(\"#txtIDPAVLStationaryIntervalCell\").val(props.StationaryIntervalCell);\r\n\t\t$j(\"#txtIDPAVLMovingIntervalCell\").val(props.MovingIntervalCell);\r\n\t\t$j(\"#txtIDPAVLStationaryIntervalSat\").val(props.StationaryIntervalSat);\r\n\t\t$j(\"#txtIDPAVLMovingIntervalSat\").val(props.MovingIntervalSat);\r\n\t\t$j(\"#txtIDPAVLShmReportingHour\").val(props.ShmReportingHour);\r\n\t\t$j(\"#txtIDPAVLOdometerDistanceIncrement\").val(props.OdometerDistanceIncrement);\r\n\t\t$j(\"#txtIDPAVLOdometer\").val(props.Odometer);\r\n\t\t$j(\"#txtIDPAVLTurnThreshold\").val(props.TurnThreshold);\r\n\t\t$j(\"#txtIDPAVLTurnDebounceTime\").val(props.TurnDebounceTime);\r\n\t\t$j(\"#txtIDPAVLDistanceCellThld\").val(props.DistanceCellThreshold);\r\n\t\t$j(\"#txtIDPAVLDistanceSatThld\").val(props.DistanceSatThreshold);\r\n\t\t$j(\"#txtIDPAVLMaxDrivingTime\").val(props.MaxDrivingTime);\r\n\t\t$j(\"#txtIDPAVLMinRestTime\").val(props.MinRestTime);\r\n\t\t$j(\"#txtIDPAVLAirBlockageTime\").val(props.AirBlockageTime);\r\n\t\t$j(\"#txtIDPAVLMaxIdlingTime\").val(props.MaxIdlingTime);\r\n\t\t$j(\"input:radio[name=rbIDPAVLIdleTimerAutoRestart][value=\" + props.IdleTimerAutoRestart + \"]\").prop(\r\n\t\t\t\"checked\",\r\n\t\t\ttrue\r\n\t\t);\r\n\t\t$j(\"#txtIDPAVLDefaultGeoDwellTime\").val(props.DefaultGeoDwellTime);\r\n\t\t$j(\"input:radio[name=rbIDPAVLGeoDwellTimerAutoRestart][value=\" + props.GeoDwellTimerAutoRestart + \"]\").prop(\r\n\t\t\t\"checked\",\r\n\t\t\ttrue\r\n\t\t);\r\n\t\t$j(\"#txtIDPAVLImmobilizeOnBlockage\").val(props.ImmobilizeOnBlockage);\r\n\t\t$j(\"#txtIDPAVLGpsJamDebounceTime\").val(props.GpsJamDebounceTime);\r\n\t\t$j(\"#txtIDPAVLCellJamDebounceTime\").val(props.CellJamDebounceTime);\r\n\t\t// todo: Version\r\n\t\t//$j('#txtIDPAVLLpmTrigger').val(props.LpmTrigger);\r\n\t\tif (props.LpmTriggerDef != null) {\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLLpmTriggerIgnitionOff][value=\" + props.LpmTriggerDef.IgnitionOff + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLLpmTriggerBuiltInBattery][value=\" + props.LpmTriggerDef.BuiltInBattery + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t}\r\n\t\t$j(\"#txtIDPAVLLpmEntryDelay\").val(props.LpmEntryDelay);\r\n\t\t$j(\"#txtIDPAVLLpmGeoInterval\").val(props.LpmGeoInterval);\r\n\t\t$j(\"#ddlIDPAVLLpmModemWakeupInterval\").val(props.LpmModemWakeupInterval);\r\n\t\t$j(\"#txtIDPAVLExitLpmOnTowingMaxTime\").val(props.ExitLpmOnTowingMaxTime);\r\n\t\t$j(\"#txtIDPAVLTowStartCheckInterval\").val(props.TowStartCheckInterval);\r\n\t\t$j(\"#txtIDPAVLTowStartDebCount\").val(props.TowStartDebCount);\r\n\t\t$j(\"#txtIDPAVLTowStopCheckInterval\").val(props.TowStopCheckInterval);\r\n\t\t$j(\"#txtIDPAVLTowStopDebCount\").val(props.TowStopDebCount);\r\n\t\t$j(\"#txtIDPAVLTowInterval\").val(props.TowInterval);\r\n\r\n\t\t$j(\"#txtIDPAVLHarshBrakingThld\").val(props.HarshBrakingThld);\r\n\t\t$j(\"#txtIDPAVLMinHarshBrakingTime\").val(props.MinHarshBrakingTime);\r\n\t\t$j(\"#txtIDPAVLReArmHarshBrakingTime\").val(props.ReArmHarshBrakingTime);\r\n\t\t$j(\"#txtIDPAVLHarshAccelThld\").val(props.HarshAccelThld);\r\n\t\t$j(\"#txtIDPAVLMinHarshAccelTime\").val(props.MinHarshAccelTime);\r\n\t\t$j(\"#txtIDPAVLReArmHarshAccelTime\").val(props.ReArmHarshAccelTime);\r\n\t\t$j(\"#txtIDPAVLAccidentThld\").val(props.AccidentThld);\r\n\t\t$j(\"#txtIDPAVLMinAccidentTime\").val(props.MinAccidentTime);\r\n\t\t$j(\"#txtIDPAVLSeatbeltDebounceTime\").val(props.SeatbeltDebounceTime);\r\n\t\t$j(\"#ddlIDPAVLDriverIdPort\").val(props.DriverIdPort);\r\n\t\t$j(\"#txtIDPAVLDriverIdPollingInterval\").val(props.DriverIdPollingInterval);\r\n\t\t$j(\"#txtIDPAVLDriverIdAutoLogoutDelay\").val(props.DriverIdAutoLogoutDelay);\r\n\t\t$j(\"input:radio[name=rbIDPAVLAccidentAccelDataCapture][value=\" + props.AccidentAccelDataCapture + \"]\").prop(\r\n\t\t\t\"checked\",\r\n\t\t\ttrue\r\n\t\t);\r\n\t\t$j(\"input:radio[name=rbIDPAVLAccidentGpsDataCapture][value=\" + props.AccidentGpsDataCapture + \"]\").prop(\r\n\t\t\t\"checked\",\r\n\t\t\ttrue\r\n\t\t);\r\n\t\t$j(\"#txtIDPAVLHarshTurnThld\").val(props.HarshTurnThld);\r\n\t\t$j(\"#txtIDPAVLMinHarshTurnTime\").val(props.MinHarshTurnTime);\r\n\t\t$j(\"#txtIDPAVLReArmHarshTurnTime\").val(props.ReArmHarshTurnTime);\r\n\r\n\t\tif (props.OptionalFieldsDef != null) {\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLOptionalFieldsInMsgsOdometer][value=\" + props.OptionalFieldsDef.Odometer + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLOptionalFieldsInMsgsSensor1][value=\" + props.OptionalFieldsDef.Sensor1 + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLOptionalFieldsInMsgsSensor2][value=\" + props.OptionalFieldsDef.Sensor2 + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLOptionalFieldsInMsgsSensor3][value=\" + props.OptionalFieldsDef.Sensor3 + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLOptionalFieldsInMsgsSensor4][value=\" + props.OptionalFieldsDef.Sensor4 + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLOptionalFieldsInMsgsDriverId][value=\" + props.OptionalFieldsDef.DriverId + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\r\n\t\t\t\t\"input:radio[name=rbIDPAVLOptionalFieldsInMsgsAvlStates][value=\" + props.OptionalFieldsDef.AvlStates + \"]\"\r\n\t\t\t).prop(\"checked\", true);\r\n\t\t\t$j(\r\n\t\t\t\t\"input:radio[name=rbIDPAVLOptionalFieldsInMsgsDigitalPorts][value=\" + props.OptionalFieldsDef.DigitalPorts + \"]\"\r\n\t\t\t).prop(\"checked\", true);\r\n\t\t}\r\n\r\n\t\t$j(\"#txtIDPAVLPositionMsgInterval\").val(props.PositionMsgInterval);\r\n\r\n\t\t// i/o properties\r\n\t\t$j(\"#ddlIDPAVLFuncDigOut1\").val(props.FuncDigOut1);\r\n\t\t$j(\"#ddlIDPAVLFuncDigOut2\").val(props.FuncDigOut2);\r\n\t\t$j(\"#ddlIDPAVLFuncDigOut3\").val(props.FuncDigOut3);\r\n\t\t$j(\"#ddlIDPAVLFuncDigOut4\").val(props.FuncDigOut4);\r\n\t\t$j(\"#ddlIDPAVLFuncDigOut5\").val(props.FuncDigOut5);\r\n\t\t$j(\"#ddlIDPAVLFuncDigOut6\").val(props.FuncDigOut6);\r\n\r\n\t\t$j(\"#ddlIDPAVLFuncDigInp1\").val(props.FuncDigInp1);\r\n\t\t$j(\"#ddlIDPAVLFuncDigInp2\").val(props.FuncDigInp2);\r\n\t\t$j(\"#ddlIDPAVLFuncDigInp3\").val(props.FuncDigInp3);\r\n\t\t$j(\"#ddlIDPAVLFuncDigInp4\").val(props.FuncDigInp4);\r\n\t\t$j(\"#ddlIDPAVLFuncDigInp5\").val(props.FuncDigInp5);\r\n\t\t$j(\"#ddlIDPAVLFuncDigInp6\").val(props.FuncDigInp6);\r\n\t\t$j(\"#ddlIDPAVLFuncDigInp7\").val(props.FuncDigInp7);\r\n\t\t$j(\"#ddlIDPAVLFuncDigInp8\").val(props.FuncDigInp8);\r\n\t\t$j(\"#ddlIDPAVLFuncDigInp9\").val(props.FuncDigInp9);\r\n\t\t$j(\"#ddlIDPAVLFuncDigInp10\").val(props.FuncDigInp10);\r\n\t\t$j(\"#ddlIDPAVLFuncDigInp11\").val(props.FuncDigInp11);\r\n\t\t$j(\"#ddlIDPAVLFuncDigInp12\").val(props.FuncDigInp12);\r\n\t\t$j(\"#ddlIDPAVLFuncDigInp13\").val(props.FuncDigInp13);\r\n\t\t$j(\"#txtIDPAVLSensorReportingInterval\").val(props.SensorReportingInterval);\r\n\t\tif (props.DigStatesDef != null) {\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLDigStatesDefIgnitionOn][value=\" + props.DigStatesDef.IgnitionOn + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLDigStatesDefSeatbeltOff][value=\" + props.DigStatesDef.SeatbeltBuckled + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLDigStatesDefSM1Active][value=\" + props.DigStatesDef.SM1Active + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLDigStatesDefSM2Active][value=\" + props.DigStatesDef.SM2Active + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLDigStatesDefSM3Active][value=\" + props.DigStatesDef.SM3Active + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t\t$j(\"input:radio[name=rbIDPAVLDigStatesDefSM4Active][value=\" + props.DigStatesDef.SM4Active + \"]\").prop(\r\n\t\t\t\t\"checked\",\r\n\t\t\t\ttrue\r\n\t\t\t);\r\n\t\t}\r\n\t\tif (props.Sensor1Properties != null) {\r\n\t\t\t$j(\"#txtIDPAVLSensor1SourceSIN\").val(props.Sensor1Properties.SourceSIN);\r\n\t\t\t$j(\"#txtIDPAVLSensor1SourcePIN\").val(props.Sensor1Properties.SourcePIN);\r\n\t\t\t$j(\"#txtIDPAVLSensor1NormalSampleInterval\").val(props.Sensor1Properties.NormalSampleInterval);\r\n\t\t\t$j(\"#txtIDPAVLSensor1LpmSampleInterval\").val(props.Sensor1Properties.LpmSampleInterval);\r\n\t\t\t$j(\"#txtIDPAVLSensor1MaxReportInterval\").val(props.Sensor1Properties.MaxReportInterval);\r\n\t\t\t$j(\"#txtIDPAVLSensor1ChangeThld\").val(props.Sensor1Properties.ChangeThld);\r\n\t\t\t$j(\"#txtIDPAVLSensor1MinThld\").val(props.Sensor1Properties.MinThld);\r\n\t\t\t$j(\"#txtIDPAVLSensor1MaxThld\").val(props.Sensor1Properties.MaxThld);\r\n\t\t}\r\n\t\tif (props.Sensor2Properties != null) {\r\n\t\t\t$j(\"#txtIDPAVLSensor2SourceSIN\").val(props.Sensor2Properties.SourceSIN);\r\n\t\t\t$j(\"#txtIDPAVLSensor2SourcePIN\").val(props.Sensor2Properties.SourcePIN);\r\n\t\t\t$j(\"#txtIDPAVLSensor2NormalSampleInterval\").val(props.Sensor2Properties.NormalSampleInterval);\r\n\t\t\t$j(\"#txtIDPAVLSensor2LpmSampleInterval\").val(props.Sensor2Properties.LpmSampleInterval);\r\n\t\t\t$j(\"#txtIDPAVLSensor2MaxReportInterval\").val(props.Sensor2Properties.MaxReportInterval);\r\n\t\t\t$j(\"#txtIDPAVLSensor2ChangeThld\").val(props.Sensor2Properties.ChangeThld);\r\n\t\t\t$j(\"#txtIDPAVLSensor2MinThld\").val(props.Sensor2Properties.MinThld);\r\n\t\t\t$j(\"#txtIDPAVLSensor2MaxThld\").val(props.Sensor2Properties.MaxThld);\r\n\t\t}\r\n\t\tif (props.Sensor3Properties != null) {\r\n\t\t\t$j(\"#txtIDPAVLSensor3SourceSIN\").val(props.Sensor3Properties.SourceSIN);\r\n\t\t\t$j(\"#txtIDPAVLSensor3SourcePIN\").val(props.Sensor3Properties.SourcePIN);\r\n\t\t\t$j(\"#txtIDPAVLSensor3NormalSampleInterval\").val(props.Sensor3Properties.NormalSampleInterval);\r\n\t\t\t$j(\"#txtIDPAVLSensor3LpmSampleInterval\").val(props.Sensor3Properties.LpmSampleInterval);\r\n\t\t\t$j(\"#txtIDPAVLSensor3MaxReportInterval\").val(props.Sensor3Properties.MaxReportInterval);\r\n\t\t\t$j(\"#txtIDPAVLSensor3ChangeThld\").val(props.Sensor3Properties.ChangeThld);\r\n\t\t\t$j(\"#txtIDPAVLSensor3MinThld\").val(props.Sensor3Properties.MinThld);\r\n\t\t\t$j(\"#txtIDPAVLSensor3MaxThld\").val(props.Sensor3Properties.MaxThld);\r\n\t\t}\r\n\t\tif (props.Sensor4Properties != null) {\r\n\t\t\t$j(\"#txtIDPAVLSensor4SourceSIN\").val(props.Sensor4Properties.SourceSIN);\r\n\t\t\t$j(\"#txtIDPAVLSensor4SourcePIN\").val(props.Sensor4Properties.SourcePIN);\r\n\t\t\t$j(\"#txtIDPAVLSensor4NormalSampleInterval\").val(props.Sensor4Properties.NormalSampleInterval);\r\n\t\t\t$j(\"#txtIDPAVLSensor4LpmSampleInterval\").val(props.Sensor4Properties.LpmSampleInterval);\r\n\t\t\t$j(\"#txtIDPAVLSensor4MaxReportInterval\").val(props.Sensor4Properties.MaxReportInterval);\r\n\t\t\t$j(\"#txtIDPAVLSensor4ChangeThld\").val(props.Sensor4Properties.ChangeThld);\r\n\t\t\t$j(\"#txtIDPAVLSensor4MinThld\").val(props.Sensor4Properties.MinThld);\r\n\t\t\t$j(\"#txtIDPAVLSensor4MaxThld\").val(props.Sensor4Properties.MaxThld);\r\n\t\t}\r\n\t}\r\n\r\n\tvar utility = result.UtilityConfigurations;\r\n\tvar props = utility.UtilityConfigurations;\r\n\tif (utility.LastRetrievedOn == null) {\r\n\t\t$j(\"#IDPUtilityConfigurationsLastRetrieved\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\"#IDPUtilityConfigurationsLastRetrieved\").text(utility.LastRetrievedOn);\r\n\t}\r\n\tif (utility.LastQueriedOn == null) {\r\n\t\t$j(\"#IDPUtilityConfigurationsLastQueried\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\"#IDPUtilityConfigurationsLastQueried\").text(utility.LastQueriedOn);\r\n\t}\r\n\tif (props != null) {\r\n\t\t// todo: utility configuration properties\r\n\t}\r\n\r\n\tvar arc = result.ARCProperties;\r\n\tvar props = arc.ARCProperties;\r\n\tif (arc.LastRetrievedOn == null) {\r\n\t\t$j(\"#IDPARCPropertiesLastRetrieved\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\"#IDPARCPropertiesLastRetrieved\").text(arc.LastRetrievedOn);\r\n\t}\r\n\tif (arc.LastQueriedOn == null) {\r\n\t\t$j(\"#IDPARCPropertiesLastQueried\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\"#IDPARCPropertiesLastQueried\").text(arc.LastQueriedOn);\r\n\t}\r\n\tif (props != null) {\r\n\t\tif (props.EIO1 != null) {\r\n\t\t\t$j(\"#ddlIDPARCEIO1EventType\").val(props.EIO1.EventType);\r\n\t\t\t$j(\"#txtIDPARCEIO1TriggerDebounce\").val(props.EIO1.TriggerDebounce);\r\n\t\t\t$j(\"#txtIDPARCEIO1AnalogThresholds\").val(props.EIO1.AnalogThresholds);\r\n\t\t\t$j(\"#txtIDPARCEIO1Value\").val(props.EIO1.Value);\r\n\t\t}\r\n\t\tif (props.EIO2 != null) {\r\n\t\t\t$j(\"#ddlIDPARCEIO2EventType\").val(props.EIO2.EventType);\r\n\t\t\t$j(\"#txtIDPARCEIO2TriggerDebounce\").val(props.EIO2.TriggerDebounce);\r\n\t\t\t$j(\"#txtIDPARCEIO2AnalogThresholds\").val(props.EIO2.AnalogThresholds);\r\n\t\t\t$j(\"#txtIDPARCEIO2Value\").val(props.EIO2.Value);\r\n\t\t}\r\n\t\tif (props.EIO3 != null) {\r\n\t\t\t$j(\"#ddlIDPARCEIO3EventType\").val(props.EIO3.EventType);\r\n\t\t\t$j(\"#txtIDPARCEIO3TriggerDebounce\").val(props.EIO3.TriggerDebounce);\r\n\t\t\t$j(\"#txtIDPARCEIO3AnalogThresholds\").val(props.EIO3.AnalogThresholds);\r\n\t\t\t$j(\"#txtIDPARCEIO3Value\").val(props.EIO3.Value);\r\n\t\t}\r\n\t\tif (props.EIO4 != null) {\r\n\t\t\t$j(\"#ddlIDPARCEIO4EventType\").val(props.EIO4.EventType);\r\n\t\t\t$j(\"#txtIDPARCEIO4TriggerDebounce\").val(props.EIO4.TriggerDebounce);\r\n\t\t\t$j(\"#txtIDPARCEIO4AnalogThresholds\").val(props.EIO4.AnalogThresholds);\r\n\t\t\t$j(\"#txtIDPARCEIO4Value\").val(props.EIO4.Value);\r\n\t\t}\r\n\t\t$j(\"#txtIDPARCHeartbeatInterval\").val(props.HeartbeatInterval);\r\n\t\t$j(\"input:radio[name=rbIDPARCIsSatQualityReported][value=\" + props.IsSatQualityReported + \"]\").prop(\r\n\t\t\t\"checked\",\r\n\t\t\ttrue\r\n\t\t);\r\n\t\t$j(\"#ddlIDPARCModemPowerMode\").val(props.ModemPowerMode);\r\n\t\t$j(\"#ddlIDPARCModemWakeUpInterval\").val(props.ModemWakeUpInterval);\r\n\t\t$j(\"input:radio[name=rbIDPARCFlashLedOnTransmit][value=\" + props.FlashLedOnTransmit + \"]\").prop(\"checked\", true);\r\n\t\t$j(\"input:radio[name=rbIDPARCEnablePositionReporting][value=\" + props.EnablePositionReporting + \"]\").prop(\r\n\t\t\t\"checked\",\r\n\t\t\ttrue\r\n\t\t);\r\n\t\t$j(\"#txtIDPARCMotionTestInterval\").val(props.MotionTestInterval);\r\n\t\t$j(\"#txtIDPARCDistanceThreshold\").val(props.DistanceThreshold);\r\n\t\t$j(\"#txtIDPARCLedInstallFlashTime\").val(props.LedInstallFlashTime);\r\n\t\t$j(\"#txtIDPARCContractHour\").val(props.ContractHour);\r\n\t\t$j(\"#txtIDPARCMaxContractDispersion\").val(props.MaxContractDispersion);\r\n\t\t$j(\"#txtIDPARCDispersionOffsetSeconds\").val(props.DispersionOffsetSeconds);\r\n\t\t$j(\"input:radio[name=rbIDPARCSendContractDayValues][value=\" + props.SendContractDayValues + \"]\").prop(\r\n\t\t\t\"checked\",\r\n\t\t\ttrue\r\n\t\t);\r\n\t\t$j(\"#txtIDPARCSupplyVoltageThreshold\").val(props.SupplyVoltageThreshold);\r\n\t\t$j(\"#txtIDPARCSupplyVoltageTriggerDebounce\").val(props.SupplyVoltageTriggerDebounce);\r\n\t\t$j(\"#txtIDPARCSupplyVoltage\").val(props.SupplyVoltage);\r\n\t\t$j(\"input:radio[name=rbIDPARCIsDebugEnabled][value=\" + props.IsDebugEnabled + \"]\").prop(\"checked\", true);\r\n\t\t$j(\"#txtIDPARCVersion\").val(props.Version);\r\n\t}\r\n\r\n\t// garmin parameters\r\n\tvar garmin = result.GarminProperties;\r\n\tvar props = garmin.GarminProperties;\r\n\r\n\tif (garmin.LastRetrievedOn == null) {\r\n\t\t$j(\"#IDPGarminParametersLastRetrieved\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\"#IDPGarminParametersLastRetrieved\").text(garmin.LastRetrievedOn);\r\n\t}\r\n\tif (garmin.LastQueriedOn == null) {\r\n\t\t$j(\"#IDPGarminParametersLastQueried\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\"#IDPGarminParametersLastQueried\").text(garmin.LastQueriedOn);\r\n\t}\r\n\tif (props != null) {\r\n\t\t// populate\r\n\t\t$j(\"input:radio[name=rbIDPGarminFmiEnabled][value=\" + props.FmiEnabled + \"]\").prop(\"checked\", true);\r\n\t\t$j(\"input:radio[name=rbIDPGarminSafeModeEnabled][value=\" + props.SafeModeEnabled + \"]\").prop(\"checked\", true);\r\n\t\t$j(\"#txtIDPGarminDispatchIconText\").val(props.DispatchIconText);\r\n\t\t$j(\"#ddlIDPGarminDeleteGarminData\").val(props.DeleteGarminData);\r\n\t\t$j(\"#txtIDPGarminWelcomeMessage\").val(props.WelcomeMessage);\r\n\t\t$j(\"input:radio[name=rbIDPGarminOpenTextMsgAllowed][value=\" + props.OpenTextMsgAllowed + \"]\").prop(\"checked\", true);\r\n\t\t$j(\"input:radio[name=rbIDPGarminTextingRequiresDriverId][value=\" + props.TextingRequiresDriverId + \"]\").prop(\r\n\t\t\t\"checked\",\r\n\t\t\ttrue\r\n\t\t);\r\n\t\t$j(\"input:radio[name=rbIDPGarminMultiDriverEnabled][value=\" + props.MultiDriverEnabled + \"]\").prop(\"checked\", true);\r\n\t\t$j(\"input:radio[name=rbIDPGarminDriverPwdEnabled][value=\" + props.DriverPwdEnabled + \"]\").prop(\"checked\", true);\r\n\t\t$j(\"input:radio[name=rbIDPGarminDriverIdCaseSensitive][value=\" + props.DriverIdCaseSensitive + \"]\").prop(\r\n\t\t\t\"checked\",\r\n\t\t\ttrue\r\n\t\t);\r\n\t\t$j(\"input:radio[name=rbIDPGarminPasswordCaseSensitive][value=\" + props.PasswordCaseSensitive + \"]\").prop(\r\n\t\t\t\"checked\",\r\n\t\t\ttrue\r\n\t\t);\r\n\t\t$j(\"input:radio[name=rbIDPGarminReportFailedLogins][value=\" + props.ReportFailedLogins + \"]\").prop(\"checked\", true);\r\n\t\t$j(\"#txtIDPGarminAutoArrivalTime\").val(props.AutoArrivalTime);\r\n\t\t$j(\"#txtIDPGarminAutoArrivalDistance\").val(props.AutoArrivalDistance);\r\n\t\t$j(\"#ddlIDPGarminSpeedLimitMode\").val(props.SpeedLimitMode);\r\n\t\t$j(\"#txtIDPGarminSpeedLimitThreshold\").val(props.SpeedLimitThreshold);\r\n\t\t$j(\"#txtIDPGarminSpeedLimitTimeOver\").val(props.SpeedLimitTimeOver);\r\n\t\t$j(\"#txtIDPGarminSpeedLimitTimeUnder\").val(props.SpeedLimitTimeUnder);\r\n\t\t$j(\"input:radio[name=rbIDPGarminSpeedLimitAlertUser][value=\" + props.SpeedLimitAlertUser + \"]\").prop(\r\n\t\t\t\"checked\",\r\n\t\t\ttrue\r\n\t\t);\r\n\t\t$j(\"input:radio[name=rbIDPGarminHosEnabled][value=\" + props.HosEnabled + \"]\").prop(\"checked\", true);\r\n\t\t$j(\"input:radio[name=rbIDPGarminSubmitFormAsFile][value=\" + props.SubmitFormAsFile + \"]\").prop(\"checked\", true);\r\n\t}\r\n\r\n\t// immobilizer/driver admin\r\n\tvar immobilizer = result.ImmobilizerProperties;\r\n\tvar props = immobilizer.Properties;\r\n\tif (immobilizer.LastRetrievedOn == null) {\r\n\t\t$(\"#IDPImmobilizerParametersLastRetrieved\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$(\"#IDPImmobilizerParametersLastRetrieved\").text(immobilizer.LastRetrievedOn);\r\n\t}\r\n\tif (immobilizer.LastQueriedOn == null) {\r\n\t\t$(\"#IDPImmobilizerParametersLastQueried\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$(\"#IDPImmobilizerParametersLastQueried\").text(immobilizer.LastQueriedOn);\r\n\t}\r\n\tif (props != null) {\r\n\t\t$(\"#txtIDPImmobilizerDriverLoginCheckInterval\").val(props.DriverLoginCheckInterval);\r\n\t\t$(\"input:radio[name=rbIDPImmobilizerNotifyOnlyWhenMoving][value=\" + props.NotifyOnlyWhenMoving + \"]\").prop(\r\n\t\t\t\"checked\",\r\n\t\t\ttrue\r\n\t\t);\r\n\t}\r\n\r\n\t// updater\r\n\tpopulateIDPUpdaterInformation(result.UpdaterInfo);\r\n\r\n\t// crypto\r\n\tpopulateIDPCryptoInformation(result.CryptoInfo);\r\n\r\n\t// gateway counters\r\n\tvar counters = result.GatewayCounters;\r\n\t$j(\"#CounterSatellite\").text(counters.CounterSatellite);\r\n\t$j(\"#CounterSatelliteBytes\").text(counters.CounterSatelliteBytes);\r\n\t$j(\"#CounterGPRS\").text(counters.CounterGPRS);\r\n\t$j(\"#CounterGPRSBytes\").text(counters.CounterGPRSBytes);\r\n\tif (counters.CountersResetOn == null) {\r\n\t\t$j(\"#AVLCountersLastReset\").text(strings.NEVER);\r\n\t} else {\r\n\t\t$j(\"#AVLCountersLastReset\").text(counters.CountersResetOn);\r\n\t}\r\n\r\n\t// garmin info\r\n\tvar garminInfos = result.GarminInfo;\r\n\tvar infoData = [];\r\n\tfor (var i = 0; i < garminInfos.Responses.length; i++) {\r\n\t\tvar item = garminInfos.Responses[i];\r\n\t\tif (item.Info != null) {\r\n\t\t\tvar protocols = item.Info.SupportedProtocols;\r\n\t\t\tif (protocols != null) {\r\n\t\t\t\tprotocols = protocols.split(\",\").join(\", \");\r\n\t\t\t}\r\n\t\t\tinfoData.push([\r\n\t\t\t\titem.Info.Latitude,\r\n\t\t\t\titem.Info.Longitude,\r\n\t\t\t\tprotocols,\r\n\t\t\t\titem.Info.UnitId,\r\n\t\t\t\titem.Info.ProductId,\r\n\t\t\t\titem.Info.SwVer,\r\n\t\t\t\titem.CreatedOn,\r\n\t\t\t]);\r\n\t\t}\r\n\t}\r\n\t$(\"#IDPGarminInfos\").dataTable({\r\n\t\tdata: infoData,\r\n\t\tdestroy: true,\r\n\t\tfilter: false,\r\n\t\tinfo: false,\r\n\t\tjQueryUI: true,\r\n\t\tautoWidth: false,\r\n\t\tlengthChange: false,\r\n\t\tpaging: true,\r\n\t\tpageLength: 3,\r\n\t\tdeferRender: true,\r\n\t\torder: [[6, \"desc\"]],\r\n\t\tcolumnDefs: [\r\n\t\t\t{\r\n\t\t\t\ttargets: \"_all\",\r\n\t\t\t\trender: $.fn.dataTable.render.text(),\r\n\t\t\t},\r\n\t\t],\r\n\t\tcolumns: [{}, {}, {}, {}, {}, {}, {}],\r\n\t\tlanguage: strings.DATATABLE,\r\n\t});\r\n\r\n\t// diagnostics\r\n\tvar diagnostics = result.AVLDiagnostics;\r\n\tvar diagData = [];\r\n\r\n\tfor (var i = 0; i < diagnostics.Responses.length; i++) {\r\n\t\tvar item = diagnostics.Responses[i];\r\n\t\tif (item.Diagnostics != null) {\r\n\t\t\tdiagData.push([\r\n\t\t\t\titem.Diagnostics.SatCnr / 100,\r\n\t\t\t\titem.Diagnostics.CellRssi,\r\n\t\t\t\titem.Diagnostics.PowerUpTime,\r\n\t\t\t\titem.Diagnostics.BattChargerState,\r\n\t\t\t\titem.Diagnostics.BattVoltage != null ? item.Diagnostics.BattVoltage + \"mV\" : \"\",\r\n\t\t\t\titem.Diagnostics.ExtVoltage != null ? item.Diagnostics.ExtVoltage + \"mV\" : \"\",\r\n\t\t\t\titem.Diagnostics.Temperature != null ? item.Diagnostics.Temperature + \"°C\" : \"\",\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line1 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line2 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line3 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line4 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line5 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line6 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line7 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line8 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line9 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line10 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line11 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line12 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line13 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line14 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line15 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line16 ? strings.ON : strings.OFF,\r\n\t\t\t\titem.Diagnostics.DigitalPorts.Line17 ? strings.ON : strings.OFF,\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.InLPM),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.OnMainPower),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.Speeding),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.Moving),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.Towing),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.GPSJammed),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.CellJammed),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.Tamper),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.Blocked),\r\n\t\t\t\t//disabledCheckbox(item.Diagnostics.AvlStates.AccelerometerEnabled),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.SeatbeltViolation),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.IgnitionOn),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.EngineIdling),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.SM1Active),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.SM2Active),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.SM3Active),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.SM4Active),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.AvlStates.GeoDwelling),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.DigStatesDefMap.IgnitionOn),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.DigStatesDefMap.SeatbeltBuckled),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.DigStatesDefMap.SM1Active),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.DigStatesDefMap.SM2Active),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.DigStatesDefMap.SM3Active),\r\n\t\t\t\tdisabledCheckboxEl(item.Diagnostics.DigStatesDefMap.SM4Active),\r\n\t\t\t\titem.CreatedOn,\r\n\t\t\t]);\r\n\t\t}\r\n\t}\r\n\r\n\t$(\"#AVLDiagnostics\").dataTable({\r\n\t\tdata: diagData,\r\n\t\tscrollX: \"100%\",\r\n\t\t//\"sScrollXInner\": \"100%\",\r\n\t\tscrollCollapse: false,\r\n\t\tdestroy: true,\r\n\t\tfilter: false,\r\n\t\tinfo: false,\r\n\t\tjQueryUI: true,\r\n\t\tautoWidth: true,\r\n\t\tlengthChange: false,\r\n\t\tpaging: true,\r\n\t\tpageLength: 3,\r\n\t\tdeferRender: true,\r\n\t\torder: [[47, \"desc\"]],\r\n\t\tcolumnDefs: [\r\n\t\t\t{\r\n\t\t\t\ttargets: \"_all\",\r\n\t\t\t\trender: $.fn.dataTable.render.text(),\r\n\t\t\t},\r\n\t\t],\r\n\t\tcolumns: [\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\", render: renderDomElement },\r\n\t\t\t{ sWidth: \"50px\" },\r\n\t\t],\r\n\t\tlanguage: strings.DATATABLE,\r\n\t});\r\n\r\n\tvar commandLog = result.CommandLog;\r\n\trenderIDPCommandLog(commandLog.Commands);\r\n\r\n\tconsole.log(result);\r\n\tvar serviceLists = result.ServiceLists;\r\n\tvar serviceVersions = serviceLists.Versions;\r\n\tvar serviceListData = [];\r\n\tvar activeServices = null;\r\n\r\n\tfor (var i = 0; i < serviceLists.Responses.length; i++) {\r\n\t\tvar item = serviceLists.Responses[i];\r\n\t\tif (item.ServiceList != null) {\r\n\t\t\tif (activeServices == null) {\r\n\t\t\t\tactiveServices = {};\r\n\t\t\t\tif (item.ServiceList.Report == true) {\r\n\t\t\t\t\tactiveServices.Report = serviceVersions.Report;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.Position == true) {\r\n\t\t\t\t\tactiveServices.Position = serviceVersions.Position;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.AVL == true) {\r\n\t\t\t\t\tactiveServices.AVL = serviceVersions.AVL;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.GarminFMI == true) {\r\n\t\t\t\t\tactiveServices.GarminFMI = serviceVersions.GarminFMI;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.GarminDispatch == true) {\r\n\t\t\t\t\tactiveServices.GarminDispatch = serviceVersions.GarminDispatch;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.GarminExt == true) {\r\n\t\t\t\t\tactiveServices.GarminExt = serviceVersions.GarminExt;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.J1939 == true) {\r\n\t\t\t\t\tactiveServices.J1939 = serviceVersions.J1939;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.Analytics == true) {\r\n\t\t\t\t\tactiveServices.Analytics = serviceVersions.Analytics;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.ARC == true) {\r\n\t\t\t\t\tactiveServices.ARC = serviceVersions.ARC;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.Utility == true) {\r\n\t\t\t\t\tactiveServices.Utility = serviceVersions.Utility;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.PackageVersion != null) {\r\n\t\t\t\t\tactiveServices.PackageVersion = item.ServiceList.PackageVersion;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.FLS == true) {\r\n\t\t\t\t\tactiveServices.FLS = serviceVersions.FLS;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.VMS == true) {\r\n\t\t\t\t\tactiveServices.VMS = serviceVersions.VMS;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.Unibox == true) {\r\n\t\t\t\t\tactiveServices.Unibox = serviceVersions.Unibox;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.Updater == true) {\r\n\t\t\t\t\tactiveServices.Updater = serviceVersions.Updater;\r\n\t\t\t\t}\r\n\t\t\t\tif (item.ServiceList.Crypto == true) {\r\n\t\t\t\t\tactiveServices.Crypto = serviceVersions.Crypto;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tserviceListData.push([\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.Report),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.Position),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.AVL),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.GarminFMI),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.GarminDispatch),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.GarminExt),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.J1939),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.Analytics),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.Utility),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.ARC),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.FLS),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.VMS),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.Unibox),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.EyeAlert),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.Immobilizer),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.Updater),\r\n\t\t\t\tdisabledCheckboxEl(item.ServiceList.Crypto),\r\n\t\t\t\titem.CreatedOn,\r\n\t\t\t]);\r\n\t\t}\r\n\t}\r\n\t// get latest Service List (if any)\r\n\tif (serviceLists.Responses.length > 0) {\r\n\t\tvar latestServiceList = serviceLists.Responses[0].ServiceList;\r\n\t\tvar body = document.getElementById(\"IDPServiceListing\").querySelector(\"tbody\");\r\n\t\tvar sins = [];\r\n\t\tvar serviceListNames = [];\r\n\t\tserviceListNames[19] = \"Report\";\r\n\t\tserviceListNames[20] = \"Position\";\r\n\t\tserviceListNames[65] = \"ARC\";\r\n\t\tserviceListNames[115] = \"VMS\";\r\n\t\tserviceListNames[121] = \"J1939\";\r\n\t\tserviceListNames[122] = \"Analytics\";\r\n\t\tserviceListNames[124] = \"GarminDispatch\";\r\n\t\tserviceListNames[125] = \"GarminFMI\";\r\n\t\tserviceListNames[126] = \"AVL\";\r\n\t\tserviceListNames[127] = \"Utility\";\r\n\t\tserviceListNames[128] = \"GarminExt\";\r\n\t\tserviceListNames[130] = \"FLS\";\r\n\t\tserviceListNames[136] = \"GSE_CustomFields\";\r\n\t\tserviceListNames[148] = \"GSE_EyeAlert\";\r\n\t\tserviceListNames[165] = \"Unibox\";\r\n\t\tserviceListNames[160] = \"GSE_Immobilizer\";\r\n\t\tserviceListNames[199] = \"CellMonitor\";\r\n\t\tserviceListNames[224] = \"GSE_Garmin\";\r\n\t\tserviceListNames[226] = \"GSE_AAT\";\r\n\t\tserviceListNames[228] = \"GSE_Updater\";\r\n\t\tserviceListNames[255] = \"GSE_Crypto\";\r\n\r\n\t\tfor (var sin in serviceListNames) {\r\n\t\t\tif (latestServiceList.EnabledSINs.indexOf(parseInt(sin)) != -1) {\r\n\t\t\t\tif (sins.indexOf(parseInt(sin)) == -1) {\r\n\t\t\t\t\tsins.push(parseInt(sin));\r\n\t\t\t\t}\r\n\t\t\t} else if (latestServiceList.DisabledSINs.indexOf(parseInt(sin)) != -1) {\r\n\t\t\t\tif (sins.indexOf(sin) == -1) {\r\n\t\t\t\t\tsins.push(parseInt(sin));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t// add user custom services (SIN > 130)\r\n\t\tfor (var i = 0; i < latestServiceList.EnabledSINs.length; i++) {\r\n\t\t\tif (latestServiceList.EnabledSINs[i] > 130) {\r\n\t\t\t\tif (sins.indexOf(parseInt(latestServiceList.EnabledSINs[i])) == -1) {\r\n\t\t\t\t\tsins.push(parseInt(latestServiceList.EnabledSINs[i]));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (var i = 0; i < latestServiceList.DisabledSINs.length; i++) {\r\n\t\t\tif (latestServiceList.DisabledSINs[i] > 130) {\r\n\t\t\t\tif (sins.indexOf(parseInt(latestServiceList.DisabledSINs[i])) == -1) {\r\n\t\t\t\t\tsins.push(parseInt(latestServiceList.DisabledSINs[i]));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tvar rows = [];\r\n\t\tfor (var i = 0; i < sins.length; i++) {\r\n\t\t\tvar sin = sins[i];\r\n\t\t\tvar disabled = latestServiceList.DisabledSINs.indexOf(parseInt(sin)) !== -1;\r\n\t\t\tvar name = serviceListNames[sin];\r\n\t\t\trows.push(\r\n\t\t\t\tel(\"tr\", [\r\n\t\t\t\t\tel(\"td\"),\r\n\t\t\t\t\tel(\"td\", sin),\r\n\t\t\t\t\tel(\"td\", name),\r\n\t\t\t\t\tel(\"td\", disabledCheckboxEl(!disabled)),\r\n\t\t\t\t\tel(\"td\", [\r\n\t\t\t\t\t\tel(\"div.form-check\", [\r\n\t\t\t\t\t\t\tel(\"input#SIN\" + sin + \"Enable.form-check-input.enable\", {\r\n\t\t\t\t\t\t\t\ttype: \"radio\",\r\n\t\t\t\t\t\t\t\tname: \"SIN\" + sin,\r\n\t\t\t\t\t\t\t\tvalue: \"1\",\r\n\t\t\t\t\t\t\t\tdataset: { sin: sin },\r\n\t\t\t\t\t\t\t}),\r\n\t\t\t\t\t\t\tel(\"label.form-check-label\", { for: \"SIN\" + sin + \"Enable\" }, strings.ENABLE),\r\n\t\t\t\t\t\t]),\r\n\t\t\t\t\t\tel(\"div.form-check\", [\r\n\t\t\t\t\t\t\tel(\"input#SIN\" + sin + \"Disable.form-check-input.disable\", {\r\n\t\t\t\t\t\t\t\ttype: \"radio\",\r\n\t\t\t\t\t\t\t\tname: \"SIN\" + sin,\r\n\t\t\t\t\t\t\t\tvalue: \"0\",\r\n\t\t\t\t\t\t\t\tdataset: { sin: sin },\r\n\t\t\t\t\t\t\t}),\r\n\t\t\t\t\t\t\tel(\"label.form-check-label\", { for: \"SIN\" + sin + \"Disable\" }, strings.DISABLE),\r\n\t\t\t\t\t\t]),\r\n\t\t\t\t\t]),\r\n\t\t\t\t])\r\n\t\t\t);\r\n\t\t}\r\n\t\tsetChildren(body, rows);\r\n\t}\r\n\r\n\t$j(\"#IDPAgentVersions li\").hide();\r\n\t$j(\"#IDPAgentPackageVersion\").hide();\r\n\tif (activeServices != null) {\r\n\t\tconsole.log(activeServices);\r\n\t\tif (typeof activeServices.Report != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionReport\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.Report == null ? strings.UNKNOWN : activeServices.Report);\r\n\t\t}\r\n\t\tif (typeof activeServices.Position != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionPosition\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.Position == null ? strings.UNKNOWN : activeServices.Position);\r\n\t\t}\r\n\t\tif (typeof activeServices.FLS != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionFLS\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.FLS == null ? strings.UNKNOWN : activeServices.FLS);\r\n\t\t}\r\n\t\tif (typeof activeServices.AVL != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionAVL\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.AVL == null ? strings.UNKNOWN : activeServices.AVL);\r\n\t\t}\r\n\t\tif (typeof activeServices.GarminDispatch != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionGarminDispatch\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.GarminDispatch == null ? strings.UNKNOWN : activeServices.GarminDispatch);\r\n\t\t}\r\n\t\tif (typeof activeServices.ARC != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionARC\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.ARC == null ? strings.UNKNOWN : activeServices.ARC);\r\n\t\t}\r\n\t\tif (typeof activeServices.GarminFMI != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionGarminFMI\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.GarminFMI == null ? strings.UNKNOWN : activeServices.GarminFMI);\r\n\t\t}\r\n\t\tif (typeof activeServices.GarminExt != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionGarminExt\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.GarminExt == null ? strings.UNKNOWN : activeServices.GarminExt);\r\n\t\t}\r\n\t\tif (typeof activeServices.J1939 != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionJ1939\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.J1939 == null ? strings.UNKNOWN : activeServices.J1939);\r\n\t\t}\r\n\t\tif (typeof activeServices.Analytics != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionAnalytics\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.Analytics == null ? strings.UNKNOWN : activeServices.Analytics);\r\n\t\t}\r\n\t\tif (typeof activeServices.Utility != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionUtility\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.Utility == null ? strings.UNKNOWN : activeServices.Utility);\r\n\t\t}\r\n\t\tif (typeof activeServices.VMS != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionVMS\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.VMS == null ? strings.UNKNOWN : activeServices.VMS);\r\n\t\t}\r\n\t\tif (typeof activeServices.Unibox != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionUnibox\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.Unibox == null ? strings.UNKNOWN : activeServices.Unibox);\r\n\t\t}\r\n\t\tif (typeof activeServices.Updater != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionUpdater\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.Updater == null ? strings.UNKNOWN : activeServices.Updater);\r\n\t\t}\r\n\t\tif (typeof activeServices.Crypto != \"undefined\") {\r\n\t\t\t$j(\"#IDPAgentVersionCrypto\")\r\n\t\t\t\t.show()\r\n\t\t\t\t.find(\"span.version\")\r\n\t\t\t\t.text(activeServices.Crypto == null ? strings.UNKNOWN : activeServices.Crypto);\r\n\t\t}\r\n\t\tif (typeof activeServices.PackageVersion != \"undefined\") {\r\n\t\t\tvar version = activeServices.PackageVersion == null ? strings.UNKNOWN : activeServices.PackageVersion;\r\n\t\t\t$j(\"#IDPAgentPackageVersion\").show().find(\"span\").text(version);\r\n\t\t}\r\n\t}\r\n\r\n\t$(\"#IDPServiceLists\").dataTable({\r\n\t\tdata: serviceListData,\r\n\t\tscrollX: \"100%\",\r\n\t\tscrollCollapse: false,\r\n\t\tdestroy: true,\r\n\t\tfilter: false,\r\n\t\tinfo: false,\r\n\t\tjQueryUI: true,\r\n\t\tautoWidth: false,\r\n\t\tlengthChange: false,\r\n\t\tpaging: true,\r\n\t\tpageLength: 3,\r\n\t\tdeferRender: true,\r\n\t\torder: [[17, \"desc\"]],\r\n\t\tcolumnDefs: [\r\n\t\t\t{\r\n\t\t\t\ttargets: \"_all\",\r\n\t\t\t\trender: renderDomElement,\r\n\t\t\t},\r\n\t\t],\r\n\t\tcolumns: [\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{ render: $.fn.dataTable.render.text() },\r\n\t\t],\r\n\t\tlanguage: strings.DATATABLE,\r\n\t});\r\n\r\n\tvar geofenceStatus = result.GeofenceStatus;\r\n\tif (geofenceStatus.Status != null) {\r\n\t\t$j(\"#IDPGeofenceStatusDeviceLastRetrieved\").text(geofenceStatus.Status.CreatedOn);\r\n\t}\r\n\tif (geofenceStatus.Combined != null) {\r\n\t\tvar geoStatusData = [];\r\n\t\tfor (var i = 0; i < geofenceStatus.Combined.length; i++) {\r\n\t\t\tvar item = geofenceStatus.Combined[i];\r\n\t\t\tvar enabled = null;\r\n\t\t\tif (item.Enabled) {\r\n\t\t\t\tenabled = el(\"button.DisableGeofence\", { dataset: { fenceId: item.DeviceId } }, strings.DISABLE);\r\n\t\t\t}\r\n\t\t\tgeoStatusData.push([\r\n\t\t\t\titem.DeviceId,\r\n\t\t\t\tdisabledCheckboxEl(item.Enabled),\r\n\t\t\t\tdisabledCheckboxEl(item.Inside),\r\n\t\t\t\tdisabledCheckboxEl(item.Outside),\r\n\t\t\t\titem.PortalId,\r\n\t\t\t\titem.Fence,\r\n\t\t\t\titem.Alert,\r\n\t\t\t\titem.Filters,\r\n\t\t\t\tenabled,\r\n\t\t\t]);\r\n\t\t}\r\n\t\t$(\"#IDPGeofenceStatus\").dataTable({\r\n\t\t\tdata: geoStatusData,\r\n\t\t\tdestroy: true,\r\n\t\t\tfilter: false,\r\n\t\t\tinfo: false,\r\n\t\t\tjQueryUI: true,\r\n\t\t\tautoWidth: false,\r\n\t\t\tlengthChange: false,\r\n\t\t\tpaging: false,\r\n\t\t\tpageLength: 10,\r\n\t\t\tdeferRender: true,\r\n\t\t\tcolumnDefs: [\r\n\t\t\t\t{\r\n\t\t\t\t\ttargets: \"_all\",\r\n\t\t\t\t\trender: $.fn.dataTable.render.text(),\r\n\t\t\t\t},\r\n\t\t\t],\r\n\t\t\tcolumns: [\r\n\t\t\t\t{},\r\n\t\t\t\t{ render: renderDomElement },\r\n\t\t\t\t{ render: renderDomElement },\r\n\t\t\t\t{ render: renderDomElement },\r\n\t\t\t\t{},\r\n\t\t\t\t{},\r\n\t\t\t\t{},\r\n\t\t\t\t{},\r\n\t\t\t\t{ render: renderDomElement },\r\n\t\t\t],\r\n\t\t\tlanguage: strings.DATATABLE,\r\n\t\t\tdrawCallback: function (oSettings) {},\r\n\t\t});\r\n\t}\r\n\r\n\t// sleep schedules\r\n\tvar modemRegistrations = result.ModemRegistrations;\r\n\tvar modemData = [];\r\n\r\n\tfor (var i = 0; i < modemRegistrations.Responses.length; i++) {\r\n\t\tvar item = modemRegistrations.Responses[i];\r\n\t\tif (item.ModemRegistration != null) {\r\n\t\t\tmodemData.push([\r\n\t\t\t\titem.ModemRegistration.HardwareMajorVersion,\r\n\t\t\t\titem.ModemRegistration.HardwareMinorVersion,\r\n\t\t\t\titem.ModemRegistration.SoftwareMajorVersion,\r\n\t\t\t\titem.ModemRegistration.SoftwareMinorVersion,\r\n\t\t\t\titem.ModemRegistration.Product,\r\n\t\t\t\titem.ModemRegistration.WakeupPeriod,\r\n\t\t\t\titem.ModemRegistration.LastResetReason,\r\n\t\t\t\titem.ModemRegistration.VirtualCarrier,\r\n\t\t\t\titem.ModemRegistration.Beam,\r\n\t\t\t\titem.ModemRegistration.Vain,\r\n\t\t\t\titem.ModemRegistration.OperatorTxState,\r\n\t\t\t\titem.ModemRegistration.UserTxState,\r\n\t\t\t\titem.ModemRegistration.BroadcastIDCount,\r\n\t\t\t\titem.CreatedOn,\r\n\t\t\t]);\r\n\t\t}\r\n\t}\r\n\r\n\t$(\"#IDPModemRegistrations\").dataTable({\r\n\t\tdata: modemData,\r\n\t\tscrollX: \"100%\",\r\n\t\tscrollCollapse: false,\r\n\t\tdestroy: true,\r\n\t\tfilter: false,\r\n\t\tinfo: false,\r\n\t\tjQueryUI: true,\r\n\t\tautoWidth: false,\r\n\t\tlengthChange: false,\r\n\t\tpaging: true,\r\n\t\tpageLength: 3,\r\n\t\tdeferRender: true,\r\n\t\torder: [[13, \"desc\"]],\r\n\t\tcolumnDefs: [\r\n\t\t\t{\r\n\t\t\t\ttargets: \"_all\",\r\n\t\t\t\trender: $.fn.dataTable.render.text(),\r\n\t\t\t},\r\n\t\t],\r\n\t\tcolumns: [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],\r\n\t\tlanguage: strings.DATATABLE,\r\n\t});\r\n\r\n\t// modem registrations\r\n\tvar sleepSchedules = result.SleepSchedules;\r\n\tvar sleepData = [];\r\n\r\n\tfor (var i = 0; i < sleepSchedules.Responses.length; i++) {\r\n\t\tvar item = sleepSchedules.Responses[i];\r\n\t\tif (item.SleepSchedule != null) {\r\n\t\t\tsleepData.push([\r\n\t\t\t\titem.SleepSchedule.WakeupPeriod,\r\n\t\t\t\tdisabledCheckboxEl(item.SleepSchedule.MobileInitiated),\r\n\t\t\t\titem.SleepSchedule.MessageReference,\r\n\t\t\t\titem.CreatedOn,\r\n\t\t\t]);\r\n\t\t}\r\n\t}\r\n\r\n\t$(\"#IDPSleepSchedules\").dataTable({\r\n\t\tdata: sleepData,\r\n\t\tscrollX: \"100%\",\r\n\t\tscrollCollapse: false,\r\n\t\tdestroy: true,\r\n\t\tfilter: false,\r\n\t\tinfo: false,\r\n\t\tjQueryUI: true,\r\n\t\tautoWidth: false,\r\n\t\tlengthChange: false,\r\n\t\tpaging: true,\r\n\t\tpageLength: 3,\r\n\t\tdeferRender: true,\r\n\t\torder: [[3, \"desc\"]],\r\n\t\tcolumnDefs: [\r\n\t\t\t{\r\n\t\t\t\ttargets: \"_all\",\r\n\t\t\t\trender: $.fn.dataTable.render.text(),\r\n\t\t\t},\r\n\t\t],\r\n\t\tcolumns: [{}, { render: renderDomElement }, {}, {}],\r\n\t\tlanguage: strings.DATATABLE,\r\n\t});\r\n\r\n\t// gsm health checks\r\n\tvar healthChecks = result.GSMHealthChecks;\r\n\tvar itemData = [];\r\n\r\n\tfor (var i = 0; i < healthChecks.Responses.length; i++) {\r\n\t\tvar item = healthChecks.Responses[i];\r\n\t\tif (item.HealthCheck != null) {\r\n\t\t\titemData.push([\r\n\t\t\t\titem.HealthCheck.ActiveSIM,\r\n\t\t\t\tdisabledCheckboxEl(item.HealthCheck.NetworkAllowed),\r\n\t\t\t\titem.HealthCheck.LinkStability,\r\n\t\t\t\titem.HealthCheck.RSSI,\r\n\t\t\t\tdisabledCheckboxEl(item.HealthCheck.PowerOnStatus),\r\n\t\t\t\tdisabledCheckboxEl(item.HealthCheck.CoverOpen),\r\n\t\t\t\titem.HealthCheck.SIMStatus,\r\n\t\t\t\titem.HealthCheck.NetworkStatus,\r\n\t\t\t\tdisabledCheckboxEl(item.HealthCheck.APNConnected),\r\n\t\t\t\tdisabledCheckboxEl(item.HealthCheck.ServerConnected),\r\n\t\t\t\titem.HealthCheck.CurrentMode,\r\n\t\t\t\tdisabledCheckboxEl(item.HealthCheck.SIM1Present),\r\n\t\t\t\tdisabledCheckboxEl(item.HealthCheck.SIM2Present),\r\n\t\t\t\titem.CreatedOn, //,\r\n\t\t\t\t//item.Source\r\n\t\t\t]);\r\n\t\t}\r\n\t}\r\n\r\n\t$(\"#GSMHealthChecks\").dataTable({\r\n\t\tdata: itemData,\r\n\t\tscrollX: \"100%\",\r\n\t\tscrollCollapse: false,\r\n\t\tdestroy: true,\r\n\t\tfilter: false,\r\n\t\tinfo: false,\r\n\t\tjQueryUI: true,\r\n\t\tautoWidth: false,\r\n\t\tlengthChange: false,\r\n\t\tpaging: true,\r\n\t\tpageLength: 3,\r\n\t\tdeferRender: true,\r\n\t\torder: [[12, \"desc\"]],\r\n\t\tcolumnDefs: [\r\n\t\t\t{\r\n\t\t\t\ttargets: \"_all\",\r\n\t\t\t\trender: $.fn.dataTable.render.text(),\r\n\t\t\t},\r\n\t\t],\r\n\t\tcolumns: [\r\n\t\t\t{},\r\n\t\t\t{ render: renderDomElement },\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{ render: renderDomElement },\r\n\t\t\t{ render: renderDomElement },\r\n\t\t\t{},\r\n\t\t\t{},\r\n\t\t\t{ render: renderDomElement },\r\n\t\t\t{ render: renderDomElement },\r\n\t\t\t{},\r\n\t\t\t{\r\n\t\t\t\tvisible:\r\n\t\t\t\t\tasset.DeviceId == devices.SKYWAVE_782 ||\r\n\t\t\t\t\tasset.DeviceId == devices.SKYWAVE_782_CELL ||\r\n\t\t\t\t\tasset.DeviceId == devices.SKYWAVE_ST9100 ||\r\n\t\t\t\t\tasset.DeviceId == devices.ORBCOMM_ST9101,\r\n\t\t\t\trender: renderDomElement,\r\n\t\t\t}, // 782-only\r\n\t\t\t{\r\n\t\t\t\tvisible:\r\n\t\t\t\t\tasset.DeviceId == devices.SKYWAVE_782 ||\r\n\t\t\t\t\tasset.DeviceId == devices.SKYWAVE_782_CELL ||\r\n\t\t\t\t\tasset.DeviceId == devices.SKYWAVE_ST9100 ||\r\n\t\t\t\t\tasset.DeviceId == devices.ORBCOMM_ST9101,\r\n\t\t\t\trender: renderDomElement,\r\n\t\t\t}, // 782-only\r\n\t\t\t{}, //,\r\n\t\t\t//{}\r\n\t\t],\r\n\t\tlanguage: strings.DATATABLE,\r\n\t});\r\n}\r\n","import strings from \"./strings.js\";\r\nimport trkData from \"./data.js\";\r\nimport state from \"./state.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { openDialogPanel } from \"./panel-nav.js\";\r\nimport { createListing, defaultListItemSort } from \"./item-listing.js\";\r\nimport { mapModes } from \"./const.js\";\r\nimport user from \"./user.js\";\r\nimport { getDisplayFilterForEventType } from \"./display-filter.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport { toggleLoadingMessage } from \"./ajax.js\";\r\nimport { handleWebServiceError } from \"./ajax.js\";\r\n\r\nimport _ from \"lodash\";\r\nimport $j from \"jquery\";\r\nimport { el, svg } from \"redom\"; // https://redom.js.org/\r\n\r\nexport function openAlertsForAsset(asset) {\r\n\tif (user.isAnonymous) {\r\n\t\treturn;\r\n\t}\r\n\t// TODO in live mode we should include any alerts still requiring acknowledgement that aren't already included in the live listing\r\n\tvar dataSource =\r\n\t\tstate.activeMapMode === mapModes.LIVE\r\n\t\t\t? trkData.live.normalizedEventsByAssetId\r\n\t\t\t: trkData.history.normalizedEventsByAssetId;\r\n\tvar alerts = _.sortBy(\r\n\t\t_.filter(dataSource[asset.Id], getDisplayFilterForEventType(\"alerts\")),\r\n\t\tdefaultListItemSort\r\n\t).reverse();\r\n\tcreateListing(alerts, \"alerts\");\r\n\topenDialogPanel(\r\n\t\tdomNodes.dialogs.assetAlerts,\r\n\t\tstrings.ALERTS,\r\n\t\tasset,\r\n\t\tfalse,\r\n\t\tnull,\r\n\t\t\"asset\",\r\n\t\t\"asset-alerts\",\r\n\t\topenAlertsForAsset\r\n\t);\r\n}\r\n\r\nexport function loadAssetAlerts(asset) {\r\n\t// clear existing\r\n\tvar table = $j(\"#AssetAlerts\").DataTable();\r\n\ttable.clear().draw();\r\n\r\n\tvar btn = $j(\"#RefreshAssetAlerts\");\r\n\tvar data = { assetId: asset.Id };\r\n\tbtn.addClass(\"disabled\");\r\n\ttoggleLoadingMessage(true, \"asset-alerts\");\r\n\treturn $j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/GetAssetAlerts\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tbtn.removeClass(\"disabled\");\r\n\t\t\tif (msg.d) {\r\n\t\t\t\tvar result = msg.d;\r\n\t\t\t\tif (result.Success == true) {\r\n\t\t\t\t\t// populate alerts table\r\n\t\t\t\t\tvar assetAlertsData = [];\r\n\t\t\t\t\tvar alerts = result.Alerts;\r\n\t\t\t\t\tfor (var i = 0; i < alerts.length; i++) {\r\n\t\t\t\t\t\tvar alert = alerts[i];\r\n\t\t\t\t\t\tvar filterItems = [];\r\n\t\t\t\t\t\tfor (var j = 0; j < alert.Filters.length; j++) {\r\n\t\t\t\t\t\t\tfilterItems.push(el(\"li\", alert.Filters[j]));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tvar filters = el(\"ul\", filterItems);\r\n\t\t\t\t\t\tassetAlertsData.push([\r\n\t\t\t\t\t\t\talert.Id,\r\n\t\t\t\t\t\t\tel(\r\n\t\t\t\t\t\t\t\t\"form\",\r\n\t\t\t\t\t\t\t\t{ method: \"get\", action: \"Alerts/EditAlert/\" + alert.Id },\r\n\t\t\t\t\t\t\t\tel(\r\n\t\t\t\t\t\t\t\t\t\"button.alert-edit.btn.btn-secondary\",\r\n\t\t\t\t\t\t\t\t\t{ title: strings.EDIT, dataset: { alertId: alert.Id } },\r\n\t\t\t\t\t\t\t\t\tsvg(\"svg\", svg(\"use\", { xlink: { href: \"/content/svg/tracking.svg?v=15#edit\" } }))\r\n\t\t\t\t\t\t\t\t)\r\n\t\t\t\t\t\t\t),\r\n\t\t\t\t\t\t\talert.Name,\r\n\t\t\t\t\t\t\talert.Description,\r\n\t\t\t\t\t\t\talert.Type,\r\n\t\t\t\t\t\t\tfilters,\r\n\t\t\t\t\t\t\tel(\r\n\t\t\t\t\t\t\t\t\"button.alert-remove.btn.btn-secondary\",\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\ttitle: strings.REMOVE_FROM_ALERT,\r\n\t\t\t\t\t\t\t\t\tdisabled: alert.IsLinkedByGroup,\r\n\t\t\t\t\t\t\t\t\tdataset: { alertId: alert.Id, alertType: alert.Type, linkedByGroup: alert.IsLinkedByGroup },\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\tsvg(\"svg\", svg(\"use\", { xlink: { href: \"/content/svg/tracking.svg?v=15#minus\" } }))\r\n\t\t\t\t\t\t\t),\r\n\t\t\t\t\t\t]);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttable.rows.add(assetAlertsData).draw();\r\n\t\t\t\t} else {\r\n\t\t\t\t\thandleWebServiceError(strings.MSG_GET_ALERTS_ERROR);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ttoggleLoadingMessage(false, \"asset-alerts\");\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\thandleWebServiceError(strings.MSG_GET_ALERTS_ERROR);\r\n\t\t\ttoggleLoadingMessage(false, \"asset-alerts\");\r\n\t\t\tbtn.removeClass(\"disabled\");\r\n\t\t},\r\n\t});\r\n}\r\n","import { findTripById } from \"./trips.js\";\r\nimport { findSharedViewById } from \"./shared-view.js\";\r\nimport { findJourneyById } from \"./journey.js\";\r\nimport { handleAjaxFormSubmission, toggleLoadingMessage } from \"./ajax.js\";\r\nimport trkData from \"./data.js\";\r\nimport { findAssetIdsUnderGroup } from \"./assets.js\";\r\nimport { findGroupById } from \"./asset-group.js\";\r\nimport { throttles } from \"./timers.js\";\r\nimport strings from \"./strings.js\";\r\nimport { renderDomElement } from \"./datatables.js\";\r\nimport user from \"./user.js\";\r\nimport { devices, findDeviceById, isSendCommandDisabledForDevice } from \"./devices.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport { addAssetMessages } from \"./messages.js\";\r\nimport { trkDataGroups } from \"./const.js\";\r\nimport { handleWebServiceError } from \"./ajax.js\";\r\nimport { convertToLatLngPreference } from \"./preferences.js\";\r\nimport { formattedTextToDiv } from \"./dom-util.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { openDialogPanel } from \"./panel-nav.js\";\r\nimport { getPositionLinkForEvent } from \"./positions.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport $j from \"jquery\";\r\nimport _ from \"lodash\";\r\nimport { el, svg, text } from \"redom\"; // https://redom.js.org/\r\nimport moment from \"moment\"; // https://www.npmjs.com/package/moment\r\n\r\nexport function loadHistoryMessagesForSharedView(sharedViewId) {\r\n\tvar sharedView = findSharedViewById(sharedViewId);\r\n\tvar isLoaded = $.Deferred();\r\n\r\n\t// check if already loaded\r\n\tif (trkData.sharedView.isMessagesLoaded) {\r\n\t\tisLoaded.resolve(true);\r\n\t\treturn isLoaded;\r\n\t}\r\n\r\n\tvar from = null;\r\n\tvar to = null;\r\n\tif (sharedView.FromDateEpoch !== null) {\r\n\t\tfrom = moment.utc(sharedView.FromDateEpoch).format(user.dateFormat);\r\n\t}\r\n\tif (sharedView.ToDateEpoch !== null) {\r\n\t\tto = moment.utc(sharedView.ToDateEpoch).format(user.dateFormat);\r\n\t}\r\n\r\n\tvar queryAssetIds = sharedView.AssetIds.slice(0);\r\n\tvar assetGroupIds = sharedView.AssetGroupIds;\r\n\t_.each(assetGroupIds, function (assetGroupId) {\r\n\t\tvar group = findGroupById(assetGroupId);\r\n\t\tif (group !== null) {\r\n\t\t\tvar groupAssetIds = findAssetIdsUnderGroup(group);\r\n\t\t\tqueryAssetIds = queryAssetIds.concat(groupAssetIds);\r\n\t\t}\r\n\t});\r\n\r\n\tif (queryAssetIds.length === 0) {\r\n\t\tisLoaded.resolve(true);\r\n\t\treturn isLoaded;\r\n\t}\r\n\r\n\t// query for the asset's messages for this date range\r\n\tvar data = {\r\n\t\tassetIds: queryAssetIds,\r\n\t\tfromDate: from,\r\n\t\ttoDate: to,\r\n\t\tisUtc: true,\r\n\t\tformat: user.dateFormat,\r\n\t\tlang: user.dateCulture,\r\n\t};\r\n\r\n\thandleAjaxFormSubmission(\r\n\t\t\"GetMessageHistoryForAssetsByDateRange\",\r\n\t\tdata,\r\n\t\tnull,\r\n\t\tnull,\r\n\t\tnull,\r\n\t\tstrings.MSG_MESSAGE_HISTORY_ERROR,\r\n\t\tfunction (result) {\r\n\t\t\ttrkData.sharedView.isMessagesLoaded = true;\r\n\t\t\t_.each(result.Assets, function (assetResult) {\r\n\t\t\t\taddAssetMessages(assetResult, trkDataGroups.SHARED_VIEW_HISTORY, null, sharedView);\r\n\t\t\t});\r\n\t\t\tisLoaded.resolve(true);\r\n\t\t},\r\n\t\tfunction (xhr, staus, error) {\r\n\t\t\tisLoaded.reject(false);\r\n\t\t}\r\n\t);\r\n\r\n\treturn isLoaded;\r\n}\r\n\r\nexport function loadHistoryMessagesForTrip(tripId) {\r\n\t// separate query per date range here\r\n\tvar trip = findTripById(tripId);\r\n\tvar journey = findJourneyById(trip.JourneyId);\r\n\r\n\tvar isLoaded = $.Deferred();\r\n\r\n\tvar queryAssetIds = [];\r\n\tvar tripMessages = trkData.trips.messagesByTripId[tripId];\r\n\tif (tripMessages === undefined || tripMessages === null) {\r\n\t\tqueryAssetIds.push(journey.AssetId);\r\n\t}\r\n\r\n\tif (queryAssetIds.length === 0) {\r\n\t\tisLoaded.resolve(true);\r\n\t\treturn isLoaded;\r\n\t}\r\n\r\n\t// query for the asset's messages for this date range\r\n\tvar data = {\r\n\t\tassetIds: queryAssetIds,\r\n\t\tfromDate: moment.utc(trip.FromEpoch).format(user.dateFormat),\r\n\t\ttoDate: moment.utc(trip.ToEpoch).format(user.dateFormat),\r\n\t\tisUtc: true,\r\n\t\tformat: user.dateFormat,\r\n\t\tlang: user.dateCulture,\r\n\t};\r\n\tvar loadingKey = \"message-history-trip-\" + queryAssetIds[0];\r\n\ttoggleLoadingMessage(true, loadingKey);\r\n\t$.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/GetMessageHistoryForAssetsByDateRange\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tif (msg.d) {\r\n\t\t\t\tvar result = msg.d;\r\n\t\t\t\tif (result.Success == true) {\r\n\t\t\t\t\t_.each(result.Assets, function (assetResult) {\r\n\t\t\t\t\t\taddAssetMessages(assetResult, trkDataGroups.JOURNEY_HISTORY, trip);\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ttoggleLoadingMessage(false, loadingKey);\r\n\t\t\tisLoaded.resolve(true);\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\tisLoaded.reject(false);\r\n\t\t\thandleWebServiceError(strings.MSG_MESSAGE_HISTORY_ERROR);\r\n\t\t\ttoggleLoadingMessage(false, loadingKey);\r\n\t\t},\r\n\t});\r\n\r\n\treturn isLoaded;\r\n}\r\n\r\nexport function loadHistoryMessagesForAssets(assetIds) {\r\n\t// todo: loading indicator and error should be populated in the message dialog\r\n\r\n\tvar isLoaded = $.Deferred();\r\n\tvar queryAssetIds = [];\r\n\t_.each(assetIds, function (assetId) {\r\n\t\tvar assetMessages = trkData.history.messagesByAssetId[assetId];\r\n\t\tif (assetMessages === undefined || assetMessages === null) {\r\n\t\t\tqueryAssetIds.push(assetId);\r\n\t\t}\r\n\t});\r\n\r\n\tif (queryAssetIds.length === 0) {\r\n\t\tisLoaded.resolve(true);\r\n\t\treturn isLoaded;\r\n\t}\r\n\r\n\t// query for the asset's messages for this date range\r\n\tvar data = {\r\n\t\tassetIds: queryAssetIds,\r\n\t\tfromDate: trkData.history.fromDate,\r\n\t\ttoDate: trkData.history.toDate,\r\n\t\tisUtc: false,\r\n\t\tformat: user.dateFormat,\r\n\t\tlang: user.dateCulture,\r\n\t};\r\n\tvar loadingKey = \"message-history-\" + queryAssetIds[0];\r\n\ttoggleLoadingMessage(true, loadingKey);\r\n\t$.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/GetMessageHistoryForAssetsByDateRange\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tif (msg.d) {\r\n\t\t\t\tvar result = msg.d;\r\n\t\t\t\tif (result.Success == true) {\r\n\t\t\t\t\t_.each(result.Assets, function (assetResult) {\r\n\t\t\t\t\t\taddAssetMessages(assetResult, trkDataGroups.NORMAL_HISTORY);\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ttoggleLoadingMessage(false, loadingKey);\r\n\t\t\tisLoaded.resolve(true);\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\tisLoaded.reject(false);\r\n\t\t\thandleWebServiceError(strings.MSG_MESSAGE_HISTORY_ERROR);\r\n\t\t\ttoggleLoadingMessage(false, loadingKey);\r\n\t\t},\r\n\t});\r\n\r\n\treturn isLoaded;\r\n}\r\n\r\nexport function loadMessageHistory(asset) {\r\n\tvar device = findDeviceById(asset.DeviceId);\r\n\tif (isSendCommandDisabledForDevice(device)) {\r\n\t\t$j(\"#MessagesSendCommand\").prop(\"disabled\", true);\r\n\t} else {\r\n\t\t$j(\"#MessagesSendCommand\").prop(\"disabled\", false);\r\n\t}\r\n\r\n\ttoggleLoadingMessage(true, \"message-history\");\r\n\tvar btn = $j(\"#RefreshMessages\");\r\n\tbtn.prop(\"disabled\", true);\r\n\tvar data = { assetId: asset.Id };\r\n\t$j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/GetMessageHistoryForAsset\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tbtn.prop(\"disabled\", false);\r\n\t\t\tif (msg.d) {\r\n\t\t\t\tvar result = msg.d;\r\n\t\t\t\tif (result.Success == true && result.Assets.length > 0) {\r\n\t\t\t\t\tresult = result.Assets[0];\r\n\r\n\t\t\t\t\tvar includeGateway = false;\r\n\t\t\t\t\tif (_.indexOf(devices.SKYWAVE_IDP_DUAL_MODE, asset.DeviceId) !== -1) {\r\n\t\t\t\t\t\tincludeGateway = true;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// todo: limit the amount of data for rendering purposes?\r\n\t\t\t\t\tvar inboxData = [];\r\n\t\t\t\t\tfor (var i = 0; i < result.Inbox.length; i++) {\r\n\t\t\t\t\t\tvar item = result.Inbox[i];\r\n\t\t\t\t\t\tvar labelItems = [];\r\n\t\t\t\t\t\tif (item.IsAcknowledged) {\r\n\t\t\t\t\t\t\tif (item.AcknowledgedBy != null) {\r\n\t\t\t\t\t\t\t\tlabelItems.push(text(item.AcknowledgedBy));\r\n\t\t\t\t\t\t\t\tlabelItems.push(el(\"br\"));\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (item.AcknowledgedOn != null) {\r\n\t\t\t\t\t\t\t\tlabelItems.push(text(item.AcknowledgedOn));\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tvar checkbox = el(\"input.custom-control-input\", {\r\n\t\t\t\t\t\t\ttype: \"checkbox\",\r\n\t\t\t\t\t\t\tdisabled: true,\r\n\t\t\t\t\t\t\tchecked: item.IsAcknowledged,\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tif (item.IsAcknowledged) {\r\n\t\t\t\t\t\t\tcheckbox.setAttribute(\"checked\", \"checked\");\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tvar acknowledgedElement = el(\"div.custom-control.custom-checkbox\", [\r\n\t\t\t\t\t\t\tcheckbox,\r\n\t\t\t\t\t\t\ttext(\" \"),\r\n\t\t\t\t\t\t\tel(\"label.custom-control-label\", labelItems),\r\n\t\t\t\t\t\t]);\r\n\t\t\t\t\t\tvar priorityImage = el(\"img\", {\r\n\t\t\t\t\t\t\tsrc: \"/content/images/icon-priority-\" + item.PriorityValue + \".png\",\r\n\t\t\t\t\t\t\talt: item.Priority,\r\n\t\t\t\t\t\t\tstyle: { border: 0 },\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tvar address = null;\r\n\t\t\t\t\t\tif (item.Position != null) {\r\n\t\t\t\t\t\t\taddress = item.Position.Address;\r\n\t\t\t\t\t\t\tif (address == null || address.trim() == \"\" || asset.HideAddress) {\r\n\t\t\t\t\t\t\t\taddress = convertToLatLngPreference(\r\n\t\t\t\t\t\t\t\t\titem.Position.DisplayLat,\r\n\t\t\t\t\t\t\t\t\titem.Position.DisplayLng,\r\n\t\t\t\t\t\t\t\t\titem.Position.Grid\r\n\t\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\taddress = el(\"a.location\", { href: \"#\", dataset: { marker: item.Position.Id } }, address);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tinboxData.push([\r\n\t\t\t\t\t\t\tpriorityImage,\r\n\t\t\t\t\t\t\tformattedTextToDiv(item.Text),\r\n\t\t\t\t\t\t\t//el('pre', item.Text), // would be preferable?\r\n\t\t\t\t\t\t\taddress,\r\n\t\t\t\t\t\t\titem.CreatedOn,\r\n\t\t\t\t\t\t\titem.Source,\r\n\t\t\t\t\t\t\tacknowledgedElement,\r\n\t\t\t\t\t\t\tel(\r\n\t\t\t\t\t\t\t\t\"button.command.delete.delete-message.btn.btn-outline-danger\",\r\n\t\t\t\t\t\t\t\t{ title: strings.DELETE, dataset: { messageId: item.Id } },\r\n\t\t\t\t\t\t\t\tsvg(\"svg\", svg(\"use\", { xlink: { href: \"/content/svg/tracking.svg?v=15#trash-alt-light\" } }))\r\n\t\t\t\t\t\t\t),\r\n\t\t\t\t\t\t]);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tvar inboxCompleted = new $j.Deferred();\r\n\t\t\t\t\tvar outboxCompleted = new $j.Deferred();\r\n\t\t\t\t\tvar alertsCompleted = new $j.Deferred();\r\n\r\n\t\t\t\t\t$(\"#MessageHistoryInbox\").dataTable({\r\n\t\t\t\t\t\tdata: inboxData,\r\n\t\t\t\t\t\tdestroy: true,\r\n\t\t\t\t\t\tfilter: false,\r\n\t\t\t\t\t\tinfo: false,\r\n\t\t\t\t\t\tjQueryUI: true,\r\n\t\t\t\t\t\tautoWidth: false,\r\n\t\t\t\t\t\tlengthChange: false,\r\n\t\t\t\t\t\tpaging: true,\r\n\t\t\t\t\t\tpagingType: \"simple\",\r\n\t\t\t\t\t\tpageLength: 10,\r\n\t\t\t\t\t\tdeferRender: true,\r\n\t\t\t\t\t\torder: [[3, \"desc\"]],\r\n\t\t\t\t\t\tcolumnDefs: [\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\ttargets: \"_all\",\r\n\t\t\t\t\t\t\t\trender: $.fn.dataTable.render.text(),\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t],\r\n\t\t\t\t\t\tcolumns: [\r\n\t\t\t\t\t\t\t{ width: \"45px\", class: \"center\", type: \"string\", render: renderDomElement }, // priority\r\n\t\t\t\t\t\t\t{ sortable: false, render: renderDomElement }, // text\r\n\t\t\t\t\t\t\t{ sortable: false, render: renderDomElement }, // position\r\n\t\t\t\t\t\t\t{ width: \"75px\" }, // time\r\n\t\t\t\t\t\t\t{ width: \"50px\" }, // source\r\n\t\t\t\t\t\t\t{ width: \"75px\", class: \"center\", type: \"string\", render: renderDomElement }, // isacknowledged\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tsortable: false,\r\n\t\t\t\t\t\t\t\tclass: \"center\",\r\n\t\t\t\t\t\t\t\tvisible: user.isAdmin || user.canEditAssets,\r\n\t\t\t\t\t\t\t\trender: renderDomElement,\r\n\t\t\t\t\t\t\t}, // delete\r\n\t\t\t\t\t\t],\r\n\t\t\t\t\t\tlanguage: strings.DATATABLE,\r\n\t\t\t\t\t\tdrawCallback: function (settings) {\r\n\t\t\t\t\t\t\t//$j('button.command.delete', dialog).button({ text: null, icons: { primary: 'ui-icon-trash' } });\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tinitComplete: function (settings, json) {\r\n\t\t\t\t\t\t\tinboxCompleted.resolve();\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t});\r\n\r\n\t\t\t\t\t// outbox\r\n\t\t\t\t\tvar outboxData = [];\r\n\t\t\t\t\tfor (var i = 0; i < result.Outbox.length; i++) {\r\n\t\t\t\t\t\tvar item = result.Outbox[i];\r\n\t\t\t\t\t\toutboxData.push([\r\n\t\t\t\t\t\t\titem.Type,\r\n\t\t\t\t\t\t\titem.Text,\r\n\t\t\t\t\t\t\titem.RawText,\r\n\t\t\t\t\t\t\titem.Source,\r\n\t\t\t\t\t\t\titem.CreatedOn,\r\n\t\t\t\t\t\t\titem.IsSent,\r\n\t\t\t\t\t\t\titem.IsError,\r\n\t\t\t\t\t\t\titem.Response,\r\n\t\t\t\t\t\t\titem.SentOn,\r\n\t\t\t\t\t\t\titem.Id,\r\n\t\t\t\t\t\t\titem.Status,\r\n\t\t\t\t\t\t\tel(\r\n\t\t\t\t\t\t\t\t\"button.command.delete.delete-message.btn.btn-outline-danger\",\r\n\t\t\t\t\t\t\t\t{ title: strings.DELETE, dataset: { messageId: item.Id } },\r\n\t\t\t\t\t\t\t\tsvg(\"svg\", svg(\"use\", { xlink: { href: \"/content/svg/tracking.svg?v=15#trash-alt-light\" } }))\r\n\t\t\t\t\t\t\t),\r\n\t\t\t\t\t\t]);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t$(\"#MessageHistoryOutbox\").dataTable({\r\n\t\t\t\t\t\tdata: outboxData,\r\n\t\t\t\t\t\tdestroy: true,\r\n\t\t\t\t\t\tfilter: false,\r\n\t\t\t\t\t\tinfo: false,\r\n\t\t\t\t\t\tjQueryUI: true,\r\n\t\t\t\t\t\tautoWidth: false,\r\n\t\t\t\t\t\tlengthChange: false,\r\n\t\t\t\t\t\tpaging: true,\r\n\t\t\t\t\t\tpagingType: \"simple\",\r\n\t\t\t\t\t\tpageLength: 10,\r\n\t\t\t\t\t\tdeferRender: true,\r\n\t\t\t\t\t\torder: [[4, \"desc\"]],\r\n\t\t\t\t\t\tcolumnDefs: [\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\ttargets: \"_all\",\r\n\t\t\t\t\t\t\t\trender: $.fn.dataTable.render.text(),\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t],\r\n\t\t\t\t\t\tcolumns: [\r\n\t\t\t\t\t\t\t{ class: \"center\", width: \"100px\" }, // type\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// text\r\n\t\t\t\t\t\t\t\tsortable: false,\r\n\t\t\t\t\t\t\t\trender: function (data, type, row, meta) {\r\n\t\t\t\t\t\t\t\t\tif (type == \"display\") {\r\n\t\t\t\t\t\t\t\t\t\tvar raw = row[meta.col + 1];\r\n\t\t\t\t\t\t\t\t\t\tif (data == null || data == \"\") {\r\n\t\t\t\t\t\t\t\t\t\t\tif (raw != null && raw != \"\") {\r\n\t\t\t\t\t\t\t\t\t\t\t\tvar btn = el(\"button.btn.btn-sm.message-info.btn-secondary\", { title: raw }, [\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tsvg(\"svgn\", svg(\"use\", { xlink: { href: \"/content/svg/tracking.svg?v=15#info-circle\" } })),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\ttext(\" \"),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tel(\"span\", \"Info\"), // TODO: i18n\r\n\t\t\t\t\t\t\t\t\t\t\t\t]);\r\n\t\t\t\t\t\t\t\t\t\t\t\treturn btn.outerHTML;\r\n\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\treturn $.fn.dataTable.render.text().display(data);\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\treturn data;\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t}, // text\r\n\t\t\t\t\t\t\t{ visible: false }, // rawtext\r\n\t\t\t\t\t\t\t{ width: \"50px\", visible: includeGateway }, // source\r\n\t\t\t\t\t\t\t{ width: \"125px\" }, // createdon\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\twidth: \"50px\",\r\n\t\t\t\t\t\t\t\tclass: \"center\",\r\n\t\t\t\t\t\t\t\trender: function (data, type, row, meta) {\r\n\t\t\t\t\t\t\t\t\tvar isSent = data;\r\n\t\t\t\t\t\t\t\t\tvar isError = row[meta.col + 1];\r\n\t\t\t\t\t\t\t\t\tvar response = row[meta.col + 2];\r\n\t\t\t\t\t\t\t\t\tvar id = row[9];\r\n\t\t\t\t\t\t\t\t\tvar status = row[10];\r\n\t\t\t\t\t\t\t\t\tvar error = null;\r\n\t\t\t\t\t\t\t\t\tif (isError) {\r\n\t\t\t\t\t\t\t\t\t\terror = el(\"a.error\", { title: response, href: \"#\", dataset: { messageId: id } }, strings.ERROR);\r\n\t\t\t\t\t\t\t\t\t\tstatus = \"\";\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tif (status == null) {\r\n\t\t\t\t\t\t\t\t\t\tstatus = \"\";\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tvar checkbox = el(\"input.custom-control-input\", {\r\n\t\t\t\t\t\t\t\t\t\ttype: \"checkbox\",\r\n\t\t\t\t\t\t\t\t\t\tdisabled: true,\r\n\t\t\t\t\t\t\t\t\t\tchecked: isSent,\r\n\t\t\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t\t\t\tif (isSent) {\r\n\t\t\t\t\t\t\t\t\t\tcheckbox.setAttribute(\"checked\", \"checked\");\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tvar sent = el(\"div.custom-control.custom-checkbox\", [\r\n\t\t\t\t\t\t\t\t\t\tcheckbox,\r\n\t\t\t\t\t\t\t\t\t\tel(\"label.custom-control-label\", [error, text(status)]),\r\n\t\t\t\t\t\t\t\t\t]);\r\n\t\t\t\t\t\t\t\t\treturn sent.outerHTML;\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t}, // issent\r\n\t\t\t\t\t\t\t{ visible: false }, // IsError\r\n\t\t\t\t\t\t\t{ visible: false }, // Response\r\n\t\t\t\t\t\t\t{ width: \"125px\" },\r\n\t\t\t\t\t\t\t{ visible: false }, // Id\r\n\t\t\t\t\t\t\t{ visible: false }, // Status\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tsortable: false,\r\n\t\t\t\t\t\t\t\tclass: \"center\",\r\n\t\t\t\t\t\t\t\tvisible: user.isAdmin || user.canEditAssets,\r\n\t\t\t\t\t\t\t\trender: renderDomElement,\r\n\t\t\t\t\t\t\t}, // delete\r\n\t\t\t\t\t\t],\r\n\t\t\t\t\t\tlanguage: strings.DATATABLE,\r\n\t\t\t\t\t\tinitComplete: function (settings, json) {\r\n\t\t\t\t\t\t\toutboxCompleted.resolve();\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tdrawCallback: function (settings) {\r\n\t\t\t\t\t\t\t//$j('button.command.delete', dialog).button({ text: null, icons: { primary: 'ui-icon-trash' } });\r\n\t\t\t\t\t\t\t//$j('#MessageHistoryOutbox button.message-info').button({ text: null, icons: { primary: 'ui-icon-info' } }).tooltip();\r\n\t\t\t\t\t\t\t$j(\"#MessageHistoryOutbox button.message-info\").bsTooltip({ placement: \"right\" });\r\n\t\t\t\t\t\t\t$j(\"#MessageHistoryOutbox a.error\").bsTooltip().parent().addClass(\"error\");\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t});\r\n\r\n\t\t\t\t\tvar alertsData = [];\r\n\t\t\t\t\tfor (var i = 0; i < result.Alerts.length; i++) {\r\n\t\t\t\t\t\tvar item = result.Alerts[i].Event;\r\n\t\t\t\t\t\titem.Position = result.Alerts[i].Position;\r\n\t\t\t\t\t\tif (item.Alert == null) {\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tvar eventposition = getPositionLinkForEvent(item);\r\n\r\n\t\t\t\t\t\tvar type = item.Alert.Type;\r\n\t\t\t\t\t\tif (item.Alert.Name != null) {\r\n\t\t\t\t\t\t\ttype = item.Alert.Name + \": \" + type;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\ttype = el(\"span\", [text(item.TypeName + \":\"), el(\"br\"), text(type)]);\r\n\t\t\t\t\t\tvar ack = el(\"span\", item.Alert.AcknowledgedStatus);\r\n\t\t\t\t\t\tif (item.Type === 14) {\r\n\t\t\t\t\t\t\tif (item.Alert.RequiresAcknowledgement) {\r\n\t\t\t\t\t\t\t\tack = el(\r\n\t\t\t\t\t\t\t\t\t\"button.AlertAcknowledge.btn.btn-sm.btn-primary\",\r\n\t\t\t\t\t\t\t\t\t{ role: \"button\", dataset: { alert: item.Id } },\r\n\t\t\t\t\t\t\t\t\tstrings.ACKNOWLEDGE\r\n\t\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (item.Alert.Acknowledged) {\r\n\t\t\t\t\t\t\t\tack = el(\r\n\t\t\t\t\t\t\t\t\t\"span\",\r\n\t\t\t\t\t\t\t\t\tstrings.ACKNOWLEDGE_STATUS.replace(\"{Status}\", item.Alert.AcknowledgedStatus)\r\n\t\t\t\t\t\t\t\t\t\t.replace(\"{Time}\", item.Alert.AcknowledgedOn)\r\n\t\t\t\t\t\t\t\t\t\t.replace(\"{User}\", item.Alert.AcknowledgedBy)\r\n\t\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\talertsData.push([\r\n\t\t\t\t\t\t\t\"\",\r\n\t\t\t\t\t\t\titem.Alert.Priority,\r\n\t\t\t\t\t\t\ttype,\r\n\t\t\t\t\t\t\tformattedTextToDiv(item.Alert.AcknowledgedText),\r\n\t\t\t\t\t\t\teventposition, // Position\r\n\t\t\t\t\t\t\titem.Time,\r\n\t\t\t\t\t\t\tack,\r\n\t\t\t\t\t\t\titem.Type,\r\n\t\t\t\t\t\t\titem.Alert.Color,\r\n\t\t\t\t\t\t]);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t$(\"#MessageHistoryAlerts\").dataTable({\r\n\t\t\t\t\t\tdata: alertsData,\r\n\t\t\t\t\t\tdestroy: true,\r\n\t\t\t\t\t\tfilter: false,\r\n\t\t\t\t\t\tinfo: false,\r\n\t\t\t\t\t\tjQueryUI: true,\r\n\t\t\t\t\t\tautoWidth: false,\r\n\t\t\t\t\t\tlengthChange: false,\r\n\t\t\t\t\t\tpaging: true,\r\n\t\t\t\t\t\tpagingType: \"simple\",\r\n\t\t\t\t\t\tpageLength: 10,\r\n\t\t\t\t\t\tdeferRender: true,\r\n\t\t\t\t\t\torder: [[5, \"desc\"]],\r\n\t\t\t\t\t\tcolumnDefs: [\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\ttargets: \"_all\",\r\n\t\t\t\t\t\t\t\trender: $.fn.dataTable.render.text(),\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t],\r\n\t\t\t\t\t\tcolumns: [\r\n\t\t\t\t\t\t\t{ sortable: false, width: \"20px\" }, // Color Display\r\n\t\t\t\t\t\t\t{ sortable: true }, // Priority\r\n\t\t\t\t\t\t\t{ sortable: true, render: renderDomElement }, // Type\r\n\t\t\t\t\t\t\t{ sortable: false, render: renderDomElement }, // Resolution\r\n\t\t\t\t\t\t\t{ sortable: false, render: renderDomElement }, // Position/lat/lng\r\n\t\t\t\t\t\t\t{ width: \"75px\" }, // Time\r\n\t\t\t\t\t\t\t{ sortable: false, render: renderDomElement }, // Acknowledge\r\n\t\t\t\t\t\t\t{ visible: false }, // Event Type Id\r\n\t\t\t\t\t\t\t{ visible: false }, // Color\r\n\t\t\t\t\t\t],\r\n\t\t\t\t\t\tlanguage: strings.DATATABLE,\r\n\t\t\t\t\t\tinitComplete: function (settings, json) {\r\n\t\t\t\t\t\t\talertsCompleted.resolve();\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tdrawCallback: function (settings) {},\r\n\t\t\t\t\t\trowCallback: function (row, data, index) {\r\n\t\t\t\t\t\t\tif (data[8] != \"\") {\r\n\t\t\t\t\t\t\t\t$j(\"td:eq(0)\", row).css(\"background-color\", data[8]);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t});\r\n\r\n\t\t\t\t\ttrkData.messaging.alerts = result.Alerts;\r\n\t\t\t\t\ttrkData.messaging.inbox = result.Inbox;\r\n\t\t\t\t\ttrkData.messaging.outbox = result.Outbox;\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// output result.ErrorMessage\r\n\t\t\t\t}\r\n\t\t\t\tasset.LastIncomingMessage = null;\r\n\t\t\t\tasset.MessageStatuses = [];\r\n\t\t\t\tasset.UnconfirmedMessages = [];\r\n\t\t\t\tthrottles.updatePositionStatus();\r\n\t\t\t\t$j.when(inboxCompleted, outboxCompleted, alertsCompleted).done(function () {\r\n\t\t\t\t\t// todo: hide loading indicators\r\n\t\t\t\t\t//dialog.dialog('open');\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t\ttoggleLoadingMessage(false, \"message-history\");\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\tbtn.prop(\"disabled\", false);\r\n\t\t\thandleWebServiceError(strings.MSG_MESSAGE_HISTORY_ERROR);\r\n\t\t\t// re-enable show button and clear loading message\r\n\t\t\ttoggleLoadingMessage(false, \"message-history\");\r\n\t\t},\r\n\t});\r\n}\r\n\r\nexport function loadMessageHistoryDialog(asset) {\r\n\t$(domNodes.dialogs.messageHistory).data(\"assetId\", asset.Id);\r\n\topenDialogPanel(\r\n\t\tdomNodes.dialogs.messageHistory,\r\n\t\tstrings.MESSAGE_LOG,\r\n\t\tasset,\r\n\t\ttrue,\r\n\t\tfunction () {\r\n\t\t\ttrkData.messaging.inbox = null;\r\n\t\t\ttrkData.messaging.outbox = null;\r\n\t\t},\r\n\t\t\"asset\",\r\n\t\t\"view-logs-message\",\r\n\t\tloadMessageHistoryDialog\r\n\t);\r\n\r\n\t// clear table rows\r\n\tloadMessageHistory(asset);\r\n}\r\n","/**\r\n* maxChar jQuery plugin\r\n* @author Mitch Wilson\r\n* @version 0.3.0\r\n* @requires jQuery 1.3.2 (only version tested)\r\n* @see http://mitchwilson.net/2009/08/03/new-jquery-plugin-maxchar/\r\n* @param {Boolean}\tdebug\t\t\t\tSpecify whether to send message updates to the Firebug console. Default is false.\r\n* @param {String}\tindicator \t\t\tSpecify alternate indicator element by id. Default is indicator created dynamically.\r\n* @param {String}\tlabel\t\t\t\tSpecify a default label displayed when input element is not in focus. Default is blank.\r\n* @param {String}\tpluralMessage \t\tSet the plural form of the remaining count message. Default is ' remaining'.\r\n* @param {Number}\trate \t\t\t\tSet the update rate in milliseconds. Default is 200.\r\n* @param {String}\tsingularMessage \tSet the singular form of the remaining count message. Default is ' remaining'.\r\n* @param {String}\tspaceBeforeMessage \tSet spacing in front of (to the left of) the indicator message. Default is ' '.\r\n* @param {Boolean}\ttruncate\t\t\tTruncate submitted value down to limit on form submit. Default is true.\r\n* @description Enforces max character limit on any input or textarea HTML element and provides user feedback and many options. \r\n* New features added in 0.3.0 are: \r\n* 1) Feature change: Displays negative characters when past limit rather than truncating characters in form input.\r\n* 2) New option: truncate - If true, on form submit truncates submitted value down specified by limit. Does not change (respects) user text in form field. Default is true.\r\n* 3) Bug fixes: Fixed serveral issues related to removing over-the-limit characters in the form field.\r\n*/\r\n\r\n(function ($) {\r\n var methods = {\r\n init: function (limit, options) {\r\n // Start the timer that updates indicator.\r\n function start() {\r\n data.timer = setInterval(function () { update(data.limit) }, settings.rate);\r\n }\r\n\r\n // Stop the timer that updates the indicator.\r\n function stop() {\r\n if (data.timer != null) {\r\n clearInterval(data.timer);\r\n data.timer = null;\r\n }\r\n }\r\n\r\n // Update the indicator.\r\n function update(limit) {\r\n let currentMessage;\r\n if ((limit == null) || (limit == 0)) {\r\n currentMessage = '';\r\n } else {\r\n var remaining = limit - target.val().length;\r\n // Update remaining count and message.\r\n if (remaining == 1) {\r\n currentMessage = remaining + settings.singularMessage;\r\n } else {\r\n currentMessage = remaining + settings.pluralMessage;\r\n }\r\n }\r\n // Update indicator.\r\n data.indicator.text(currentMessage);\r\n log(currentMessage);\r\n }\r\n\r\n function handleFocus() {\r\n if (data.timer == null) {\r\n if (settings.label) {\r\n data.indicator.fadeOut(function () { data.indicator.text('') }).fadeIn(function () { start() });\r\n } else {\r\n start();\r\n }\r\n }\r\n }\r\n\r\n function handleBlur() {\r\n // Stop timer that updates count and the indicator message.\r\n stop();\r\n // Update view.\r\n if (settings.label) {\r\n data.indicator.fadeOut(function () { data.indicator.text(settings.label) }).fadeIn();\r\n }\r\n }\r\n\r\n function truncateFormSubmit() {\r\n if ((data.limit != null) && (data.limit > 0)) {\r\n target.val(target.val().slice(0, data.limit));\r\n }\r\n }\r\n\r\n function getIndicator(id) {\r\n // Get indicator element in the dom.\r\n var indicator = jQuery('#' + id);\r\n // If indicator element does not already exist in the dom, create it.\r\n if (indicator.length == 0) {\r\n target.after(spaceBeforeMessage + ' ');\r\n indicator = jQuery('#' + id)\r\n }\r\n // Return reference to indicator element.\r\n return indicator;\r\n }\r\n\r\n // Create helper functions.\r\n function log(message) {\r\n // Display \r\n if (settings.debug) {\r\n try {\r\n if (console) {\r\n console.log(message);\r\n }\r\n } catch (e) {\r\n // Do nothing on error.\r\n }\r\n }\r\n }\r\n\r\n // Define default settings and override w/ options.\t\r\n let settings = jQuery.extend({\r\n debug: false,\r\n indicator: 'indicator',\r\n label: '',\r\n pluralMessage: ' remaining',\r\n rate: 200,\r\n singularMessage: ' remaining',\r\n spaceBeforeMessage: ' ',\r\n truncate: true\r\n }, options);\r\n\r\n // Get maxChar target element.\r\n\r\n var target = jQuery(this); // Must get target first, since it is used in setting other local variables.\r\n\r\n var data = {\r\n settings: settings,\r\n currentMessage: '',\r\n indicator: getIndicator(settings.indicator),\r\n limit: limit,\r\n remaining: limit,\r\n timer: null\r\n }\r\n target.data('maxChar', data);\r\n\r\n if (settings.label) {\r\n data.indicator.text(settings.label);\r\n } else {\r\n update(data.limit);\r\n }\r\n\r\n // When user focuses on the target element, do the following.\r\n target.bind('focus.maxchar', handleFocus);\r\n\r\n // When user removes focus from the target element, do the following.\r\n target.bind('blur.maxchar', handleBlur);\r\n\r\n // Truncate submitted value down to limit on form submit.\r\n if (settings.truncate) {\r\n var form_id = '#' + jQuery(this).closest(\"form\").attr(\"id\");\r\n jQuery(form_id).bind('submit.maxchar', truncateFormSubmit);\r\n }\r\n },\r\n destroy: function () {\r\n // unbind all events\r\n jQuery(this).unbind('.maxchar');\r\n var data = jQuery(this).data('maxChar');\r\n if (data != null) {\r\n clearInterval(data.timer);\r\n data.indicator.text('');\r\n }\r\n }\r\n };\r\n\r\n $.extend($.fn, {\r\n maxChar: function (method) {\r\n // Method calling logic\r\n if (methods[method]) {\r\n return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));\r\n } else if (typeof method === 'object' || !method) {\r\n return methods.init.apply(this, arguments);\r\n } else {\r\n $.error('Method ' + method + ' does not exist on jQuery.maxChar');\r\n }\r\n }\r\n });\r\n\r\n})(jQuery);","import strings from \"./strings.js\";\r\nimport trkData from \"./data.js\";\r\nimport state from \"./state.js\";\r\nimport options from \"./options.js\";\r\nimport user from \"./user.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { mapModes, trkDataGroups } from \"./const.js\";\r\nimport { openDialogPanel } from \"./panel-nav.js\";\r\nimport { findAssetById, normalizeAssetData } from \"./assets.js\";\r\nimport { getGroupAssetStatus, findGroupById } from \"./asset-group.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport { toggleLoadingMessage } from \"./ajax.js\";\r\nimport { handleWebServiceError } from \"./ajax.js\";\r\nimport { checkForShareViewChange } from \"./shared-view.js\";\r\nimport { createListing } from \"./item-listing.js\";\r\nimport { getDisplayFilterForEventType } from \"./display-filter.js\";\r\nimport { updateAssetNotificationTime } from \"./asset-notification.js\";\r\nimport { updateGroupFunctionBadges, updateAssetFunctionBadges } from \"./badges.js\";\r\nimport { getAssetDataGroupForCurrentViewMode } from \"./map-viewmode.js\";\r\nimport {\r\n\tloadHistoryMessagesForAssets,\r\n\tloadHistoryMessagesForSharedView,\r\n\tloadHistoryMessagesForTrip,\r\n} from \"./messages-history.js\";\r\nimport { devices, findDeviceById } from \"./devices.js\";\r\nimport { findAssetIdsInGeofence } from \"./fence.js\";\r\nimport { sortByName } from \"./item-sorting.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport $j from \"jquery\";\r\nimport _ from \"lodash\";\r\nimport moment from \"moment\"; // https://www.npmjs.com/package/moment\r\n\r\nimport \"../legacy/jquery.maxchar.js\"\r\n\r\nexport function openMessagesForAsset(asset) {\r\n\tif (user.isAnonymous) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar loadMessageCallback = function (dataSource) {\r\n\t\treturn function () {\r\n\t\t\tvar messages = _.filter(dataSource[asset.Id], getDisplayFilterForEventType(\"messages\"));\r\n\t\t\tcreateListing(messages, \"messages\");\r\n\t\t};\r\n\t};\r\n\r\n\tvar dataSource = trkData.history.normalizedMessagesByAssetId;\r\n\tif (state.activeMapMode === mapModes.HISTORY) {\r\n\t\tif (state.hasQueriedHistory) {\r\n\t\t\t$.when(loadHistoryMessagesForAssets([asset.Id])).done(loadMessageCallback(dataSource));\r\n\t\t} else {\r\n\t\t\tcreateListing([], \"messages\");\r\n\t\t}\r\n\t} else if (state.activeMapMode === mapModes.LIVE) {\r\n\t\tdataSource = trkData.live.normalizedMessagesByAssetId;\r\n\t\t$.when(loadLiveMessagesForAssets([asset.Id])).done(loadMessageCallback(dataSource));\r\n\t}\r\n\r\n\topenDialogPanel(\r\n\t\tdomNodes.dialogs.assetMessages,\r\n\t\tstrings.MESSAGES,\r\n\t\tasset,\r\n\t\tfalse,\r\n\t\tnull,\r\n\t\t\"asset\",\r\n\t\t\"asset-messages\",\r\n\t\topenMessagesForAsset\r\n\t);\r\n}\r\n\r\nexport function openMessagesForGroup(group) {\r\n\tif (user.isAnonymous) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar status = getGroupAssetStatus(group.Id);\r\n\r\n\tvar isLive = state.activeMapMode === mapModes.LIVE;\r\n\tvar messages = [];\r\n\tvar isDataLoaded = $.Deferred();\r\n\tif (!isLive && !state.hasQueriedHistory) {\r\n\t\t// can't populate history when it hasn't been queried\r\n\t\tisDataLoaded.resolve(true);\r\n\t} else {\r\n\t\t// TODO only load visible assets...?\r\n\t\tvar dataLoader = isLive\r\n\t\t\t? loadLiveMessagesForAssets(status.assetIds)\r\n\t\t\t: loadHistoryMessagesForAssets(status.assetIds);\r\n\t\tvar dataSource = isLive ? trkData.live.normalizedMessagesByAssetId : trkData.history.normalizedMessagesByAssetId;\r\n\t\t$.when(dataLoader).done(function () {\r\n\t\t\t_.each(status.assetIds, function (assetId) {\r\n\t\t\t\tvar deviceMessages = _.filter(dataSource[assetId], getDisplayFilterForEventType(\"messages\"));\r\n\t\t\t\tmessages = messages.concat(deviceMessages);\r\n\t\t\t});\r\n\t\t\tisDataLoaded.resolve(true);\r\n\t\t});\r\n\t}\r\n\r\n\t$.when(isDataLoaded).done(function () {\r\n\t\tcreateListing(messages, \"messages\");\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.assetMessages,\r\n\t\t\tstrings.MESSAGES,\r\n\t\t\tgroup,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\t\"group\",\r\n\t\t\t\"group-messages\",\r\n\t\t\topenMessagesForGroup\r\n\t\t);\r\n\t});\r\n}\r\n\r\nexport function openMessagesForTrip(trip) {\r\n\tif (user.isAnonymous) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar loadMessagesCallback = function () {\r\n\t\tvar messages = _.filter(\r\n\t\t\ttrkData.trips.normalizedMessagesByTripId[trip.Id],\r\n\t\t\tgetDisplayFilterForEventType(\"messages\")\r\n\t\t);\r\n\t\tcreateListing(messages, \"messages\");\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.assetMessages,\r\n\t\t\tstrings.MESSAGES,\r\n\t\t\ttrip,\r\n\t\t\tfalse,\r\n\t\t\tundefined,\r\n\t\t\t\"trip\",\r\n\t\t\t\"trip-messages\",\r\n\t\t\topenMessagesForTrip\r\n\t\t);\r\n\t};\r\n\r\n\t$.when(loadHistoryMessagesForTrip(trip.Id)).done(loadMessagesCallback);\r\n}\r\n\r\nexport function openMessagesForJourney(journey) {\r\n\tif (user.isAnonymous) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar messages = [];\r\n\tvar deferreds = [];\r\n\tvar tripIds = [];\r\n\r\n\t_.each(journey.Trips, function (trip) {\r\n\t\ttripIds.push(trip.Id);\r\n\t});\r\n\t_.each(tripIds, function (tripId) {\r\n\t\tdeferreds.push(loadHistoryMessagesForTrip(tripId));\r\n\t});\r\n\r\n\t$.when.apply($, deferreds).done(function () {\r\n\t\t_.each(tripIds, function (tripId) {\r\n\t\t\tvar deviceMessages = _.filter(\r\n\t\t\t\ttrkData.trips.normalizedMessagesByTripId[tripId],\r\n\t\t\t\tgetDisplayFilterForEventType(\"messages\")\r\n\t\t\t);\r\n\t\t\tmessages = messages.concat(deviceMessages);\r\n\t\t});\r\n\t\tcreateListing(messages, \"messages\");\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.assetMessages,\r\n\t\t\tstrings.MESSAGES,\r\n\t\t\tjourney,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\t\"journey\",\r\n\t\t\t\"journey-messages\",\r\n\t\t\topenMessagesForJourney\r\n\t\t);\r\n\t});\r\n}\r\n\r\nexport function openChatForAsset(asset) {\r\n\tif (user.isAnonymous && !options.allowAnonymousMessaging) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar dataSource = trkData.history.normalizedMessagesByAssetId;\r\n\tvar loadMessageCallback = function (dataSource) {\r\n\t\treturn function () {\r\n\t\t\tvar chatMessages = _.filter(dataSource[asset.Id], getDisplayFilterForEventType(\"chat\"));\r\n\t\t\tcreateListing(chatMessages, \"chat\");\r\n\t\t\topenDialogPanel(\r\n\t\t\t\tdomNodes.dialogs.assetChat,\r\n\t\t\t\tstrings.CHAT,\r\n\t\t\t\tasset,\r\n\t\t\t\tfalse,\r\n\t\t\t\tnull,\r\n\t\t\t\t\"asset\",\r\n\t\t\t\t\"asset-chat\",\r\n\t\t\t\topenChatForAsset\r\n\t\t\t);\r\n\t\t};\r\n\t};\r\n\r\n\tif (state.activeMapMode === mapModes.HISTORY) {\r\n\t\tif (state.hasQueriedHistory) {\r\n\t\t\t$.when(loadHistoryMessagesForAssets([asset.Id])).done(loadMessageCallback(dataSource));\r\n\t\t} else {\r\n\t\t\tcreateListing([], \"chat\");\r\n\t\t}\r\n\t} else if (state.activeMapMode === mapModes.LIVE) {\r\n\t\tdataSource = trkData.live.normalizedMessagesByAssetId;\r\n\t\t$.when(loadLiveMessagesForAssets([asset.Id])).done(loadMessageCallback(dataSource));\r\n\t}\r\n}\r\n\r\nexport function openChatForGroup(group) {\r\n\tif (user.isAnonymous && !options.allowAnonymousMessaging) {\r\n\t\treturn;\r\n\t}\r\n\tvar status = getGroupAssetStatus(group.Id);\r\n\r\n\tvar isLive = state.activeMapMode === mapModes.LIVE;\r\n\tvar messages = [];\r\n\tvar isDataLoaded = $.Deferred();\r\n\tif (!isLive && !state.hasQueriedHistory) {\r\n\t\t// can't populate history when it hasn't been queried\r\n\t\tisDataLoaded.resolve(true);\r\n\t} else {\r\n\t\tvar dataLoader = isLive\r\n\t\t\t? loadLiveMessagesForAssets(status.assetIds)\r\n\t\t\t: loadHistoryMessagesForAssets(status.assetIds);\r\n\t\tvar dataSource = isLive ? trkData.live.normalizedMessagesByAssetId : trkData.history.normalizedMessagesByAssetId;\r\n\t\t$.when(dataLoader).done(function () {\r\n\t\t\t_.each(status.assetIds, function (assetId) {\r\n\t\t\t\tvar chatMessages = _.filter(dataSource[assetId], getDisplayFilterForEventType(\"chat\"));\r\n\t\t\t\tmessages = messages.concat(chatMessages);\r\n\t\t\t});\r\n\t\t\tisDataLoaded.resolve(true);\r\n\t\t});\r\n\t}\r\n\r\n\t$.when(isDataLoaded).done(function () {\r\n\t\tcreateListing(messages, \"chat\");\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.assetChat,\r\n\t\t\tstrings.CHAT,\r\n\t\t\tgroup,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\t\"group\",\r\n\t\t\t\"group-chat\",\r\n\t\t\topenChatForGroup\r\n\t\t);\r\n\t});\r\n}\r\n\r\nexport function openChatForSharedView(sharedView) {\r\n\tvar loadMessagesCallback = function () {\r\n\t\tvar messages = _.filter(trkData.sharedView.normalizedMessages, getDisplayFilterForEventType(\"chat\"));\r\n\t\tcreateListing(messages, \"chat\");\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.assetChat,\r\n\t\t\tstrings.CHAT,\r\n\t\t\tsharedView,\r\n\t\t\tfalse,\r\n\t\t\tcheckForShareViewChange(sharedView),\r\n\t\t\t\"shared-view\",\r\n\t\t\t\"shared-view-chat\",\r\n\t\t\topenChatForSharedView\r\n\t\t);\r\n\t};\r\n\r\n\tif (!sharedView.IsMessagingEnabled) {\r\n\t\t// TODO show notice\r\n\t\tloadMessagesCallback();\r\n\t\treturn;\r\n\t}\r\n\r\n\t$.when(loadHistoryMessagesForSharedView(sharedView.Id)).done(loadMessagesCallback);\r\n}\r\n\r\nexport function openChatForTrip(trip) {\r\n\tif (user.isAnonymous && !options.allowAnonymousMessaging) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar loadMessagesCallback = function () {\r\n\t\tvar messages = _.filter(trkData.trips.normalizedMessagesByTripId[trip.Id], getDisplayFilterForEventType(\"chat\"));\r\n\t\tcreateListing(messages, \"chat\");\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.assetChat,\r\n\t\t\tstrings.CHAT,\r\n\t\t\ttrip,\r\n\t\t\tfalse,\r\n\t\t\tundefined,\r\n\t\t\t\"trip\",\r\n\t\t\t\"trip-chat\",\r\n\t\t\topenChatForTrip\r\n\t\t);\r\n\t};\r\n\r\n\t$.when(loadHistoryMessagesForTrip(trip.Id)).done(loadMessagesCallback);\r\n}\r\n\r\nexport function openChatForJourney(journey) {\r\n\tif (user.isAnonymous && !options.allowAnonymousMessaging) {\r\n\t\treturn;\r\n\t}\r\n\tvar messages = [];\r\n\tvar deferreds = [];\r\n\tvar tripIds = [];\r\n\r\n\t_.each(journey.Trips, function (trip) {\r\n\t\ttripIds.push(trip.Id);\r\n\t});\r\n\t_.each(tripIds, function (tripId) {\r\n\t\tdeferreds.push(loadHistoryMessagesForTrip(tripId));\r\n\t});\r\n\r\n\t$.when.apply($, deferreds).done(function () {\r\n\t\t_.each(tripIds, function (tripId) {\r\n\t\t\tvar chat = _.filter(trkData.trips.normalizedMessagesByTripId[tripId], getDisplayFilterForEventType(\"chat\"));\r\n\t\t\tmessages = messages.concat(chat);\r\n\t\t});\r\n\t\tcreateListing(messages, \"chat\");\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.assetChat,\r\n\t\t\tstrings.CHAT,\r\n\t\t\tjourney,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\t\"journey\",\r\n\t\t\t\"journey-chat\",\r\n\t\t\topenChatForJourney\r\n\t\t);\r\n\t});\r\n}\r\n\r\nexport function loadLiveMessagesForAssets(assetIds) {\r\n\tif (state.portalLoadedEpoch === null) {\r\n\t\treturn;\r\n\t}\r\n\tvar queryAssetIds = [];\r\n\t_.each(assetIds, function (assetId) {\r\n\t\tvar assetMessages = trkData.live.messagesByAssetId[assetId];\r\n\t\tif (assetMessages === undefined || assetMessages === null) {\r\n\t\t\tqueryAssetIds.push(assetId);\r\n\t\t}\r\n\t});\r\n\r\n\tvar isLoaded = $.Deferred();\r\n\tif (queryAssetIds.length === 0) {\r\n\t\tisLoaded.resolve(true);\r\n\t\treturn isLoaded;\r\n\t}\r\n\r\n\t// query for the assets' messages for this date range\r\n\tvar data = {\r\n\t\tassetIds: queryAssetIds,\r\n\t\tfromDate: moment.utc(state.portalLoadedEpoch).format(user.dateFormat),\r\n\t\ttoDate: null,\r\n\t\tisUtc: true,\r\n\t\tformat: user.dateFormat,\r\n\t\tlang: user.dateCulture,\r\n\t};\r\n\tvar loadingKey = \"message-live-\" + queryAssetIds[0];\r\n\ttoggleLoadingMessage(true, loadingKey);\r\n\t$.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/GetMessageHistoryForAssetsByDateRange\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tif (msg.d) {\r\n\t\t\t\tvar result = msg.d;\r\n\t\t\t\tif (result.Success == true) {\r\n\t\t\t\t\t_.each(result.Assets, function (assetResult) {\r\n\t\t\t\t\t\taddAssetMessages(assetResult, trkDataGroups.NORMAL_LIVE);\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ttoggleLoadingMessage(false, loadingKey);\r\n\t\t\tisLoaded.resolve(true);\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\tisLoaded.reject(false);\r\n\t\t\thandleWebServiceError(strings.MSG_MESSAGE_HISTORY_ERROR);\r\n\t\t\ttoggleLoadingMessage(false, loadingKey);\r\n\t\t},\r\n\t});\r\n\treturn isLoaded;\r\n}\r\n\r\nexport function addAssetMessages(assetResult, forDataGroup, trip) {\r\n\tvar fromMobileMessages = _.map(assetResult.Inbox, function (item) {\r\n\t\treturn mapMessageToCommonFormat(item, true);\r\n\t});\r\n\tvar toMobileMessages = _.map(assetResult.Outbox, function (item) {\r\n\t\treturn mapMessageToCommonFormat(item, false);\r\n\t});\r\n\tvar allAssetMessages = fromMobileMessages.concat(toMobileMessages);\r\n\tvar normalizedMessages = [];\r\n\r\n\tvar dataSource = trkData;\r\n\tif (forDataGroup === trkDataGroups.SHARED_VIEW_HISTORY) {\r\n\t\tdataSource = trkData.sharedView;\r\n\t}\r\n\r\n\t_.each(allAssetMessages, function (message) {\r\n\t\tif (dataSource.messagesById[message.Id] === undefined) {\r\n\t\t\tdataSource.messagesById[message.Id] = normalizeAssetData(message.AssetId, \"message\", message);\r\n\t\t}\r\n\t\tnormalizedMessages.push(dataSource.messagesById[message.Id]);\r\n\t});\r\n\r\n\tif (forDataGroup === trkDataGroups.NORMAL_LIVE) {\r\n\t\ttrkData.live.messages.push(assetResult);\r\n\t\ttrkData.live.messagesByAssetId[assetResult.AssetId] = assetResult;\r\n\t\tif (normalizedMessages.length > 0) {\r\n\t\t\t_.each(normalizedMessages, function (item) {\r\n\t\t\t\ttrkData.live.normalizedMessages.push(item);\r\n\t\t\t});\r\n\t\t\ttrkData.live.normalizedMessagesByAssetId[assetResult.AssetId] = normalizedMessages;\r\n\t\t}\r\n\t} else if (forDataGroup === trkDataGroups.NORMAL_HISTORY) {\r\n\t\ttrkData.history.messages.push(assetResult);\r\n\t\ttrkData.history.messagesByAssetId[assetResult.AssetId] = assetResult;\r\n\t\tif (normalizedMessages.length > 0) {\r\n\t\t\t_.each(normalizedMessages, function (item) {\r\n\t\t\t\ttrkData.history.normalizedMessages.push(item);\r\n\t\t\t});\r\n\t\t\ttrkData.history.normalizedMessagesByAssetId[assetResult.AssetId] = normalizedMessages;\r\n\t\t}\r\n\t} else if (forDataGroup === trkDataGroups.JOURNEY_HISTORY && trip !== undefined) {\r\n\t\ttrkData.trips.messages.push(assetResult);\r\n\t\ttrkData.trips.messagesByTripId[trip.Id] = assetResult;\r\n\t\tif (normalizedMessages.length > 0) {\r\n\t\t\t_.each(normalizedMessages, function (item) {\r\n\t\t\t\ttrkData.trips.normalizedMessages.push(item);\r\n\t\t\t});\r\n\t\t\ttrkData.trips.normalizedMessagesByTripId[trip.Id] = normalizedMessages;\r\n\t\t}\r\n\t} else if (forDataGroup === trkDataGroups.SHARED_VIEW_HISTORY) {\r\n\t\t//trkData.sharedView.messages.push(assetResult);\r\n\t\ttrkData.sharedView.normalizedMessages = trkData.sharedView.normalizedMessages.concat(normalizedMessages);\r\n\t}\r\n}\r\n\r\nfunction mapMessageToCommonFormat(message, isFromMobile) {\r\n\tvar item = {\r\n\t\tId: message.Id,\r\n\t\tAssetId: message.AssetId,\r\n\t\tIsFromMobile: isFromMobile,\r\n\t\tCreatedOn: message.CreatedOn,\r\n\t\tCreatedEpoch: message.CreatedEpoch,\r\n\t\tType: message.Type,\r\n\t\tTypeId: message.TypeId,\r\n\t\tText: message.Text,\r\n\t\tSource: message.Source,\r\n\t\tPriority: message.Priority,\r\n\t\tPosition: message.Position,\r\n\t};\r\n\r\n\t// TODO .Position a reference to positionsById instead?\r\n\tif (isFromMobile) {\r\n\t\titem.IsAcknowledged = message.IsAcknowledged;\r\n\t\titem.AcknowledgedOn = message.AcknowledgedOn;\r\n\t} else {\r\n\t\titem.RawText = message.RawText;\r\n\t\titem.SentOn = message.SentOn;\r\n\t\titem.IsSent = message.IsSent;\r\n\t\titem.IsError = message.IsError;\r\n\t\titem.Status = message.Status;\r\n\t\titem.Response = message.Response;\r\n\t}\r\n\treturn item;\r\n}\r\n\r\nexport function addMessageToAssetMessageCounts(assetId, messageId, deliveryType, isForChat) {\r\n\t// TODO support for viewMode - though this method appears to apply to normal_live mode only\r\n\t// calling function needs to take shared views into consideration\r\n\tconsole.log(\"addMessageToAssetMessageCounts: \" + assetId + \", \" + messageId + \", \" + deliveryType + \", \" + isForChat);\r\n\tassetId = parseInt(assetId);\r\n\tmessageId = parseInt(messageId);\r\n\tif (trkData.live.messageCountsByAssetId[assetId] === undefined) {\r\n\t\tvar messageCount = {\r\n\t\t\tId: assetId,\r\n\t\t\tFromMobile: deliveryType === 1 ? 1 : 0,\r\n\t\t\tFromMobileChats: deliveryType === 1 && isForChat ? 1 : 0,\r\n\t\t\tFromMobileDevice: deliveryType === 1 && !isForChat ? 1 : 0,\r\n\t\t\tToMobile: deliveryType === 0 ? 1 : 0,\r\n\t\t\tToMobileChats: deliveryType === 0 && isForChat ? 1 : 0,\r\n\t\t\tToMobileDevice: deliveryType === 0 && !isForChat ? 1 : 0,\r\n\t\t\tFromMobileUnread: deliveryType === 1 ? [messageId] : [],\r\n\t\t\tToMobileUnread: deliveryType === 0 ? [messageId] : [],\r\n\t\t};\r\n\t\ttrkData.live.messageCounts.push(messageCount);\r\n\t\ttrkData.live.messageCountsByAssetId[assetId] = messageCount;\r\n\t} else {\r\n\t\tvar counts = trkData.live.messageCountsByAssetId[assetId];\r\n\t\tif (deliveryType === 1) {\r\n\t\t\tcounts.FromMobile += 1;\r\n\t\t\tif (isForChat) {\r\n\t\t\t\tcounts.FromMobileChats += 1;\r\n\t\t\t} else {\r\n\t\t\t\tcounts.FromMobileDevice += 1;\r\n\t\t\t}\r\n\t\t\tif (counts.FromMobileUnread === undefined) {\r\n\t\t\t\tcounts.FromMobileUnread = [messageId];\r\n\t\t\t} else {\r\n\t\t\t\tcounts.FromMobileUnread.push(messageId);\r\n\t\t\t}\r\n\t\t} else if (deliveryType === 0) {\r\n\t\t\tcounts.ToMobile += 1;\r\n\t\t\tif (isForChat) {\r\n\t\t\t\tcounts.ToMobileChats += 1;\r\n\t\t\t} else {\r\n\t\t\t\tcounts.ToMobileDevice += 1;\r\n\t\t\t}\r\n\t\t\tif (counts.ToMobileUnread === undefined) {\r\n\t\t\t\tcounts.ToMobileUnread = [messageId];\r\n\t\t\t} else {\r\n\t\t\t\tcounts.ToMobileUnread.push(messageId);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tupdateAssetNotificationTime(assetId, \"messages\", new Date().getTime());\r\n\tupdateAssetFunctionBadges(getAssetDataGroupForCurrentViewMode(), assetId);\r\n\tupdateGroupFunctionBadges(getAssetDataGroupForCurrentViewMode(), [assetId], \"asset\");\r\n}\r\n\r\nfunction openSendMessageToFenceDialog(fence) {\r\n\topenSendMessageDialog(null, null, fence);\r\n}\r\n\r\nfunction openSendMessageToAssetGroupDialog(group) {\r\n\topenSendMessageDialog(null, group);\r\n}\r\n\r\nexport function openSendMessageToAssetDialog(asset) {\r\n\topenSendMessageDialog(asset);\r\n}\r\n\r\nexport function openSendMessageDialog(asset, group, fence) {\r\n\tif (asset == null && group == null && fence == null) {\r\n\t\treturn;\r\n\t}\r\n\ttrkData.validation.sendMessage.resetForm();\r\n\ttrkData.validation.sendMessage.currentForm.reset();\r\n\r\n\tvar dialog = $j(domNodes.dialogs.sendMessage);\r\n\t$j(\"#send-message-assets\").hide();\r\n\t$j(\"#send-message-assets-container\").empty();\r\n\t$j(\"#sendMessageStatus\").text(\"\").hide();\r\n\t$j(\"#send-message-beam-templates\").hide();\r\n\t$j(\"#send-message-quick\").hide();\r\n\t$j(\"#quick-messages\").empty();\r\n\t$j(\"#message-text-label\").text(strings.TEXT + \":\");\r\n\t$j(\"#txtMessageText\").addClass(\"required\");\r\n\t$j(\"div.idp-only\", dialog).hide();\r\n\t$j(\"#chkMessageNotifyOnRead\").prop(\"checked\", false);\r\n\t$j(dialog).removeData(\"assetId\");\r\n\t$j(dialog).removeData(\"groupId\");\r\n\t$j(dialog).removeData(\"fenceId\");\r\n\tif (asset != null) {\r\n\t\tvar device = findDeviceById(asset.DeviceId);\r\n\t\tif (!device.SupportsMessaging) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t$j(\"#txtMessageDestination\").text(asset.Name + \" (\" + asset.UniqueId + \")\");\r\n\r\n\t\t// message length indicator based on device of asset\r\n\t\t// todo: standardsize messagemaxsize to be characters... (byte limits aren't much use in the UI)\r\n\t\t// clear previous maxchars\r\n\t\t$j(\"#txtMessageText\").val(\"\").maxChar(\"destroy\");\r\n\t\tif (device.MessageMaxSize > 0 && device.MessageMaxSize < 1500) {\r\n\t\t\t$j(\"#txtMessageText\").maxChar(\"init\", device.MessageMaxSize, { indicator: \"txtMessageTextIndicator\" });\r\n\t\t}\r\n\r\n\t\tif (asset.DeviceId === devices.BEAM) {\r\n\t\t\t$j(\"#send-message-beam-templates\").show().find(\"option:selected\").prop(\"selected\", false);\r\n\t\t}\r\n\r\n\t\tif (device.SupportsQuickMessages) {\r\n\t\t\tif (asset.QuickMessageToMobileTemplateId != \"\") {\r\n\t\t\t\t$j(\"#send-message-quick\").show().find(\"#quick-messages\").append($j(\"\").val(\"\").text(\"\"));\r\n\t\t\t\tloadQuickMessageTemplate(asset.QuickMessageToMobileTemplateId);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (\r\n\t\t\t$j.inArray(asset.DeviceId, devices.SKYWAVE_IDP_DUAL_MODE) != -1 ||\r\n\t\t\t$j.inArray(asset.DeviceId, devices.SKYWAVE_IDP) != -1\r\n\t\t) {\r\n\t\t\t$j(\"div.idp-only\", dialog).show();\r\n\t\t}\r\n\t\t$j(dialog).data(\"assetId\", asset.Id);\r\n\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.sendMessage,\r\n\t\t\tstrings.SEND_MESSAGE,\r\n\t\t\tasset,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\t\"asset\",\r\n\t\t\t\"send-message\",\r\n\t\t\topenSendMessageToAssetDialog\r\n\t\t);\r\n\t} else if (group != null) {\r\n\t\t$j(\"#txtMessageDestination\").text(group.Name);\r\n\t\t$j(dialog).data(\"groupId\", group.Id);\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.sendMessage,\r\n\t\t\tstrings.SEND_MESSAGE,\r\n\t\t\tgroup,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\t\"group\",\r\n\t\t\t\"send-message\",\r\n\t\t\topenSendMessageToAssetGroupDialog\r\n\t\t);\r\n\t} else if (fence != null) {\r\n\t\t$j(\"#txtMessageDestination\").text(fence.Name);\r\n\t\t$j(dialog).data(\"fenceId\", fence.Id);\r\n\t\t// populate assets\r\n\t\tvar assetIds = findAssetIdsInGeofence(fence);\r\n\t\tvar cont = $j(\"#send-message-assets-container\");\r\n\t\tvar assets = new Array();\r\n\t\tfor (var i = 0; i < assetIds.length; i++) {\r\n\t\t\tvar asset = findAssetById(assetIds[i]);\r\n\t\t\tif (asset == null) continue;\r\n\t\t\tassets.push(asset);\r\n\t\t}\r\n\t\tassets.sort(sortByName);\r\n\t\tfor (var i = 0; i < assets.length; i++) {\r\n\t\t\tvar asset = assets[i];\r\n\t\t\tvar input = $j(\r\n\t\t\t\t' '\r\n\t\t\t)\r\n\t\t\t\t.val(asset.Id)\r\n\t\t\t\t.prop(\"checked\", true);\r\n\t\t\tvar label = $j(' ').text(asset.Name);\r\n\t\t\tcont.append($('').append(input).append(label));\r\n\t\t}\r\n\t\t$j(\"#send-message-assets\").show();\r\n\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.sendMessage,\r\n\t\t\tstrings.SEND_MESSAGE,\r\n\t\t\tfence,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\t\"fence\",\r\n\t\t\t\"send-message\",\r\n\t\t\topenSendMessageToFenceDialog\r\n\t\t);\r\n\t}\r\n\r\n\tdocument.getElementById(\"txtMessageText\").focus();\r\n}\r\n\r\nfunction loadQuickMessageTemplate(templateId) {\r\n\tif (trkData.quickMessages[templateId] != null) {\r\n\t\trenderQuickMessageTemplate(templateId);\r\n\t} else {\r\n\t\ttoggleLoadingMessage(true, \"quick-messages\");\r\n\t\tvar data = { id: templateId };\r\n\t\treturn $j.ajax({\r\n\t\t\ttype: \"POST\",\r\n\t\t\turl: wrapUrl(\"/services/GPSService.asmx/GetQuickMessageToMobileTemplate\"),\r\n\t\t\tdata: JSON.stringify(data),\r\n\t\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\t\tdataType: \"json\",\r\n\t\t\tsuccess: function (msg) {\r\n\t\t\t\tif (msg.d) {\r\n\t\t\t\t\tvar result = msg.d;\r\n\t\t\t\t\tif (result.Success == true) {\r\n\t\t\t\t\t\ttrkData.quickMessages[templateId] = result.Messages;\r\n\t\t\t\t\t\trenderQuickMessageTemplate(templateId);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\thandleWebServiceError(\"\");\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\ttoggleLoadingMessage(false, \"quick-messages\");\r\n\t\t\t},\r\n\t\t\terror: function (xhr, status, error) {\r\n\t\t\t\thandleWebServiceError(\"\");\r\n\t\t\t\ttoggleLoadingMessage(false, \"quick-messages\");\r\n\t\t\t\t// btn.prop(\"disabled\", false);\r\n\t\t\t},\r\n\t\t});\r\n\t}\r\n}\r\n\r\nfunction renderQuickMessageTemplate(templateId) {\r\n\tvar messages = trkData.quickMessages[templateId];\r\n\tif (messages == null) return;\r\n\tvar cont = $j(\"#quick-messages\");\r\n\tfor (var i = 0; i < messages.length; i++) {\r\n\t\tvar message = messages[i];\r\n\t\tcont.append($j(\"
\").val(message.Id).text(message.Text));\r\n\t}\r\n}\r\n","import strings from \"./strings.js\";\r\nimport trkData from \"./data.js\";\r\nimport state from \"./state.js\";\r\nimport options from \"./options.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport user from \"./user.js\";\r\nimport { mapModes } from \"./const.js\";\r\nimport { openDialogPanel } from \"./panel-nav.js\";\r\nimport { createListing, defaultListItemSort } from \"./item-listing.js\";\r\nimport { getGroupAssetStatus } from \"./asset-group.js\";\r\nimport { checkForShareViewChange } from \"./shared-view.js\";\r\nimport { loadLiveMessagesForAssets } from \"./messages.js\";\r\nimport {\r\n\tloadHistoryMessagesForTrip,\r\n\tloadHistoryMessagesForAssets,\r\n\tloadHistoryMessagesForSharedView,\r\n} from \"./messages-history.js\";\r\nimport { getDisplayFilterForEventType } from \"./display-filter.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport _ from \"lodash\";\r\n\r\nexport function openActivityForSharedView(sharedView) {\r\n\tvar includeChatMessages = sharedView.IsMessagingEnabled;\r\n\tvar deferreds = [];\r\n\r\n\tvar positions = trkData.sharedView.normalizedPositions;\r\n\tvar events = trkData.sharedView.normalizedEvents;\r\n\tvar messages = [];\r\n\tif (includeChatMessages) {\r\n\t\tdeferreds.push(loadHistoryMessagesForSharedView(sharedView.Id));\r\n\t}\r\n\r\n\t$.when.apply($, deferreds).done(function () {\r\n\t\tmessages = trkData.sharedView.normalizedMessages;\r\n\t\tvar others = events.concat(messages);\r\n\t\tpositions = filterPositionsAlreadyIncluded(positions, others);\r\n\t\tlet items = others.concat(positions);\r\n\t\titems = _.sortBy(_.filter(items, getDisplayFilterForEventType(\"activity\")), defaultListItemSort).reverse();\r\n\t\tcreateListing(items, \"activity\");\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.assetActivity,\r\n\t\t\tstrings.ACTIVITY_LOG,\r\n\t\t\tsharedView,\r\n\t\t\tfalse,\r\n\t\t\tcheckForShareViewChange(sharedView),\r\n\t\t\t\"shared-view\",\r\n\t\t\t\"shared-view-activity\",\r\n\t\t\topenActivityForSharedView\r\n\t\t);\r\n\t});\r\n}\r\n\r\nexport function openActivityForAsset(asset) {\r\n\tvar includeChatMessages = !(user.isAnonymous && !options.allowAnonymousMessaging);\r\n\tvar includeDeviceMessages = !user.isAnonymous;\r\n\tvar items = [];\r\n\tvar deferreds = [];\r\n\tvar dataSource = state.activeMapMode === mapModes.LIVE ? trkData.live : trkData.history;\r\n\r\n\tvar positions = [];\r\n\tif (dataSource.normalizedPositionsByAssetId[asset.Id] !== undefined) {\r\n\t\tpositions = dataSource.normalizedPositionsByAssetId[asset.Id];\r\n\t}\r\n\r\n\tvar events = [];\r\n\tif (dataSource.normalizedEventsByAssetId[asset.Id] !== undefined) {\r\n\t\tevents = dataSource.normalizedEventsByAssetId[asset.Id];\r\n\t}\r\n\r\n\tvar messages = [];\r\n\tif (includeChatMessages || includeDeviceMessages) {\r\n\t\tvar loadMessages = state.activeMapMode === mapModes.LIVE ? loadLiveMessagesForAssets : loadHistoryMessagesForAssets;\r\n\t\tdeferreds.push(loadMessages([asset.Id]));\r\n\t}\r\n\r\n\t$.when.apply($, deferreds).done(function () {\r\n\t\tif (dataSource.normalizedMessagesByAssetId[asset.Id] !== undefined) {\r\n\t\t\tmessages = dataSource.normalizedMessagesByAssetId[asset.Id];\r\n\t\t}\r\n\t\tvar others = events.concat(messages);\r\n\t\tpositions = filterPositionsAlreadyIncluded(positions, others);\r\n\t\titems = others.concat(positions);\r\n\t\tvar filteredItems = _.filter(items, getDisplayFilterForEventType(\"activity\"));\r\n\t\tconsole.log(filteredItems);\r\n\t\titems = _.sortBy(filteredItems, defaultListItemSort).reverse();\r\n\t\tcreateListing(items, \"activity\");\r\n\t\tconsole.log(\r\n\t\t\t_.sortBy(filteredItems, function (item) {\r\n\t\t\t\treturn item.Epoch;\r\n\t\t\t}).reverse()\r\n\t\t);\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.assetActivity,\r\n\t\t\tstrings.ACTIVITY_LOG,\r\n\t\t\tasset,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\t\"asset\",\r\n\t\t\t\"asset-activity\",\r\n\t\t\topenActivityForAsset\r\n\t\t);\r\n\t});\r\n}\r\n\r\nexport function openActivityForGroup(group) {\r\n\tvar status = getGroupAssetStatus(group.Id);\r\n\tvar includeChatMessages = !(user.isAnonymous && !options.allowAnonymousMessaging);\r\n\tvar includeDeviceMessages = !user.isAnonymous;\r\n\tvar items = [];\r\n\tvar deferreds = [];\r\n\tvar dataSource = state.activeMapMode === mapModes.LIVE ? trkData.live : trkData.history;\r\n\r\n\tvar positions = [];\r\n\tvar events = [];\r\n\t_.each(status.assetIds, function (assetId) {\r\n\t\tif (dataSource.normalizedPositionsByAssetId[assetId] !== undefined) {\r\n\t\t\tpositions = positions.concat(dataSource.normalizedPositionsByAssetId[assetId]);\r\n\t\t}\r\n\r\n\t\tif (dataSource.normalizedEventsByAssetId[assetId] !== undefined) {\r\n\t\t\tevents = events.concat(dataSource.normalizedEventsByAssetId[assetId]);\r\n\t\t}\r\n\t});\r\n\r\n\tvar messages = [];\r\n\tif (includeChatMessages || includeDeviceMessages) {\r\n\t\tvar loadMessages = state.activeMapMode === mapModes.LIVE ? loadLiveMessagesForAssets : loadHistoryMessagesForAssets;\r\n\t\tdeferreds.push(loadMessages(status.assetIds));\r\n\t}\r\n\r\n\t$.when.apply($, deferreds).done(function () {\r\n\t\t_.each(status.assetIds, function (assetId) {\r\n\t\t\tif (dataSource.normalizedMessagesByAssetId[assetId] !== undefined) {\r\n\t\t\t\tmessages = messages.concat(dataSource.normalizedMessagesByAssetId[assetId]);\r\n\t\t\t}\r\n\t\t});\r\n\t\tvar others = events.concat(messages);\r\n\t\tpositions = filterPositionsAlreadyIncluded(positions, others);\r\n\t\titems = others.concat(positions);\r\n\t\titems = _.sortBy(_.filter(items, getDisplayFilterForEventType(\"activity\")), defaultListItemSort).reverse();\r\n\t\tcreateListing(items, \"activity\");\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.assetActivity,\r\n\t\t\tstrings.ACTIVITY_LOG,\r\n\t\t\tgroup,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\t\"group\",\r\n\t\t\t\"group-activity\",\r\n\t\t\topenActivityForGroup\r\n\t\t);\r\n\t});\r\n}\r\n\r\nexport function openActivityForTrip(trip) {\r\n\tvar includeChatMessages = !(user.isAnonymous && !options.allowAnonymousMessaging);\r\n\tvar includeDeviceMessages = !user.isAnonymous;\r\n\tvar items = [];\r\n\tvar deferreds = [];\r\n\r\n\tvar positions = [];\r\n\tif (trkData.trips.normalizedPositionsByTripId[trip.Id] !== undefined) {\r\n\t\tpositions = trkData.trips.normalizedPositionsByTripId[trip.Id];\r\n\t}\r\n\r\n\tvar events = [];\r\n\tif (trkData.trips.normalizedEventsByTripId[trip.Id] !== undefined) {\r\n\t\tevents = trkData.trips.normalizedEventsByTripId[trip.Id];\r\n\t}\r\n\r\n\tvar messages = [];\r\n\tif (includeChatMessages || includeDeviceMessages) {\r\n\t\tdeferreds.push(loadHistoryMessagesForTrip(trip.Id));\r\n\t}\r\n\r\n\t$.when.apply($, deferreds).done(function () {\r\n\t\tif (trkData.trips.normalizedMessagesByTripId[trip.Id] !== undefined) {\r\n\t\t\tmessages = trkData.trips.normalizedMessagesByTripId[trip.Id];\r\n\t\t}\r\n\t\tvar others = events.concat(messages);\r\n\t\tpositions = filterPositionsAlreadyIncluded(positions, others);\r\n\t\titems = others.concat(positions);\r\n\t\titems = _.sortBy(_.filter(items, getDisplayFilterForEventType(\"activity\")), defaultListItemSort).reverse();\r\n\t\tcreateListing(items, \"activity\");\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.assetActivity,\r\n\t\t\tstrings.ACTIVITY_LOG,\r\n\t\t\ttrip,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\t\"trip\",\r\n\t\t\t\"trip-activity\",\r\n\t\t\topenActivityForTrip\r\n\t\t);\r\n\t});\r\n}\r\n\r\nexport function openActivityForJourney(journey) {\r\n\tvar includeChatMessages = !(user.isAnonymous && !options.allowAnonymousMessaging);\r\n\tvar includeDeviceMessages = !user.isAnonymous;\r\n\tvar items = [];\r\n\tvar deferreds = [];\r\n\r\n\tvar positions = [];\r\n\tvar events = [];\r\n\tvar messages = [];\r\n\r\n\t_.each(journey.Trips, function (trip) {\r\n\t\tif (trkData.trips.normalizedPositionsByTripId[trip.Id] !== undefined) {\r\n\t\t\tpositions = positions.concat(trkData.trips.normalizedPositionsByTripId[trip.Id]);\r\n\t\t}\r\n\t\tif (trkData.trips.normalizedEventsByTripId[trip.Id] !== undefined) {\r\n\t\t\tevents = events.concat(trkData.trips.normalizedEventsByTripId[trip.Id]);\r\n\t\t}\r\n\t\tif (includeChatMessages || includeDeviceMessages) {\r\n\t\t\tdeferreds.push(loadHistoryMessagesForTrip(trip.Id));\r\n\t\t}\r\n\t});\r\n\r\n\t$.when.apply($, deferreds).done(function () {\r\n\t\t_.each(journey.Trips, function (trip) {\r\n\t\t\tif (trkData.trips.normalizedMessagesByTripId[trip.Id] !== undefined) {\r\n\t\t\t\tmessages = trkData.trips.normalizedMessagesByTripId[trip.Id];\r\n\t\t\t}\r\n\t\t});\r\n\t\tvar others = events.concat(messages);\r\n\t\tpositions = filterPositionsAlreadyIncluded(positions, others);\r\n\t\titems = others.concat(positions);\r\n\t\titems = _.sortBy(_.filter(items, getDisplayFilterForEventType(\"activity\")), defaultListItemSort).reverse();\r\n\t\tcreateListing(items, \"activity\");\r\n\t\topenDialogPanel(\r\n\t\t\tdomNodes.dialogs.assetActivity,\r\n\t\t\tstrings.ACTIVITY_LOG,\r\n\t\t\tjourney,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\t\"journey\",\r\n\t\t\t\"journey-activity\",\r\n\t\t\topenActivityForJourney\r\n\t\t);\r\n\t});\r\n}\r\n\r\nexport function filterPositionsAlreadyIncluded(positions, others) {\r\n\tvar positionIds = _.filter(\r\n\t\t_.map(others, function (item) {\r\n\t\t\tif (item.Event !== undefined && item.Position !== undefined) {\r\n\t\t\t\treturn item.Position.Id;\r\n\t\t\t} else if (item.Message !== undefined && item.Position !== undefined) {\r\n\t\t\t\treturn item.Position.Id;\r\n\t\t\t} else if (item.Chat !== undefined && item.Position !== undefined) {\r\n\t\t\t\treturn item.Position.Id;\r\n\t\t\t}\r\n\t\t}),\r\n\t\tfunction (item) {\r\n\t\t\treturn item !== undefined;\r\n\t\t}\r\n\t);\r\n\tvar positionIdLookup = {};\r\n\t_.each(positionIds, function (id) {\r\n\t\tpositionIdLookup[id] = true;\r\n\t});\r\n\treturn _.filter(positions, function (item) {\r\n\t\treturn positionIdLookup[item.Position.Id] === undefined;\r\n\t});\r\n}\r\n","import strings from \"./strings.js\";\r\nimport trkData from \"./data.js\";\r\nimport state from \"./state.js\";\r\nimport options from \"./options.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport log from \"./log.js\";\r\nimport user from \"./user.js\";\r\nimport { mapModes } from \"./const.js\";\r\nimport { findAssetById } from \"./assets.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport { handleWebServiceError } from \"./ajax.js\";\r\nimport { findGroupById, openEventsForGroup, openStatusForGroup, openAlertsForGroup } from \"./asset-group.js\";\r\nimport { checkMarkerBounce } from \"./asset-live.js\";\r\nimport { normalizeAssetData } from \"./assets.js\";\r\nimport { updateGroupFunctionBadges, updateAssetFunctionBadges } from \"./badges.js\";\r\nimport { hasAVLAssets } from \"./avl.js\";\r\nimport { getAssetDataGroupForCurrentViewMode } from \"./map-viewmode.js\";\r\nimport { openDialogPanel } from \"./panel-nav.js\";\r\nimport { createListing, defaultListItemSort } from \"./item-listing.js\";\r\nimport { openStatusForAsset } from \"./asset-state.js\";\r\nimport { openAlertsForAsset } from \"./asset-alerts.js\";\r\nimport { createMarkerPath } from \"./marker-path.js\";\r\nimport { getPositionLinkForEvent, mapPositionForEvent } from \"./positions.js\";\r\nimport { getGroupAssetStatus } from \"./asset-group.js\";\r\nimport { htmlEscape } from \"./dom-util.js\";\r\nimport { createIconForAssetEvent } from \"./asset-state.js\";\r\nimport { findPlaceByUniqueKey } from \"./place.js\";\r\nimport { openActivityForAsset, openActivityForGroup } from \"./activities.js\";\r\nimport { getDisplayFilterForEventType } from \"./display-filter.js\";\r\nimport { updateAssetNotificationTime } from \"./asset-notification.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport $j from \"jquery\";\r\nimport _ from \"lodash\";\r\n\r\n// The list of events that denote a change in the asset's status\r\nexport const EVENTS_STATUS = [\r\n\t47, // moving start\r\n\t48, // moving stop\r\n\t1, // start\r\n\t2, // stop\r\n\t21, // ignition on\r\n\t22, // ignition off\r\n\t32, // idling\r\n\t98, // idling stop\r\n\t5, // speeding start\r\n\t6, // speeding stop\r\n\t3, // power on\r\n\t4, // power off\r\n\t41, // dwelling start (stopped around a place for an amount of time)\r\n\t97, // dwelling stop\r\n\t45, // towing start\r\n\t46, // towing stop\r\n\t19, // on main power\r\n\t20, // on backup power\r\n\t35, // antenna cut start\r\n\t129, // antenna cut stop\r\n\t36, // gps jamming start\r\n\t37, // gps jamming end\r\n\t38, // cell jamming start\r\n\t39, // cell jamming end\r\n\t//9, // emergency on\r\n\t//124, // emergency off\r\n\t//126, // help\r\n\t//278, // cancel help\r\n\t//271, // man down\r\n\t//15, // check in\r\n\t//10, // reset\r\n\t133, // low battery\r\n\t305, // immobilizer enabled\r\n\t306, // immobilizer disabled\r\n];\r\n\r\n// Events related to text messages.\r\n// NOTE: Garmin quick message events (120 msg, 123 response) are handled elsewhere.\r\nexport const EVENTS_TEXT_MESSAGE = [\r\n\t51, // text message\r\n\t52, // text message status\r\n];\r\n\r\n// Events related to emergency (and signalling end of emergency)\r\nexport const EVENTS_EMERGENCY = [\r\n\t9, // emergency on\r\n\t124, // emergency off\r\n\t126, // help\r\n\t278, // help cancel\r\n\t29, // panic button\r\n\t291, // fall down\r\n\t271, // man down\r\n];\r\n\r\n// Events related to alerts\r\nexport const EVENTS_ALERT = [\r\n\t14, // alert triggered\r\n\t16, // alert no longer triggered\r\n];\r\n\r\nexport function addAssetEvents(events, forMapMode) {\r\n\tvar addedEvents = [];\r\n\r\n\tfor (var i = 0; i < events.length; i++) {\r\n\t\tvar item = events[i];\r\n\r\n\t\tif (item.Event != null) {\r\n\t\t\titem = item.Event;\r\n\t\t}\r\n\r\n\t\tif (events[i].Position != null) {\r\n\t\t\t// what\r\n\t\t\titem.Position = events[i].Position;\r\n\t\t}\r\n\r\n\t\t// bounce the existing position when a new bounce event comes in without a position attached\r\n\t\tif (\r\n\t\t\tstate.activeMapMode === mapModes.LIVE &&\r\n\t\t\toptions.bounceOnEvents.indexOf(item.Type) !== -1 &&\r\n\t\t\titem.Position == null\r\n\t\t) {\r\n\t\t\tvar asset = findAssetById(item.AssetId);\r\n\t\t\tvar assetLivePosition = trkData.live.latestPositionsByAssetId[asset.Id];\r\n\t\t\tif (assetLivePosition !== undefined && assetLivePosition.Position != null) {\r\n\t\t\t\tvar positionMarker = trkData.live.markersByPositionId[assetLivePosition.Position.Id];\r\n\t\t\t\tif (positionMarker !== undefined) {\r\n\t\t\t\t\tcheckMarkerBounce(positionMarker);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (trkData.eventsById[item.Id] === undefined) {\r\n\t\t\ttrkData.eventsById[item.Id] = normalizeAssetData(item.AssetId, \"event\", item);\r\n\t\t}\r\n\r\n\t\t// only add an item if its not already in the list\r\n\t\tif (forMapMode === mapModes.LIVE) {\r\n\t\t\tif (trkData.live.normalizedEventIds[item.Id] !== undefined) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\ttrkData.live.normalizedEventIds[item.Id] = true;\r\n\t\t\ttrkData.live.events.push(item);\r\n\t\t\ttrkData.live.eventIds.push(item.Id);\r\n\t\t\ttrkData.live.normalizedEvents.push(trkData.eventsById[item.Id]);\r\n\r\n\t\t\tvar thisId = parseInt(item.Id);\r\n\t\t\tif (trkData.lastEventId === null) {\r\n\t\t\t\ttrkData.lastEventId = thisId;\r\n\t\t\t}\r\n\t\t\tif (trkData.lastEventId < thisId) {\r\n\t\t\t\ttrkData.lastEventId = thisId;\r\n\t\t\t}\r\n\r\n\t\t\tupdateAssetEventNotificationTime(item);\r\n\t\t} else if (forMapMode === mapModes.HISTORY) {\r\n\t\t\tif (trkData.history.normalizedEventIds[item.Id] !== undefined) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\ttrkData.history.events.push(item);\r\n\t\t\ttrkData.history.normalizedEvents.push(trkData.eventsById[item.Id]);\r\n\t\t\ttrkData.history.normalizedEventIds[item.Id] = true;\r\n\t\t}\r\n\r\n\t\taddedEvents.push(item);\r\n\t}\r\n\r\n\tif (addedEvents.length > 0) {\r\n\t\tif (forMapMode === mapModes.LIVE) {\r\n\t\t\ttrkData.live.normalizedEventsByAssetId = _.groupBy(trkData.live.normalizedEvents, \"AssetId\");\r\n\t\t} else if (forMapMode === mapModes.HISTORY) {\r\n\t\t\ttrkData.history.normalizedEventsByAssetId = _.groupBy(trkData.history.normalizedEvents, \"AssetId\");\r\n\t\t}\r\n\t}\r\n\r\n\tvar assetIdsUpdated = _.chain(addedEvents).map(\"AssetId\").uniq().value();\r\n\tvar assetsUpdated = [];\r\n\tif (state.activeMapMode === mapModes.LIVE) {\r\n\t\t_.each(assetIdsUpdated, function (assetId) {\r\n\t\t\tupdateAssetFunctionBadges(getAssetDataGroupForCurrentViewMode(), assetId);\r\n\t\t\tassetsUpdated.push(findAssetById(assetId));\r\n\t\t});\r\n\t\tupdateGroupFunctionBadges(getAssetDataGroupForCurrentViewMode(), assetIdsUpdated, \"asset\");\r\n\t\tlog(\"Update event/status/alert notifications for assets: \" + assetIdsUpdated.join(\", \"));\r\n\t}\r\n\r\n\t// refresh the events, alerts, or status dialogs if it is currently opened for a related asset or group\r\n\tif (\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-group-for\") === \"dialog\" &&\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-item-type\") === \"assets\" &&\r\n\t\tdocument.getElementById(\"dialog-functions\").querySelector(\".dialog\") === domNodes.dialogs.assetEvents\r\n\t) {\r\n\t\t// todo: only append to the existing listing, don't recreate\r\n\t\tvar assetId = parseInt(domNodes.panels.secondary.getAttribute(\"data-item-id\"));\r\n\t\tif (assetIdsUpdated.indexOf(assetId) !== -1) {\r\n\t\t\tvar updatedAsset = findAssetById(assetId);\r\n\t\t\topenEventsForAsset(updatedAsset);\r\n\t\t}\r\n\t} else if (\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-group-for\") === \"dialog\" &&\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-item-type\") === \"groups\" &&\r\n\t\tdocument.getElementById(\"dialog-functions\").querySelector(\".dialog\") === domNodes.dialogs.assetEvents\r\n\t) {\r\n\t\t// todo: only append to the existing listing, don't recreate\r\n\t\tvar groupId = domNodes.panels.secondary.getAttribute(\"data-item-id\");\r\n\t\tvar assetInGroup = _.find(assetsUpdated, function (asset) {\r\n\t\t\treturn asset.ParentGroupIds.indexOf(groupId) !== -1;\r\n\t\t});\r\n\t\tif (assetInGroup !== undefined) {\r\n\t\t\topenEventsForGroup(findGroupById(groupId));\r\n\t\t}\r\n\t} else if (\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-group-for\") === \"dialog\" &&\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-item-type\") === \"assets\" &&\r\n\t\tdocument.getElementById(\"dialog-functions\").querySelector(\".dialog\") === domNodes.dialogs.assetStatus\r\n\t) {\r\n\t\t// todo: only append to the existing listing, don't recreate\r\n\t\tvar assetId = parseInt(domNodes.panels.secondary.getAttribute(\"data-item-id\"));\r\n\t\tif (assetIdsUpdated.indexOf(assetId) !== -1) {\r\n\t\t\tvar updatedAsset = findAssetById(assetId);\r\n\t\t\topenStatusForAsset(updatedAsset);\r\n\t\t}\r\n\t} else if (\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-group-for\") === \"dialog\" &&\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-item-type\") === \"groups\" &&\r\n\t\tdocument.getElementById(\"dialog-functions\").querySelector(\".dialog\") === domNodes.dialogs.assetStatus\r\n\t) {\r\n\t\t// todo: only append to the existing listing, don't recreate\r\n\t\tvar groupId = domNodes.panels.secondary.getAttribute(\"data-item-id\");\r\n\t\tvar assetInGroup = _.find(assetsUpdated, function (asset) {\r\n\t\t\treturn asset.ParentGroupIds.indexOf(groupId) !== -1;\r\n\t\t});\r\n\t\tif (assetInGroup !== undefined) {\r\n\t\t\topenStatusForGroup(findGroupById(groupId));\r\n\t\t}\r\n\t} else if (\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-group-for\") === \"dialog\" &&\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-item-type\") === \"assets\" &&\r\n\t\tdocument.getElementById(\"dialog-functions\").querySelector(\".dialog\") === domNodes.dialogs.assetAlerts\r\n\t) {\r\n\t\t// todo: only append to the existing listing, don't recreate\r\n\t\tvar assetId = parseInt(domNodes.panels.secondary.getAttribute(\"data-item-id\"));\r\n\t\tif (assetIdsUpdated.indexOf(assetId) !== -1) {\r\n\t\t\tvar updatedAsset = findAssetById(assetId);\r\n\t\t\topenAlertsForAsset(updatedAsset);\r\n\t\t}\r\n\t} else if (\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-group-for\") === \"dialog\" &&\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-item-type\") === \"groups\" &&\r\n\t\tdocument.getElementById(\"dialog-functions\").querySelector(\".dialog\") === domNodes.dialogs.assetAlerts\r\n\t) {\r\n\t\t// todo: only append to the existing listing, don't recreate\r\n\t\tvar groupId = domNodes.panels.secondary.getAttribute(\"data-item-id\");\r\n\t\tvar assetInGroup = _.find(assetsUpdated, function (asset) {\r\n\t\t\treturn asset.ParentGroupIds.indexOf(groupId) !== -1;\r\n\t\t});\r\n\t\tif (assetInGroup !== undefined) {\r\n\t\t\topenAlertsForGroup(findGroupById(groupId));\r\n\t\t}\r\n\t} else if (\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-group-for\") === \"dialog\" &&\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-item-type\") === \"groups\" &&\r\n\t\tdocument.getElementById(\"dialog-functions\").querySelector(\".dialog\") === domNodes.dialogs.assetActivity\r\n\t) {\r\n\t\t// todo: only append to the existing listing, don't recreate\r\n\t\tvar groupId = domNodes.panels.secondary.getAttribute(\"data-item-id\");\r\n\t\tvar assetInGroup = _.find(assetsUpdated, function (asset) {\r\n\t\t\treturn asset.ParentGroupIds.indexOf(groupId) !== -1;\r\n\t\t});\r\n\t\tif (assetInGroup !== undefined) {\r\n\t\t\topenActivityForGroup(findGroupById(groupId));\r\n\t\t}\r\n\t} else if (\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-group-for\") === \"dialog\" &&\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-item-type\") === \"assets\" &&\r\n\t\tdocument.getElementById(\"dialog-functions\").querySelector(\".dialog\") === domNodes.dialogs.assetActivity\r\n\t) {\r\n\t\t// todo: only append to the existing listing, don't recreate\r\n\t\tvar assetId = parseInt(domNodes.panels.secondary.getAttribute(\"data-item-id\"));\r\n\t\tif (assetIdsUpdated.indexOf(assetId) !== -1) {\r\n\t\t\tvar updatedAsset = findAssetById(assetId);\r\n\t\t\topenActivityForAsset(updatedAsset);\r\n\t\t}\r\n\t}\r\n\r\n\tif (state.activeMapMode === forMapMode) {\r\n\t\taddEventsToActiveNotificationList(addedEvents); // todo: seems unused\r\n\t\t//addAssetEventsToPanelListing(addedEvents);\r\n\t}\r\n}\r\n\r\n///\r\nfunction addAssetEventsToPanelListing(events) {\r\n\t// unused\r\n\tif ($j(\"#event-data\").data(\"init\") !== true) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// todo: only update the table if the shown events have actually changed\r\n\tvar eventTable = $(\"#event-data\").DataTable();\r\n\r\n\tvar tableData = [];\r\n\t_.each(events, function (item) {\r\n\t\tvar row = mapAssetEventToTableRow(item, false);\r\n\t\tif (row !== undefined && row !== null) {\r\n\t\t\ttableData.push(row);\r\n\t\t}\r\n\t});\r\n\r\n\teventTable.rows.add(tableData).draw();\r\n\ttrkData.pendingEvents = [];\r\n}\r\n\r\nexport function queryLatestEvents(defaultEvent) {\r\n\tif (trkData.pending.events) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tlet eventId;\r\n\r\n\tif (trkData.lastEventId === null) {\r\n\t\tif (defaultEvent === undefined || defaultEvent === null) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\teventId = defaultEvent;\r\n\t} else {\r\n\t\teventId = trkData.lastEventId;\r\n\t}\r\n\r\n\ttrkData.pending.events = true;\r\n\tvar dataPost = { eventId: eventId };\r\n\t$j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/GetLatestEvents\"),\r\n\t\tdata: JSON.stringify(dataPost),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\ttrkData.pending.events = false;\r\n\t\t\tif (msg.d) {\r\n\t\t\t\tvar events = msg.d;\r\n\t\t\t\tvar eventsBeforeCount = trkData.live.events.length;\r\n\t\t\t\tif (events.length > 0) {\r\n\t\t\t\t\tlog(events.length + \" events received.\");\r\n\t\t\t\t}\r\n\t\t\t\taddAssetEvents(events, mapModes.LIVE);\r\n\t\t\t\t//if (trkData.live.events.length !== eventsBeforeCount) {\r\n\t\t\t\t// // flash update notification to indicate new events added\r\n\t\t\t\t// var currBg = $j('#event-panel-tab-events').css('background-color');\r\n\t\t\t\t// $j('#event-panel-tab-events').stop().css('background-color', '#ffff9c').animate({ backgroundColor: currBg }, 3000, function () {\r\n\t\t\t\t// $j('#event-panel-tab-events').css('background-color', '');\r\n\t\t\t\t// });\r\n\t\t\t\t// $j('#event-control-btn').stop().css('background-color', '#ffff9c').animate({ backgroundColor: '#ffffff' }, 3000);\r\n\t\t\t\t//}\r\n\t\t\t}\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\ttrkData.pending.events = false;\r\n\t\t\thandleWebServiceError(strings.MSG_EVENTS_ERROR);\r\n\t\t},\r\n\t});\r\n}\r\n\r\nexport function populateEvents(events) {\r\n\t$(\"#event-data\").DataTable({\r\n\t\tdestroy: true,\r\n\t\tfilter: true,\r\n\t\tinfo: true,\r\n\t\tjQueryUI: false,\r\n\t\tautoWidth: false,\r\n\t\tlengthChange: false,\r\n\t\tpaging: true,\r\n\t\tpagingType: \"full_numbers\",\r\n\t\tdeferRender: true,\r\n\t\tprocessing: false,\r\n\t\torder: [[4, \"desc\"]],\r\n\t\tcolumns: [\r\n\t\t\t{ sortable: true }, // Asset\r\n\t\t\t{ sortable: true }, // Event Type\r\n\t\t\t{ sortable: false }, // Position/lat/lng\r\n\t\t\t{ sortable: false, className: \"break-text\" }, // Details/link\r\n\t\t\t{ width: \"75px\" }, // Time\r\n\t\t\t{ visible: false }, // AssetId (hidden)\r\n\t\t\t{ visible: false }, // Event Type Id\r\n\t\t\t{ visible: false }, // Is Time Accurate\r\n\t\t\t{ visible: false }, // Event Id\r\n\t\t],\r\n\t\tdom: '<\"H\"lfr>t<\"F\"ip>',\r\n\t\tlanguage: strings.DATATABLE,\r\n\t\tinitComplete: function (oSettings, json) {\r\n\t\t\tconsole.log(\"init complete for populateEvents\");\r\n\t\t\tvar api = this.api();\r\n\t\t\t$j(\"#event-data\").data(\"init\", true);\r\n\t\t\tapi.clear();\r\n\r\n\t\t\taddAssetEventsToPanelListing(events);\r\n\t\t\t//addAssetEvents(events);\r\n\r\n\t\t\t// move clear events button to toolbar\r\n\t\t\tvar filterDiv = $j(\"#event-data_filter\").parent().eq(0);\r\n\t\t\tvar btn = $j(' ')\r\n\t\t\t\t.attr(\"id\", \"ClearEvents\")\r\n\t\t\t\t.text(strings.BUTTON_CLEAR_EVENTS);\r\n\t\t\tif (state.activeMapMode !== mapModes.LIVE) {\r\n\t\t\t\tbtn.attr(\"disabled\", true);\r\n\t\t\t}\r\n\t\t\tbtn.appendTo(filterDiv);\r\n\r\n\t\t\t// create filter events link\r\n\t\t\tvar filter = $j(\" \")\r\n\t\t\t\t.attr(\"id\", \"FilterEvents\")\r\n\t\t\t\t.attr(\"href\", \"#\")\r\n\t\t\t\t.text(strings.EVENTS_FILTER)\r\n\t\t\t\t.appendTo(filterDiv);\r\n\t\t\t$j(\"#event-filter-types\").appendTo(filter);\r\n\r\n\t\t\tcreateFilteredEventsList();\r\n\t\t},\r\n\t\trowCallback: function (row, data, index) {\r\n\t\t\tif (data[7] != null && data[7] == false) {\r\n\t\t\t\t$j(\"td:eq(4)\", row).addClass(\"inaccurate\");\r\n\t\t\t}\r\n\t\t},\r\n\t\tdrawCallback: function (oSettings) {\r\n\t\t\tvar api = this.api();\r\n\t\t\tvar rowCount = api.rows({ search: \"applied\" }).eq(0).length;\r\n\t\t\tif (rowCount > 0) {\r\n\t\t\t\t$j(\"#event-control-btn a .badge,#event-panel-tab-events .badge\")\r\n\t\t\t\t\t.text(rowCount)\r\n\t\t\t\t\t.addClass(\"active\")\r\n\t\t\t\t\t.removeClass(\"inactive\");\r\n\t\t\t} else {\r\n\t\t\t\t$j(\"#event-control-btn a .badge,#event-panel-tab-events .badge\")\r\n\t\t\t\t\t.text(rowCount)\r\n\t\t\t\t\t.removeClass(\"active\")\r\n\t\t\t\t\t.addClass(\"inactive\");\r\n\t\t\t}\r\n\t\t},\r\n\t});\r\n}\r\n\r\nexport function createFilteredEventsList() {\r\n\t// in live mode, you can filter all events\r\n\t// in history mode, you can only filter events that were submitted\r\n\r\n\t// update filtered list based on event data (this is good for the history view but not the live view)\r\n\tvar includedEventIds = [];\r\n\tif (state.activeMapMode === mapModes.LIVE) {\r\n\t\tincludedEventIds = _.uniq(\r\n\t\t\t_.map(trkData.live.normalizedEvents, function (item) {\r\n\t\t\t\treturn item.Event.Type;\r\n\t\t\t})\r\n\t\t);\r\n\t} else if (state.activeMapMode === mapModes.HISTORY) {\r\n\t\tincludedEventIds = _.uniq(\r\n\t\t\t_.map(trkData.history.normalizedEvents, function (item) {\r\n\t\t\t\treturn item.Event.Type;\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n\r\n\tvar cont = document.getElementById(\"event-filter-items\");\r\n\t// empty it first!\r\n\tcont.innerHTML = \"\";\r\n\tif (state.activeMapMode === mapModes.LIVE) {\r\n\t\tcont.classList.add(\"multiple\");\r\n\t} else {\r\n\t\tcont.classList.remove(\"multiple\");\r\n\t}\r\n\tvar eventFilters = trkData.live.eventFilters;\r\n\tif (state.activeMapMode === mapModes.HISTORY) {\r\n\t\teventFilters = trkData.history.eventFilters;\r\n\t}\r\n\tvar isAllChecked = _.includes(eventFilters, \"all\");\r\n\tvar filterOptions = document.createDocumentFragment();\r\n\tvar filterAll = document.createElement(\"div\");\r\n\tfilterAll.className = \"col-md-4\";\r\n\tvar filterAllDiv = document.createElement(\"div\");\r\n\tfilterAllDiv.className = \"custom-control custom-checkbox\";\r\n\tvar filterAllCheckbox = document.createElement(\"input\");\r\n\tfilterAllCheckbox.className = \"custom-control-input\";\r\n\tfilterAllCheckbox.setAttribute(\"type\", \"checkbox\");\r\n\tfilterAllCheckbox.setAttribute(\"id\", \"event-filter-all\");\r\n\tfilterAllCheckbox.setAttribute(\"name\", \"event-filter\");\r\n\tif (isAllChecked) {\r\n\t\tfilterAllCheckbox.setAttribute(\"checked\", \"checked\");\r\n\t}\r\n\tvar filterAllLabel = document.createElement(\"label\");\r\n\tfilterAllLabel.className = \"custom-control-label\";\r\n\tfilterAllLabel.setAttribute(\"for\", \"event-filter-all\");\r\n\tfilterAllLabel.textContent = strings.EVENTS_ALL;\r\n\tfilterAllDiv.appendChild(filterAllCheckbox);\r\n\tfilterAllDiv.appendChild(filterAllLabel);\r\n\tfilterAll.appendChild(filterAllDiv);\r\n\tfilterOptions.appendChild(filterAll);\r\n\tvar isAVL = hasAVLAssets();\r\n\r\n\tvar standardEvents = _.sortBy(\r\n\t\t_.filter(trkData.eventTypes, function (item) {\r\n\t\t\treturn item.Id <= 16;\r\n\t\t}),\r\n\t\t\"Text\"\r\n\t);\r\n\tvar avlEvents = _.sortBy(\r\n\t\t_.filter(trkData.eventTypes, function (item) {\r\n\t\t\treturn item.Id > 16;\r\n\t\t}),\r\n\t\t\"Text\"\r\n\t);\r\n\r\n\t// output standard events\r\n\t_.each(standardEvents, function (evt) {\r\n\t\t// in history mode, only have options for actual events recorded\r\n\t\tif (state.activeMapMode !== mapModes.LIVE && !_.includes(includedEventIds, evt.Id)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tvar filterLi = createEventFilterNode(evt, isAllChecked);\r\n\t\tfilterOptions.appendChild(filterLi);\r\n\t});\r\n\r\n\tif (isAVL) {\r\n\t\tvar hr = document.createElement(\"div\");\r\n\t\thr.className = \"w-100 py-2\";\r\n\t\t//hr.style.cssText = 'float: none; width: auto; padding: 5px;';\r\n\r\n\t\tvar border = document.createElement(\"div\");\r\n\t\tborder.style.cssText = \"border-bottom: 2px solid #ccc;\";\r\n\t\thr.appendChild(border);\r\n\r\n\t\tfilterOptions.appendChild(hr);\r\n\r\n\t\t_.each(avlEvents, function (evt) {\r\n\t\t\tif (state.activeMapMode !== mapModes.LIVE && !_.includes(includedEventIds, evt.Id)) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tvar filterLi = createEventFilterNode(evt, isAllChecked);\r\n\t\t\tfilterOptions.appendChild(filterLi);\r\n\t\t});\r\n\t}\r\n\tcont.appendChild(filterOptions);\r\n}\r\n\r\nexport function openEventsForAsset(asset) {\r\n\tvar dataSource = state.activeMapMode === mapModes.LIVE ? trkData.live : trkData.history;\r\n\tvar events = _.sortBy(\r\n\t\t_.filter(dataSource.normalizedEventsByAssetId[asset.Id], getDisplayFilterForEventType(\"events\")),\r\n\t\tdefaultListItemSort\r\n\t).reverse();\r\n\tcreateListing(events, \"events\");\r\n\topenDialogPanel(\r\n\t\tdomNodes.dialogs.assetEvents,\r\n\t\tstrings.EVENTS,\r\n\t\tasset,\r\n\t\tfalse,\r\n\t\tnull,\r\n\t\t\"asset\",\r\n\t\t\"asset-events\",\r\n\t\topenEventsForAsset\r\n\t);\r\n}\r\n\r\nfunction createEventFilterNode(evt, isAllChecked) {\r\n\tvar eventFilters = trkData.live.eventFilters;\r\n\tif (state.activeMapMode === mapModes.HISTORY) {\r\n\t\teventFilters = trkData.history.eventFilters;\r\n\t}\r\n\tvar isChecked = _.includes(eventFilters, evt.Id) || isAllChecked;\r\n\tvar isDisabled = isAllChecked;\r\n\tvar filterLi = document.createElement(\"div\");\r\n\tfilterLi.className = \"col-md-4\";\r\n\tvar filterDiv = document.createElement(\"div\");\r\n\tfilterDiv.className = \"custom-control custom-checkbox\";\r\n\tvar filterInput = document.createElement(\"input\");\r\n\tfilterInput.className = \"custom-control-input\";\r\n\tfilterInput.setAttribute(\"type\", \"checkbox\");\r\n\tfilterInput.setAttribute(\"id\", \"event-filter-\" + evt.Id);\r\n\tfilterInput.setAttribute(\"name\", \"event-filter\");\r\n\tfilterInput.setAttribute(\"value\", evt.Id);\r\n\tif (isChecked) {\r\n\t\tfilterInput.setAttribute(\"checked\", \"checked\");\r\n\t}\r\n\tif (isDisabled) {\r\n\t\tfilterInput.setAttribute(\"disabled\", \"disabled\");\r\n\t}\r\n\tvar filterLabel = document.createElement(\"label\");\r\n\tfilterLabel.className = \"custom-control-label\";\r\n\tfilterLabel.setAttribute(\"for\", \"event-filter-\" + evt.Id);\r\n\tfilterLabel.textContent = evt.Text;\r\n\tfilterDiv.appendChild(filterInput);\r\n\tfilterDiv.appendChild(filterLabel);\r\n\tfilterLi.appendChild(filterDiv);\r\n\treturn filterLi;\r\n}\r\n\r\nfunction addEventsToActiveNotificationList(addedEvents) {\r\n\t// check dialog type and filter based on that?\r\n\tif (state.activeMapMode !== mapModes.LIVE) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar filteredEvents = [];\r\n\r\n\t// filter for dialog type\r\n\tvar openDialog = document.getElementById(\"dialog-functions\").querySelector(\".dialog\");\r\n\tif (openDialog === domNodes.dialogs.assetEvents) {\r\n\t\tfilteredEvents = _.filter(addedEvents, function (status) {\r\n\t\t\treturn (\r\n\t\t\t\t!status.Hide &&\r\n\t\t\t\tEVENTS_STATUS.indexOf(status.Type) === -1 &&\r\n\t\t\t\tEVENTS_ALERT.indexOf(status.Type) === -1 &&\r\n\t\t\t\tEVENTS_EMERGENCY.indexOf(status.Type) === -1 &&\r\n\t\t\t\tEVENTS_TEXT_MESSAGE.indexOf(status.Type) === -1\r\n\t\t\t);\r\n\t\t});\r\n\t} else if (openDialog === domNodes.dialogs.assetStatus) {\r\n\t\tfilteredEvents = _.filter(addedEvents, function (status) {\r\n\t\t\treturn !status.Hide && EVENTS_STATUS.indexOf(status.Type) !== -1;\r\n\t\t});\r\n\t} else if (openDialog === domNodes.dialogs.assetAlerts) {\r\n\t\tfilteredEvents = _.filter(addedEvents, function (status) {\r\n\t\t\treturn (\r\n\t\t\t\t!status.Hide &&\r\n\t\t\t\t(EVENTS_ALERT.indexOf(status.Type) !== -1 || EVENTS_EMERGENCY.indexOf(status.Type) !== -1)\r\n\t\t\t);\r\n\t\t});\r\n\t} else if (openDialog === domNodes.dialogs.assetActivity) {\r\n\t} else {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (filteredEvents.length === 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// filter for assets/groups\r\n\tvar assetId = null;\r\n\tvar groupId = null;\r\n\tif (\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-group-for\") === \"dialog\" &&\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-item-type\") === \"assets\"\r\n\t) {\r\n\t\tassetId = parseInt(domNodes.panels.secondary.getAttribute(\"data-item-id\"));\r\n\t} else if (\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-group-for\") === \"dialog\" &&\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-item-type\") === \"groups\"\r\n\t) {\r\n\t\tgroupId = domNodes.panels.secondary.getAttribute(\"data-item-id\");\r\n\t}\r\n\tif (assetId !== null) {\r\n\t\tfilteredEvents = _.filter(addedEvents, function (item) {\r\n\t\t\treturn item.AssetId === assetId;\r\n\t\t});\r\n\t} else {\r\n\t\tvar status = getGroupAssetStatus(groupId);\r\n\t\t_.each(addedEvents, function (item) {\r\n\t\t\tif (status.assetIds.indexOf(item.AssetId) !== -1) {\r\n\t\t\t\tfilteredEvents.push(item);\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\tif (filteredEvents.length === 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// include asset info for groups\r\n\tvar eventData = [];\r\n\t_.each(filteredEvents, function (event) {\r\n\t\tvar eventListing = mapAssetEventToListing(event);\r\n\t\tif (eventListing !== null) {\r\n\t\t\teventData.push(eventListing);\r\n\t\t}\r\n\t});\r\n\r\n\t// add filtered events to active list\r\n\t//console.log('events to add');\r\n\t//console.log(filteredEvents);\r\n}\r\n\r\nfunction mapAssetEventToTableRow(item, isAlert) {\r\n\t// unused\r\n\tvar asset = findAssetById(item.AssetId);\r\n\tvar itemData = null;\r\n\r\n\tif (isAlert) {\r\n\t\tvar eventicon = \"\";\r\n\t\tif (asset != null) {\r\n\t\t\teventicon =\r\n\t\t\t\t'
';\r\n\t\t}\r\n\t\tvar eventposition = getPositionLinkForEvent(item);\r\n\r\n\t\tif (item.Alert.Hide) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tvar type = item.Alert.Type;\r\n\t\tif (item.Alert.Name != null) {\r\n\t\t\ttype = item.Alert.Name + \": \" + type;\r\n\t\t}\r\n\t\titemData = [\r\n\t\t\t\"\",\r\n\t\t\titem.Alert.Priority,\r\n\t\t\tasset != null ? asset.Name : \"\",\r\n\t\t\ttype,\r\n\t\t\titem.Alert.Description != null ? item.Alert.Description.replace(/\\r?\\n/g, \" \") : \"\",\r\n\t\t\titem.Alert.ResolutionProcedure != null ? item.Alert.ResolutionProcedure.replace(/\\r?\\n/g, \" \") : \"\",\r\n\t\t\teventposition, // Position\r\n\t\t\t//(item.Details != null) ? item.Details.replace(/\\r?\\n/g, ' ') : '',\r\n\t\t\titem.Time,\r\n\t\t\t'' +\r\n\t\t\t\tstrings.ACKNOWLEDGE +\r\n\t\t\t\t\" \", // ack button\r\n\t\t\tasset.Id,\r\n\t\t\titem.Type,\r\n\t\t\titem.Alert.Color,\r\n\t\t];\r\n\t} else {\r\n\t\tvar item = mapAssetEventToListing(item);\r\n\t\tif (item === null) {\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\titemData = [\r\n\t\t\tasset != null ? asset.Name : \"\",\r\n\t\t\titem.icon + ' ' + item.name + \" \",\r\n\t\t\t\"\", //item.position,\r\n\t\t\titem.details,\r\n\t\t\titem.time,\r\n\t\t\tasset.Id,\r\n\t\t\titem.type,\r\n\t\t\titem.isAccurate,\r\n\t\t\titem.id,\r\n\t\t];\r\n\t}\r\n\treturn itemData;\r\n}\r\n\r\nfunction updateAssetEventNotificationTime(event) {\r\n\tif (EVENTS_ALERT.indexOf(event.Type) !== -1 || EVENTS_EMERGENCY.indexOf(event.Type) !== -1) {\r\n\t\tupdateAssetNotificationTime(event.AssetId, \"alerts\", event.Epoch);\r\n\t} else if (EVENTS_STATUS.indexOf(event.Type) !== -1) {\r\n\t\tupdateAssetNotificationTime(event.AssetId, \"status\", event.Epoch);\r\n\t} else if (EVENTS_TEXT_MESSAGE.indexOf(event.Type) !== -1) {\r\n\t\t// messages handled by .messagesByAssetId\r\n\t} else {\r\n\t\tupdateAssetNotificationTime(event.AssetId, \"events\", event.Epoch);\r\n\t}\r\n}\r\n\r\nfunction mapAssetEventToListing(item) {\r\n\t// unused\r\n\t// TODO move this out of rendering\r\n\tif (options.hideAlertTriggeredEvents || item.Hide || user.isAnonymous) {\r\n\t\tif (EVENTS_ALERT.indexOf(item.Type) !== -1) {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t}\r\n\tif (options.hideEmergencyEvents || user.isAnonymous) {\r\n\t\tif (EVENTS_EMERGENCY.indexOf(item.Type) !== -1) {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t}\r\n\r\n\tif (item.Type === 268) {\r\n\t\t// SL Summary\r\n\t\treturn null;\r\n\t}\r\n\r\n\tvar asset = findAssetById(item.AssetId);\r\n\tvar svgIcon = createIconForAssetEvent(asset, item.Type);\r\n\tvar eventIcon =\r\n\t\t'
';\r\n\tvar details = item.Details != null ? htmlEscape(item.Details).replace(/\\r?\\n/g, \" \") : \"\";\r\n\tswitch (item.Type) {\r\n\t\tcase 127: // garmin form submitted\r\n\t\t\tif (item.Details != null) {\r\n\t\t\t\tvar formDetails = item.Details.split(\"|\");\r\n\t\t\t\tvar formId = formDetails[0];\r\n\t\t\t\tvar formName = strings.VIEW;\r\n\t\t\t\tif (formDetails.length > 1) {\r\n\t\t\t\t\tformName = formDetails[1];\r\n\t\t\t\t}\r\n\t\t\t\tdetails =\r\n\t\t\t\t\t'' +\r\n\t\t\t\t\tformName +\r\n\t\t\t\t\t\" \";\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 270: // beacon read\r\n\t\t\tif (item.Details != null) {\r\n\t\t\t\tdetails = \"\";\r\n\t\t\t\tvar beacons = item.Details.split(\"\\n\");\r\n\t\t\t\tfor (var k = 0; k < beacons.length; k++) {\r\n\t\t\t\t\tvar beacon = beacons[k].split(\"|\");\r\n\t\t\t\t\tif (beacon.length > 1) {\r\n\t\t\t\t\t\tvar beaconUniqueKey = beacon[0];\r\n\t\t\t\t\t\tvar beaconRSSI = beacon[1];\r\n\t\t\t\t\t\tvar beaconTxPower = beacon[2];\r\n\t\t\t\t\t\tif (beaconUniqueKey == null) {\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tvar beaconPlace = findPlaceByUniqueKey(beaconUniqueKey);\r\n\t\t\t\t\t\tif (beaconPlace != null) {\r\n\t\t\t\t\t\t\tdetails +=\r\n\t\t\t\t\t\t\t\t'' +\r\n\t\t\t\t\t\t\t\tbeaconPlace.Name +\r\n\t\t\t\t\t\t\t\t\" @ \" +\r\n\t\t\t\t\t\t\t\tbeaconRSSI +\r\n\t\t\t\t\t\t\t\t\" RSSI\";\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tdetails += beaconUniqueKey + \" @ \" + beaconRSSI + \" RSSI\";\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (beaconTxPower != \"\") {\r\n\t\t\t\t\t\t\tdetails += \", \" + beaconTxPower + \" Tx\";\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tdetails += \" \";\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 272:\r\n\t\tcase 273:\r\n\t\tcase 274:\r\n\t\t\t// driver fatigue\r\n\t\t\tif (item.Details != null) {\r\n\t\t\t\tdetails =\r\n\t\t\t\t\t'' +\r\n\t\t\t\t\tstrings.VIEW_PHOTO +\r\n\t\t\t\t\t\" \";\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 275:\r\n\t\t\tif (item.Details != null) {\r\n\t\t\t\tvar parts = item.Details.split(\"|||\");\r\n\t\t\t\tdetails =\r\n\t\t\t\t\t'' +\r\n\t\t\t\t\tstrings.VIEW_PHOTO +\r\n\t\t\t\t\t\" \";\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tvar fullName = item.TypeName;\r\n\tif (item.Alert !== undefined && item.Alert !== null) {\r\n\t\tvar alertName = item.Alert.Type;\r\n\t\tif (item.Alert.Name !== null) {\r\n\t\t\talertName = item.Alert.Name + \" [ \" + item.Alert.Type + \" ]\";\r\n\t\t}\r\n\t\tfullName += \", \" + alertName;\r\n\t}\r\n\r\n\treturn {\r\n\t\tid: item.Id,\r\n\t\ticon: eventIcon,\r\n\t\tsvgIcon: svgIcon,\r\n\t\tname: item.TypeName,\r\n\t\tfullName: fullName,\r\n\t\tposition: mapPositionForEvent(item, asset),\r\n\t\tdetails: details,\r\n\t\ttime: item.Time,\r\n\t\tepoch: item.Epoch,\r\n\t\ttype: item.Type,\r\n\t\tisAccurate: item.IsAcc,\r\n\t\talert: item.Alert,\r\n\t\tassetId: item.AssetId,\r\n\t};\r\n}\r\n","import trkData from \"./data.js\";\r\nimport options from \"./options.js\";\r\nimport user from \"./user.js\";\r\n\r\nimport { EVENTS_STATUS, EVENTS_TEXT_MESSAGE, EVENTS_EMERGENCY, EVENTS_ALERT } from \"./asset-events.js\";\r\n\r\nexport function getDisplayFilterForEventType(type) {\r\n\tswitch (type) {\r\n\t\tcase \"activity\":\r\n\t\t\treturn function (item) {\r\n\t\t\t\t// basically a duplicate of the below filters, but I don't see a way around it\r\n\t\t\t\tif (item.Chat !== undefined) {\r\n\t\t\t\t\tvar isChatDisabled = user.isAnonymous && !options.allowAnonymousMessaging;\r\n\t\t\t\t\treturn !isChatDisabled && item.Chat !== undefined;\r\n\t\t\t\t} else if (item.Event !== undefined) {\r\n\t\t\t\t\tif (item.Event.Hide) {\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar hideAlertTriggeredEvents = options.hideAlertTriggeredEvents || user.isAnonymous;\r\n\t\t\t\t\tvar hideEmergencyEvents = options.hideEmergencyEvents || user.isAnonymous;\r\n\t\t\t\t\tvar isAlertEvent = EVENTS_ALERT.indexOf(item.Event.Type) !== -1;\r\n\t\t\t\t\tif (isAlertEvent && hideAlertTriggeredEvents) {\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar isEmergencyEvent = EVENTS_EMERGENCY.indexOf(item.Event.Type) !== -1;\r\n\t\t\t\t\tif (isEmergencyEvent && hideEmergencyEvents) {\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (item.Event.Type === 268) {\r\n\t\t\t\t\t\t// SL Summary\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (EVENTS_TEXT_MESSAGE.indexOf(item.Event.Type) !== -1) {\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\treturn true;\r\n\t\t\t};\r\n\t\tcase \"chat\":\r\n\t\t\treturn function (item) {\r\n\t\t\t\tvar isChatDisabled = user.isAnonymous && !options.allowAnonymousMessaging;\r\n\t\t\t\treturn !isChatDisabled && item.Chat !== undefined;\r\n\t\t\t};\r\n\t\tcase \"messages\":\r\n\t\t\treturn function (item) {\r\n\t\t\t\treturn item.Chat === undefined && item.Message !== undefined;\r\n\t\t\t};\r\n\t\tcase \"positions\":\r\n\t\t\treturn function (item) {\r\n\t\t\t\treturn item.Position !== undefined;\r\n\t\t\t};\r\n\t\tcase \"status\":\r\n\t\t\treturn function (item) {\r\n\t\t\t\treturn !item.Event.Hide && EVENTS_STATUS.indexOf(item.Event.Type) !== -1;\r\n\t\t\t};\r\n\t\tcase \"alerts\":\r\n\t\t\treturn function (item) {\r\n\t\t\t\tif (item.Event.Hide) {\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\tvar hideAlertTriggeredEvents = options.hideAlertTriggeredEvents || user.isAnonymous;\r\n\t\t\t\tvar hideEmergencyEvents = options.hideEmergencyEvents || user.isAnonymous;\r\n\t\t\t\tvar isAlertEvent = EVENTS_ALERT.indexOf(item.Event.Type) !== -1;\r\n\t\t\t\tif (isAlertEvent && hideAlertTriggeredEvents) {\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\tvar isEmergencyEvent = EVENTS_EMERGENCY.indexOf(item.Event.Type) !== -1;\r\n\t\t\t\tif (isEmergencyEvent && hideEmergencyEvents) {\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\treturn isAlertEvent || isEmergencyEvent;\r\n\t\t\t};\r\n\t\tcase \"events\":\r\n\t\tdefault:\r\n\t\t\treturn function (item) {\r\n\t\t\t\treturn (\r\n\t\t\t\t\t!item.Event.Hide &&\r\n\t\t\t\t\titem.Event.Type !== 268 && // SL Summary\r\n\t\t\t\t\tEVENTS_STATUS.indexOf(item.Event.Type) === -1 &&\r\n\t\t\t\t\tEVENTS_ALERT.indexOf(item.Event.Type) === -1 &&\r\n\t\t\t\t\tEVENTS_EMERGENCY.indexOf(item.Event.Type) === -1 &&\r\n\t\t\t\t\tEVENTS_TEXT_MESSAGE.indexOf(item.Event.Type) === -1\r\n\t\t\t\t); // because it will be a chat item?\r\n\t\t\t};\r\n\t}\r\n}\r\n","import strings from \"./strings.js\";\r\nimport trkData from \"./data.js\";\r\nimport user from \"./user.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { findGroupById, createAssetNode } from \"./asset-group.js\";\r\nimport { isItemIncluded } from \"./polyfills.js\";\r\nimport { toggleGroupExpandedIcon } from \"./asset-group.js\";\r\nimport { sortItemsByMode } from \"./item-sorting.js\";\r\nimport { updateGroupVisibilityStatus, createGroupNode } from \"./asset-group.js\";\r\nimport { findAssetById } from \"./assets.js\";\r\nimport { createFenceNode } from \"./fence.js\";\r\nimport { saveItemCustomSortOrder } from \"./item-sorting.js\";\r\nimport { createSharedViewNode } from \"./shared-view.js\";\r\nimport { createPlaceNode } from \"./place.js\";\r\nimport { createTripNode } from \"./trips.js\";\r\nimport { resizeApp } from \"./window-layout.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport $j from \"jquery\";\r\nimport _ from \"lodash\";\r\n\r\nfunction populateSidePanelItems(data) {\r\n\tvar itemNodes = {};\r\n\tvar groupNodes = {};\r\n\r\n\tvar groupItems = {}; // for all groups: groupId -> { groups: {*full child group object*}[], assets: {*full asset object*}[] }\r\n\r\n\t// initialize groups\r\n\t_.each(data.groups, function (group) {\r\n\t\tgroupItems[group.Id] = { groups: [], items: [] };\r\n\t});\r\n\r\n\t// assign subgroups to groups\r\n\t_.each(data.groups, function (group) {\r\n\t\tif (group.ParentGroupId !== null && groupItems[group.ParentGroupId] !== undefined) {\r\n\t\t\tgroupItems[group.ParentGroupId].groups.push(group);\r\n\t\t\tvar parentGroup = data.groups.find(g => g.Id === group.ParentGroupId);\r\n\t\t\tif (parentGroup !== null) {\r\n\t\t\t\tparentGroup.GroupIds.push(group.Id);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// render baseline group for dom\r\n\t\tgroupNodes[group.Id] = createGroupNode(group);\r\n\t});\r\n\r\n\t// initialize group nodes cache and set colors for stylesheet\r\n\t_.each(groupNodes, function (group, key, list) {\r\n\t\tdomNodes.groups[key] = groupNodes[key];\r\n\t\tvar actualGroup = data.groups.find(g => g.Id === key);\r\n\t\tif (actualGroup !== null) {\r\n\t\t\tdomNodes.groupColors[key] = actualGroup.Color;\r\n\t\t}\r\n\t});\r\n\r\n\tgroupItems[\"all-\" + data.itemType].items = sortItemsByMode(data.itemType, data.items, \"all-\" + data.itemType, data.itemType);\r\n\tvar primaryGroups = sortItemsByMode(\r\n\t\tdata.itemType,\r\n\t\t_.filter(data.groups, function (group) {\r\n\t\t\treturn group.ParentGroupId === null && !group.IsDefault;\r\n\t\t}),\r\n\t\tdata.itemType + \"-root\",\r\n\t\t\"groups\"\r\n\t);\r\n\tvar primaryGroups = _.concat(\r\n\t\t_.filter(data.groups, function (group) {\r\n\t\t\treturn group.IsDefault;\r\n\t\t}),\r\n\t\tprimaryGroups\r\n\t)\r\n\r\n\t// assign items to groups\r\n\t_.each(data.items, function (item, index, list) {\r\n\t\t_.each(item.GroupIds, function (groupId, ind, li) {\r\n\t\t\tif (groupItems[groupId] !== undefined) {\r\n\t\t\t\tgroupItems[groupId].items.push(item);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\t// render baseline item for dom\r\n\t\titemNodes[item.Id] = data.createItemNode(item);\r\n\t});\r\n\r\n\t// sort items and subgroups within groups\r\n\t_.each(groupItems, function (value, key, list) {\r\n\t\tlist[key].items = sortItemsByMode(data.itemType, value.items, key, data.itemType);\r\n\t\tlist[key].groups = sortItemsByMode(data.itemType, value.groups, key, \"groups\");\r\n\t});\r\n\r\n\t// console.log(groupItems);\r\n\r\n\t_.each(groupItems, function (group, key, list) {\r\n\t\tvar groupContentsNode = groupNodes[key].querySelector(\".group-contents\");\r\n\t\tvar groupContentsItems = groupContentsNode.querySelector(\"ul.group-list-list\");\r\n\t\tvar groupData = groupItems[key];\r\n\r\n\t\t// add subgroup nodes to group dom\r\n\t\t_.each(groupData.groups, function (subGroup, index, list) {\r\n\t\t\t// groups can only be assigned to one parent group, so do not clone their nodes\r\n\t\t\tgroupContentsItems.appendChild(groupNodes[subGroup.Id]);\r\n\t\t});\r\n\r\n\t\t// add items nodes to group dom\r\n\t\t_.each(groupData.items, function (item, index, list) {\r\n\t\t\t// items can be added to multiple groups, so they must be cloned\r\n\t\t\tvar groupItem = itemNodes[item.Id].cloneNode(true);\r\n\r\n\t\t\tgroupContentsItems.appendChild(groupItem);\r\n\t\t\tif (data.domNodesItems[item.Id] === undefined) {\r\n\t\t\t\tdata.domNodesItems[item.Id] = [];\r\n\t\t\t}\r\n\t\t\tdata.domNodesItems[item.Id].push(groupItem);\r\n\t\t});\r\n\r\n\t\t// cache group content nodes so they can be detached/reattached to the dom\r\n\t\t// based on whether the group is expanded/visible\r\n\t\tdomNodes.groupContents[key] = groupContentsNode;\r\n\r\n\t\tif (!isItemIncluded(user.displayPreferences.expandedGroups, key)) {\r\n\t\t\t// only render group contents when the group is visible (expanded)\r\n\t\t\tgroupContentsNode.parentNode.removeChild(groupContentsNode);\r\n\t\t\ttoggleGroupExpandedIcon(key, false);\r\n\t\t} else {\r\n\t\t\ttoggleGroupExpandedIcon(key, true);\r\n\t\t}\r\n\t});\r\n\r\n\t// toggle active groups within fragment\r\n\t// by default groups are inactive unless they contain at least one active asset\r\n\t// this isn't done on creation as it would be pretty tricky and not worth the effort\r\n\t_.each(groupItems, function (group, key, list) {\r\n\t\tupdateGroupVisibilityStatus(key, data.itemType);\r\n\t});\r\n\r\n\tvar assetsGroupsFragment = document.createDocumentFragment();\r\n\tassetsGroupsFragment.appendChild(groupNodes[\"all-\" + data.itemType]);\r\n\t_.each(primaryGroups, function (value, key, list) {\r\n\t\tassetsGroupsFragment.appendChild(groupNodes[value.Id]);\r\n\t});\r\n\r\n\tif (data.items.length === 0) {\r\n\t\tdocument.getElementById(\"no-\" + data.itemType).classList.add(\"is-visible\");\r\n\t\tdocument.getElementById(data.itemType + \"-all\").classList.remove(\"is-visible\");\r\n\t\tdocument.getElementById(\"filter-\" + data.itemType).querySelector(\".filter-box\").classList.remove(\"is-visible\");\r\n\t} else {\r\n\t\tdocument.getElementById(\"no-\" + data.itemType).classList.remove(\"is-visible\");\r\n\t\tdocument.getElementById(data.itemType + \"-all\").classList.add(\"is-visible\");\r\n\t\tdocument.getElementById(\"filter-\" + data.itemType).querySelector(\".filter-box\").classList.add(\"is-visible\");\r\n\t}\r\n\r\n\tvar itemGroupsContainer = document.getElementById(data.itemType + \"-all\");\r\n\titemGroupsContainer.appendChild(assetsGroupsFragment);\r\n\t// root item group sorting\r\n\t$(itemGroupsContainer).sortable({\r\n\t\taxis: \"y\",\r\n\t\titems: \"> li.group\",\r\n\t\thandle: \"> .group-header .group-drag\",\r\n\t\tupdate: function (event, ui) {\r\n\t\t\tsaveItemCustomSortOrder();\r\n\t\t},\r\n\t});\r\n\r\n\t// only initialize the sorting when the group contents are rendered\r\n\t_.each(domNodes.groupContents, function (groupContentsNode, key, list) {\r\n\t\tif (groupContentsNode.parentNode != null)\r\n\t\t{\r\n\t\t\tinitializeOrRefreshGroupSortable(key);\r\n\t\t}\r\n\t});\r\n}\r\n\r\nexport function initializeOrRefreshGroupSortable(groupId) {\r\n\t// refresh the sortable so it can be aware of new items being added to the container\r\n\tif (domNodes.groupContents[groupId] == null) {\r\n\t\tconsole.log(\"unknown group contents for id\", groupId);\r\n\t\treturn;\r\n\t}\r\n\tvar groupContentsNode = domNodes.groupContents[groupId];\r\n\tvar groupContentsItems = groupContentsNode.querySelector(\"ul.group-list-list\");\r\n\tif (groupContentsNode.classList.contains('ui-sortable')) {\r\n\t\t// already initialized, just refresh for newly added item(s)\r\n\t\t// subgroup ordering\r\n\t\t$(groupContentsItems).sortable(\"refresh\");\r\n\t\t// group items ordering\r\n\t\t$(groupContentsNode).sortable(\"refresh\");\r\n\t} else {\r\n\t\t// subgroup ordering\r\n\t\t$(groupContentsItems).sortable({\r\n\t\t\taxis: 'y',\r\n\t\t\titems: '> li.group',\r\n\t\t\thandle: '> .group-header .group-drag',\r\n\t\t\tupdate: function (event, ui) {\r\n\t\t\t\tsaveItemCustomSortOrder();\r\n\t\t\t},\r\n\t\t});\r\n\r\n\t\t// group items ordering\r\n\t\t$(groupContentsNode).sortable({\r\n\t\t\taxis: 'y',\r\n\t\t\titems: '> .group-list-list > li.group-item',\r\n\t\t\thandle: '.item-drag',\r\n\t\t\tupdate: function (event, ui) {\r\n\t\t\t\tsaveItemCustomSortOrder();\r\n\t\t\t},\r\n\t\t});\r\n\r\n\t\tdomNodes.groups[groupId].setAttribute(\"data-sort-initialized\", true);\r\n\t}\r\n}\r\n\r\nfunction populateSidePanelJourneys() {\r\n\t// journeys - just like asset groups\r\n\tif (trkData.journeys.length === 0) {\r\n\t\t// no journeys, add to journeys-all?\r\n\t\tvar noExtrasNode = document.createElement(\"li\");\r\n\t\tnoExtrasNode.className = \"toggle-content no-items is-visible\";\r\n\t\tnoExtrasNode.setAttribute(\"id\", \"no-journeys\");\r\n\t\tvar noExtrasText = document.createElement(\"span\");\r\n\t\tnoExtrasText.textContent = strings.NO_JOURNEYS;\r\n\t\tnoExtrasNode.appendChild(noExtrasText);\r\n\t\tdocument.getElementById(\"journeys-all\").appendChild(noExtrasNode);\r\n\t\t//document.getElementById('filter-journeys').querySelector('.filter-box').classList.remove('is-visible');\r\n\t}\r\n\t_.each(trkData.journeys, function (item) {\r\n\t\tvar journeyAsset = findAssetById(item.AssetId);\r\n\t\tif (journeyAsset === null) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tvar groupId = \"journey-\" + item.Id;\r\n\t\tvar extraGroupNode = createGroupNode({ Id: groupId, Name: item.Name, Color: item.Color, Type: \"journeys\" });\r\n\t\tdomNodes.groups[groupId] = extraGroupNode;\r\n\r\n\t\tvar extraGroupContentsNode = extraGroupNode.querySelector(\".group-contents\");\r\n\t\tvar extraGroupContentsItems = extraGroupContentsNode.querySelector(\"ul.group-list-list\");\r\n\t\tvar noExtrasNode = document.createElement(\"li\");\r\n\t\tnoExtrasNode.className = \"toggle-content no-items\";\r\n\t\tif (item.Trips.length === 0) {\r\n\t\t\tnoExtrasNode.className += \" is-visible\";\r\n\t\t\t//document.getElementById('filter-journeys').querySelector('.filter-box').classList.remove('is-visible');\r\n\t\t}\r\n\t\tnoExtrasNode.setAttribute(\"id\", \"no-\" + groupId);\r\n\t\tvar noExtrasText = document.createElement(\"span\");\r\n\t\tnoExtrasText.textContent = strings.NO_TRIPS;\r\n\t\tnoExtrasNode.appendChild(noExtrasText);\r\n\t\textraGroupContentsItems.appendChild(noExtrasNode);\r\n\r\n\t\tvar journey = item;\r\n\t\t_.each(item.Trips, function (item, index, list) {\r\n\t\t\tvar extraNode = createTripNode(journey, item, journeyAsset);\r\n\t\t\tdomNodes.trips[item.Id] = extraNode;\r\n\t\t\textraGroupContentsItems.appendChild(extraNode);\r\n\t\t});\r\n\r\n\t\tvar extraAllItems = extraGroupNode.getElementsByClassName(\"journeys-item\").length;\r\n\t\tvar extraActiveItems = extraGroupNode.getElementsByClassName(\"journeys-item active\").length;\r\n\t\tif (extraActiveItems > 0) {\r\n\t\t\tvar extraVisibility = extraGroupNode.querySelector(\".showhide\");\r\n\r\n\t\t\tif (extraAllItems !== extraActiveItems) {\r\n\t\t\t\textraVisibility\r\n\t\t\t\t\t.querySelector(\"use\")\r\n\t\t\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#indeterminate\");\r\n\t\t\t\textraVisibility.classList.add(\"indeterminate\");\r\n\t\t\t} else {\r\n\t\t\t\textraVisibility\r\n\t\t\t\t\t.querySelector(\"use\")\r\n\t\t\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#visible\");\r\n\t\t\t\textraVisibility.classList.add(\"active\");\r\n\t\t\t}\r\n\t\t\textraGroupNode.classList.add(\"active\");\r\n\t\t}\r\n\t\tdomNodes.groupContents[groupId] = extraGroupContentsNode;\r\n\t\tif (item.Color !== undefined && item.Color !== null) {\r\n\t\t\tdomNodes.groupColors[groupId] = item.Color;\r\n\t\t}\r\n\t\tif (!isItemIncluded(user.displayPreferences.expandedGroups, groupId)) {\r\n\t\t\t// only render group contents when the group is visible (expanded)\r\n\t\t\textraGroupContentsNode.parentNode.removeChild(extraGroupContentsNode);\r\n\t\t\ttoggleGroupExpandedIcon(groupId, false);\r\n\t\t} else {\r\n\t\t\ttoggleGroupExpandedIcon(groupId, true);\r\n\t\t}\r\n\r\n\t\tvar allJourneys = document.getElementById(\"journeys-all\");\r\n\t\tallJourneys.appendChild(extraGroupNode);\r\n\r\n\t\tupdateGroupVisibilityStatus(groupId);\r\n\t});\r\n}\r\n\r\nfunction populateSidePanelExtraGroups() {\r\n\tvar extraGroups = [{\r\n\t\ttype: \"shared-views\",\r\n\t\tcreateNodeFunction: createSharedViewNode,\r\n\t\tname: strings.ALL_SHARED_VIEWS,\r\n\t\tcolor: null,\r\n\t\temptyText: strings.NO_SHARED_VIEWS,\r\n\t\tnoItemsText: strings.NO_SHARED_VIEWS_HINT,\r\n\t\titems: sortItemsByMode(\"shared-views\", trkData.sharedViews, \"all-shared-views\", \"shared-views\"),\r\n\t\tnodeList: domNodes.sharedViews,\r\n\t}];\r\n\r\n\t_.each(extraGroups, function (group, index, list) {\r\n\t\tvar groupId = \"all-\" + group.type;\r\n\t\tvar extraGroupNode = createGroupNode({ Id: groupId, Name: group.name, Color: group.color, Type: group.type });\r\n\t\tdomNodes.groups[groupId] = extraGroupNode;\r\n\t\tvar extraGroupContentsNode = extraGroupNode.querySelector(\".group-contents\");\r\n\t\tvar extraGroupContentsItems = extraGroupContentsNode.querySelector(\"ul.group-list-list\");\r\n\t\tvar noExtrasNode = document.createElement(\"li\");\r\n\t\tnoExtrasNode.className = \"toggle-content no-items\";\r\n\t\tif (group.items.length === 0) {\r\n\t\t\tnoExtrasNode.className += \" is-visible\";\r\n\t\t\tdocument\r\n\t\t\t\t.getElementById(\"filter-\" + group.type)\r\n\t\t\t\t.querySelector(\".filter-box\")\r\n\t\t\t\t.classList.remove(\"is-visible\");\r\n\t\t} else {\r\n\t\t\tdocument\r\n\t\t\t\t.getElementById(\"filter-\" + group.type)\r\n\t\t\t\t.querySelector(\".filter-box\")\r\n\t\t\t\t.classList.add(\"is-visible\");\r\n\t\t}\r\n\t\tnoExtrasNode.setAttribute(\"id\", \"no-\" + groupId);\r\n\r\n\t\tif (group.type == \"shared-views\" && group.items.length === 0) {\r\n\t\t\tdocument.getElementById(\"no-shared-views\").classList.add(\"is-visible\");\r\n\t\t\tdocument.getElementById(\"shared-views-all\").classList.remove(\"is-visible\");\r\n\t\t\t//document.getElementById('filter-shared-views').classList.remove('is-visible');\r\n\t\t}\r\n\r\n\t\tvar noExtrasText = document.createElement(\"span\");\r\n\t\tnoExtrasText.textContent = group.emptyText;\r\n\t\tnoExtrasNode.appendChild(noExtrasText);\r\n\t\textraGroupContentsItems.appendChild(noExtrasNode);\r\n\r\n\t\t_.each(group.items, function (item, index, list) {\r\n\t\t\tvar extraNode = group.createNodeFunction(item);\r\n\t\t\tgroup.nodeList[item.Id] = extraNode;\r\n\t\t\textraGroupContentsItems.appendChild(extraNode);\r\n\t\t});\r\n\r\n\t\tvar extraAllItems = extraGroupNode.getElementsByClassName(group.type + \"-item\").length;\r\n\t\tvar extraActiveItems = extraGroupNode.getElementsByClassName(group.type + \"-item active\").length;\r\n\t\tif (extraActiveItems > 0) {\r\n\t\t\tvar extraVisibility = extraGroupNode.querySelector(\".showhide\");\r\n\r\n\t\t\tif (extraAllItems !== extraActiveItems) {\r\n\t\t\t\textraVisibility\r\n\t\t\t\t\t.querySelector(\"use\")\r\n\t\t\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#indeterminate\");\r\n\t\t\t\textraVisibility.classList.add(\"indeterminate\");\r\n\t\t\t} else {\r\n\t\t\t\textraVisibility\r\n\t\t\t\t\t.querySelector(\"use\")\r\n\t\t\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#visible\");\r\n\t\t\t\textraVisibility.classList.add(\"active\");\r\n\t\t\t}\r\n\t\t\textraGroupNode.classList.add(\"active\");\r\n\t\t}\r\n\t\tdomNodes.groupContents[groupId] = extraGroupContentsNode;\r\n\t\tif (group.color !== undefined && group.color !== null) {\r\n\t\t\tdomNodes.groupColors[groupId] = group.color;\r\n\t\t}\r\n\t\tif (!isItemIncluded(user.displayPreferences.expandedGroups, \"all-\" + group.type)) {\r\n\t\t\t// only render group contents when the group is visible (expanded)\r\n\t\t\textraGroupContentsNode.parentNode.removeChild(extraGroupContentsNode);\r\n\t\t\ttoggleGroupExpandedIcon(groupId, false);\r\n\t\t} else {\r\n\t\t\ttoggleGroupExpandedIcon(groupId, true);\r\n\t\t}\r\n\r\n\t\t// insert into separate panel/container\r\n\t\tvar container = document.getElementById(group.type + \"-all\");\r\n\t\tcontainer.appendChild(extraGroupNode);\r\n\r\n\t\tupdateGroupVisibilityStatus(groupId);\r\n\r\n\t\t$(extraGroupContentsNode).sortable({\r\n\t\t\taxis: \"y\",\r\n\t\t\titems: \"> .group-list-list > li.group-item\",\r\n\t\t\thandle: \".item-drag\",\r\n\t\t\tupdate: function (event, ui) {\r\n\t\t\t\tsaveItemCustomSortOrder();\r\n\t\t\t},\r\n\t\t});\r\n\t});\r\n}\r\n\r\nexport function populateSidePanel() {\r\n\tpopulateSidePanelItems({\r\n\t\titemType: \"assets\",\r\n\t\tgroups: trkData.groups,\r\n\t\titems: trkData.assets,\r\n\t\tcreateItemNode: createAssetNode,\r\n\t\tdomNodesItems: domNodes.assets\r\n\t});\r\n\tpopulateSidePanelItems({\r\n\t\titemType: \"places\",\r\n\t\tgroups: trkData.placeGroups,\r\n\t\titems: trkData.places,\r\n\t\tcreateItemNode: createPlaceNode,\r\n\t\tdomNodesItems: domNodes.places\r\n\t});\r\n\tpopulateSidePanelItems({\r\n\t\titemType: \"fences\",\r\n\t\tgroups: trkData.fenceGroups,\r\n\t\titems: trkData.fences,\r\n\t\tcreateItemNode: createFenceNode,\r\n\t\tdomNodesItems: domNodes.fences\r\n\t});\r\n\tpopulateSidePanelJourneys();\r\n\tpopulateSidePanelExtraGroups();\r\n}\r\n\r\nexport function hideSidePanel() {\r\n\t$j(\"#topbar-left\").css(\"left\", \"-25em\");\r\n\t$j(\"#topbar-right\").css(\"margin-left\", \"0\");\r\n\t$j(\"#panel\").hide();\r\n\t$j(\"#map\").css(\"left\", 0).css(\"margin-right\", 0);\r\n\t$j(\"#map_tools,#map_tools_bottom,#map_panels\").css(\"margin-left\", 0);\r\n\t$j(\"#panel-expand\").show();\r\n\t$j(\"#ds-v .shade, #event-panel,#event-panel-container\").css(\"left\", \"0\");\r\n\t$j(\"#panel-contract\").hide();\r\n\tresizeApp(true);\r\n}\r\n\r\nexport function showSidePanel() {\r\n\t$j(\"#topbar-left\").css(\"left\", \"0\");\r\n\t$j(\"#topbar-right\").css(\"margin-left\", \"25em\");\r\n\t$j(\"#panel\").show();\r\n\t$j(\"#map\").css(\"left\", \"25em\").css(\"margin-right\", \"25em\");\r\n\t$j(\"#map_tools,#map_tools_bottom,#map_panels\").css(\"margin-left\", \"25em\");\r\n\t$j(\"#panel-contract\").show();\r\n\t$j(\"#ds-v .shade, #event-panel,#event-panel-container\").css(\"left\", \"25em\");\r\n\t$j(\"#panel-expand\").hide();\r\n\tresizeApp(true);\r\n}\r\n","import strings from \"./strings.js\";\r\nimport trkData from \"./data.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport state from \"./state.js\";\r\nimport { findAssetById } from \"./assets.js\";\r\nimport { getDisplayFilterForEventType } from \"./display-filter.js\";\r\nimport user, { displayPreferencesAdd, displayPreferencesRemove, loadDisplayPreferences } from \"./user.js\";\r\nimport log from \"./log.js\";\r\nimport { isItemIncluded } from \"./polyfills.js\";\r\nimport { openDialogPanel } from \"./panel-nav.js\";\r\nimport { mapModes } from \"./const.js\";\r\nimport { createListing, defaultListItemSort } from \"./item-listing.js\";\r\nimport { createMarkerPath } from \"./marker-path.js\";\r\nimport options from \"./options.js\";\r\nimport templates from \"./templates.js\";\r\nimport { populateCheckboxList } from \"./dom-util.js\";\r\nimport { changePrimaryButtonLabel } from \"./modal.js\";\r\nimport { populateGroupList } from \"./group-list.js\";\r\nimport { sortItemsByMode, sortByName } from \"./item-sorting.js\";\r\nimport { openAssetGroupSettingsPanel } from \"./panel-settings.js\";\r\nimport { initializeOrRefreshGroupSortable } from \"./panel-side.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport { toggleLoadingMessage } from \"./ajax.js\";\r\nimport { handleWebServiceError } from \"./ajax.js\";\r\nimport { getDbg } from \"./log.js\";\r\nimport { getBackgroundColorAsHex, convertHexToSortable, convertNamedColorToHex } from \"./color.js\";\r\nimport { getSharedViewLink } from \"./shared-view.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport $j from \"jquery\";\r\nimport _ from \"lodash\";\r\n\r\n/*global JsSearch */\r\n// import JsSearch from '../js-search.js';\r\n\r\nexport function findGroupById(id, groupFor = \"assets\") {\r\n\tvar item = _.find(\r\n\t\tgroupFor === \"assets\" ? trkData.groups :\r\n\t\tgroupFor === \"places\" ? trkData.placeGroups :\r\n\t\tgroupFor === \"fences\" ? trkData.fenceGroups : {}\r\n\t, { Id: id });\r\n\treturn item === undefined ? null : item;\r\n}\r\n\r\nfunction getGroupStatus(groupId, groupFor) {\r\n\tvar result = {\r\n\t\titems: 0,\r\n\t\tactive: 0,\r\n\t\tassets: 0,\r\n\t\tassetIds: [],\r\n\t\tfences: 0,\r\n\t\tfenceIds: [],\r\n\t\tplaces: 0,\r\n\t\tplaceIds: [],\r\n\t\ttrips: 0,\r\n\t\ttripIds: [],\r\n\t\tsharedViews: 0,\r\n\t\tsharedViewIds: [],\r\n\t\tcountNumber: 0,\r\n\t};\r\n\r\n\tvar groupContents = domNodes.groupContents[groupId];\r\n\tif (groupContents === undefined) {\r\n\t\tconsole.trace(`Group ${groupId} not found`);\r\n\t\treturn result;\r\n\t}\r\n\r\n\tresult.items = groupContents.getElementsByClassName(\"group-item\").length;\r\n\tresult.active = groupContents.getElementsByClassName(\"group-item active\").length;\r\n\tvar assets = groupContents.getElementsByClassName(\"assets-item\");\r\n\t_.each(assets, function (elem) {\r\n\t\tresult.assetIds.push(parseInt(elem.getAttribute(\"data-asset-id\")));\r\n\t});\r\n\tresult.assets = assets.length;\r\n\tvar places = groupContents.getElementsByClassName(\"places-item\");\r\n\t_.each(places, function (elem) {\r\n\t\tresult.placeIds.push(parseInt(elem.getAttribute(\"data-place-id\")));\r\n\t});\r\n\tresult.places = places.length;\r\n\tvar fences = groupContents.getElementsByClassName(\"fences-item\");\r\n\t_.each(fences, function (elem) {\r\n\t\tresult.fenceIds.push(elem.getAttribute(\"data-fence-id\"));\r\n\t});\r\n\tresult.fences = fences.length;\r\n\tvar trips = groupContents.getElementsByClassName(\"journeys-item\");\r\n\t_.each(trips, function (elem) {\r\n\t\tresult.tripIds.push(parseInt(elem.getAttribute(\"data-trip-id\")));\r\n\t});\r\n\tresult.trips = trips.length;\r\n\tvar sharedViews = groupContents.getElementsByClassName(\"shared-views-item\");\r\n\t_.each(sharedViews, function (elem) {\r\n\t\tresult.sharedViewIds.push(parseInt(elem.getAttribute(\"data-shared-view-id\")));\r\n\t});\r\n\tresult.sharedViews = sharedViews.length;\r\n\r\n\tswitch (groupId) {\r\n\t\tcase \"all-shared-views\":\r\n\t\t\treturn {\r\n\t\t\t\titems: result.sharedViewIds.length,\r\n\t\t\t\tactive: result.sharedViewIds.length,\r\n\t\t\t\tcountNumber: result.sharedViewIds.length,\r\n\t\t\t};\r\n\t\tdefault:\r\n\t\t\tif (groupId.indexOf(\"journey-\") !== -1) {\r\n\t\t\t\tresult.countNumber = result.tripIds.length;\r\n\t\t\t\treturn result;\r\n\t\t\t}\r\n\t}\r\n\r\n\tvar group = findGroupById(groupId, groupFor);\r\n\r\n\tif (group !== null) {\r\n\t\tif (group.GroupIds !== undefined) {\r\n\t\t\t_.each(group.GroupIds, function (subGroupId) {\r\n\t\t\t\tvar groupCounts = getGroupStatus(subGroupId, groupFor);\r\n\t\t\t\tresult.items += groupCounts.items;\r\n\t\t\t\tresult.active += groupCounts.active;\r\n\t\t\t\tresult.assets += groupCounts.assets;\r\n\t\t\t\tresult.assetIds = _.union(result.assetIds, groupCounts.assetIds);\r\n\t\t\t\tresult.places += groupCounts.places;\r\n\t\t\t\tresult.placeIds = _.union(result.placeIds, groupCounts.placeIds);\r\n\t\t\t\tresult.fences += groupCounts.fences;\r\n\t\t\t\tresult.fenceIds = _.union(result.fenceIds, groupCounts.fenceIds);\r\n\t\t\t\tresult.trips += groupCounts.trips;\r\n\t\t\t\tresult.tripIds = _.union(result.tripIds, groupCounts.tripIds);\r\n\t\t\t\tresult.sharedViews += groupCounts.sharedViews;\r\n\t\t\t\tresult.sharedViewIds = _.union(result.sharedViewIds, groupCounts.sharedViewIds);\r\n\t\t\t});\r\n\t\t}\r\n\t\tif(groupFor === \"assets\") {\r\n\t\t\tgroup.AssetIds = _.map(result.assetIds, function (assetId) {\r\n\t\t\t\treturn parseInt(assetId);\r\n\t\t\t});\r\n\t\t}\r\n\t} else {\r\n\t\tconsole.trace(`Group ${groupId} for ${groupFor} not found`);\r\n\t}\r\n\r\n\t_.each(result.assetIds, function (id) {\r\n\t\tvar assetId = parseInt(id);\r\n\t\tvar asset = findAssetById(assetId);\r\n\t\tif (asset.ParentGroupIds == null) {\r\n\t\t\tasset.ParentGroupIds = [];\r\n\t\t}\r\n\t\tif (asset.ParentGroupIds.indexOf(groupId) === -1) {\r\n\t\t\tasset.ParentGroupIds.push(groupId);\r\n\t\t}\r\n\t});\r\n\r\n\tswitch (groupFor) {\r\n\t\tcase \"fences\":\r\n\t\t\tresult.countNumber = result.fenceIds.length;\r\n\t\t\tbreak;\r\n\t\tcase \"places\":\r\n\t\t\tresult.countNumber = result.placeIds.length;\r\n\t\t\tbreak;\r\n\t\tcase \"assets\":\r\n\t\t\tresult.countNumber = result.assetIds.length;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tthrow new Error(\"Invalid group type: \" + groupFor);\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\nexport function getGroupAssetStatus(groupId) {\r\n\treturn getGroupStatus(groupId, \"assets\");\r\n}\r\n\r\nexport function updateGroupVisibilityStatus(groupId, groupFor) {\r\n\tif (!groupFor) {\r\n\t\tif (groupId === \"all-assets\") {\r\n\t\t\tgroupFor = \"assets\";\r\n\t\t} else if (groupId === \"all-fences\") {\r\n\t\t\tgroupFor = \"fences\";\r\n\t\t} else if (groupId === \"all-places\") {\r\n\t\t\tgroupFor = \"places\";\r\n\t\t}\r\n\t}\r\n\tif (!groupFor) {\r\n\t\tgroupFor = \"assets\";\r\n\t}\r\n\r\n\tvar groupNode = document.getElementById(\"group-\" + groupId);\r\n\tif (groupNode === null) {\r\n\t\tgroupNode = domNodes.groups[groupId];\r\n\t\tif (groupNode === undefined) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tvar visibilityIcon = groupNode.querySelector(\".showhide\");\r\n\tvar groupStats = getGroupStatus(groupId, groupFor);\r\n\tif (groupStats.active > 0) {\r\n\t\tif (groupStats.items === groupStats.active) {\r\n\t\t\tvisibilityIcon\r\n\t\t\t\t.querySelector(\"use\")\r\n\t\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#visible\");\r\n\t\t\tvisibilityIcon.classList.add(\"active\");\r\n\t\t\tvisibilityIcon.classList.remove(\"indeterminate\");\r\n\t\t} else {\r\n\t\t\tvisibilityIcon\r\n\t\t\t\t.querySelector(\"use\")\r\n\t\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#indeterminate\");\r\n\t\t\tvisibilityIcon.classList.add(\"indeterminate\");\r\n\t\t\tvisibilityIcon.classList.remove(\"active\");\r\n\t\t}\r\n\t} else {\r\n\t\tvisibilityIcon\r\n\t\t\t.querySelector(\"use\")\r\n\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#invisible\");\r\n\t\tvisibilityIcon.classList.remove(\"active\");\r\n\t\tvisibilityIcon.classList.remove(\"indeterminate\");\r\n\t}\r\n\tvar groupCount = groupNode.querySelector(\".item-count\");\r\n\tif (groupCount !== null) {\r\n\t\tgroupCount.textContent = groupStats.countNumber;\r\n\t\tif (groupStats.countNumber >= 1000) {\r\n\t\t\tgroupCount.classList.add(\"large\");\r\n\t\t} else {\r\n\t\t\tgroupCount.classList.remove(\"large\");\r\n\t\t}\r\n\t}\r\n\tvar group = findGroupById(groupId, groupFor);\r\n\tif (group && group.ParentGroupId) {\r\n\t\tupdateGroupVisibilityStatus(group.ParentGroupId, groupFor);\r\n\t}\r\n}\r\n\r\nexport function openEventsForGroup(group) {\r\n\tvar events = getFilteredEventsForGroup(group.Id, getDisplayFilterForEventType(\"events\"));\r\n\tcreateListing(events, \"events\");\r\n\topenDialogPanel(\r\n\t\tdomNodes.dialogs.assetEvents,\r\n\t\tstrings.EVENTS,\r\n\t\tgroup,\r\n\t\tfalse,\r\n\t\tnull,\r\n\t\t\"group\",\r\n\t\t\"group-events\",\r\n\t\topenEventsForGroup\r\n\t);\r\n}\r\n\r\nexport function openStatusForGroup(group) {\r\n\tvar events = getFilteredEventsForGroup(group.Id, getDisplayFilterForEventType(\"status\"));\r\n\tcreateListing(events, \"status\");\r\n\topenDialogPanel(\r\n\t\tdomNodes.dialogs.assetStatus,\r\n\t\tstrings.STATUS,\r\n\t\tgroup,\r\n\t\tfalse,\r\n\t\tnull,\r\n\t\t\"group\",\r\n\t\t\"group-status\",\r\n\t\topenStatusForGroup\r\n\t);\r\n}\r\n\r\nexport function openAlertsForGroup(group) {\r\n\tif (user.isAnonymous) {\r\n\t\treturn;\r\n\t}\r\n\tvar events = getFilteredEventsForGroup(group.Id, getDisplayFilterForEventType(\"alerts\"));\r\n\tcreateListing(events, \"alerts\");\r\n\topenDialogPanel(\r\n\t\tdomNodes.dialogs.assetAlerts,\r\n\t\tstrings.ALERTS,\r\n\t\tgroup,\r\n\t\tfalse,\r\n\t\tnull,\r\n\t\t\"group\",\r\n\t\t\"group-alerts\",\r\n\t\topenAlertsForGroup\r\n\t);\r\n}\r\n\r\nexport function addItemToGroup(item, groupId, groupFor) {\r\n\tvar group = findGroupById(groupId, groupFor);\r\n\tif (group == null) {\r\n\t\tgroupId = \"all-\" + groupFor;\r\n\t}\r\n\r\n\tvar groupContentsNode = domNodes.groupContents[groupId].querySelector(\"ul.group-list-list\");\r\n\r\n\t// itemNode may not be created\r\n\tvar groupItemNode;\r\n\tif (domNodes[groupFor][item.Id] === undefined) {\r\n\t\tgroupItemNode = createAssetNode(item);\r\n\t\tdomNodes[groupFor][item.Id] = [];\r\n\t} else {\r\n\t\tgroupItemNode = domNodes[groupFor][item.Id][0].cloneNode(true);\r\n\t}\r\n\tdomNodes[groupFor][item.Id].push(groupItemNode);\r\n\r\n\t// find the appropriate point in the groups asset list to add the item\r\n\tvar groupItems = trkData[groupFor];\r\n\tif (!groupId.startsWith(\"all-\")) {\r\n\t\tgroupItems = _.filter(groupItems, function (asset) {\r\n\t\t\treturn _.indexOf(asset.GroupIds, groupId) !== -1;\r\n\t\t});\r\n\t}\r\n\tgroupItems = sortItemsByMode(groupFor, groupItems, groupId, groupFor);\r\n\tif (groupItems.length > 1) {\r\n\t\tvar itemIndex = _.indexOf(groupItems, item);\r\n\t\tvar subgroups = group !== null ? group.GroupIds.length : 0;\r\n\t\tgroupContentsNode.insertBefore(groupItemNode, groupContentsNode.children[itemIndex + subgroups]);\r\n\t} else {\r\n\t\tgroupContentsNode.appendChild(groupItemNode);\r\n\t}\r\n\tupdateGroupVisibilityStatus(groupId, groupFor);\r\n\r\n\tdocument.getElementById(\"no-\" + groupFor).classList.remove(\"is-visible\");\r\n\tdocument.getElementById(groupFor + \"-all\").classList.add(\"is-visible\");\r\n\tdocument.getElementById(\"filter-\" + groupFor).querySelector(\".filter-box\").classList.add(\"is-visible\");\r\n}\r\n\r\nexport function addAssetToGroup(asset, groupId) {\r\n\taddItemToGroup(asset, groupId, \"assets\");\r\n}\r\n\r\nexport function removeItemFromGroup(asset, groupId, groupFor) {\r\n\t// remove assetNode from group contents and cache\r\n\tvar groupContents = domNodes.groupContents[groupId];\r\n\tif (groupContents === undefined) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tgroupContents = groupContents.querySelector(\"ul.group-list-list\");\r\n\tif (groupContents === null) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar foundIndex = -1;\r\n\t_.each(domNodes[groupFor][asset.Id], function (itemNode, index) {\r\n\t\tfoundIndex = _.indexOf(groupContents.childNodes, itemNode);\r\n\t\tif (foundIndex !== -1) {\r\n\t\t\tgroupContents.removeChild(itemNode);\r\n\t\t\titemNode = null;\r\n\t\t\treturn;\r\n\t\t}\r\n\t});\r\n\r\n\tif (foundIndex !== -1) {\r\n\t\tdomNodes[groupFor][asset.Id].splice(foundIndex, 1);\r\n\t}\r\n\r\n\tupdateGroupVisibilityStatus(groupId, groupFor);\r\n}\r\n\r\nexport function removeAssetFromGroup(asset, groupId) {\r\n\treturn removeItemFromGroup(asset, groupId, \"assets\");\r\n}\r\n\r\nfunction expandGroup(groupId) {\r\n\tvar groupContainer = domNodes.groups[groupId];\r\n\t// render the group contents\r\n\tdisplayPreferencesAdd(\"expandedGroups\", groupId);\r\n\tgroupContainer.appendChild(domNodes.groupContents[groupId]);\r\n\tif (groupId === \"all-fences\" || groupId === \"all-places\") {\r\n\t\tif (domNodes.groupContents[groupId].childNodes.length === 0) {\r\n\t\t\tvar noExtraItems = groupContainer.querySelector(\"#no-\" + groupId);\r\n\t\t\tnoExtraItems.classList.add(\"is-visible\");\r\n\t\t}\r\n\t}\r\n\ttoggleGroupExpandedIcon(groupId, true);\r\n\r\n\tif (!groupContainer.hasAttribute(\"data-sort-initialized\")) {\r\n\t\tinitializeOrRefreshGroupSortable(groupId);\r\n\t\tgroupContainer.setAttribute(\"data-sort-initialized\", true);\r\n\t}\r\n}\r\n\r\nfunction collapseGroup(groupId) {\r\n\tvar groupContainer = domNodes.groups[groupId];\r\n\t// remove the group contents\r\n\tdisplayPreferencesRemove(\"expandedGroups\", groupId);\r\n\tgroupContainer.removeChild(domNodes.groupContents[groupId]);\r\n\tif (groupId === \"all-fences\" || groupId === \"all-places\") {\r\n\t\tvar noItems = groupContainer.querySelector(\"#no-\" + groupId);\r\n\t\tif (noItems !== null) {\r\n\t\t\tnoItems.classList.remove(\"is-visible\");\r\n\t\t}\r\n\t}\r\n\ttoggleGroupExpandedIcon(groupId, false);\r\n}\r\n\r\nexport function toggleGroupExpanded(groupId) {\r\n\tif (isItemIncluded(user.displayPreferences.expandedGroups, groupId)) {\r\n\t\tcollapseGroup(groupId);\r\n\t} else {\r\n\t\texpandGroup(groupId);\r\n\t}\r\n}\r\n\r\nexport function toggleGroupExpandedIcon(groupId, isVisible) {\r\n\tvar group = domNodes.groups[groupId];\r\n\tif (group === undefined) {\r\n\t\treturn;\r\n\t}\r\n\tconst toggleIcon = group.querySelector(\".group-toggle\");\r\n\tif (toggleIcon === null) {\r\n\t\treturn;\r\n\t}\r\n\tif (isVisible) {\r\n\t\tgroup.classList.add(\"is-expanded\");\r\n\t\ttoggleIcon\r\n\t\t\t.querySelector(\"use\")\r\n\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#folder-open-solid\");\r\n\t\ttoggleIcon.classList.add(\"active\");\r\n\t} else {\r\n\t\tgroup.classList.remove(\"is-expanded\");\r\n\t\ttoggleIcon\r\n\t\t\t.querySelector(\"use\")\r\n\t\t\t.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", \"/content/svg/tracking.svg?v=15#folder-solid\");\r\n\t\ttoggleIcon.classList.remove(\"active\");\r\n\t}\r\n}\r\n\r\nexport function indexAssetGroupsForSearch() {\r\n\ttrkData.search.assetGroups = new JsSearch.Search(\"Id\");\r\n\ttrkData.search.assetGroups.indexStrategy = new JsSearch.AllSubstringsIndexStrategy();\r\n\tvar attributes = [\"Name\", \"DestinationId\"];\r\n\t_.each(attributes, function (attribute) {\r\n\t\ttrkData.search.assetGroups.addIndex(attribute);\r\n\t});\r\n\ttrkData.search.assetGroups.addDocuments(trkData.groups);\r\n\tlog(\"Asset Groups indexed for search filtering.\");\r\n}\r\n\r\nfunction getFilteredEventsForGroup(groupId, filter) {\r\n\tvar status = getGroupAssetStatus(groupId);\r\n\tvar events = [];\r\n\tvar eventsSource =\r\n\t\tstate.activeMapMode === mapModes.HISTORY\r\n\t\t\t? trkData.history.normalizedEventsByAssetId\r\n\t\t\t: trkData.live.normalizedEventsByAssetId;\r\n\t_.each(status.assetIds, function (assetId) {\r\n\t\tevents = events.concat(_.filter(eventsSource[assetId], filter));\r\n\t});\r\n\tevents = _.sortBy(events, defaultListItemSort).reverse();\r\n\treturn events;\r\n}\r\n\r\nexport function createAssetNode(asset) {\r\n\tif (asset == null) return null;\r\n\tconst isActive = !isItemIncluded(user.displayPreferences.hiddenAssets, asset.Id);\r\n\tif (isActive) {\r\n\t\tif (_.indexOf(trkData.visible.assets, asset.Id) === -1) {\r\n\t\t\ttrkData.visible.assets.push(asset.Id);\r\n\t\t}\r\n\t}\r\n\tconst alpha = isActive ? null : 50;\r\n\r\n\tconst assetDto = {\r\n\t\tid: asset.Id,\r\n\t\tname: asset.Name,\r\n\t\tcolor: asset.Color,\r\n\t\ticon: createMarkerPath(asset.Class, asset.Color, null, alpha, asset.Id, true),\r\n\t\tisVisible: !isItemIncluded(user.displayPreferences.hiddenAssets, asset.Id),\r\n\t\tvisibilityClass: !isItemIncluded(user.displayPreferences.hiddenAssets, asset.Id) ? \"active\" : \"disabled\",\r\n\t\tserviceClass: asset.IsOutOfService ? \"noservice\" : \"\",\r\n\t\tlocation: {\r\n\t\t\taddress: null,\r\n\t\t\tlatitude: null,\r\n\t\t\tlongitude: null,\r\n\t\t\ttime: null,\r\n\t\t\tspeed: null,\r\n\t\t},\r\n\t\tnotifications: {\r\n\t\t\tsymbol: user.isAnonymous\r\n\t\t\t\t? options.allowAnonymousMessaging\r\n\t\t\t\t\t? \"notifications-sh\"\r\n\t\t\t\t\t: \"notifications-sh-nc\"\r\n\t\t\t\t: \"notifications\",\r\n\t\t\talerts: 0,\r\n\t\t\tevents: 0,\r\n\t\t\tstatus: 0,\r\n\t\t\tmessages: 0,\r\n\t\t},\r\n\t};\r\n\r\n\tconst fragment = templates.asset(assetDto);\r\n\treturn fragment.childNodes[0];\r\n\r\n\t// var device = trkData.devicesById[asset.DeviceId];\r\n\t//\r\n\t// var assetDto = {\r\n\t// \tId: asset.Id,\r\n\t// \tName: asset.Name,\r\n\t// \tServiceClass: asset.IsOutOfService ? \" noservice\" : \"\",\r\n\t// \tSupportsMessaging: device.SupportsMessaging && !user.isAnonymous,\r\n\t// \tImagePath: createMarkerPath(asset.Class, asset.Color, null, alpha, asset.Id, true),\r\n\t// \tIsActive: isActive,\r\n\t// };\r\n\t//\r\n\t// var mailbox = document.createDocumentFragment();\r\n\t// if (assetDto.SupportsMessaging) {\r\n\t// \t//\r\n\t// \t//mailbox = document.createElement('div');\r\n\t// \t//mailbox.className = 'mailbox';\r\n\t// \tvar box = document.createElement(\"a\");\r\n\t// \tbox.setAttribute(\"href\", \"#\");\r\n\t// \tbox.className = \"mailbox t-icon t-icon-mail\";\r\n\t// \t//var icon = document.createElement('span');\r\n\t// \t//icon.className = 't-icon t-icon-mail';\r\n\t// \t//link.appendChild(icon);\r\n\t// \tmailbox.appendChild(box);\r\n\t// }\r\n\t// var serviceClass = \"\";\r\n\t// if (asset.IsOutOfService) {\r\n\t// \tserviceClass = \" noservice\";\r\n\t// }\r\n\t//\r\n\t// var assetLi = document.createElement(\"li\");\r\n\t// assetLi.className =\r\n\t// \t\"assets-item group-item asset-\" +\r\n\t// \tassetDto.Id +\r\n\t// \tassetDto.ServiceClass +\r\n\t// \t(!assetDto.IsActive ? \" disabled\" : \" active\");\r\n\t// assetLi.setAttribute(\"data-asset-id\", assetDto.Id);\r\n\t// assetLi.style.cssText = \"background-image: url(\" + assetDto.ImagePath + \");\";\r\n\t// var assetShowHide = document.createElement(\"input\");\r\n\t// assetShowHide.setAttribute(\"type\", \"checkbox\");\r\n\t// assetShowHide.className = \"showhide\";\r\n\t// assetShowHide.setAttribute(\"data-asset-id\", assetDto.Id);\r\n\t// if (assetDto.IsActive) {\r\n\t// \tassetShowHide.setAttribute(\"checked\", \"checked\");\r\n\t// }\r\n\t// var assetName = document.createElement(\"a\");\r\n\t// assetName.className = \"asset-name\";\r\n\t// assetName.setAttribute(\"for\", \"asset-\" + assetDto.Id);\r\n\t// assetName.setAttribute(\"href\", \"#\");\r\n\t// assetName.textContent = assetDto.Name;\r\n\t// //var assetTreeControl = document.createElement('div');\r\n\t// //assetTreeControl.className = 'tree-control toggle-content is-visible';\r\n\t// var assetTreeControlLink = document.createElement(\"a\");\r\n\t// assetTreeControlLink.setAttribute(\"href\", \"#\");\r\n\t// assetTreeControlLink.className = \"tree-toggle show recent-positions-no toggle-content\";\r\n\t// //var assetEdit = document.createElement('div');\r\n\t// //assetEdit.className = 'edit';\r\n\t// var assetEditLink = document.createElement(\"a\");\r\n\t// assetEditLink.setAttribute(\"href\", \"#\");\r\n\t// assetEditLink.className = \"edit t-icon t-icon-context\";\r\n\t// //var assetEditIcon = document.createElement('span');\r\n\t// //assetEditIcon.className = 't-icon t-icon-context';\r\n\t// var assetIndicators = document.createElement(\"div\");\r\n\t// assetIndicators.className = \"indicators\";\r\n\t//\r\n\t// //assetEditLink.appendChild(assetEditIcon);\r\n\t// //assetEdit.appendChild(assetEditLink);\r\n\t//\r\n\t// //assetTreeControl.appendChild(assetTreeControlLink);\r\n\t// assetIndicators.appendChild(mailbox);\r\n\t//\r\n\t// assetLi.appendChild(assetShowHide);\r\n\t// assetLi.appendChild(assetName);\r\n\t// //assetLi.appendChild(assetTreeControl);\r\n\t// assetLi.appendChild(assetTreeControlLink);\r\n\t// //assetLi.appendChild(assetEdit);\r\n\t// assetLi.appendChild(assetEditLink);\r\n\t// assetLi.appendChild(assetIndicators);\r\n\t//\r\n\t// return assetLi;\r\n}\r\n\r\nexport function populateGroupDialog(group) {\r\n\t// populate fields with assetGroup information\r\n\t$(\"#txtGroupName\").val(group.Name);\r\n\t$(\"#txtGroupDestinationId\").val(group.DestinationId);\r\n\t$(\"#txtColor\").val(group.Color);\r\n\t$(\"#txtColor\").css(\"background-color\", group.Color);\r\n\t$(\"#txtColor\").next(\"span\").css(\"background-color\", group.Color);\r\n\t$(\"#EditAssetGroupAllowChat\").prop(\"checked\", group.IsChatEnabled);\r\n\t$(\"#EditAssetGroupAllowLocationSharing\").prop(\"checked\", group.IsLocationSharingEnabled);\r\n}\r\n\r\nexport function populateAssetGroupDialog(assetGroup) {\r\n\tpopulateGroupDialog(assetGroup);\r\n}\r\n\r\nexport function openAssetGroupDialog(assetGroup) {\r\n\tif (options.enabledFeatures.indexOf(\"UI_GROUPS\") === -1) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar dialog = domNodes.dialogs.editGroup;\r\n\tstate.groupDialog.isEditing = assetGroup !== null;\r\n\tstate.groupDialog.type = \"asset\";\r\n\r\n\tvar buttonText = state.groupDialog.isEditing ? strings.SAVE_CHANGES : strings.CREATE_GROUP;\r\n\tchangePrimaryButtonLabel(domNodes.dialogs.editGroup, buttonText);\r\n\r\n\tif (!state.groupDialog.isEditing) {\r\n\t\t$(\"#accordion-edit-asset-group-main-content\").collapse(\"show\");\r\n\t}\r\n\r\n\t$(\".section-asset-group\").show();\r\n\t$(\"#edit-group-item-name\").text(strings.ASSETS);\r\n\r\n\ttrkData.validation.addGroup.resetForm();\r\n\ttrkData.validation.addGroup.currentForm.reset();\r\n\r\n\tpopulateGroupList();\r\n\tvar dialog = $j(domNodes.dialogs.editGroup);\r\n\t$(\"#edit-asset-group-accordion .primary-card button\").removeClass(\"disabled\");\r\n\tvar dialogTitle = strings.ADD_ASSET_GROUP;\r\n\tif (state.groupDialog.isEditing) {\r\n\t\t$j(\"#asset-group-parent\").hide();\r\n\t\tdialogTitle = strings.EDIT_ASSET_GROUP;\r\n\r\n\t\t$j(dialog).data(\"groupId\", assetGroup.Id);\r\n\t} else {\r\n\t\t$j(\"#asset-group-parent\").show();\r\n\t}\r\n\r\n\tif (!user.isAdmin) {\r\n\t\t$(\"#accordion-edit-asset-group-users-head button\").addClass(\"disabled\");\r\n\t}\r\n\r\n\t// checkbox lists...\r\n\tvar userList = user.isAdmin ? trkData.users : [];\r\n\tpopulateCheckboxList(\r\n\t\t\"edit-asset-group-users-list\",\r\n\t\tuserList,\r\n\t\t\"EditAssetGroupUserIds\",\r\n\t\tfunction (item) {\r\n\t\t\tif (assetGroup === null) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tvar itemUsers = _.find(trkData.assetGroupUsers, { AssetGroupId: assetGroup.Id });\r\n\t\t\tif (itemUsers === undefined) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\treturn _.indexOf(itemUsers.UserIds, item.Id) !== -1;\r\n\t\t},\r\n\t\tfunction (item) {\r\n\t\t\treturn item.Name;\r\n\t\t},\r\n\t\t\"users\",\r\n\t\tfunction (item) {\r\n\t\t\treturn item.Username;\r\n\t\t}\r\n\t);\r\n\tpopulateCheckboxList(\r\n\t\t\"edit-asset-group-assets-list\",\r\n\t\ttrkData.assets,\r\n\t\t\"EditAssetGroupAssetIds\",\r\n\t\tfunction (item) {\r\n\t\t\tif (assetGroup === null) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\treturn _.indexOf(item.GroupIds, assetGroup.Id) !== -1;\r\n\t\t},\r\n\t\tfunction (item) {\r\n\t\t\treturn item.Name;\r\n\t\t},\r\n\t\t\"assets\",\r\n\t\tfunction (item) {\r\n\t\t\treturn item.UniqueId;\r\n\t\t}\r\n\t);\r\n\r\n\tif (assetGroup !== null) {\r\n\t\tpopulateAssetGroupDialog(assetGroup);\r\n\t}\r\n\r\n\topenDialogPanel(\r\n\t\tdomNodes.dialogs.editGroup,\r\n\t\tdialogTitle,\r\n\t\tassetGroup,\r\n\t\tfalse,\r\n\t\tnull,\r\n\t\t\"group\",\r\n\t\tassetGroup !== null ? \"edit-group\" : null,\r\n\t\tassetGroup !== null ? openAssetGroupDialog : null\r\n\t);\r\n\tdocument.getElementById(\"txtGroupName\").focus();\r\n}\r\n\r\nexport function createGroupNode(group) {\r\n\tvar groupDto = {\r\n\t\tid: group.Id,\r\n\t\tisFavorite: false,\r\n\t\tisVisible: isItemIncluded(user.displayPreferences.expandedGroups, group.Id),\r\n\t\tcolor: group.Color,\r\n\t\tname: group.Name,\r\n\t\tdescription: \"\",\r\n\t\ttype: group.Type,\r\n\t\tnotifications: {\r\n\t\t\tsymbol: user.isAnonymous\r\n\t\t\t\t? options.allowAnonymousMessaging\r\n\t\t\t\t\t? \"notifications-sh\"\r\n\t\t\t\t\t: \"notifications-sh-nc\"\r\n\t\t\t\t: \"notifications\",\r\n\t\t},\r\n\t};\r\n\tvar fragment = templates.assetGroup(groupDto);\r\n\tvar item = fragment.childNodes[0];\r\n\tvar noSettingsGroups = [\"all-fences\", \"all-places\", \"all-shared-views\"];\r\n\tif (_.indexOf(noSettingsGroups, group.Id) !== -1) {\r\n\t\tvar groupSettings = item.querySelector(\".item-settings\");\r\n\t\tgroupSettings.parentNode.removeChild(groupSettings);\r\n\t}\r\n\tif (group.Type !== \"assets\" && group.Type !== \"journeys\") {\r\n\t\tvar groupIndicators = item.querySelector(\".asset-indicators\");\r\n\t\tgroupIndicators.parentNode.removeChild(groupIndicators);\r\n\t}\r\n\treturn item;\r\n}\r\n\r\nexport function addGroup(group, groupItemsIds) {\r\n\tvar groupNode = createGroupNode(group);\r\n\tvar groupContentsNode = groupNode.querySelector(\".group-contents\");\r\n\tvar groupContentsItems = groupContentsNode.querySelector(\"ul.group-list-list\");\r\n\r\n\tvar groupItems = _.filter(trkData[group.Type], function (item) {\r\n\t\treturn _.indexOf(groupItemsIds, item.Id) !== -1;\r\n\t}).sort(sortByName);\r\n\t_.each(groupItems, function (item) {\r\n\t\titem.GroupIds.push(group.Id);\r\n\t\tvar groupAssetNode = domNodes[group.Type][item.Id][0].cloneNode(true);\r\n\t\tdomNodes[group.Type][item.Id].push(groupAssetNode);\r\n\t\tgroupContentsItems.appendChild(groupAssetNode);\r\n\t});\r\n\r\n\t// cache group content nodes so they can be detached/reattached to the dom\r\n\t// based on whether the group is expanded/visible\r\n\tdomNodes.groups[group.Id] = groupNode;\r\n\tdomNodes.groupContents[group.Id] = groupContentsNode;\r\n\r\n\tvar allGroups = group.Type === \"assets\" ? trkData.groups :\r\n\t\tgroup.Type === \"places\" ? trkData.placeGroups :\r\n\t\tgroup.Type === \"fences\" ? trkData.fenceGroups : {};\r\n\r\n\t// add group to appropriate place\r\n\tif (group.ParentGroupId != null) {\r\n\t\tvar parentGroup = findGroupById(group.ParentGroupId, group.Type);\r\n\t\tif (parentGroup !== null) {\r\n\t\t\tvar parentGroupContents = domNodes.groupContents[parentGroup.Id].querySelector(\"ul.group-list-list\");\r\n\t\t\t// place in appropriate order within group's subgroups\r\n\t\t\tparentGroup.GroupIds.push(group.Id);\r\n\t\t\tif (parentGroup.GroupIds.length == 1) {\r\n\t\t\t\tparentGroupContents.insertBefore(groupNode, parentGroupContents.firstChild);\r\n\t\t\t} else {\r\n\t\t\t\tvar subGroups = _.filter(allGroups, function (item) {\r\n\t\t\t\t\treturn _.indexOf(parentGroup.GroupIds, item.Id) !== -1;\r\n\t\t\t\t}).sort(sortByName);\r\n\t\t\t\tvar groupIndex = _.indexOf(subGroups, group);\r\n\t\t\t\tparentGroupContents.insertBefore(groupNode, parentGroupContents.children[groupIndex]);\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\t// add to root groups listing\r\n\t\tvar groupsContainer = document.getElementById(group.Type + \"-all\");\r\n\t\tvar subGroups = _.filter(allGroups, function (item) {\r\n\t\t\treturn item.ParentGroupId == null && !item.IsDefault;\r\n\t\t}).sort(sortByName);\r\n\t\tif (subGroups.length > 1) {\r\n\t\t\tvar groupIndex = _.indexOf(subGroups, group);\r\n\t\t\tgroupsContainer.insertBefore(groupNode, groupsContainer.children[groupIndex + 1]);\r\n\t\t} else {\r\n\t\t\tgroupsContainer.insertBefore(groupNode, groupsContainer.children[1]);\r\n\t\t}\r\n\t}\r\n\tdomNodes.groupColors[group.Id] = group.Color;\r\n\tupdateGroupVisibilityStatus(group.Id, group.Type);\r\n\tcreateGroupColorStyles();\r\n}\r\n\r\nexport function deleteAssetGroup(deleted) {\r\n\t// remove group from UI\r\n\tvar li = $j(\"#group-\" + deleted.Id);\r\n\tli.remove();\r\n\r\n\t// remove group from trkData.groups\r\n\tfor (var i = 0; i < trkData.groups.length; i++) {\r\n\t\tif (trkData.groups[i].Id == deleted.Id) {\r\n\t\t\ttrkData.groups.splice(i, 1);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\ttrkData.groupsById = _.keyBy(trkData.groups, \"Id\");\r\n\r\n\tvar modifiedGroupIds = [];\r\n\t_.each(trkData.groups, function (group) {\r\n\t\tif (_.indexOf(group.GroupIds, deleted.Id)) {\r\n\t\t\tgroup.GroupIds = _.without(group.GroupIds, deleted.Id);\r\n\t\t\tmodifiedGroupIds.push(group.Id);\r\n\t\t}\r\n\t});\r\n\r\n\tif (trkData.assetGroupUsers != null) {\r\n\t\tfor (var i = trkData.assetGroupUsers.length - 1; i >= 0; i -= 1) {\r\n\t\t\tif (trkData.assetGroupUsers[i].AssetGroupId == deleted.Id) {\r\n\t\t\t\ttrkData.assetGroupUsers.splice(i, 1);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// remove group id from all asset's groupIds listings\r\n\tfor (var i = 0; i < trkData.assets.length; i++) {\r\n\t\tvar asset = trkData.assets[i];\r\n\t\tfor (var j = 0; j < asset.GroupIds.length; j++) {\r\n\t\t\tif (asset.GroupIds[j] == deleted.Id) {\r\n\t\t\t\tasset.GroupIds.splice(j, 1);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// remove group expanded preference\r\n\tdisplayPreferencesRemove(\"expandedGroups\", deleted.Id);\r\n\r\n\t// update group status for parent groups\r\n\t_.each(modifiedGroupIds, function (groupId) {\r\n\t\tupdateGroupVisibilityStatus(groupId);\r\n\t});\r\n}\r\n\r\nexport function updateGroup(updated) {\r\n\t// find li for group and update name/color\r\n\t// group could be hidden so search domNodes\r\n\tdomNodes.groupColors[updated.Id] = updated.Color;\r\n\r\n\t// may also be open in secondaryPanel, so refresh in case name/color was updated\r\n\tif (\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-group-for\") === \"groups\" &&\r\n\t\tdomNodes.panels.secondary.getAttribute(\"data-item-id\") === updated.Id\r\n\t) {\r\n\t\topenAssetGroupSettingsPanel(updated);\r\n\t}\r\n\r\n\tvar li = domNodes.groups[updated.Id];\r\n\tif (li !== undefined) {\r\n\t\tli.style.borderColor = updated.Color;\r\n\t\tvar name = li.querySelector(\".group-name\");\r\n\t\tname.textContent = updated.Name;\r\n\t}\r\n\r\n\tcreateGroupColorStyles();\r\n\t//var li = $j('#group-' + updated.Id).eq(0);\r\n\t//if (li != null) {\r\n\t// //li.css('background-color', updated.Color);\r\n\t// li.css('border-color', updated.Color);\r\n\t// $j('a.group span', li).text(updated.Name);\r\n\t//}\r\n}\r\n\r\nexport function createGroupColorStyles() {\r\n\tvar existingStyle = document.getElementById(\"group-colors-style\");\r\n\tvar colors = \"\";\r\n\t_.each(domNodes.groupColors, function (elem, index, list) {\r\n\t\t//colors += '#group-' + index + ' .group-color, #group-' + index + ' > .list-item-action.active { color: ' + elem + '; border-color: ' + elem + '; }' + \"\\n\";\r\n\t\t//colors += '#group-' + index + ' > .group-header, #group-' + index + ' > .group-header > .list-item-action.active { color: ' + elem + '; border-color: ' + elem + '; }' + \"\\n\";\r\n\t\t//colors += '#group-' + index + ' .group-color { color: ' + elem + '; border-color: ' + elem + '; }' + \"\\n\";\r\n\t\t//colors += '#group-' + index + ' > .group-header { color: ' + elem + '; border-color: ' + elem + '; }' + \"\\n\";\r\n\t\tcolors += \"#group-\" + index + \" > .group-header { border-color: \" + elem + \"; }\" + \"\\n\";\r\n\t\t//colors += '#group-' + index + ' .list-item-action.showhide.active { color: ' + elem + '; }' + \"\\n\";\r\n\t});\r\n\tif (existingStyle === null) {\r\n\t\tvar groupColors = document.createElement(\"style\");\r\n\t\tgroupColors.id = \"group-colors-style\";\r\n\t\tgroupColors.type = \"text/css\";\r\n\t\tgroupColors.innerHTML = colors;\r\n\t\tdocument.getElementsByTagName(\"head\")[0].appendChild(groupColors);\r\n\t} else {\r\n\t\texistingStyle.innerHTML = colors;\r\n\t}\r\n}\r\n\r\nexport function indexCustomAttributes(attributes) {\r\n\treturn _.map(attributes, function (attribute) {\r\n\t\treturn attribute.Value;\r\n\t});\r\n}\r\n\r\nexport function queryGroupsAndAssets() {\r\n\ttoggleLoadingMessage(true, \"assetGroups\");\r\n\tvar data = {\r\n\t\tdbg: getDbg(),\r\n\t};\r\n\treturn $.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/GetGroupsAndAssetsReq\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json\",\r\n\t\tdataType: \"json\",\r\n\t})\r\n\t\t.done(function (msg) {\r\n\t\t\tif (!msg.d) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\ttoggleLoadingMessage(false, \"assetGroups\");\r\n\t\t\tvar result = msg.d;\r\n\r\n\t\t\ttrkData.devices = result.Devices;\r\n\t\t\ttrkData.devicesById = _.keyBy(trkData.devices, \"Id\");\r\n\r\n\t\t\ttrkData.assets = result.Assets;\r\n\t\t\t_.each(trkData.assets, function (asset) {\r\n\t\t\t\tasset.ColorSorted = convertHexToSortable(convertNamedColorToHex(asset.Color));\r\n\t\t\t\tasset.Tags = indexCustomAttributes(asset.Attributes);\r\n\t\t\t});\r\n\t\t\ttrkData.assetsById = _.keyBy(trkData.assets, \"Id\");\r\n\r\n\t\t\ttrkData.fences = result.Fences;\r\n\t\t\t_.each(trkData.fences, function (fence) {\r\n\t\t\t\tfence.ColorSorted = convertHexToSortable(fence.Color);\r\n\t\t\t});\r\n\t\t\t_.each(result.FenceGroups, function (group) {\r\n\t\t\t\tgroup.GroupIds = [];\r\n\t\t\t\tgroup.Type = \"fences\";\r\n\t\t\t});\r\n\t\t\ttrkData.fenceGroups = result.FenceGroups;\r\n\t\t\tvar allFencesGroup = {\r\n\t\t\t\tId: \"all-fences\",\r\n\t\t\t\tIsDefault: true,\r\n\t\t\t\tName: strings.ALL_GEOFENCES,\r\n\t\t\t\tColor: getBackgroundColorAsHex(document.getElementById(\"nav-toggle\")),\r\n\t\t\t\tParentGroupId: null,\r\n\t\t\t\tGroupIds: [],\r\n\t\t\t\tType: \"fences\",\r\n\t\t\t};\r\n\t\t\ttrkData.fenceGroups.splice(0, 0, allFencesGroup);\r\n\t\t\t_.each(trkData.fenceGroups, function (group) {\r\n\t\t\t\tgroup.ColorSorted = convertHexToSortable(group.Color);\r\n\t\t\t});\r\n\t\t\ttrkData.fencesById = _.keyBy(trkData.fences, \"Id\");\r\n\r\n\t\t\ttrkData.sharedViews = result.SharedViews;\r\n\t\t\t_.each(trkData.sharedViews, function (sharedView) {\r\n\t\t\t\tsharedView.ColorSorted = convertHexToSortable(sharedView.Color);\r\n\t\t\t\tsharedView.Link = getSharedViewLink(sharedView); // TODO remove this\r\n\t\t\t});\r\n\t\t\ttrkData.sharedViewsById = _.keyBy(trkData.sharedViews, \"Id\");\r\n\r\n\t\t\ttrkData.places = result.Places;\r\n\t\t\t_.each(trkData.places, function (place) {\r\n\t\t\t\tplace.ColorSorted = convertHexToSortable(convertNamedColorToHex(place.Color));\r\n\t\t\t});\r\n\t\t\ttrkData.placesById = _.keyBy(trkData.places, \"Id\");\r\n\t\t\t_.each(result.PlaceGroups, function (group) {\r\n\t\t\t\tgroup.GroupIds = [];\r\n\t\t\t\tgroup.Type = \"places\";\r\n\t\t\t});\r\n\t\t\ttrkData.placeGroups = result.PlaceGroups;\r\n\t\t\tvar allPlacesGroup = {\r\n\t\t\t\tId: \"all-places\",\r\n\t\t\t\tIsDefault: true,\r\n\t\t\t\tName: strings.ALL_PLACES,\r\n\t\t\t\tColor: getBackgroundColorAsHex(document.getElementById(\"nav-toggle\")),\r\n\t\t\t\tParentGroupId: null,\r\n\t\t\t\tGroupIds: [],\r\n\t\t\t\tType: \"places\",\r\n\t\t\t};\r\n\t\t\ttrkData.placeGroups.splice(0, 0, allPlacesGroup);\r\n\t\t\t_.each(trkData.placeGroups, function (group) {\r\n\t\t\t\tgroup.ColorSorted = convertHexToSortable(convertNamedColorToHex(group.Color));\r\n\t\t\t});\r\n\r\n\t\t\ttrkData.journeys = result.Journeys;\r\n\t\t\t_.each(trkData.journeys, function (journey) {\r\n\t\t\t\t_.each(journey.Trips, function (trip) {\r\n\t\t\t\t\ttrip.JourneyId = journey.Id;\r\n\t\t\t\t});\r\n\t\t\t});\r\n\t\t\ttrkData.journeysById = _.keyBy(trkData.journeys, \"Id\");\r\n\r\n\t\t\ttrkData.waypoints = result.Waypoints;\r\n\r\n\t\t\ttrkData.driverStatuses = result.DriverStatuses;\r\n\r\n\t\t\ttrkData.attributes = result.Attributes;\r\n\r\n\t\t\ttrkData.attributeGroups = result.AttributeGroups;\r\n\r\n\t\t\t_.each(result.Groups, function (group) {\r\n\t\t\t\tgroup.Groups = [];\r\n\t\t\t\tgroup.GroupIds = [];\r\n\t\t\t\tgroup.Type = \"assets\";\r\n\t\t\t});\r\n\t\t\ttrkData.groups = result.Groups;\r\n\t\t\tvar allAssetsGroup = {\r\n\t\t\t\tId: \"all-assets\",\r\n\t\t\t\tName: strings.ALL_ASSETS,\r\n\t\t\t\tColor: getBackgroundColorAsHex(document.getElementById(\"nav-toggle\")), // todo: pass default colors in here, or extract from CSS value? window.getComputedStyle(document.getElementById('group-all-assets)).borderLeftColor // RBG\r\n\t\t\t\tParentGroupId: null,\r\n\t\t\t\tGroupIds: [],\r\n\t\t\t\tGroups: [],\r\n\t\t\t\tAssetIds: [],\r\n\t\t\t\tDestinationId: \"\",\r\n\t\t\t\tIsDefault: true,\r\n\t\t\t\tType: \"assets\",\r\n\t\t\t};\r\n\t\t\ttrkData.groups.splice(0, 0, allAssetsGroup);\r\n\t\t\t_.each(trkData.groups, function (group) {\r\n\t\t\t\tgroup.ColorSorted = convertHexToSortable(group.Color);\r\n\t\t\t});\r\n\t\t\ttrkData.groupsById = _.keyBy(trkData.groups, \"Id\");\r\n\r\n\t\t\t// load preferences for asset/group/fence UI show/hide\r\n\t\t\tloadDisplayPreferences();\r\n\t\t})\r\n\t\t.fail(function (xhr, status, error) {\r\n\t\t\thandleWebServiceError(strings.MSG_QUERY_GROUPS_ERROR);\r\n\t\t\ttoggleLoadingMessage(false, \"assetGroups\");\r\n\t\t});\r\n}\r\n","import trkData from \"./data.js\";\r\nimport { displayPreferencesRemove } from \"./user.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport { updateGroupVisibilityStatus } from \"./asset-group.js\";\r\nimport { closeSecondaryPanel } from \"./panel.js\";\r\nimport { deleteTrip } from \"./trips.js\";\r\n\r\nimport _ from \"lodash\";\r\n\r\nexport function findJourneyById(id) {\r\n\tvar item = _.find(trkData.journeys, { Id: parseInt(id) });\r\n\treturn item === undefined ? null : item;\r\n}\r\n\r\nexport function deleteJourney(journey) {\r\n\tvar groupId = \"journey-\" + journey.Id;\r\n\tdomNodes.groups[groupId].parentNode.removeChild(domNodes.groups[groupId]);\r\n\tvar panel = domNodes.panels.secondary;\r\n\tif (\r\n\t\tpanel.getAttribute(\"data-group-for\") === \"journeys\" &&\r\n\t\tparseInt(panel.getAttribute(\"data-item-id\")) === journey.Id\r\n\t) {\r\n\t\tcloseSecondaryPanel();\r\n\t}\r\n\r\n\tfor (var j = journey.Trips.length - 1; j >= 0; j--) {\r\n\t\tdeleteTrip(journey.Trips[j]);\r\n\t}\r\n\r\n\tfor (var i = 0; i < trkData.journeys.length; i++) {\r\n\t\tif (trkData.journeys[i].Id == journey.Id) {\r\n\t\t\ttrkData.journeys.splice(i, 1);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\ttrkData.journeysById = _.keyBy(trkData.journeys, \"Id\");\r\n\tdisplayPreferencesRemove(\"expandedGroups\", groupId);\r\n\tupdateGroupVisibilityStatus(groupId);\r\n}\r\n","import preferences from \"./preferences.js\";\r\nimport { findAssetById } from \"./assets.js\";\r\nimport user from \"./user.js\";\r\nimport { findJourneyById } from \"./journey.js\";\r\n\r\nexport function createMarkerPath(icon, color, heading, alpha, assetId, forceAlpha, type, isFirst, isLast, number) {\r\n\tif (color === undefined || color === null) {\r\n\t\tcolor = \"\";\r\n\t}\r\n\tif (heading === undefined || heading === null) {\r\n\t\theading = \"\";\r\n\t}\r\n\tif (alpha === undefined || alpha === null) alpha = \"\";\r\n\r\n\tnumber = typeof number !== \"undefined\" ? number : \"\";\r\n\ttype = typeof type !== \"undefined\" ? type : \"\";\r\n\r\n\tvar headingVal = \"\";\r\n\tif (heading != \"\") {\r\n\t\theading = Math.floor(heading);\r\n\t\theading = Math.floor(heading / 5) * 5; // round to nearest 5 degrees\r\n\t\theadingVal = \"&heading=\" + heading;\r\n\t}\r\n\r\n\tvar alphaVal = \"\";\r\n\tif (alpha !== \"\") {\r\n\t\tif (preferences.PREFERENCE_ALPHA_POSITIONS || forceAlpha) {\r\n\t\t\tif (Math.ceil(alpha) !== 255) {\r\n\t\t\t\talphaVal = \"&alpha=\" + Math.ceil(alpha);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tvar colorVal = \"&color=\" + color;\r\n\t// if custom icon and no heading, no color needed\r\n\tif (icon.toLowerCase() === \"upload\" && heading === \"\") {\r\n\t\tcolorVal = \"\";\r\n\t}\r\n\r\n\tvar aidVal = \"\";\r\n\tvar lmVal = \"\";\r\n\tif (icon.toLowerCase() === \"upload\") {\r\n\t\taidVal = \"&aid=\" + assetId;\r\n\t\tif (assetId != null) {\r\n\t\t\tvar asset = findAssetById(assetId);\r\n\t\t\tif (asset !== null) {\r\n\t\t\t\tlmVal = \"&lm=\" + asset.IconModified;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tvar typeVal = \"\";\r\n\tif (type !== null && type !== \"\") {\r\n\t\ttypeVal = \"&type=\" + type;\r\n\t}\r\n\r\n\tvar numberVal = \"\";\r\n\tif (number !== null && number !== \"\") {\r\n\t\tnumberVal = \"&num=\" + number;\r\n\t}\r\n\r\n\tvar flagVal = \"\";\r\n\tvar hideFlags = false;\r\n\tif ((isFirst === true || isLast === true) && assetId != null) {\r\n\t\tif (assetId != null) {\r\n\t\t\tvar asset = findAssetById(assetId);\r\n\t\t\thideFlags = asset.HideFlags;\r\n\t\t}\r\n\t}\r\n\tif (!hideFlags) {\r\n\t\tif (isFirst === true) {\r\n\t\t\tflagVal = \"&flag=begin\";\r\n\t\t} else if (isLast === true) {\r\n\t\t\tflagVal = \"&flag=end\";\r\n\t\t}\r\n\t}\r\n\r\n\tvar imagePath =\r\n\t\t\"/markers/\" + icon + \"?\" + colorVal + headingVal + alphaVal + aidVal + typeVal + flagVal + numberVal + lmVal;\r\n\tif (user.isImpersonated && aidVal !== \"\") {\r\n\t\timagePath += \"&ishr=\" + encodeURIComponent(user.id);\r\n\t}\r\n\t// if (options.useStaticSubdomains) {\r\n\t// \t// TODO: handle this with a httpmodule instead?\r\n\t// \t// serve static content from other subdomains to improve request handling\r\n\t// \tvar domain = \"static\";\r\n\t// \tswitch (icon.toLowerCase()) {\r\n\t// \t\tcase \"person\":\r\n\t// \t\tcase \"boat\":\r\n\t// \t\tcase \"airplane\":\r\n\t// \t\tcase \"yacht\":\r\n\t// \t\t\tdomain += \"1\";\r\n\t// \t\t\tbreak;\r\n\t// \t\tcase \"truck\":\r\n\t// \t\tcase \"car\":\r\n\t// \t\tcase \"upload\":\r\n\t// \t\tcase \"helicopter\":\r\n\t// \t\t\tdomain += \"2\";\r\n\t// \t\t\tbreak;\r\n\t// \t\tdefault:\r\n\t// \t\t\tbreak;\r\n\t// \t}\r\n\t// \t// return 'https://domain.actualdomain.com{imagePath}'\r\n\t// }\r\n\treturn imagePath;\r\n}\r\n\r\nexport function getGenericIconUrlForItemType(type, item) {\r\n\tvar icon = null;\r\n\tswitch (type) {\r\n\t\tcase \"fences\":\r\n\t\t\ticon =\r\n\t\t\t\t\"url(\" + createMarkerPath(\"Fence\", item.Color.substring(1), null, null, null, false, null, false, false) + \")\";\r\n\t\t\tbreak;\r\n\t\tcase \"places\":\r\n\t\t\ticon = \"url(\" + createMarkerPath(\"Generic\", item.Color, null, null, null, false, null, false, false) + \")\";\r\n\t\t\tbreak;\r\n\t\tcase \"assets\":\r\n\t\t\ticon = \"url(\" + createMarkerPath(item.Class, item.Color, null, null, item.Id, false, null, false, false) + \")\";\r\n\t\t\tbreak;\r\n\t\t//case 'journeys': // fallthrough\r\n\t\tcase \"trips\":\r\n\t\t\tif (type === \"trips\") {\r\n\t\t\t\tvar journey = findJourneyById(item.JourneyId);\r\n\t\t\t\tvar asset = findAssetById(journey.AssetId);\r\n\t\t\t\ticon =\r\n\t\t\t\t\t\"url(\" + createMarkerPath(asset.Class, asset.Color, null, null, asset.Id, false, null, false, false) + \")\";\r\n\t\t\t} else {\r\n\t\t\t\ticon =\r\n\t\t\t\t\t\"url(\" +\r\n\t\t\t\t\tcreateMarkerPath(\"Fence\", item.Color.substring(1), null, null, null, false, null, false, false) +\r\n\t\t\t\t\t\")\";\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t//case 'groups': // TODO... SVG support here to match listing\r\n\t\t// icon = 'url(' + createMarkerPath('Fence', item.Color.substring(1), null, null, null, false, null, false, false) + ')';\r\n\t\t// break;\r\n\t\t//case 'shared-views': // TODO... SVG support here\r\n\t\t// break;\r\n\t\tdefault: // dialog\r\n\t\t\tbreak;\r\n\t}\r\n\treturn icon;\r\n}\r\n","import $j from \"jquery\";\r\nimport options from \"./options.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\n\r\nexport function reverseGeocode(latlng, callback) {\r\n\tif (options.enabledFeatures.indexOf(\"UI_GEOCODING\") === -1) {\r\n\t\treturn;\r\n\t}\r\n\tvar data = { Lat: latlng.lat, Lng: latlng.lng };\r\n\treturn $j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/ReverseGeocode\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tvar result = msg.d;\r\n\t\t\tif (result) {\r\n\t\t\t\tconsole.log(result);\r\n\t\t\t\tif (result.Success == true) {\r\n\t\t\t\t\tcallback(true, result.Address);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tcallback(false);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\tcallback(false);\r\n\t\t},\r\n\t});\r\n}\r\n\r\nexport function addressSearch(address, callback) {\r\n\tvar data = { address: address };\r\n\treturn $j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/AddressSearch\"),\r\n\t\tdata: JSON.stringify(data),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tconsole.log(\"address search success\");\r\n\t\t\tvar result = msg.d;\r\n\t\t\tif (result) {\r\n\t\t\t\tconsole.log(result);\r\n\t\t\t\tif (result.Success === true) {\r\n\t\t\t\t\tcallback(true, result.Result);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tcallback(false);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\tcallback(false);\r\n\t\t},\r\n\t});\r\n}\r\n","import state from \"./state.js\";\r\nimport { map } from \"./map-base.js\";\r\nimport { addItemToMap, removeItemFromMap } from \"./map-items.js\";\r\nimport { createMarkerPath } from \"./marker-path.js\";\r\nimport { addPointToRuler } from \"./ruler.js\";\r\nimport { addPointToRouting } from \"./routing.js\";\r\nimport { reverseGeocode } from \"./geocode.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport L from \"leaflet\";\r\nimport _ from \"lodash\";\r\n\r\nexport function startChoosingMapLocation(handler) {\r\n\tvar handlerIndex = _.indexOf(state.mapClickQueue, handler);\r\n\tif (handlerIndex === -1) {\r\n\t\tstate.mapClickQueue.push(handler);\r\n\t\tL.DomUtil.addClass(map._container, \"crosshair-cursor-enabled\");\r\n\t}\r\n}\r\n\r\nexport function stopChoosingMapLocation(handler) {\r\n\tvar handlerIndex = _.indexOf(state.mapClickQueue, handler);\r\n\tif (handlerIndex !== -1) {\r\n\t\tstate.mapClickQueue.splice(handlerIndex);\r\n\t}\r\n\tif (state.mapClickQueue.length === 0) {\r\n\t\tif (state.chosenLocations[handler] !== null && state.chosenLocations[handler] !== undefined) {\r\n\t\t\tremoveItemFromMap(state.chosenLocations[handler]);\r\n\t\t}\r\n\t\tL.DomUtil.removeClass(map._container, \"crosshair-cursor-enabled\");\r\n\t}\r\n}\r\n\r\nexport function updateChosenLocation(latlng, handler) {\r\n\tif (!(latlng instanceof L.LatLng)) {\r\n\t\tlatlng = L.latLng(latlng);\r\n\t}\r\n\r\n\tif (state.mapClickQueue.length === 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar clickHandler = state.mapClickQueue[state.mapClickQueue.length - 1];\r\n\tif (handler === null || handler === undefined) {\r\n\t\thandler = clickHandler;\r\n\t}\r\n\r\n\t// place/move a marker icon at the spot for handlers adding/selecting some kind of marked location\r\n\t// we need to have a marker per handler so they don't interfere with each other\r\n\t// and the dragend callback needs to be aware of the handler associated with it\r\n\tif (\r\n\t\thandler === state.mapClickHandlers.POSITION ||\r\n\t\thandler === state.mapClickHandlers.POSITION_ADD ||\r\n\t\thandler === state.mapClickHandlers.PLACE\r\n\t) {\r\n\t\tif (state.chosenLocations[handler] === null || state.chosenLocations[handler] === undefined) {\r\n\t\t\tvar locationIcon = L.icon({\r\n\t\t\t\ticonUrl: createMarkerPath(\"Generic\", \"red\", null, null, null, false),\r\n\t\t\t\ticonSize: [36, 36],\r\n\t\t\t\ticonAnchor: [18, 18],\r\n\t\t\t});\r\n\t\t\tstate.chosenLocations[handler] = L.marker(latlng, { icon: locationIcon, draggable: true });\r\n\t\t\taddItemToMap(state.chosenLocations[handler]);\r\n\t\t\tstate.chosenLocations[handler].on(\"dragend\", function (e) {\r\n\t\t\t\tupdateChosenLocation(e.target.getLatLng(), handler);\r\n\t\t\t});\r\n\t\t} else {\r\n\t\t\taddItemToMap(state.chosenLocations[handler]);\r\n\t\t\tstate.chosenLocations[handler].setLatLng(latlng);\r\n\t\t}\r\n\t}\r\n\r\n\tswitch (handler) {\r\n\t\tcase state.mapClickHandlers.POSITION:\r\n\t\t\t$(\"#SendPositionLatLng\").text(latlng.lat.toFixed(6) + \", \" + latlng.lng.toFixed(6));\r\n\t\t\t$(\"#hfPositionLat\").val(latlng.lat);\r\n\t\t\t$(\"#hfPositionLng\").val(latlng.lng);\r\n\t\t\t$(\"#send-position-search\").removeClass(\"is-visible\");\r\n\t\t\t$(\"#form-send-position-send\").addClass(\"is-visible\");\r\n\t\t\treverseGeocode(latlng, function (success, address) {\r\n\t\t\t\tif (success && address !== \"\") {\r\n\t\t\t\t\tif ($(\"#SendPositionName\").val() === \"\") {\r\n\t\t\t\t\t\t$(\"#SendPositionName\").val(address);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t\tbreak;\r\n\t\tcase state.mapClickHandlers.POSITION_ADD:\r\n\t\t\t$(\"#txtAddPositionLat\").val(latlng.lat.toFixed(6));\r\n\t\t\t$(\"#txtAddPositionLng\").val(latlng.lng.toFixed(6));\r\n\t\t\tbreak;\r\n\t\tcase state.mapClickHandlers.PLACE:\r\n\t\t\t$(\"#add-place-location\").text(latlng.lat.toFixed(6) + \", \" + latlng.lng.toFixed(6));\r\n\t\t\t$(\"#add-place-search\").removeClass(\"is-visible\");\r\n\t\t\t$(\"#form-add-place\").addClass(\"is-visible\");\r\n\t\t\t$(\"#hfPlaceLat\").val(latlng.lat);\r\n\t\t\t$(\"#hfPlaceLng\").val(latlng.lng);\r\n\r\n\t\t\treverseGeocode(latlng, function (success, address) {\r\n\t\t\t\tif (success && address !== \"\") {\r\n\t\t\t\t\tif ($(\"#txtPlaceName\").val() === \"\") {\r\n\t\t\t\t\t\t$(\"#txtPlaceName\").val(address);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t\tbreak;\r\n\t\tcase state.mapClickHandlers.RULER:\r\n\t\t\taddPointToRuler(latlng);\r\n\t\t\tbreak;\r\n\t\tcase state.mapClickHandlers.GEOFENCE:\r\n\t\t\tbreak;\r\n\t\tcase state.mapClickHandlers.ROUTING:\r\n\t\t\taddPointToRouting(latlng);\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n","import { handleWebServiceError } from \"./ajax.js\";\r\nimport { addItemToMap, removeItemFromMap } from \"./map-items.js\";\r\nimport strings from \"./strings.js\";\r\nimport trkData from \"./data.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport { intervals } from \"./timers.js\";\r\n\r\nimport $j from \"jquery\";\r\nconst Cookies = window.Cookies; // from 'js.cookie.js', v2.2.0\r\nimport L from \"leaflet\";\r\n\r\nfunction wrapLat(lat) {\r\n\tif (lat > 90) {\r\n\t\tlat = -90 + (lat - 90);\r\n\t}\r\n\tif (lat < -90) {\r\n\t\tlat = 90 - (-90 - lat);\r\n\t}\r\n\treturn lat;\r\n}\r\n\r\nfunction wrapLng(lng) {\r\n\tif (lng > 180) {\r\n\t\tlng = -180 + (lng - 180);\r\n\t}\r\n\tif (lng < -180) {\r\n\t\tlng = 180 - (-180 - lng);\r\n\t}\r\n\treturn lng;\r\n}\r\n\r\nexport function enableLayerIridiumNext() {\r\n\tif (trkData.iridiumnext.isActive) return;\r\n\ttrkData.iridiumnext.isActive = true;\r\n\tstartSatelliteOverlay(\"IridiumNext\");\r\n\t$j(\"#map-layers-list .iridiumnext\").addClass(\"active\");\r\n\tCookies.set(\"layer-iridiumnext\", true, { expires: 365, path: \"/\", secure: true });\r\n}\r\n\r\nexport function enableLayerGlobalstar() {\r\n\tif (trkData.globalstar.isActive) return;\r\n\ttrkData.globalstar.isActive = true;\r\n\tstartSatelliteOverlay(\"Globalstar\");\r\n\t$j(\"#map-layers-list .globalstar\").addClass(\"active\");\r\n\tCookies.set(\"layer-globalstar\", true, { expires: 365, path: \"/\", secure: true });\r\n}\r\n\r\nexport function enableLayerInmarsat() {\r\n\tif (trkData.inmarsat.isActive) return;\r\n\ttrkData.inmarsat.isActive = true;\r\n\tstartSatelliteOverlay(\"Inmarsat\");\r\n\t$j(\"#map-layers-list .inmarsat\").addClass(\"active\");\r\n\tCookies.set(\"layer-inmarsat\", true, { expires: 365, path: \"/\", secure: true });\r\n}\r\n\r\nexport function enableLayerOrbcomm() {\r\n\tif (trkData.orbcomm.isActive) return;\r\n\ttrkData.orbcomm.isActive = true;\r\n\tstartSatelliteOverlay(\"Orbcomm\");\r\n\t$j(\"#map-layers-list .orbcomm\").addClass(\"active\");\r\n\tCookies.set(\"layer-orbcomm\", true, { expires: 365, path: \"/\", secure: true });\r\n}\r\n\r\nexport function enableLayerGeostationary() {\r\n\tif (trkData.geostationary.isActive) return;\r\n\ttrkData.geostationary.isActive = true;\r\n\tstartSatelliteOverlay(\"Geostationary\");\r\n\t$j(\"#map-layers-list .geostationary\").addClass(\"active\");\r\n\tCookies.set(\"layer-geostationary\", true, { expires: 365, path: \"/\", secure: true });\r\n}\r\n\r\nexport function disableLayerIridiumNext() {\r\n\tif (!trkData.iridiumnext.isActive) return;\r\n\ttrkData.iridiumnext.isActive = false;\r\n\tstopSatelliteOverlay(\"IridiumNext\");\r\n\t$j(\"#map-layers-list .iridiumnext\").removeClass(\"active\");\r\n\tCookies.remove(\"layer-iridiumnext\");\r\n}\r\n\r\nexport function disableLayerGlobalstar() {\r\n\tif (!trkData.globalstar.isActive) return;\r\n\ttrkData.globalstar.isActive = false;\r\n\tstopSatelliteOverlay(\"Globalstar\");\r\n\t$j(\"#map-layers-list .globalstar\").removeClass(\"active\");\r\n\tCookies.remove(\"layer-globalstar\");\r\n}\r\n\r\nexport function disableLayerInmarsat() {\r\n\tif (!trkData.inmarsat.isActive) return;\r\n\ttrkData.inmarsat.isActive = false;\r\n\tstopSatelliteOverlay(\"Inmarsat\");\r\n\t$j(\"#map-layers-list .inmarsat\").removeClass(\"active\");\r\n\tCookies.remove(\"layer-inmarsat\");\r\n}\r\n\r\nexport function disableLayerOrbcomm() {\r\n\tif (!trkData.orbcomm.isActive) return;\r\n\ttrkData.orbcomm.isActive = false;\r\n\tstopSatelliteOverlay(\"Orbcomm\");\r\n\t$j(\"#map-layers-list .orbcomm\").removeClass(\"active\");\r\n\tCookies.remove(\"layer-orbcomm\");\r\n}\r\n\r\nexport function disableLayerGeostationary() {\r\n\tif (!trkData.geostationary.isActive) return;\r\n\ttrkData.geostationary.isActive = false;\r\n\tstopSatelliteOverlay(\"Geostationary\");\r\n\t$j(\"#map-layers-list .geostationary\").removeClass(\"active\");\r\n\tCookies.remove(\"layer-geostationary\");\r\n}\r\n\r\nfunction startSatelliteOverlay(constellation) {\r\n\t// map current positions\r\n\tvar dataPost = { constellation: constellation };\r\n\t$j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/GetSatelliteTelemetry\"),\r\n\t\tdata: JSON.stringify(dataPost),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tif (msg.d) {\r\n\t\t\t\tvar result = msg.d;\r\n\t\t\t\tif (result) {\r\n\t\t\t\t\tif (result.Success === false) {\r\n\t\t\t\t\t\thandleWebServiceError(strings.MSG_SATELLITE_ORBIT_ERROR + \" \" + result.ErrorMessage);\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ttrkData.satelliteMarkers[constellation] = [];\r\n\t\t\t\t\ttrkData.satelliteOrbits[constellation] = result.Satellites;\r\n\t\t\t\t\ttrkData.satelliteIndex[constellation] = 1;\r\n\t\t\t\t\t// map the current positions\r\n\t\t\t\t\tfor (var i = 0; i < result.Satellites.length; i++) {\r\n\t\t\t\t\t\tvar sat = result.Satellites[i];\r\n\t\t\t\t\t\tif (sat.Positions == null) {\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (sat.Positions.length == 0) {\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tvar pos = sat.Positions[0];\r\n\t\t\t\t\t\t// wrap locations\r\n\t\t\t\t\t\tvar lat = wrapLat(pos.Lat);\r\n\t\t\t\t\t\tvar lng = wrapLng(pos.Lng);\r\n\t\t\t\t\t\tvar latlng = L.latLng(lat, lng);\r\n\r\n\t\t\t\t\t\tvar icon = L.icon({\r\n\t\t\t\t\t\t\ticonUrl: \"/content/images/marker-satellite-small.png\",\r\n\t\t\t\t\t\t\ticonSize: [20, 20],\r\n\t\t\t\t\t\t\ticonAnchor: [10, 10],\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tvar tooltip = sat.Name;\r\n\t\t\t\t\t\tif (sat.Description != null) {\r\n\t\t\t\t\t\t\ttooltip += \" - \" + sat.Description;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tvar satelliteMarker = L.marker(latlng, {\r\n\t\t\t\t\t\t\ticon: icon,\r\n\t\t\t\t\t\t\t//title: sat.Name\r\n\t\t\t\t\t\t}).bindTooltip(tooltip);\r\n\t\t\t\t\t\taddItemToMap(satelliteMarker);\r\n\t\t\t\t\t\tsat.Marker = satelliteMarker;\r\n\t\t\t\t\t\ttrkData.satelliteMarkers[constellation].push(satelliteMarker);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// set timeout to show the next\r\n\t\t\t\t\tintervals.satelliteInterval[constellation] = setInterval(function () {\r\n\t\t\t\t\t\tnextTelemetryPosition(constellation);\r\n\t\t\t\t\t}, 10000);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {\r\n\t\t\thandleWebServiceError(strings.MSG_SATELLITE_ORBIT_ERROR);\r\n\t\t},\r\n\t});\r\n}\r\n\r\nfunction stopSatelliteOverlay(constellation) {\r\n\tif (trkData.satelliteMarkers[constellation] != null) {\r\n\t\tfor (var j = 0; j < trkData.satelliteMarkers[constellation].length; j++) {\r\n\t\t\tvar marker = trkData.satelliteMarkers[constellation][j];\r\n\t\t\tremoveItemFromMap(marker);\r\n\t\t}\r\n\t}\r\n\tclearInterval(intervals.satelliteInterval[constellation]);\r\n\ttrkData.satelliteIndex[constellation] = 0;\r\n}\r\n\r\nfunction nextTelemetryPosition(constellation) {\r\n\tif (trkData.satelliteIndex[constellation] >= 60) {\r\n\t\t// it's time to requery\r\n\t\tstopSatelliteOverlay(constellation);\r\n\t\tstartSatelliteOverlay(constellation);\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (var i = 0; i < trkData.satelliteOrbits[constellation].length; i++) {\r\n\t\tvar sat = trkData.satelliteOrbits[constellation][i];\r\n\t\tvar pos = sat.Positions[trkData.satelliteIndex[constellation]];\r\n\t\tif (pos == null) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tvar lat = wrapLat(pos.Lat);\r\n\t\tvar lng = wrapLng(pos.Lng);\r\n\t\tvar latlng = L.latLng(lat, lng);\r\n\t\tsat.Marker.setLatLng(latlng);\r\n\t}\r\n\ttrkData.satelliteIndex[constellation]++;\r\n}\r\n","/// Map functionality for wheather radar (& IR, oil, maritime etc) basemap overlays.\r\n\r\nimport trkData from \"./data.js\";\r\nimport log from \"./log.js\";\r\nimport {\r\n\tmap,\r\n\tlayers,\r\n\taddOverlay,\r\n\tremoveOverlay,\r\n\taddLayer,\r\n\tremoveLayer,\r\n\tisOverlayActive,\r\n\tonTileLoaded,\r\n} from \"./map-base.js\";\r\nimport options from \"./options.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport $j from \"jquery\";\r\nimport L from \"leaflet\";\r\nconst Cookies = window.Cookies; // from 'js.cookie.js', v2.2.0\r\n\r\nvar Conv = {\r\n\ttoMercator: function (lat, lng) {\r\n\t\tvar x = (lng * 20037508.34) / 180;\r\n\t\tvar y = Math.log(Math.tan(((90 + lat) * Math.PI) / 360)) / (Math.PI / 180);\r\n\t\ty = (y * 20037508.34) / 180;\r\n\t\treturn L.point(x, y);\r\n\t},\r\n\tpointToLatLng: function (x, y) {\r\n\t\tvar lng = (x / 20037508.34) * 180;\r\n\t\tvar lat = (y / 20037508.34) * 180;\r\n\t\tlat = (180 / Math.PI) * (2 * Math.atan(Math.exp((lat * Math.PI) / 180)) - Math.PI / 2);\r\n\t\treturn L.latLng(lat, lng);\r\n\t},\r\n};\r\n\r\nexport function initMapWeather() {\r\n\tradarOverlay.on(\"tileload\", onTileLoaded(\"radar\"));\r\n\tmaritimeOverlay.on(\"tileload\", onTileLoaded(\"maritime\"));\r\n\toilOverlay.on(\"tileload\", onTileLoaded(\"oil\"));\r\n\r\n\tmap.on(\"load\", onMapLoaded);\r\n}\r\n\r\nconst oilOverlay = L.tileLayer(\r\n\t\"https://gis.boem.gov/arcgis/rest/services/BOEM_BSEE/MMC_Layers/MapServer/export?f=image&dpi=96&bboxSR=102100&imageSR=102100&format=png8&transparent=true&bbox={bbox}&size=256,256&layers=show:7,8,15,11,1,0\",\r\n\t{\r\n\t\tbbox: function (tile) {\r\n\t\t\tvar rect = TileToLocationRect(tile);\r\n\t\t\tvar mbb1 = Conv.toMercator(rect.getSouth(), rect.getWest());\r\n\t\t\tvar mbb2 = Conv.toMercator(rect.getNorth(), rect.getEast());\r\n\t\t\treturn mbb1.x + \",\" + mbb1.y + \",\" + mbb2.x + \",\" + mbb2.y;\r\n\t\t},\r\n\t\tzIndex: 4,\r\n\t}\r\n);\r\n\r\nconst maritimeOverlay = L.tileLayer(\r\n\t\"//gis.charttools.noaa.gov/arcgis/rest/services/MCS/ENCOnline/MapServer/exts/MaritimeChartService/MapServer/export?dpi=96&transparent=true&format=png8&bbox={bbox}&bboxSR=3857&size=256%2C256&f=image&layers=show:2,3,4,5,6,7\",\r\n\t{\r\n\t\tbbox: function (tile) {\r\n\t\t\tvar rect = TileToLocationRect(tile);\r\n\t\t\tvar mbb1 = Conv.toMercator(rect.getSouth(), rect.getWest());\r\n\t\t\tvar mbb2 = Conv.toMercator(rect.getNorth(), rect.getEast());\r\n\t\t\treturn mbb1.x + \",\" + mbb1.y + \",\" + mbb2.x + \",\" + mbb2.y;\r\n\t\t},\r\n\t\tzIndex: 4,\r\n\t}\r\n);\r\n\r\nconst radarAustraliaOverlay = L.tileLayer(\"/services/layer.ashx?type=radar-aus&bbox={bbox}&rnd={time}\", {\r\n\ttime: function (tile) {\r\n\t\treturn new Date().getTime();\r\n\t},\r\n\tbase: function (tile) {\r\n\t\treturn trkData.radarAustralia.basetime;\r\n\t},\r\n\tissue: function (tile) {\r\n\t\treturn trkData.radarAustralia.issuetime;\r\n\t},\r\n\tbbox: function (tile) {\r\n\t\tvar rect = TileToLocationRect(tile);\r\n\t\t//var mbb1 = Conv.toMercator(rect.getSouth(), rect.getWest());\r\n\t\t//var mbb2 = Conv.toMercator(rect.getNorth(), rect.getEast());\r\n\t\treturn rect.getWest() + \",\" + rect.getSouth() + \",\" + rect.getEast() + \",\" + rect.getNorth();\r\n\t},\r\n\tbounds: L.latLngBounds([-7.740789, 108.318991], [-44.235258, 154.901023]),\r\n\tzIndex: 5,\r\n\tminZoom: 3,\r\n});\r\n\r\nconst radarOverlay = L.tileLayer(\r\n\t\"https://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913/{z}/{x}/{y}.png?{time}\",\r\n\t{\r\n\t\ttime: function (tile) {\r\n\t\t\treturn new Date().getTime();\r\n\t\t},\r\n\t\tbounds: L.latLngBounds([71.48, -174.25], [17.0, -51.42]),\r\n\t\tzIndex: 5,\r\n\t}\r\n);\r\n\r\nconst worldCloudOverlay = L.tileLayer(\r\n\t\"https://earthlive.maptiles.arcgis.com/arcgis/rest/services/GOES/GOES31C/MapServer/tile/{z}/{y}/{x}?{time}\",\r\n\t{\r\n\t\ttime: function (tile) {\r\n\t\t\treturn new Date().getTime();\r\n\t\t},\r\n\t\tzIndex: 4,\r\n\t\topacity: 0.4,\r\n\t}\r\n);\r\n\r\nconst seamapOverlay = L.tileLayer(\"https://tiles.openseamap.org/seamark/{z}/{x}/{y}.png?type=google\", {\r\n\tmaxZoom: 18,\r\n\tattribution: \"OpenSeaMap\",\r\n\tzIndex: 4,\r\n});\r\n\r\nexport function refreshWorldIR() {\r\n\tif (isOverlayActive(worldCloudOverlay)) {\r\n\t\t//$j('#radar .loading').show();\r\n\t\tlog(\"World Cloud IR refreshing.\");\r\n\t\tremoveOverlay(worldCloudOverlay);\r\n\t\taddOverlay(worldCloudOverlay);\r\n\t\ttrkData.worldIR.timer = setTimeout(refreshWorldIR, options.worldIRRefreshMinutes * 60 * 1000);\r\n\t} else {\r\n\t\tlog(\"World cloud IR not active\");\r\n\t}\r\n}\r\n\r\nexport function refreshRadar() {\r\n\t// if the radar is enabled, refresh it\r\n\tif (isOverlayActive(radarOverlay)) {\r\n\t\tlog(\"Radar refreshing.\");\r\n\t\tremoveOverlay(radarOverlay);\r\n\t\taddOverlay(radarOverlay);\r\n\t\ttrkData.radar.timer = setTimeout(refreshRadar, options.radarRefreshMinutes * 60 * 1000);\r\n\t} else {\r\n\t\ttrkData.radar.timer = null;\r\n\t\tlog(\"radar not active\");\r\n\t}\r\n}\r\n\r\nexport function refreshRadarAustralia() {\r\n\t// if the radar is enabled, refresh it\r\n\tif (isOverlayActive(radarAustraliaOverlay)) {\r\n\t\tlog(\"Australia Radar refreshing.\");\r\n\t\tremoveOverlay(radarAustraliaOverlay);\r\n\t\taddOverlay(radarAustraliaOverlay);\r\n\t\ttrkData.radarAustralia.timer = setTimeout(refreshRadarAustralia, options.radarRefreshMinutes * 60 * 1000);\r\n\t\t//enableRadarAustralia(true, function () {\r\n\t\t// removeOverlay(radarAustraliaOverlay);\r\n\t\t// addOverlay(radarAustraliaOverlay);\r\n\t\t// trkData.radarAustralia.timer = setTimeout(refreshRadarAustralia, options.radarRefreshMinutes * 60 * 1000);\r\n\t\t//});\r\n\t} else {\r\n\t\ttrkData.radarAustralia.timer = null;\r\n\t\tlog(\"Australia radar not active.\");\r\n\t}\r\n}\r\n\r\nexport function enableLayerWeather(requestData) {\r\n\tif (trkData.weather.isActive) return;\r\n\ttrkData.weather.isActive = true;\r\n\ttrkData.weather.layer = L.geoJSON(null, {\r\n\t\tstyle: function (feature) {},\r\n\t\tonEachFeature: function (feature, layer) {\r\n\t\t\tif (feature.properties != null) {\r\n\t\t\t\tif (feature.properties.city != null) {\r\n\t\t\t\t\tif (feature.properties.temperature != null) {\r\n\t\t\t\t\t\t//var tooltipIcon = ' ';\r\n\t\t\t\t\t\tvar tooltip =\r\n\t\t\t\t\t\t\t\"\" +\r\n\t\t\t\t\t\t\tfeature.properties.city +\r\n\t\t\t\t\t\t\t\" \" +\r\n\t\t\t\t\t\t\t\" \" +\r\n\t\t\t\t\t\t\tfeature.properties.temperature +\r\n\t\t\t\t\t\t\t\"°C\" +\r\n\t\t\t\t\t\t\t\" \" +\r\n\t\t\t\t\t\t\tfeature.properties.weather;\r\n\t\t\t\t\t\tlayer.bindPopup(tooltip);\r\n\t\t\t\t\t\tlayer.bindTooltip(tooltip);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t\tpointToLayer: function (feature, latlng) {\r\n\t\t\tif (feature.properties != undefined && feature.properties.icon != undefined) {\r\n\t\t\t\tvar icon = L.icon({\r\n\t\t\t\t\ticonUrl: feature.properties.icon,\r\n\t\t\t\t\ticonSize: [50, 50],\r\n\t\t\t\t\ticonAnchor: [25, 25],\r\n\t\t\t\t\ttooltipAnchor: [25, 0],\r\n\t\t\t\t\tpopupAnchor: [0, -25],\r\n\t\t\t\t});\r\n\t\t\t\treturn L.marker(latlng, { icon: icon });\r\n\t\t\t}\r\n\t\t\treturn L.marker(latlng);\r\n\t\t},\r\n\t});\r\n\r\n\tif (requestData) {\r\n\t\tcheckWeatherForecast();\r\n\t}\r\n\taddLayer(trkData.weather.layer);\r\n\t$j(\"#map-layers-list .weather\").addClass(\"active\");\r\n\tCookies.set(\"layer-weather\", true, { expires: 365, path: \"/\", secure: true });\r\n}\r\n\r\nexport function disableLayerWeather() {\r\n\tif (!trkData.weather.isActive) return;\r\n\tremoveLayer(trkData.weather.layer);\r\n\ttrkData.weather.isActive = false;\r\n\t$j(\"#map-layers-list .weather\").removeClass(\"active\");\r\n\tCookies.remove(\"layer-weather\");\r\n}\r\n\r\nexport function disableLayerClouds() {\r\n\tif (!trkData.clouds.isActive) return;\r\n\tremoveLayer(layers.clouds);\r\n\ttrkData.clouds.isActive = false;\r\n\t$j(\"#map-layers-list .clouds\").removeClass(\"active\");\r\n\tCookies.remove(\"layer-clouds\");\r\n}\r\n\r\nexport function enableLayerClouds() {\r\n\tif (trkData.clouds.isActive) return;\r\n\taddLayer(layers.clouds);\r\n\ttrkData.clouds.isActive = true;\r\n\t$j(\"#map-layers-list .clouds\").addClass(\"active\");\r\n\tCookies.set(\"layer-clouds\", true, { expires: 365, path: \"/\", secure: true });\r\n}\r\n\r\nexport function enableLayerOil() {\r\n\tif (trkData.oil.isActive) return;\r\n\r\n\ttrkData.oil.isActive = true;\r\n\taddOverlay(oilOverlay);\r\n\t$j(\"#map-layers-list .oil\").addClass(\"active\");\r\n\tCookies.set(\"layer-oil\", true, { expires: 365, path: \"/\", secure: true });\r\n}\r\n\r\nexport function disableLayerOil() {\r\n\tif (!trkData.oil.isActive) return;\r\n\ttrkData.oil.isActive = false;\r\n\tremoveOverlay(oilOverlay);\r\n\t$j(\"#map-layers-list .oil\").removeClass(\"active\");\r\n\tCookies.remove(\"layer-oil\");\r\n}\r\n\r\nexport function enableLayerMaritime() {\r\n\tif (trkData.maritime.isActive) return;\r\n\r\n\ttrkData.maritime.isActive = true;\r\n\taddOverlay(maritimeOverlay);\r\n\t$j(\"#map-layers-list .maritime\").addClass(\"active\");\r\n\tCookies.set(\"layer-maritime\", true, { expires: 365, path: \"/\", secure: true });\r\n}\r\n\r\nexport function disableLayerMaritime() {\r\n\tif (!trkData.maritime.isActive) return;\r\n\ttrkData.maritime.isActive = false;\r\n\tremoveOverlay(maritimeOverlay);\r\n\t$j(\"#map-layers-list .maritime\").removeClass(\"active\");\r\n\tCookies.remove(\"layer-maritime\");\r\n}\r\n\r\nexport function enableWorldIR() {\r\n\tif (trkData.worldIR.isActive) return;\r\n\r\n\ttrkData.worldIR.isActive = true;\r\n\taddOverlay(worldCloudOverlay);\r\n\ttrkData.worldIR.timer = setTimeout(refreshWorldIR, options.worldIRRefreshMinutes * 60 * 1000);\r\n\t$j(\"#map-layers-list .worldIR\").addClass(\"active\");\r\n\tCookies.set(\"worldIR\", true, { expires: 365, path: \"/\", secure: true });\r\n}\r\n\r\nexport function disableWorldIR() {\r\n\tif (!trkData.worldIR.isActive) return;\r\n\ttrkData.worldIR.isActive = false;\r\n\tclearTimeout(trkData.worldIR.timer);\r\n\tremoveOverlay(worldCloudOverlay);\r\n\r\n\tCookies.remove(\"worldIR\");\r\n\t$j(\"#map-layers-list .worldIR\").removeClass(\"active\");\r\n}\r\n\r\nexport function enableRadar() {\r\n\tif (trkData.radar.isActive) return;\r\n\r\n\ttrkData.radar.isActive = true;\r\n\taddOverlay(radarOverlay);\r\n\t// use setInterval instead\r\n\ttrkData.radar.timer = setTimeout(refreshRadar, options.radarRefreshMinutes * 60 * 1000);\r\n\t//$j('#radar a').addClass('active');\r\n\t$j(\"#map-layers-list .radar\").addClass(\"active\");\r\n\t$j(\"#legend_radar\").show();\r\n\tCookies.set(\"radar\", true, { expires: 365, path: \"/\", secure: true });\r\n}\r\n\r\nexport function disableRadar() {\r\n\tif (!trkData.radar.isActive) return;\r\n\ttrkData.radar.isActive = false;\r\n\tclearTimeout(trkData.radar.timer);\r\n\tremoveOverlay(radarOverlay);\r\n\tCookies.remove(\"radar\");\r\n\t$j(\"#legend_radar\").hide();\r\n\t$j(\"#map-layers-list .radar\").removeClass(\"active\");\r\n}\r\n\r\nexport function enableRadarAustraliaActive() {\r\n\tif (trkData.radarAustralia.isActive) return;\r\n\ttrkData.radarAustralia.isActive = true;\r\n\taddOverlay(radarAustraliaOverlay);\r\n\t// use setInterval instead\r\n\ttrkData.radarAustralia.timer = setTimeout(refreshRadarAustralia, options.radarRefreshMinutes * 60 * 1000);\r\n\t$j(\"#map-layers-list .radar-australia\").addClass(\"active\");\r\n\t$j(\"#legend_radar\").show();\r\n\tCookies.set(\"radar-australia\", true, { expires: 365, path: \"/\", secure: true });\r\n}\r\n\r\nexport function disableRadarAustralia() {\r\n\tif (!trkData.radarAustralia.isActive) {\r\n\t\treturn;\r\n\t}\r\n\ttrkData.radarAustralia.isActive = false;\r\n\tclearTimeout(trkData.radarAustralia.timer);\r\n\tremoveOverlay(radarAustraliaOverlay);\r\n\tCookies.remove(\"radar-australia\");\r\n\t$(\"#legend_radar\").hide();\r\n\t$(\"#map-layers-list .radar-australia\").removeClass(\"active\");\r\n}\r\n\r\nexport function checkWeatherForecast() {\r\n\tif (!trkData.weather.isActive) return;\r\n\tif (trkData.weather.gettingData) {\r\n\t\tif (trkData.weather.request != null) {\r\n\t\t\ttrkData.weather.request.abort();\r\n\t\t}\r\n\t\ttrkData.weather.gettingData = false;\r\n\t}\r\n\tgetWeatherForecast();\r\n}\r\n\r\nexport function getWeatherForecast() {\r\n\tvar bounds = map.getBounds();\r\n\tvar NE = bounds.getNorthEast();\r\n\tvar SW = bounds.getSouthWest();\r\n\tvar northLat = NE.lat;\r\n\tvar eastLng = NE.lng;\r\n\tvar southLat = SW.lat;\r\n\tvar westLng = SW.lng;\r\n\ttrkData.weather.gettingData = true;\r\n\tvar url =\r\n\t\t\"https://api.openweathermap.org/data/2.5/box/city?bbox=\" +\r\n\t\twestLng +\r\n\t\t\",\" +\r\n\t\tnorthLat +\r\n\t\t\",\" + //left top\r\n\t\teastLng +\r\n\t\t\",\" +\r\n\t\tsouthLat +\r\n\t\t\",\" + //right bottom\r\n\t\tmap.getZoom() +\r\n\t\t\"&cluster=yes&format=json\" +\r\n\t\t\"&APPID=\" +\r\n\t\t\"551b97ca557560dfc7d8c49a81b37d89\";\r\n\ttrkData.weather.request = $j.ajax({\r\n\t\ttype: \"GET\",\r\n\t\turl: wrapUrl(url),\r\n\t\tdataType: \"json\",\r\n\t\tcontentType: false,\r\n\t\tsuccess: function (results) {\r\n\t\t\tconsole.log(results);\r\n\t\t\tif (results == null) return;\r\n\t\t\tif (results.list == null) return;\r\n\t\t\tif (results.list.length > 0) {\r\n\t\t\t\t// reset data\r\n\t\t\t\ttrkData.weather.geoJSON = {\r\n\t\t\t\t\ttype: \"FeatureCollection\",\r\n\t\t\t\t\tfeatures: [],\r\n\t\t\t\t};\r\n\r\n\t\t\t\t// clear the prior set of data\r\n\t\t\t\ttrkData.weather.layer.clearLayers();\r\n\r\n\t\t\t\tfor (var i = 0; i < results.list.length; i++) {\r\n\t\t\t\t\ttrkData.weather.geoJSON.features.push(forecastJsonToGeoJson(results.list[i]));\r\n\t\t\t\t}\r\n\t\t\t\ttrkData.weather.layer.addData(trkData.weather.geoJSON);\r\n\t\t\t\ttrkData.weather.gettingData = false;\r\n\t\t\t}\r\n\t\t},\r\n\t\terror: function () {\r\n\t\t\ttrkData.weather.gettingData = false;\r\n\t\t},\r\n\t});\r\n}\r\n\r\nexport function forecastJsonToGeoJson(weatherItem) {\r\n\tvar feature = {\r\n\t\ttype: \"Feature\",\r\n\t\tproperties: {\r\n\t\t\tcity: weatherItem.name,\r\n\t\t\tweather: weatherItem.weather[0].main,\r\n\t\t\ttemperature: weatherItem.main.temp,\r\n\t\t\tmin: weatherItem.main.temp_min,\r\n\t\t\tmax: weatherItem.main.temp_max,\r\n\t\t\thumidity: weatherItem.main.humidity,\r\n\t\t\tpressure: weatherItem.main.pressure,\r\n\t\t\twindSpeed: weatherItem.wind.speed,\r\n\t\t\twindDegrees: weatherItem.wind.deg,\r\n\t\t\twindGust: weatherItem.wind.gust,\r\n\t\t\ticon: \"https://openweathermap.org/img/w/\" + weatherItem.weather[0].icon + \".png\",\r\n\t\t\tcoordinates: [weatherItem.coord.Lon, weatherItem.coord.Lat],\r\n\t\t},\r\n\t\tgeometry: {\r\n\t\t\ttype: \"Point\",\r\n\t\t\tcoordinates: [weatherItem.coord.Lon, weatherItem.coord.Lat],\r\n\t\t},\r\n\t};\r\n\t//// Set the custom marker icon\r\n\t//trkData.weather.layer.setStyle(function(feature) {\r\n\t// return {\r\n\t// icon: {\r\n\t// url: wrapUrl(feature.getProperty('icon')),\r\n\t// anchor: new google.maps.Point(25, 25)\r\n\t// }\r\n\t// };\r\n\t//});\r\n\t// returns object\r\n\treturn feature;\r\n}\r\n\r\nfunction TileToLocationRect(tile) {\r\n\tvar mapSize = Math.pow(2, tile.z);\r\n\tvar west = (tile.x * 360) / mapSize - 180;\r\n\tvar east = ((tile.x + 1) * 360) / mapSize - 180;\r\n\r\n\tvar efactor = Math.exp((0.5 - tile.y / mapSize) * 4 * Math.PI);\r\n\tvar north = Math.asin((efactor - 1) / (efactor + 1)) * (180 / Math.PI);\r\n\r\n\tefactor = Math.exp((0.5 - (tile.y + 1) / mapSize) * 4 * Math.PI);\r\n\tvar south = Math.asin((efactor - 1) / (efactor + 1)) * (180 / Math.PI);\r\n\tvar rect = L.latLngBounds(L.latLng(north, west), L.latLng(south, east));\r\n\treturn rect;\r\n}\r\n\r\nfunction onMapLoaded() {\r\n\tif (Cookies.get(\"radar\") !== undefined || $j.inArray(\"radar\", options.enableLayers) !== -1) {\r\n\t\tenableRadar();\r\n\t}\r\n\r\n\tif (Cookies.get(\"radar-australia\") !== undefined || $j.inArray(\"radar-australia\", options.enableLayers) !== -1) {\r\n\t\t//enableRadarAustralia(false, enableRadarAustraliaActive);\r\n\t\tenableRadarAustraliaActive();\r\n\t}\r\n\r\n\tif (Cookies.get(\"worldIR\") !== undefined || $j.inArray(\"worldIR\", options.enableLayers) !== -1) {\r\n\t\tenableWorldIR();\r\n\t}\r\n\r\n\tif (Cookies.get(\"layer-oil\") !== undefined || $j.inArray(\"oil\", options.enableLayers) !== -1) {\r\n\t\tenableLayerOil();\r\n\t}\r\n\r\n\tif (Cookies.get(\"layer-maritime\") !== undefined || $j.inArray(\"maritime\", options.enableLayers) !== -1) {\r\n\t\tenableLayerMaritime();\r\n\t}\r\n\r\n\tif (Cookies.get(\"layer-weather\") !== undefined || $j.inArray(\"weather\", options.enableLayers) !== -1) {\r\n\t\tenableLayerWeather(false);\r\n\t}\r\n\r\n\tif (Cookies.get(\"layer-clouds\") !== undefined || $j.inArray(\"clouds\", options.enableLayers) !== -1) {\r\n\t\tenableLayerClouds();\r\n\t}\r\n}\r\n","import { mapModes, panels } from \"./const.js\";\r\nimport state from \"./state.js\";\r\nimport options from \"./options.js\";\r\n\r\nexport function setUrlHistoryForActivePanel(panelAction) {\r\n\tvar action = \"\";\r\n\tvar defaultAction = \" \";\r\n\tif (panelAction !== undefined) {\r\n\t\taction = \"/\" + panelAction;\r\n\t\tdefaultAction = \"#\" + panelAction;\r\n\t}\r\n\tvar modeText =\r\n\t\tstate.activeMapMode === null ? options.defaultMode : state.activeMapMode === mapModes.HISTORY ? \"history\" : \"live\";\r\n\tswitch (state.activePanel) {\r\n\t\tcase panels.ASSETS:\r\n\t\t\thistory.replaceState(\"panel-active\", \"\", \"#\" + modeText + \"/assets\" + action);\r\n\t\t\tbreak;\r\n\t\tcase panels.GEOFENCES:\r\n\t\t\thistory.replaceState(\"panel-active\", \"\", \"#\" + modeText + \"/fences\" + action);\r\n\t\t\tbreak;\r\n\t\tcase panels.PLACES:\r\n\t\t\thistory.replaceState(\"panel-active\", \"\", \"#\" + modeText + \"/places\" + action);\r\n\t\t\tbreak;\r\n\t\tcase panels.JOURNEYS:\r\n\t\t\thistory.replaceState(\"panel-active\", \"\", \"#\" + modeText + \"/journeys\" + action);\r\n\t\t\tbreak;\r\n\t\tcase panels.SHARED_VIEWS:\r\n\t\t\thistory.replaceState(\"panel-active\", \"\", \"#\" + modeText + \"/shared-views\" + action);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\thistory.replaceState(\"panel-active\", \"\", defaultAction);\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n","import user from \"./user.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport { throttles } from \"./timers.js\";\r\n\r\nimport $j from \"jquery\";\r\n\r\nexport let version = \"\";\r\n\r\nexport function overrideVersion(v) {\r\n\tversion = v;\r\n}\r\n\r\nexport function checkVersion() {\r\n\t$j.ajax({\r\n\t\ttype: \"POST\",\r\n\t\turl: wrapUrl(\"/services/GPSService.asmx/GetStatus\"),\r\n\t\tcontentType: \"application/json; charset=utf-8\",\r\n\t\tdataType: \"json\",\r\n\t\tsuccess: function (msg) {\r\n\t\t\tvar resp = msg.d;\r\n\t\t\tif (version != resp.Version || user.id != resp.UserId) {\r\n\t\t\t\tvar reloadTime = Math.floor(Math.random() * 300000);\r\n\t\t\t\tconsole.log(\r\n\t\t\t\t\t\"User or version mismatch. Version: \" +\r\n\t\t\t\t\t\tversion +\r\n\t\t\t\t\t\t\" vs \" +\r\n\t\t\t\t\t\tresp.Version +\r\n\t\t\t\t\t\t\". User: \" +\r\n\t\t\t\t\t\tuser.id +\r\n\t\t\t\t\t\t\" vs \" +\r\n\t\t\t\t\t\tresp.UserId +\r\n\t\t\t\t\t\t\". Reloading in \" + (reloadTime / 1000) + \"s.\"\r\n\t\t\t\t);\r\n\t\t\t\t// don't redirect immediately because this browser session could be the one initiating the logout and will naturally redirect\r\n\t\t\t\tsetTimeout(function () {\r\n\t\t\t\t\tlocation.reload(true);\r\n\t\t\t\t}, reloadTime);\r\n\t\t\t} else {\r\n\t\t\t\tconsole.log(\"Portal status check valid.\");\r\n\t\t\t}\r\n\t\t},\r\n\t\terror: function (xhr, status, error) {},\r\n\t});\r\n\tthrottles.updatePositionStatus();\r\n}\r\n","import strings from \"./strings.js\";\r\nimport trkData from \"./data.js\";\r\nimport domNodes from \"./domNodes.js\";\r\nimport log from \"./log.js\";\r\nimport { findAssetById } from \"./assets.js\";\r\nimport { formShowSuccessMessage } from \"./ajax.js\";\r\nimport { handleWebServiceError } from \"./ajax.js\";\r\nimport user from \"./user.js\";\r\nimport { wrapUrl } from \"./wrapurl.js\";\r\nimport { loadDialogButtons, closeButton } from \"./modal-dialog-buttons.js\";\r\nimport { getPositionLinkForEvent } from \"./positions.js\";\r\nimport { openDialogPanel } from \"./panel-nav.js\";\r\nimport { handleAjaxFormSubmission, toggleLoadingMessage } from \"./ajax.js\";\r\nimport { closeSecondaryPanel } from \"./panel.js\";\r\n\r\nimport $ from \"jquery\";\r\nimport $j from \"jquery\";\r\nimport _ from \"lodash\";\r\nimport { el, text } from \"redom\"; // https://redom.js.org/\r\n\r\nexport function initAlerts() {\r\n\t// unused TODO: remove\r\n\t$(\"#alert-data\").DataTable({\r\n\t\tdestroy: true,\r\n\t\tfilter: false,\r\n\t\tinfo: true,\r\n\t\tjQueryUI: true,\r\n\t\tautoWidth: false,\r\n\t\tlengthChange: false,\r\n\t\tpaging: true,\r\n\t\tpagingType: \"full_numbers\",\r\n\t\tdeferRender: true,\r\n\t\tprocessing: false,\r\n\t\torder: [[1, \"desc\"]],\r\n\t\tcolumns: [\r\n\t\t\t{ sortable: false, width: \"40px\" }, // Color Display\r\n\t\t\t{ sortable: true }, // Priority\r\n\t\t\t{ sortable: true }, // Asset\r\n\t\t\t{ sortable: true }, // Type\r\n\t\t\t{ sortable: false }, // Description\r\n\t\t\t{ sortable: false }, // Resolution Procedure\r\n\t\t\t{ sortable: false }, // Position/lat/lng\r\n\t\t\t//{ sortable: false }, // Details/link\r\n\t\t\t{ width: \"75px\" }, // Time\r\n\t\t\t{ sortable: false, class: \"center\" }, // Acknowledge\r\n\t\t\t{ visible: false }, // AssetId (hidden)\r\n\t\t\t{ visible: false }, // Event Type Id\r\n\t\t\t{ visible: false }, // Color\r\n\t\t],\r\n\t\tdom: '<\"H\"lfr>t<\"F\"ip>',\r\n\t\tlanguage: strings.DATATABLE,\r\n\t\tinitComplete: function (oSettings, json) {\r\n\t\t\tvar api = this.api();\r\n\t\t\tlog(\"Alerts table initialized.\");\r\n\t\t\t$j(\"#alert-data\").data(\"init\", true);\r\n\t\t\ttrkData.alerts = [];\r\n\t\t\tqueryAlertsRequiringAcknowledgement(null);\r\n\t\t\tapi.clear();\r\n\t\t},\r\n\t\tdrawCallback: function (oSettings) {\r\n\t\t\tvar api = this.api();\r\n\t\t\tvar rowCount = api.rows({ search: \"applied\" }).eq(0).length;\r\n\t\t\tif (rowCount > 0) {\r\n\t\t\t\t$j(\"#alerts-control-btn a .badge,#event-panel-tab-alerts .badge\")\r\n\t\t\t\t\t.text(rowCount)\r\n\t\t\t\t\t.addClass(\"active\")\r\n\t\t\t\t\t.removeClass(\"inactive\");\r\n\t\t\t} else {\r\n\t\t\t\t$j(\"#alerts-control-btn a .badge,#event-panel-tab-alerts .badge\")\r\n\t\t\t\t\t.text(rowCount)\r\n\t\t\t\t\t.removeClass(\"active\")\r\n\t\t\t\t\t.addClass(\"inactive\");\r\n\t\t\t}\r\n\r\n\t\t\t//$j('#alerts-control-btn a,#event-panel-tab-alerts').text(strings.ALERTS_HEADER.replace('{0}', api.rows({ search: 'applied' }).eq(0).length));\r\n\r\n\t\t\t//$j('.AlertAcknowledge').button({ text: null, icons: { primary: 'ui-icon-check' } });\r\n\t\t},\r\n\t\trowCallback: function (row, data, index) {\r\n\t\t\tif (data[11] != \"\") {\r\n\t\t\t\t$j(\"td:eq(0)\", row).css(\"background-color\", data[11]);\r\n\t\t\t}\r\n\t\t},\r\n\t});\r\n\r\n\tvar acknowledgeAlertButtons = [\r\n\t\t{\r\n\t\t\tid: \"AcknowledgeDialog\",\r\n\t\t\ttext: strings.ACKNOWLEDGE,\r\n\t\t\tclick: function () {\r\n\t\t\t\tacknowledgeAssetAlert(this, true);\r\n\t\t\t},\r\n\t\t},\r\n\t\t{\r\n\t\t\tid: \"AcknowledgeAltDialog\",\r\n\t\t\tbuttonType: \"secondary\",\r\n\t\t\tclass: \"alert-acknowledge-alt\",\r\n\t\t\ttext: strings.ACKNOWLEDGE_ALT,\r\n\t\t\tclick: function () {\r\n\t\t\t\tacknowledgeAssetAlert(this, true);\r\n\t\t\t},\r\n\t\t},\r\n\t\tcloseButton,\r\n\t];\r\n\tloadDialogButtons(domNodes.dialogs.acknowledgeAlert, acknowledgeAlertButtons);\r\n\t$(domNodes.dialogs.acknowledgeAlert).on(\"click\", \"#alert-prev\", function (e) {\r\n\t\te.preventDefault();\r\n\t\topenAlertInDialog(-1);\r\n\t});\r\n\t$(domNodes.dialogs.acknowledgeAlert).on(\"click\", \"#alert-next\", function (e) {\r\n\t\te.preventDefault();\r\n\t\topenAlertInDialog(1);\r\n\t});\r\n\r\n\t$(\"#panel-secondary\").on(\"click\", \"button.alert-acknowledge,button.alert-acknowledge-alt\", function (e) {\r\n\t\te.preventDefault();\r\n\t\tacknowledgeAssetAlert(this, false);\r\n\t});\r\n\r\n\t$j(domNodes.infoDialogs.mapItemInformation).on(\"click\", \"button.AlertAcknowledge\", function (e) {\r\n\t\te.preventDefault();\r\n\r\n\t\tacknowledgeAssetAlert(this, false);\r\n\t});\r\n\r\n\t$j(domNodes.infoDialogs.mapItemInformation).on(\"click\", \"button.AlertAcknowledgeAlt\", function (e) {\r\n\t\te.preventDefault();\r\n\r\n\t\tacknowledgeAssetAlert(this, false);\r\n\t});\r\n\r\n\tlet assetsContainer = $j(\"#panel-content-wrapper\");\r\n\r\n\tassetsContainer.on(\"click\", \"svg.asset-alert\", function (e) {\r\n\t\te.preventDefault();\r\n\r\n\t\tvar asset = findAssetById(parseInt(this.getAttribute(\"data-asset-id\")));\r\n\t\tif (asset == null) return;\r\n\t\tvar alert = null;\r\n\t\tfor (var i = 0; i < trkData.alerts.length; i++) {\r\n\t\t\tif (trkData.alerts[i].AssetId == asset.Id) {\r\n\t\t\t\talert = trkData.alerts[i];\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (alert == null) return;\r\n\t\topenAcknowledgeAlertDialog(asset, alert);\r\n\t\t//openAlertsRequiringAcknowledgementDialog(alt);\r\n\t});\r\n}\r\n\r\nfunction updateAlertDialog(event) {\r\n\tvar form = document.getElementById(\"acknowledge-form\");\r\n\tvar currentEventId = parseInt(form.getAttribute(\"data-event-id\"));\r\n\tvar currentAssetId = parseInt(form.getAttribute(\"data-asset-id\"));\r\n\tvar currentIndex = parseInt(form.getAttribute(\"data-index\"));\r\n\r\n\tvar asset = findAssetById(currentAssetId);\r\n\tif (asset === null) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar assetAlerts = _.filter(trkData.alerts, function (evt) {\r\n\t\treturn evt.AssetId === asset.Id;\r\n\t});\r\n\tif (event.Id === currentEventId) {\r\n\t\t// the currently opened event was acknowledged\r\n\t\t// move to the next one, if available, with an acknowledged status\r\n\t\t// and show a no more if not\r\n\t\tif (assetAlerts.length === 0) {\r\n\t\t\t// no more events requiring acknowledgement for the asset\r\n\t\t\tvar none = document.getElementById(\"asset-acknowledge-alerts-none\");\r\n\t\t\tnone.classList.add(\"is-visible\");\r\n\t\t\tform.classList.remove(\"is-visible\");\r\n\t\t} else {\r\n\t\t\tvar newIndex = currentIndex;\r\n\t\t\tif (currentIndex > assetAlerts.length) {\r\n\t\t\t\tnewIndex = assetAlerts.length;\r\n\t\t\t}\r\n\t\t\tvar event = assetAlerts[newIndex - 1];\r\n\t\t\tif (event !== undefined && event !== null) {\r\n\t\t\t\topenAcknowledgeAlertDialog(asset, event);\r\n\r\n\t\t\t\t// persist acknowledged message\r\n\t\t\t\tformShowSuccessMessage(form.querySelector(\".dialog-status\"), strings.MSG_ALERT_ACKNOWLEDGE_SUCCESS);\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tif (event.AssetId === currentAssetId) {\r\n\t\t\t// number of events is updated, update the indexes shown\r\n\t\t\tvar currentEvent = _.find(assetAlerts, { Id: currentEventId });\r\n\t\t\tpopulateAssetAlertIndex(asset, currentEvent);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction confirmAlert(event) {\r\n\tlog(\"Confirming alert.\");\r\n\tvar isInAlertsListing = false;\r\n\tfor (var i = 0; i < trkData.alerts.length; i++) {\r\n\t\tif (event.Id === trkData.alerts[i].Id) {\r\n\t\t\ttrkData.alerts.splice(i, 1);\r\n\t\t\tisInAlertsListing = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// update dialogs, if they are open\r\n\tupdateAlertDialog(event);\r\n\r\n\t// update position information dialog (if exists)\r\n\tvar form = $(\"#AcknowledgeAlert\" + event.Id + \",#asset-alert-acknowledge-\" + event.Id);\r\n\tif (form.length) {\r\n\t\t$(\"div.alert-resolution\", form)\r\n\t\t\t.empty()\r\n\t\t\t.append(\r\n\t\t\t\t$('