{"version":3,"file":"stwo_app.min.js","sources":["../tmp/stwo_app-core.js","../tmp/stwo_app-glue.js","../tmp/stwo_alarmmanager-modules.js"],"names":["angular","module","filter","obj","fields","s","recursiveGet","ob","remStr","indexOf","k","substring","length","bar","hasOwnProperty","arr","prop","value","outArr","n","push","str","replace","floatNumber","opts","Math","round","String","run","FastClick","attach","document","body","provider","_modules","_links","_categories","_rootLinks","_states","missingCustomer","notLoggedIn","_notificationHandlers","_serviceRepository","_possibleFiltersPerClazz","_flags","this","hasAccess","link","accessMap","categoryDependency","access","category","hasController","controllerName","controllers","_","removeLink","linkIndex","splice","registerLink","stwoGlobal","linkCategoryOverride","id","place","sort","console","log","registerModule","moduleInfo","categories","categoryExists","name","links","notificationHandlers","modules","flags","states","getPossibleFiltersForClazz","clazz","addPossibleFilter","JSON","stringify","stateDependentLinks","currentState","scope","l","n2","r","n3","a","b","serviceRepository","linksOfCategory","linkList","rootLinks","minimumAccess","moduleAccessOverride","$get","defaultLanguage","localStorage","find","availableLanguages","lang","code","factory","$interval","i","timers","intervals","one","five","ten","twenty","thirty","sixty","onetwenty","threehundred","lastUpdate","now","Date","getTime","interval","$translate","$filter","translations","then","data","hour","hours","minute","minutes","timeTemplate","today","clone","copy","constructor","attr","isResponseValid","response","checkLength","result","getFormattedDateFromTimestamp","date","todayLength","dd","moment","tz","retD","toDate","checkNestedProperty","object","args","Array","prototype","slice","call","arguments","$http","$location","$q","moduleStore","pushService","decorationService","amMoment","deploymentApiService","socketioService","baseUrlApi","baseUrl","smarttrackerUrl","user","token","customer","availableCustomers","availableProviders","accessRights","customerData","tokens","_language","storedTokens","parse","deferredLoginData","login","started","done","promises","url","language","languageCode","use","amLocale","amLocaleRewrites","no","changeLocale","isLoggedInDelayed","defer","isLoggedIn","resolve","promise","reject","urlToken","search","addUser","username","persist","selectUser","history","pushState","window","title","absUrl","disableRememberUser","persistUsers","tokensToPersist","userInfo","removeUser","getUsers","getLoggedInUser","getCustomerId","getProviderId","getAvailableCustomers","getAccessRights","getAvailableProviders","changeProvider","newProviderId","method","headers","X-Auth-Token","get","clear","updateUserData","changeCustomer","newCustomerId","Promise","renew","xsrf","password","replacementPassword","undefined","Content-Type","suppliedToken","doNotRedirect","setItem","tokenNotFound","path","refreshUser","getUserData","isAlarmCenter","alarmCenter","fromJson","toJson","customers","providers","userLanguage","languageAmongDefined","configure","reconnect","refresh","poll","logout","disconnect","getToken","authGet","onErrorDoNotRedirect","authPost","post","authPut","put","authDelete","ps_key","isPushSubscriptionEnabled","togglePushSubscription","getAuthToken","$timeout","onOpen","evt","onClose","pushShouldBeConnected","waitingForReconnect","onMessage","pushEnabled","nextHarvestedMessages","messageSoFar","err","onError","ws","harvestedMessages","pushChanged","counter","listeners","util","mergeState","tags","properties","mergePosition","position","valid","lastValidPosition","latitude","longitude","floor","address","textual","accuracy","observation","lastPosition","insideZones","timestamp","location","locationId","coordinate","listen","processFn","processNewPushMessages","m","process","changed","protocol","toLowerCase","hostname","port","readyState","enabled","newPushEnabledValue","WebSocket","onopen","onclose","onmessage","onerror","close","callbacks","state","connected","connecting","authenticated","connect","smarttrackerService","socket","io","deploymentApiUrl","transports","on","onConnect","onAuthenticated","onSubscribe","onUnsubscribe","isConnected","isAuthenticated","subscribe","objectName","callback","setTimeout","emit","unsubscribe","message","max","updateInProgress","TIMESTAMP_KEY","OVERLAYS_KEY","OVERLAYS_CID_KEY","reloadOverlays","offset","elements","fn","e","concat","total","getOverlays","overlayService","availableLayers","osm","type","transitionEffect","layerParams","maxZoom","maxNativeZoom","attribution","_chosenLayer","getAvailableLayers","chosenLayer","layerCode","basicMapDesign","leafletData","mapId","layers","baselayers","savedCenters","osloCenter","lat","lng","zoom","navigator","geolocation","getCurrentPosition","coords","getMap","map","layersToDelete","SELECTED_OVERLAY_KEY","selectedOverlayLevel","loadOverlays","level","overlaysList","overlayLayer","setLevel","L","layerGroup","overlay","addTo","makeNamedIcon","color","icon","colorDark","micon","divIcon","iconAnchor","className","html","popupAnchor","cache","scrubbedOfAngularVars","putMany","idField","f","downloadCache","beginDownloading","initialPromise","cacheId","expiry","timeToLive","inProgress","downloadPromise","doDownload","cacheData","download","fromCache","invalidate","urlPrefix","moduleId","out","$state","utilService","ignored","dismissed","added","updated","removed","audio","muted","snoozed","ignoreSnooze","notifications","sounds","file","add","notification","dismiss","view","Push","create","timeout","onClick","focus","go","alarmId","time","remove","silentDismiss","notificationId","snooze","u","ignore","dismissFunction","notificationsHandlers","alert","list","undismissed","getSounds","checkSoundData","soundData","ret","redAlarmSound","sound","orangeAlarmSound","greenAlarmSound","cpAlarmSound","customNotifications","ceMetaKey","registerNotification","params","preferences","meta","ev","createdDate","utc","format","messageValues","saveCustomNotifications","dismissCustomNotification","preventSave","index","dismissCustomNotifiactionsForObject","cn","forEach","notificationTypes","invitation","$localStorage","favorites","favorite","favoritesOfClazz","toggle","isFavorite","getListOfFavorites","outArray","service","toUpper","item","toUpperCase","alarmColor","danger","warning","success","logLevelFormatted","rangeColor","source","googleMaps","addressString","encodeURIComponent","isiOS","stwoPushNotificationInfo","test","userAgent","MSStream","assign","indoor","icons","$modal","prompt","text","config","cfg","open","templateUrl","controller","stwoCoreDialogPromptModalController","size","promptConfiguration","raiseAlarm","stwoCoreDialogRaiseAlarmModalController","getPosition","v","stwoCoreDialogPositionPickerModalController","stwoDialogAlertModalController","configuration","wait","showWaitButtons","$scope","$modalInstance","multiline","disablePromptText","nullAllowed","promptText","placeHolder","cancelButtonText","cancelButton","okButtonText","nullButtonText","emptyRestricted","deleteButtonText","deleteButton","cancelDisallowed","genericData","pickNull","ok","cancel","mapService","addressService","paths","TCAString","addressSelected","pos","point","setView","marker","setLatLng","createMarker","loc","Marker","draggable","mapData","center","defaults","dragging","events","enable","logic","customerMapData","LatLng","latlng","addressByCoordinates","road","house_number","county","postcode","country_code","error","invalidateSize","getLatLng","alarmType","changeCSS","sheetId","selector","property","getElementById","sheet","rules","cssRules","found","selectorText","style","setProperty","insertRule","decorations","temporaryDecorations","status","downloading","colors","tinycolor","mostReadable","includeFallbackColors","toHexString","itemType","partType","specificPart","effect","mergeInDecoration","decoration","behaviour","image","d","battery","minimum","maximum","nt","p","key","typePropertyIdentifier","isDefined","numberValue","isNaN","parseFloat","connectedTo","from","_type","to","sts","downloadDecorations","base","request","getItem","directive","$injector","indoorLocationViewerDataService","indoorLocationViewerRenderService","restrict","template","element","attrs","zoomIn","rx","ppm","drawModel","zoomOut","fitToModel","calculateBoundingBox","mx","fitToBoundingBox","boundingBox","pickFloor","floors","findFloors","floorList","structureType","_children","hierarchy","modalInstance","stwoCoreIndoorLocationFloorPickerModalController","baseLocation","rawData","basePath","dx","progress","ctx","getContext","canvas","centeredOnFirstMarkers","x","y","locationsWithMarkers","locationsById","processedMarkers","clusteredMarkers","locationModelReady","indoorMarkers","lastMousePosition","tappedMarker","updateDimension","$","width","parent","css","height","save","fillStyle","fillRect","translate","grid","markerId","restore","fillText","centerOnLocationId","updateCenterLocation","$watch","newVal","processMarkers","findMarkerUnderMouse","distanceTo","ox","oy","sqrt","pow","closest","distance","px","py","markerClick","onMarkerClick","_marker","initialize","customerId","downloadModel","bind","which","offsetX","offsetY","buttons","preventDefault","hovered","touches","target","tagName","targetTouches","pageX","clientTop","pageY","clientLeft","touchMarker","drawCounter","has","resize","requestAnimFrame","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","keepAnimating","$on","animate","assetsConnectedToLocations","box","left","right","top","bottom","shell","getShellRecursive","calculateBasePosition","min","ln","cx","cy","abs","pushHandler","info","shape","_parent","getHeightRecursive","getHolesRecursive","holes","potentialFloor","newPosition","c","skipTransformForParent","transformation","rotation","atan2","PI","cos","sin","z","markerFound","markers","markerPosition","logLevel","createdThisProcess","markerStrokeColor","previousPosition","_decoration","markersPerSpot","spotToString","clusterId","selected","spotId","meanC","_cluster","postProcess","flatList","parentLocationId","nn","downloadAssets","flatLocationList","remainingAssetsToDownloadList","assetIds","assetsToDownloadThisTime","join","sessionStorage","cachedLocModel","overlayImages","indoorViewer","doNotDrawGrid","beginPath","moveTo","lineTo","strokeStyle","stroke","fontStyle","shadowStyle","font","rotate","overlays","imageObj","Image","src","onload","scale","drawImage","movementTime","r1","r2","arc","lineWidth","measureText","textOnly","depth","_lastDecoRuleCheck","_gradient","locationHasMarkers","colorFillStyle","bound","createRadialGradient","addColorStop","fill","doNotDrawLocationBorder","rct_l","rct_r","rct_t","rct_b","w","dw","h","dh","commands","moreInfo","command","stwoCommonSentCommandDetailsModalController","sentCommandConfiguration","stwoCommonSendCommandModalController","$controller","sendCommandConfiguration","availableCommands","chosenCommand","commandData","commandSent","asset","deviceCommands","device","chooseCommand","numParamsInChosen","parameters","sendCommand","dataToSend","shown","downloadCommand","downloadingCommandData","lastDownload","stwoCommonFilterModalController","availableFilters","filterValues","valueFound","filterUrlString","field","comparator","encodeURI","stwoCommonMapModalController","$window","isAtBottom","scrollY","innerHeight","infiniteProgress","$stateParams","favoritesService","contentCacheService","filterChanged","itemsChanged","predefinedFilters","filterMessage","filterMessage2","selectedItems","selectedItemsMap","infiniteScrollHandler","downloadProgress","active","infiniteScrollProgress","startDownload","finishDownload","items","pagination","complete","downloadUrl","clearItems","downloadMore","next","clearSelection","toggleSelect","showFavorites","favoritesListAsString","clearFilter","toggleFavorite","openFilter","newFilterData","addPredefinedFilter","predefinedIdentifier","listOfFilterValues","predefinedFilterStructure","filterId","addAvailableFilter","identifier","fieldDescription","setup","moduleDefinedFilters","split","advancedFilter","oldVal","stwoCommonPickerModalController","pickerConfiguration","pickMultipleMode","multiple","fieldsToShow","pickNullAllowed","pickNullButtonText","disabledIDs","disabledItems","filters","filterString","processed","assets","vv","itemClicked","pickOne","pickMultiple","textInput","nameSearchValue","applyNameSearch","$event","keyCode","$compile","phone","phonePlaceHolder","Netherlands","Norway","Romania","Hungary","Czech","Sweden","Malaysia","Thailand","UK","Germany","Peru","Bonaire","China","Finland","Denmark","Ireland","Poland","Madagascar","France","Ukraine","Belgium","Australia","Empty","countryCodes","label","mask","currentCC","phoneNbrPlaceHolder","parseNbr","uniqueID","random","ccSearch","selectedCCIndex","ccExpanded","searchFieldKeyPressed","maxIndex","cc","changeCC","click","getCountryCodes","nbr","newValue","oldValue","nbrChanged","elem","ctrl","debug","dialogService","readonly","formattedKey","lastIndexOf","days","WHOLEWEEK","WORKWEEK","workhoursData","fromHours","fromMinutes","toHours","toMinutes","errors","inconsistent","noday","correctWHOrder","failedContacts","prepareContactsFor","contacts","originalContacts","labels","contact","prepareContact","fcString","priority","workhours","wh","dirty","whFormatted","weekday","checkWeek","day","tmpWH","formatted","wholeWeek","expandContact","currentContact","animateEditor","updatePriority","newContactInProgress","json","newContact","sms","email","new","moveContactPriority","direction","cs","newIndex","removeContact","contactName","toggleDrag","drag","TweenLite","set","resourceId","overflow","opacity","ease","delay","previous","resourceIdß","checkContact","saveContact","validateWorkHours","start","end","SELECT","Number","trim","MANAGEMENT_ASSET_NAME_EMPTY","verified","contactCode","updateAsset","cl","nc","workhoursChanged","checkContactChanged","checks","whSelect","addWorkhour","removeWorkhour","placeholder","awaitingNavigation","searchOverlay","addressData","addressSearch","addressLoading","addresses","selectedIndex","selectedAddress","expanded","performAddressRequest","setAddressExpanded","requestString","addressListBySearch","addressList","addressFieldKeyPressed","selectAddress","addressSearchKey","recentSearches","addressDetails","detailedAddress","country","latLng","lon","searchSelected","duration","stopTrim","timestring","weekdays","MON","TUE","WED","THU","FRI","SAT","SUN","evaluate","timeRestrictionJson","anyOk","wd","isoWeekday","wdOk","hourOk","parseInt","timeRestrictionService","edit","waiting","updateInternalData","rows","minWeekday","minHour","_sort","updateExternalData","removeRow","idx","modalController","row","mode","rowData","hoursStart","hoursEnd","padHours","returnRow","editRow","addRow","getTableRow","col1","col2","getGoogleMapsLink","trimPhoneNumber","getAssetInformationTable","messageData","zones","zone","assetTable","lengh","externalId","timestampFormatted","getAssetSMSContent","assetInfo","sendAssetByMail","mail","mailContent","mailBody","subject","sendAssetBySMS","number","smsContent","formatNumber","smsBody","apiKey","searchTerm","osm_type","osm_id","respons","toRadians","angle","defaultRadius","smallRadius","getBuildingBoundsData","radius","radiusStep","getBuildingBounds","checkAddressZoneExists","existingZone","errorResponse","changeArcSize","zoneResourceId","shapeMeta","points","theta","setZoom","circ","circle","step","getBounds","getNorthEast","ry","p1","newIPSPoint","buildingBounds","j","formattedAddress","match","RegExp","placeName","description","constant","preprocess","timezone","jstz","determine","$stateProvider","$urlRouterProvider","moduleStoreProvider","reload","otherwise","abstract","views","loginheader","logincontent","logincontent@","menu","tag","$translateProvider","useStaticFilesLoader","prefix","languageUrl","suffix","preferredLanguage","$rootScope","$anchorScroll","timerService","notificationService","ngAudio","createSoundFilter","sf","getSoundName","ss","checkToken","newPushEnabled","newPushTokens","newPushActive","sub","newPushWorking","errorResp","enablePush","PUSH_ON","disablePush","PUSH_OFF","newPushDebugInfo","enablePushLink","disablePushLink","ua","isAndroid","isXguard","isIOS","isIOSApp","btnCaption","useragent","togglePush","toggleNewPush","soundFilter","notificationError","userData","hiddenUi","modalContent","images","openModalImages","imageUrlArr","lastMouseMove","inactivityState","remaining","remainingPct","warningTime","inactivityTimeout","addEventListener","menuOpen","notificationsOpen","settingsOpen","notificationsChanged","customNotificationClicked","notificationCenter","allLinks","rebuildLinksPerCategory","linksPerCategory","navigationLinksPerCategory","navigationLinksCount","categoriesWithLinks","navigation","notificationAudio","checkAndPlayNotificationSound","toggleMute","toggleIgnoreSnooze","stopPlayingNotificationAudio","player","playingFile","play","setUnlock","stop","unbind","anyRedAlert","anyOrangeAlerts","anyGreenAlerts","anyAlerts","anyCPEvents","reason","viewNotification","goToNotifications","getSelectedCustomer","selectedCustomer","getSelectedProvider","selectedProvider","getActiveControllerName","current","getTitleName","titleName","getTitleIcon","titleIcon","getParentControllerName","$current","getCurrentState","getBodyClass","bodyclass","checkCurrentState","linkClicked","stateParams","sref","currentVersion","appVersion","beta","showUpdateNotification","closeUpdateNotification","tab","fieldsPerView","readInvitations","invitations","updateInvitation","showMoreCustomers","showAllCustomers","availableMapProviders","openDialog","openSoundSelector","closeAudioSelector","classList","contains","activeSound","selectSound","load","saveSound","updateSoundPrefs","removeClass","updatePushSound","Object","keys","soundDataUpdating","toggleMuted","getCurrentCustomerId","selectedCustomerIndex","customerName","customerSearch","maxSearch","chooseCustomer","getCurrentCustomerName","getCurrentProviderId","getCurrentProviderName","customerSelectWorking","chooseProvider","providerId","mapDefaultStates","MAP_DEFAULT_AUTO","MAP_DEFAULT_INDOOR","MAP_DEFAULT_OUTDOOR","alerts","textToTranslate","working","rememberLogin","renewPassword","credentialsMode","mailTemplate","setLanguage","sendRecoveryMail","usernameToRecover","action","modalAlert","performRecovery","recoveryKey","cancelRenew","storedUsers","doLogout","closeAlert","re","stateAfterLogin","tokenExpired","doLogin","passwordNew","passwordNewRepeat","newUserInfo","DemoLogin","g","isFunction","isString","isObject","isArray","extend","equals","noop","menus","include","pre","findMenu","exec","findByParent","getTree","children","hasChild","pollingForAlarms","pollSmarttrackerForAlarms","ns","notificationIdsSeen","lastUpdated","dismissable","nss","badge","dismissFn","stwoAlarmAcknowledgeModalController","alarm","alarmWarning","newAlarms","not","alm","ackNeeded","ackedBy","alarmClicked","ackAlarm","comment","changeCounter","updateMarkers","fitToBounds","boundsMarkerArray","markerCount","distanceBetweenTheMarkers","bounds","latLngBounds","fitBounds","downloadAlarm","impossibleToAck","downloadingAlarm","setAlarm","owner","conn","startDateOnSetTime","$broadcast","endDateOnSetTime","startDateBeforeRender","$dates","dateRange","activeDate","localDateValue","valueOf","selectable","applyFilter","endDateBeforeRender","$view","ts","subtract","downloadActiveAlarms","activeAlarms","nbrActiveAlarms","downloadActiveInProgress","acfKey","clearFilters","triggeringAsset","RED_ALERT","WARNING","NOTIFICATION","allSelected","resolution","acked","changeAlarmTypeFilter","val","addExternalIdFilter","o","addTriggeringAsset","removeFilter","llFilters","performUpdate","ninit","val2","nbrAckedAlarms","toggleFilters","scroll","filterExpanded","scrollTo","showFilters","uniq_fast","seen","len","setJoinMuted","conferenceSid","comparePriority","PageOpenedDate","toISOString","debugMode","responseAreas","handleCameraClick","stopPropagation","commentTemplateList","openToggle","closeToggle","modes","isDoubt","codes","qr","ra","nqr","pc","pd","bz","notificationMessage","notificationSubject","alarmID","syntax","ZMTag","QRTag","NQRTag","PDTag","BZTag","RATag","CLTag","ContactTag","allowContact","allowContactNQR","allowEmergencyContact","allowNQR","updateIntervalSeconds","refreshEvents","getTimeString","killAlarmUpdater","downloadContacts","actionStatus","mapViewAltered","selectedMarker","selectedMarkerName","mapSidebar","visible","updateBZVisibility","nbrOfContacts","allElseFailed","getActionStatusKey","getActionStatus","updateRAPropertyForCode","clipboard","Clipboard","order","setOrder","currentAlarm","commentsMeta","notificationStatusKey","notificationStatus","comments","dateCreated","dateCreatedFormatted","addCustomerMarker","addAlarmMarker","renderLineBetween","addNQRMarker","addQRMarker","chat","setupChat","initMap","ackedTS","setupConferenceCalls","resp","nqrEnabled","getPropertyValue","getAssetContactList","contactInfo","phoneFormatted","addContactsForCode","getResponseAreaForCode","downloadZones","addMarker","showNQR","downloadZonesForZone","normalMode","contactStatus","mapInitiated","maximumDistances","conferenceParseParticipants","rawParticipants","participants","alarmAssetConnected","alarmAssetConnectedStartTime","conferenceOthersConnected","conferenceSelfConnected","mutedHintClicked","participant","client","userId","userResourceId","isSelf","startTime","dccPhoneNumber","conferenceEnded","conferenceParticipants","checkboxes","dccJoinMuted","conferenceCallCode","isServiceProvider","registerEvent","event","getConferenceCallCode","callSid","setMuted","setMutedHintClicked","attempts","lessLat","lessLon","greaterLat","greaterLon","downloadCloseAssets","list_2","type_label","propertiesFormatted","usedIDS","typeIDS","anyAvailablePush","available","userID","me","updateFeedbackVariables","unavailable","getMaxDistancesForCode","collegues","applyDistanceFilter","autoCenter","guards","parseDataForZone","groups","groupIDs","idFilters","usedIDs","group","contactLists","maxDistance","removeLayer","context","repl","isContactAllowed","invisibleResponder","calculateDistance","distanceText","getDistanceText","maxLat","minLat","maxLon","minLon","zoneIDS","zs","addResponseArea","getResponseAreaTextForZone","hp","fp","area","renderResponseArea","setMode","centerOnAddress","latlngs","addPath","fillColor","clickable","weight","polygon","whcheck","getDay","startBound","setHours","setMinutes","endBound","setDate","getDate","kv","showQR","showPD","otherMap","smallScreen","setMobileView","deselectSelectedMarker","customerID","contactAllowed","testValue","isNormalMode","toggleMap","div_icon","iconSize","coreMarkers","securityGuardsVisible","_icon","addSelectedMarker","positionIsFixed","oms","core","iconAnchorX","iconAnchorY","slInit","OverlappingMarkerSpiderfier","addListener","positionKey","Icon","Default","imagePath","unspiderfy","riseOnHover","addLayer","iconCode","dashArray","initialCenterSet","setCenter","newCenter","centerOnItem","mapMode","newcenter","mapVisible","zoomNQR","zoomCore","activeMarkersPoints","padding","pos1","pos2","lat1","lat2","lon1","lon2","R","φ1","φ2","Δφ","Δλ","deg","eventText","additionalInfo","editable","expandedComment","expandComment","addEditCommentEvent","commentText","isIndoor","isInZone","isGuardsVisible","timeString","diff","toString","timeStringDate","zoneName","getComments","parseMessage","toLocaleString","offsetId","iOSversion","platform","ver","addHeader","headerOnly","header","getAddressHTML","button","acknowledgeText","acknowledgeAlarm","surveyResult","acknowledge","sendSurveyMail","acknowledgeData","updateActionStatus","startSurvey","outerScope","audioExpected","audioQualityOk","audioQualityNotOkReason","responseSettingsOk","responseSettingsComment","positionOk","locationQualityNotOkReason","customerHappy","acknowledgementComment","replacements","true","false","2","3","0","1","possibleConstants","logdataReplacements","translateArray","transData","surveyDone","lastStep","percentage","progressStyle","setStep","stepResult","marginTop","beforeTranslations","setTranslatedStep","originalResult","LocationAccuracy","CreatedDate","AcknowledgeDate","AlarmSeverity","AlarmText","IsAckedByAlarmCenter","CommentCount","FirstCommentDate","HasExternalId","sendEmail","langData","md","messageComponents","includes","components","email_position","content","component","additional","href","absolute","propertiesString","customMessage","value2","key2","dialog","templateData","mailBodyTemplated","contactCalled","showContact","showNumber","sendSMS","XGUARD_SEND_SMS_DIALOG_CONTENT","setText","smsTemplateItem","smsTemplateList","screenSmallitems","getIconColor","getTimeColor","alarmDate","appFormat","currentTab","switchTabs","togglePinSidebarMap","localPinSidebarMap","localAlarmScreenMap","toggleAlarmScreenMap","initMapDelayed","getAlarmColor","ZoomIn","ZoomOut","messageKey","titleKey","pending","responded","confirmed","failed","nsLabelKeys","contactID","sendNotifications","validAccess","idString","qrs","pickerResult","receivers","receiverContacts","recipients","recipient","updateNotificationStatusForContact","saveNotificationStatus","newStatus","receiver","createCommentLabel","eventID","sendNotificationFeedback","currentStatus","nextStatus","showFeedbackButton","showConfirmButton","assetID","sortProperties","alarms","noAlarmAvailable","gotoAlarm","gotoAlarms","enableProperty","toggleProperty","disableProperty","copyProperty","correctOrder","messageService","downloadAll","externalIdSearchValue","assetIdSearchValue","downloadInProgress","assetClicked","currentAssetID","downloadAsset","Sidebar","closeAsset","localSidebarSituation","toggleSidebarSituation","popupPath","singleAsset","downloadStatus","NQR","QR","RA","eachLayer","layer","errorMessage","isValid","md_content","assetName","contactMail","lan","assetPositionDate","Screensize","toggleSidebar","popupExpand","localCollapseResponse","toggleCollapseResponse","toggleFavorites","localFavorites","showMore","increaseBy","num","update","nl","en","fixes","subtext"],"mappings":"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","sourcesContent":["angular.module('stwo.core', [\"ui.router\", \"ngSanitize\", \"pascalprecht.translate\", \"n3-line-chart\", \"dcbImgFallback\"]);\r\n\r\nangular.module('stwo.core')\r\n .filter('getValue', function () {\r\n return function (obj, fields) {\r\n var s = null;\r\n if (obj) {\r\n \r\n var recursiveGet = function(ob, remStr) {\r\n if (!ob) {\r\n return null;\r\n }\r\n if (remStr.indexOf(\".\") >= 0) {\r\n var k = remStr.substring(0, remStr.indexOf(\".\"))\r\n return recursiveGet(ob[k], remStr.substring(k.length + 1, remStr.length));\r\n } else {\r\n return ob[remStr];\r\n }\r\n }\r\n \r\n s = recursiveGet(obj, fields)\r\n }\r\n return s;\r\n };\r\n });\r\n\r\nangular.module('stwo.core')\r\n .filter('isEmpty', function () {\r\n var bar;\r\n return function (obj) {\r\n for (bar in obj) {\r\n if (obj.hasOwnProperty(bar)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n };\r\n });\r\n\r\nangular.module('stwo.core')\r\n .filter('propertyContains', function () {\r\n return function (arr, prop, value) {\r\n var outArr = [];\r\n if (!value || value === \"\") {\r\n return arr;\r\n } else {\r\n for (var n = 0; n < arr.length; n++) {\r\n if (arr[n] && arr[n][prop] && arr[n][prop].indexOf(value) >= 0) {\r\n outArr.push(arr[n]);\r\n }\r\n }\r\n return outArr;\r\n }\r\n };\r\n });\r\nangular.module('stwo.core')\r\n .filter('replaceParameters', function () {\r\n return function (str, arr) {\r\n var s = str;\r\n if (arr) {\r\n for (var n = 0; n < arr.length; n++) {\r\n s = s.replace(\"{\" + n + \"}\", arr[n]);\r\n }\r\n }\r\n return s;\r\n };\r\n });\r\nangular.module('stwo.core')\r\n .filter('percentage', function () {\r\n return function (floatNumber, opts) {\r\n if (opts && opts.indexOf('invert') >= 0) {\r\n floatNumber = 1 - floatNumber;\r\n }\r\n if (opts && opts.indexOf('tenths') >= 0) {\r\n floatNumber = Math.round(floatNumber * 10) / 10;\r\n }\r\n return String(Math.round(floatNumber * 100)) + \"%\";\r\n };\r\n });\r\nangular.module('stwo.core').\r\n run(function() {\r\n FastClick.attach(document.body);\r\n });\nangular.module('stwo.core').provider('moduleStore', function() {\r\n\r\n var _modules = {};\r\n var _links = [];\r\n var _categories = [];\r\n var _rootLinks = [];\r\n var _states = {\r\n missingCustomer : \"^\",\r\n notLoggedIn : \"^\"\r\n };\r\n var _notificationHandlers = {};\r\n var _serviceRepository = {};\r\n\r\n var _possibleFiltersPerClazz = {};\r\n var _flags = {};\r\n \r\n this.hasAccess = function(link, accessMap) {\r\n if (!accessMap) {\r\n return false;\r\n }\r\n if (link.categoryDependency) {\r\n for (var n = 0; n < _links.length; n++) {\r\n if (_links[n].category === link.categoryDependency && this.hasAccess(_links[n], accessMap)) {\r\n return true;\r\n }\r\n }\r\n } else {\r\n return !link.access || accessMap[link.access[0]][link.access[1]];\r\n }\r\n }\r\n \r\n this.hasController = function(link, controllerName) {\r\n if (link.controllers && _.indexOf(link.controllers, controllerName) > -1) {\r\n return true;\r\n }\r\n if (link.categoryDependency) {\r\n for (var n = 0; n < _links.length; n++) {\r\n if (_links[n].category === link.categoryDependency && _links[n].controllers && _.indexOf(_links[n].controllers, controllerName) > -1) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n this.removeLink = function(linkIndex) {\r\n _links.splice(linkIndex, 1);\r\n }\r\n //\t{name: \"alarm\", links: [{label:\"ALARMS\", category: \"\" , sref: \"secure.content.alarm\", sort: 15}]}\r\n this.registerLink = function(link) {\r\n link.hasAccess = this.hasAccess;\r\n link.hasController = this.hasController;\r\n \r\n if (stwoGlobal.linkCategoryOverride && stwoGlobal.linkCategoryOverride[link.module] && stwoGlobal.linkCategoryOverride[link.module][link.id]) {\r\n link.category = stwoGlobal.linkCategoryOverride[link.module][link.id];\r\n }\r\n \r\n \r\n if (_links.length === 0) {\r\n _links.push(link)\r\n } else {\r\n for (var place = 0; place < _links.length; place++) {//keep the links and rootlinks sorted according to the \"sort\" value\r\n if (link.sort < _links[place].sort) {\r\n _links.splice(place, 0, link);\r\n break;\r\n }\r\n }\r\n if (place === _links.length) {\r\n _links.push(link);\r\n }\r\n }\r\n if (link.category === \"navigation\") {\r\n if (_rootLinks.length === 0) {\r\n _rootLinks.push(link)\r\n } else {\r\n for (var place = 0; place < _rootLinks.length; place++) {//keep the links and rootlinks sorted according to the \"sort\" value\r\n if (link.sort < _rootLinks[place].sort) {\r\n _rootLinks.splice(place, 0, link);\r\n break;\r\n }\r\n }\r\n if (place === _rootLinks.length) {\r\n _rootLinks.push(link);\r\n }\r\n }\r\n }\r\n if (!link.category || link.category == \"\") {//this test is temporary while I manage to change everywhere with meaningful cathegory names\r\n console.log(\"NO category was given. See moduleStoreProvider\");\r\n }\r\n }\r\n this.registerModule = function(moduleInfo) {\r\n if (moduleInfo.categories) {\r\n var categoryExists = false;\r\n \r\n for (var n = 0; n < _categories.length; n++) {\r\n if (moduleInfo.name === _categories[n].name) {\r\n categoryExists = true;\r\n console.log(\"Module attempted to add existing category\", _categories[n].name, moduleInfo);\r\n break;\r\n }\r\n }\r\n if (!categoryExists) {\r\n for (var n = 0; n < moduleInfo.categories.length; n++) {\r\n if (_categories.length === 0) {\r\n _categories.push(moduleInfo.categories[n])\r\n } else {\r\n for (var place = 0; place < _categories.length; place++) {\r\n if (moduleInfo.categories[n].sort < _categories[place].sort) {\r\n _categories.splice(place, 0, moduleInfo.categories[n]);\r\n break;\r\n }\r\n }\r\n if (place === _categories.length) {\r\n _categories.push(moduleInfo.categories[n]);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n if (moduleInfo.links) {\r\n for (var n = 0; n < moduleInfo.links.length; n++) {\r\n moduleInfo.links[n].module = moduleInfo.name;\r\n this.registerLink(moduleInfo.links[n]);\r\n }\r\n }\r\n \r\n if (moduleInfo.notificationHandlers) {\r\n _notificationHandlers[moduleInfo.name] = moduleInfo.notificationHandlers;\r\n }\r\n \r\n _modules[moduleInfo.name] = moduleInfo;\r\n }\r\n\r\n this.modules = function() {\r\n return _modules;\r\n };\r\n this.categories = function() {\r\n return _categories;\r\n };\r\n this.flags = function() {\r\n return _flags;\r\n };\r\n this.states = function() {\r\n return _states;\r\n };\r\n this.getPossibleFiltersForClazz = function(clazz) {\r\n return _possibleFiltersPerClazz[clazz];\r\n };\r\n this.addPossibleFilter = function(clazz, filter) {\r\n if (!_possibleFiltersPerClazz[clazz]) {\r\n _possibleFiltersPerClazz[clazz] = [];\r\n }\r\n for (var n = 0; n < _possibleFiltersPerClazz[clazz].length; n++) {\r\n if (filter.id === _possibleFiltersPerClazz[clazz][n].id) {\r\n console.log(\"Duplicate filter\", JSON.stringify(filter));\r\n return;\r\n }\r\n }\r\n _possibleFiltersPerClazz[clazz].push(filter);\r\n return _possibleFiltersPerClazz[clazz];\r\n };\r\n this.notificationHandlers = function() {\r\n return _notificationHandlers;\r\n };\r\n this.links = function() {\r\n return _links;\r\n };\r\n this.stateDependentLinks = function(currentState, scope) {\r\n var l = [];\r\n \r\n for (var k in _modules) {\r\n if (_modules[k][\"stateDependentLinks\"]) {\r\n for (var n2 = 0; n2 < _modules[k][\"stateDependentLinks\"].length; n2++) {\r\n var r = _modules[k][\"stateDependentLinks\"][n2](currentState, scope);\r\n if (r) {\r\n for (var n3 = 0; n3 < r.length; n3++) {\r\n l.push(r[n3]);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n l.sort(function(a, b) {\r\n return a.sort - b.sort;\r\n })\r\n \r\n return l;\r\n };\r\n this.serviceRepository = function() {\r\n return _serviceRepository;\r\n };\r\n this.linksOfCategory = function(category, module) {\r\n var linkList = [];\r\n for (var n = 0; n < _links.length; n++) {\r\n if ( (!module || _links[n].module === module) && (!category || _links[n].category === category) ) {\r\n linkList.push(_links[n]);\r\n }\r\n }\r\n return linkList;\r\n };\r\n this.rootLinks = function() {\r\n return _rootLinks;\r\n };\r\n\r\n this.access = function(module, minimumAccess) {\r\n if (stwoGlobal && stwoGlobal.moduleAccessOverride && stwoGlobal.moduleAccessOverride[module]) {\r\n return stwoGlobal.moduleAccessOverride[module];\r\n } else {\r\n return minimumAccess;\r\n }\r\n };\r\n this.$get = function() {\r\n return this;\r\n };\r\n \r\n this.defaultLanguage = function() {\r\n return localStorage[\"language\"] && _.find(stwoGlobal.availableLanguages, function(lang) { return localStorage[\"language\"] === lang.code; }) ? localStorage[\"language\"] : stwoGlobal.defaultLanguage;\r\n }\r\n\r\n}); \nangular.module('stwo.core').factory('timerService', function($interval) {\n\n var i = {};\n \n \n var timers = {};\n var intervals = {one: 1000, five: 5000, ten: 10000, twenty: 20000, thirty: 30000, sixty: 60000, onetwenty: 120000, threehundred: 300000};\n var lastUpdate = {};\n \n i.timers = function() {\n return timers;\n }\n \n $interval(function() {\n var now = (new Date()).getTime();\n for (var interval in intervals) {\n if (!lastUpdate[interval]) {\n lastUpdate[interval] = 0;\n }\n if (now - lastUpdate[interval] > intervals[interval]) {\n lastUpdate[interval] = now;\n if (!timers[interval]) {\n timers[interval] = 0;\n }\n timers[interval]++;\n }\n }\n }, 900);\n \n return i;\n});\nangular.module('stwo.core').factory('utilService', function ($translate, $filter) {\n\n var i = {};\n var translations = {};\n $translate([\"XGUARD_MINUTES\", \"XGUARD_MINUTE\", \"XGUARD_HOUR\", \"XGUARD_HOURS\", \"XGUARD_TIME_MEASURE_TEMPLATE\", \"XGUARD_TIMESTAMP_TODAY\"])\n .then(function (data) {\n translations = {\n hour: data['XGUARD_HOUR'],\n hours: data['XGUARD_HOURS'],\n minute: data['XGUARD_MINUTE'],\n minutes: data['XGUARD_MINUTES'],\n timeTemplate: data['XGUARD_TIME_MEASURE_TEMPLATE'],\n today: data['XGUARD_TIMESTAMP_TODAY']\n };\n });\n \n i.clone = function(obj) {\n if (null == obj || \"object\" != typeof obj) return obj;\n var copy = obj.constructor();\n for (var attr in obj) {\n if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];\n }\n return copy;\n }\n \n i.isResponseValid = function(response, checkLength) {\n return response&&response.data&&response.data.result&&(checkLength?response.data.result.length>0:true);\n }\n\n i.getFormattedDateFromTimestamp = function (date, todayLength) {\n var dd = moment.tz(date, \"YYYY-MM-DDTHH:mm:ss.SSS\", \"UTC\");\n if(!todayLength)\n todayLength = 43200000;\n var retD = false;\n if(new Date() - dd.toDate() < todayLength)\n retD = translations.today + \", \" + $filter(\"amDateFormat\")(date, 'HH:mm:ss');\n else\n retD = $filter(\"amDateFormat\")(date, 'YYYY-DD-MM, HH:mm:ss');\n return retD;\n }\n\n i.checkNestedProperty = function (object) {\n var args = Array.prototype.slice.call(arguments, 1);\n\n for (var i = 0; i < args.length; i++) {\n if (!object || !object.hasOwnProperty(args[i])) {\n return false;\n }\n object = object[args[i]];\n }\n return true;\n }\n \n return i;\n});\nangular.module('stwo.core').factory('smarttrackerService', function($http, $location, $translate, $q, moduleStore, pushService, decorationService, amMoment, deploymentApiService, socketioService) {\r\n // change these URLs accordingly\r\n var baseUrlApi = 'api3/';\r\n var baseUrl = stwoGlobal.smarttrackerUrl;//'https://stage.smarttracker.no/web/';\r\n\r\n var user = {};\r\n var token = null;\r\n var customer = null;\r\n var availableCustomers = [];\r\n var provider = null;\r\n var availableProviders = [];\r\n var accessRights = {};\r\n var customerData = null;\r\n\r\n\r\n\r\n //example user {username: 'brukernavn', token: 'TOKENTOKEN'}\r\n var tokens = [];\r\n \r\n var _language = moduleStore.defaultLanguage();\r\n\r\n //restoring previously stored tokens\r\n if (localStorage[\"tokens\"] && localStorage[\"tokens\"] !== null) {\r\n var storedTokens = JSON.parse(localStorage[\"tokens\"]);\r\n for (var n = 0; n < storedTokens.length; n++) {\r\n tokens.push(storedTokens[n]);\r\n }\r\n }\r\n \r\n \r\n var deferredLoginData = {login: {started: false, done: false, promises: []}};\r\n \r\n \r\n\r\n var i = {};\r\n \r\n i.url = function() {\r\n return baseUrl;\r\n }\r\n \r\n i.language = function(languageCode) {\r\n if (languageCode) {\r\n localStorage[\"language\"] = languageCode;\r\n $translate.use(languageCode);\r\n \r\n var amLocale = languageCode;\r\n var amLocaleRewrites = {no: \"nb\"};\r\n if (amLocaleRewrites[languageCode]) {\r\n amLocale = amLocaleRewrites[languageCode];\r\n }\r\n console.log(\"Setting moment locale: \" + amLocale)\r\n amMoment.changeLocale(amLocale);\r\n \r\n _language = languageCode;\r\n }\r\n return _language;\r\n }\r\n \r\n i.isLoggedInDelayed = function() {\r\n var defer = $q.defer();\r\n \r\n if (i.isLoggedIn()) {\r\n defer.resolve();\r\n return defer.promise;\r\n }\r\n\r\n \r\n if (deferredLoginData.login.done) {\r\n if (i.isLoggedIn()) {\r\n defer.resolve();\r\n } else {\r\n defer.reject();\r\n }\r\n return defer.promise;\r\n }\r\n \r\n if (!deferredLoginData.login.started) {\r\n\r\n // check url token\r\n var urlToken = ($location.search() || {}).token;\r\n if(typeof urlToken !== 'undefined') { \r\n\r\n console.log('URL TOKEN LOGIN');\r\n\r\n deferredLoginData.login.started = true;\r\n deferredLoginData.login.done = false;\r\n deferredLoginData.login.promises = [];\r\n deferredLoginData.login.promises.push(defer);\r\n\r\n i.addUser({\r\n username : 'temporary-login-token',\r\n token : urlToken,\r\n persist: true\r\n });\r\n\r\n i.selectUser('temporary-login-token', urlToken, true).then(function() {\r\n\r\n history.pushState({}, window.title, $location.absUrl().replace('?token='+urlToken, ''));\r\n\r\n deferredLoginData.login.done = true;\r\n for (var n = 0; n < deferredLoginData.login.promises.length; n++) {\r\n deferredLoginData.login.promises[n].resolve();\r\n }\r\n \r\n }, function() {\r\n deferredLoginData.login.done = true;\r\n for (var n = 0; n < deferredLoginData.login.promises.length; n++) {\r\n deferredLoginData.login.promises[n].reject();\r\n }\r\n })\r\n\r\n } else {\r\n\r\n if (!stwoGlobal.disableRememberUser && localStorage[\"lastUsername\"] && localStorage[\"lastUsername\"] !== \"\" && localStorage[\"lastUsername\"] !== \"null\") {\r\n deferredLoginData.login.started = true;\r\n deferredLoginData.login.done = false;\r\n deferredLoginData.login.promises = [];\r\n deferredLoginData.login.promises.push(defer);\r\n i.selectUser(localStorage[\"lastUsername\"], null, true).then(function() {\r\n deferredLoginData.login.done = true;\r\n for (var n = 0; n < deferredLoginData.login.promises.length; n++) {\r\n deferredLoginData.login.promises[n].resolve();\r\n }\r\n \r\n }, function() {\r\n deferredLoginData.login.done = true;\r\n for (var n = 0; n < deferredLoginData.login.promises.length; n++) {\r\n deferredLoginData.login.promises[n].reject();\r\n }\r\n })\r\n\r\n } else {\r\n deferredLoginData.login.started = true;\r\n deferredLoginData.login.done = true;\r\n defer.reject();\r\n }\r\n\r\n }\r\n\r\n } else {\r\n deferredLoginData.login.promises.push(defer);\r\n }\r\n \r\n return defer.promise;\r\n }\r\n \r\n\r\n\r\n i.persistUsers = function() {\r\n var tokensToPersist = [];\r\n for (var n = 0; n < tokens.length; n++) {\r\n if (tokens[n].persist) {\r\n tokensToPersist.push(tokens[n]);\r\n }\r\n }\r\n localStorage[\"tokens\"] = JSON.stringify(tokensToPersist);\r\n }\r\n\r\n i.addUser = function(userInfo) {\r\n i.removeUser(userInfo.username);\r\n tokens.push(userInfo);\r\n i.persistUsers();\r\n }\r\n i.removeUser = function(username) {\r\n for (var n = tokens.length - 1; n >= 0; n--) {\r\n if (tokens[n].username === username) {\r\n tokens.splice(n, 1);\r\n }\r\n }\r\n i.persistUsers();\r\n }\r\n i.getUsers = function() {\r\n return tokens;\r\n }\r\n\r\n i.isLoggedIn = function() {\r\n return user && user.user && token;\r\n }\r\n\r\n i.getLoggedInUser = function() {\r\n return user;\r\n }\r\n\r\n i.getCustomerId = function() {\r\n return customer;\r\n }\r\n\r\n i.getProviderId = function() {\r\n return provider;\r\n }\r\n\r\n i.getAvailableCustomers = function() {\r\n return availableCustomers;\r\n }\r\n\r\n i.getAccessRights = function() {\r\n return accessRights;\r\n }\r\n\r\n i.getAvailableProviders = function() {\r\n return availableProviders;\r\n }\r\n\r\n i.changeProvider = function(newProviderId) {\r\n return $http({\r\n method : 'PUT',\r\n url : baseUrl + \"api2/index\",\r\n data : {\r\n provider : newProviderId\r\n },\r\n headers : {\r\n \"X-Auth-Token\" : token\r\n }\r\n }).then(function(response) {\r\n $http.get(baseUrl + baseUrlApi, {\r\n headers : {\r\n \"X-Auth-Token\" : token\r\n }\r\n }).then(function(response) {\r\n if (moduleStore.serviceRepository()[\"notificationService\"]) {\r\n moduleStore.serviceRepository()[\"notificationService\"].clear();\r\n }\r\n i.updateUserData(response.data);\r\n return response;\r\n });\r\n });\r\n }\r\n\r\n i.changeCustomer = function(newCustomerId) {\r\n return new Promise(function (resolve, reject) {\r\n $http({\r\n method : 'PUT',\r\n url : baseUrl + \"api2/index\",\r\n data : {\r\n customer : newCustomerId\r\n },\r\n headers : {\r\n \"X-Auth-Token\" : token\r\n }\r\n }).then(function(response) {\r\n $http.get(baseUrl + baseUrlApi, {\r\n headers : {\r\n \"X-Auth-Token\" : token\r\n }\r\n }).then(function(response) {\r\n\r\n if (moduleStore.serviceRepository()[\"notificationService\"]) {\r\n moduleStore.serviceRepository()[\"notificationService\"].clear();\r\n }\r\n i.updateUserData(response.data);\r\n resolve(response);\r\n\r\n deploymentApiService.delete('/v1/cache/session')\r\n\r\n });\r\n });\r\n });\r\n }\r\n\r\n i.login = function(user, renew) {\r\n var xsrf = {\r\n token : \"true\",\r\n username : user.username,\r\n password : user.password,\r\n /*createNewToken:true,\r\n expireOtherTokens:true,*/\r\n replacementPassword : renew ? user.replacementPassword : undefined\r\n };\r\n return $http({\r\n method : 'POST',\r\n url : baseUrl + \"api2/login\",\r\n data : xsrf,\r\n headers : {\r\n 'Content-Type' : 'application/json'\r\n }\r\n }).then(function(response) {\r\n console.log(response);\r\n console.log(response.headers(\"X-Auth-Token\"));\r\n console.log(response.data.token);\r\n \r\n i.addUser({\r\n username : user.username,\r\n token : response.data.token,\r\n persist: user.persist\r\n });\r\n \r\n return response;\r\n });\r\n }\r\n\r\n i.selectUser = function(username, suppliedToken, doNotRedirect) {\r\n \r\n if (!suppliedToken) {\r\n for (var n = tokens.length - 1; n >= 0; n--) {\r\n if (tokens[n].username === username) {\r\n token = tokens[n].token;\r\n }\r\n }\r\n } else {\r\n token = suppliedToken;\r\n }\r\n\r\n localStorage.setItem('authToken', token);\r\n localStorage[\"lastUsername\"] = username;\r\n \r\n return $http.get(baseUrl + baseUrlApi, {\r\n headers : {\r\n \"X-Auth-Token\" : token\r\n }\r\n }).then(function(response) {\r\n i.updateUserData(response.data);\r\n return response;\r\n }, function(response) {\r\n if (response && response.data && response.data.tokenNotFound) {\r\n $location.path('/logout');\r\n }\r\n if (!doNotRedirect) {\r\n if (user) {\r\n $location.path('/logout');\r\n } else {\r\n $location.path('/login');\r\n }\r\n $location.replace();\r\n return response;\r\n }\r\n });\r\n\r\n }\r\n\r\n i.refreshUser = function() {\r\n return $http.get(baseUrl + baseUrlApi, {\r\n headers : {\r\n \"X-Auth-Token\" : token\r\n }\r\n }).then(function(response) {\r\n i.updateUserData(response.data);\r\n return response;\r\n }, function(response) {\r\n if (user) {\r\n $location.path('/logout');\r\n } else {\r\n $location.path('/login');\r\n }\r\n $location.replace();\r\n return;\r\n });\r\n\r\n }\r\n \r\n i.getUserData = function() {\r\n return user;\r\n }\r\n\r\n i.isAlarmCenter = function() {\r\n return customerData != null && customerData.alarmCenter;\r\n }\r\n\r\n i.updateUserData = function(data) {\r\n data = angular.fromJson(angular.toJson(data));\r\n for (var k in user) {\r\n delete user[k];\r\n }\r\n for (var k in data) {\r\n user[k] = data[k];\r\n }\r\n\r\n customer = data && data.customer ? data.customer.id : null;\r\n provider = data && data.provider ? data.provider.id : null;\r\n customerData = data && data.customer ? data.customer : null;\r\n\r\n availableCustomers.splice(0, availableCustomers.length);\r\n if (data && data.customers) {\r\n for (var n = 0; n < data.customers.length; n++) {\r\n availableCustomers.push(data.customers[n]);\r\n }\r\n }\r\n\r\n availableProviders.splice(0, availableProviders.length);\r\n if (data && data.providers) {\r\n for (var n = 0; n < data.providers.length; n++) {\r\n availableProviders.push(data.providers[n]);\r\n }\r\n }\r\n \r\n for (var k in accessRights) {\r\n delete accessRights[k];\r\n }\r\n for (var k in user.access) {\r\n accessRights[k] = user.access[k];\r\n }\r\n \r\n var userLanguage = stwoGlobal.defaultLanguage;\r\n if (data && data.user && data.user.language) {\r\n userLanguage = data.user.language;\r\n console.log(\"Language gotten from user settings: \" + userLanguage)\r\n }\r\n var languageAmongDefined = false;\r\n for (var n = 0; n < stwoGlobal.availableLanguages.length; n++) {\r\n if (stwoGlobal.availableLanguages[n].code === userLanguage) {\r\n languageAmongDefined = true;\r\n break;\r\n }\r\n }\r\n if (!languageAmongDefined) {\r\n userLanguage = localStorage[\"language\"] ? localStorage[\"language\"] : stwoGlobal.defaultLanguage;\r\n }\r\n i.language(userLanguage);\r\n \r\n moduleStore.serviceRepository()[\"pushService\"].configure(token, user, customer, provider);\r\n moduleStore.serviceRepository()[\"pushService\"].reconnect();\r\n moduleStore.serviceRepository()[\"decorationService\"].refresh();\r\n \r\n if (moduleStore.serviceRepository()[\"notificationService\"]) {\r\n moduleStore.serviceRepository()[\"notificationService\"].poll();\r\n }\r\n }\r\n\r\n i.logout = function() {\r\n for (var k in user) {\r\n delete user[k];\r\n }\r\n for (var n = tokens.length - 1; n >= 0; n--) {\r\n if (!tokens[n].persist) {\r\n tokens.splice(n, 1);\r\n }\r\n }\r\n i.persistUsers();\r\n \r\n if (moduleStore.serviceRepository()[\"notificationService\"]) {\r\n moduleStore.serviceRepository()[\"notificationService\"].clear();\r\n }\r\n if (moduleStore.serviceRepository()[\"pushService\"]) {\r\n moduleStore.serviceRepository()[\"pushService\"].disconnect();\r\n }\r\n }\r\n \r\n i.getToken = function() {\r\n return token;\r\n }\r\n\r\n i.authGet = function(url, opts) {\r\n if (!token) {\r\n if (i.isLoggedIn()) {\r\n $location.path('/logout');\r\n } else {\r\n $location.path('/login');\r\n }\r\n $location.replace();\r\n return;\r\n }\r\n\r\n return $http.get(baseUrl + baseUrlApi + url, {\r\n headers : {\r\n \"X-Auth-Token\" : token\r\n }\r\n }).then(function(response) {\r\n return response;\r\n }, function(response) {\r\n if (!opts || !opts.onErrorDoNotRedirect) {\r\n if (i.isLoggedIn()) {\r\n $location.path('/logout');\r\n } else {\r\n $location.path('/login');\r\n }\r\n $location.replace();\r\n }\r\n return response;\r\n });\r\n }\r\n\r\n i.authPost = function(url, data) {\r\n if (!token) {\r\n if (i.isLoggedIn()) {\r\n $location.path('/logout');\r\n } else {\r\n $location.path('/login');\r\n }\r\n $location.replace();\r\n return;\r\n }\r\n\r\n return $http.post(baseUrl + baseUrlApi + url, data, {\r\n headers : {\r\n \"X-Auth-Token\" : token\r\n }\r\n });\r\n }\r\n\r\n i.authPut = function(url, data) {\r\n if (!token) {\r\n if (i.isLoggedIn()) {\r\n $location.path('/logout');\r\n } else {\r\n $location.path('/login');\r\n }\r\n $location.replace();\r\n return;\r\n }\r\n\r\n return $http.put(baseUrl + baseUrlApi + url, data, {\r\n headers : {\r\n \"X-Auth-Token\" : token\r\n }\r\n });\r\n }\r\n\r\n i.authDelete = function(url) {\r\n if (!token) {\r\n if (i.isLoggedIn()) {\r\n $location.path('/logout');\r\n } else {\r\n $location.path('/login');\r\n }\r\n $location.replace();\r\n return;\r\n }\r\n\r\n return $http[\"delete\"] (baseUrl + baseUrlApi + url, {\r\n data: \"\",\r\n headers : {\r\n \"X-Auth-Token\" : token\r\n }\r\n });\r\n }\r\n\r\n\r\n var ps_key = \"pushSubscriptionKey\";\r\n i.isPushSubscriptionEnabled = function () {\r\n return localStorage[ps_key];\r\n }\r\n\r\n i.togglePushSubscription = function() {\r\n if(localStorage[ps_key] != '')\r\n localStorage[ps_key] = '';\r\n else \r\n localStorage[ps_key] = ps_key;\r\n console.log(localStorage[ps_key]);\r\n console.log(ps_key);\r\n console.log(localStorage[ps_key] != '');\r\n\r\n }\r\n\r\n i.getAuthToken = function() {\r\n return token;\r\n }\r\n\r\n moduleStore.serviceRepository()[\"smarttrackerService\"] = i;\r\n return i;\r\n\r\n});\r\n\nangular.module('stwo.core').factory('pushService', function($http, $location, $translate, $q, $timeout, moduleStore) {\n \n var url = null;\n \n var ws = null;\n \n var pushShouldBeConnected = false;\n var pushEnabled = false;\n \n var harvestedMessages = [];\n var nextHarvestedMessages = [];\n var pushChanged = {counter: 0};\n \n var waitingForReconnect = false;\n \n var listeners = [];\n var messageSoFar = null;\n \n function onOpen(evt) {\n console.log(\"CONNECTED\");\n }\n function onClose(evt) {\n console.log(\"DISCONNECTED, RETRYING CONNECTION IN 5000 MS\");\n if (pushShouldBeConnected) {\n if (waitingForReconnect) {\n console.log(\"RETRY CANCELLED, WAITING FOR RECONNECT\");\n return;\n }\n waitingForReconnect = true;\n $timeout(function() {\n i.reconnect();\n }, 5000, false)\n }\n }\n function onMessage(evt) {\n //console.log('onMessage', evt.data, evt.data ? evt.data.length : \"\");\n \n if (pushEnabled && evt.data) {\n try {\n nextHarvestedMessages.push(JSON.parse(evt.data));\n console.log(\"socketMessage: whole message parsable\")\n messageSoFar = null;\n } catch (err) {\n console.log(\"socketMessage: cannot parse message as JSON, adding to messageSoFar\")\n if (!messageSoFar) {\n //console.log(\"socketMessage: messageSoFar is empty\")\n messageSoFar = String(evt.data);\n } else {\n //console.log(\"socketMessage: appending to messageSoFar\")\n messageSoFar = messageSoFar + String(evt.data);\n \n try {\n //console.log(\"socketMessage: attempting to parse messageSoFar\")\n nextHarvestedMessages.push(JSON.parse(messageSoFar));\n messageSoFar = null;\n console.log(\"socketMessage: messageSoFar parsed, message ok\")\n } catch (err) {\n console.log(\"socketMessage: unable to parse messageSoFar, waiting for more\")\n }\n }\n }\n } \n }\n function onError(evt) {\n console.log(\"ERROR, RETRYING IN 5000 MS\");\n if (waitingForReconnect) {\n console.log(\"RETRY CANCELLED, WAITING FOR RECONNECT\");\n return;\n }\n waitingForReconnect = true;\n $timeout(function() {\n i.reconnect();\n }, 5000, false)\n }\n \n var util = {\n mergeState: function(obj, push) {\n if (obj.hasOwnProperty(\"tags\") && push.hasOwnProperty(\"tags\")) {\n while (obj.tags.length) {\n obj.tags.splice(0, 1);\n }\n for (var n = 0; n < push.tags.length; n++) {\n obj.tags.push(push.tags[n]);\n }\n console.log(\"Pushservice merged tags\" + obj.name)\n }\n if (obj.hasOwnProperty(\"properties\") && push.hasOwnProperty(\"properties\")) {\n while (obj.properties.length) {\n obj.properties.splice(0, 1);\n }\n for (var n = 0; n < push.properties.length; n++) {\n obj.properties.push(push.properties[n]);\n }\n console.log(\"Pushservice merged properties\" + obj.name)\n }\n },\n mergePosition: function(obj, push) {\n if (push.position && push.position.valid) {\n if (!obj.lastValidPosition) {\n obj.lastValidPosition = {valid: true};\n }\n obj.lastValidPosition.latitude = push.position.latitude;\n obj.lastValidPosition.longitude = push.position.longitude;\n obj.lastValidPosition.floor = push.position.floor;\n obj.lastValidPosition.address = push.position.address;\n if (push.position.textual && push.position.textual !== \"\") {\n obj.lastValidPosition.address = push.position.textual + (obj.lastValidPosition.address && obj.lastValidPosition.address !== \"\" ? \", \" + obj.lastValidPosition.address: \"\") ;\n }\n if(push.position.accuracy) {\n obj.lastValidPosition.accuracy = push.position.accuracy;\n }\n if(push.observation && push.observation.properties) {\n obj.lastPosition.properties = push.observation.properties;\n }\n\n obj.lastValidPosition.insideZones = push.position.insideZones;\n obj.lastValidPosition.timestamp = push.position.timestamp;\n console.log(\"Pushservice merged lat lon position\" + obj.name)\n }\n if (push.position && obj.lastPosition) {\n obj.lastPosition.timestamp = push.position.timestamp;\n }\n if (push.position && push.position.location && push.position.location.locationId) {\n if (!obj.lastValidPosition) {\n obj.lastValidPosition = {};\n }\n obj.lastValidPosition.location = push.position.location;\n obj.lastValidPosition.coordinate = push.position.coordinate;\n obj.lastValidPosition.address = push.position.address;\n if (push.position.textual && push.position.textual !== \"\") {\n obj.lastValidPosition.address = push.position.textual + (obj.lastValidPosition.address && obj.lastValidPosition.address !== \"\" ? \", \" + obj.lastValidPosition.address: \"\");\n }\n console.log(\"Pushservice merged indoor position\" + obj.name)\n }\n }\n }\n \n var i = {};\n \n i.listen = function(processFn) {\n listeners.push(processFn);\n }\n \n i.processNewPushMessages = function() {\n harvestedMessages = nextHarvestedMessages;\n \n for (var m = 0; m < harvestedMessages.length; m++) {\n for (var n = 0; n < listeners.length; n++) {\n listeners[n](harvestedMessages[m], util);\n }\n }\n if (nextHarvestedMessages.length > 0) {\n pushChanged.counter++;\n }\n nextHarvestedMessages = [];\n }\n\n \n i.process = function(processFn) {\n for (var n = 0; n < harvestedMessages.length; n++) {\n processFn(harvestedMessages[n], util);\n }\n }\n \n i.changed = function() {\n return pushChanged;\n }\n \n i.configure = function(token, user, customer, provider) {\n url = moduleStore.serviceRepository()[\"smarttrackerService\"].url();\n \n if (url.indexOf(\"/\") === 0) {\n url = window.location.protocol.toLowerCase() + \"//\" + window.location.hostname + (window.location.port ? \":\" + window.location.port : '') + url;\n }\n \n url = url.replace(\"http\", \"ws\").replace(\"/web/\", \"/push/\") + \"api3/\" + customer + \"/event?X-Auth-Token=\" + token;\n \n if (pushEnabled && pushShouldBeConnected && ws && ws.readyState < 2) {\n i.reconnect();\n }\n }\n \n i.enabled = function (newPushEnabledValue) {\n pushEnabled = newPushEnabledValue;\n if (pushEnabled && pushShouldBeConnected && (!ws || ws.readyState > 1)) {\n i.reconnect();\n }\n }\n \n i.reconnect = function() {\n waitingForReconnect = false;\n if (pushEnabled) {\n ws = new WebSocket(url);\n ws.onopen = function(evt) { onOpen(evt) };\n ws.onclose = function(evt) { onClose(evt) };\n ws.onmessage = function(evt) { onMessage(evt) };\n ws.onerror = function(evt) { onError(evt) };\n }\n pushShouldBeConnected = true;\n }\n \n i.disconnect = function() {\n if (ws) {\n ws.close();\n }\n pushShouldBeConnected = false;\n }\n\n moduleStore.serviceRepository()[\"pushService\"] = i;\n return i;\n});\n\nangular.module('stwo.core').factory('socketioService', function ($http, $location, $translate, $q, $timeout, moduleStore) {\n\n // init\n var i = {\n callbacks: {},\n state: {\n connected: false,\n connecting: false,\n authenticated: false,\n },\n };\n\n // Function: Connect\n i.connect = function(){\n\n // service\n var smarttrackerService = moduleStore.serviceRepository()[\"smarttrackerService\"];\n\n // check already connected\n if(i.state.connected === true || i.state.connecting === true) { \n\n return;\n\n }\n\n // set\n i.state.connecting = true;\n\n // log\n console.log('Class: socketioService', '- Function: Connect');\n\n // create socket instance\n i.socket = io(stwoGlobal.deploymentApiUrl + '/?x-auth-token=' + smarttrackerService.getToken(), {\n transports: ['websocket']\n });\n\n i.socket.on('reconnect_attempt', function() {\n i.socket.io.opts.transports = ['polling', 'websocket'];\n });\n\n i.socket.on('connect', i.onConnect);\n i.socket.on('authenticated', i.onAuthenticated);\n i.socket.on('subscribed', i.onSubscribe);\n i.socket.on('unsubscribed', i.onUnsubscribe);\n i.socket.on('message', i.onMessage);\n\n }\n\n // Function: checkConnected\n i.isConnected = function(){\n\n return i.state.connected || false;\n\n }\n\n i.isAuthenticated = function(){\n\n return i.state.authenticated || false;\n\n }\n\n // Function: Subscribe\n i.subscribe = function(objectName, callback){\n\n // log\n console.log('Class: socketioService', '- Function: Subscribe');\n\n // check connection\n if(i.isConnected() === false || i.isAuthenticated() === false){\n\n // log\n console.log('Class: socketioService', '- Function: Subscribe', '- Error: Not connected, waiting 200ms');\n setTimeout(function(){\n\n // retry\n i.subscribe(objectName, callback)\n\n }, 250);\n return;\n\n }\n\n // save\n this.callbacks[objectName] = callback;\n\n // emit\n i.socket.emit('subscribe', objectName);\n\n }\n\n // Function: Subscribe\n i.unsubscribe = function(object){\n\n // log\n console.log('Class: socketioService', '- Function: Unsubscribe');\n\n // check connection\n if(i.isConnected() === false){\n\n // log\n console.log('Class: socketioService', '- Function: Unsubscribe', '- Error: Not connected');\n return;\n\n }\n\n // emit\n i.socket.emit('unsubscribe', object);\n\n }\n\n // Event: Connected\n i.onConnect = function(message) {\n\n // log\n console.log('Class: socketioService', '- Event: onConnect');\n\n // set connected\n i.state.connecting = false;\n i.state.connected = true;\n\n }\n\n // Event: Connected\n i.onAuthenticated = function(message) {\n\n // log\n console.log('Class: socketioService', '- Event: onAuthenticated');\n\n // set connected\n i.state.authenticated = true;\n\n }\n\n // Event: Connected\n i.onSubscribe = function(message) {\n\n // log\n console.log('Class: socketioService', '- Event: onSubscribe', '- Message:', message);\n\n }\n\n // Event: Connected\n i.onUnsubscribe = function(message) {\n\n // log\n console.log('Class: socketioService', '- Event: onUnsubscribe', '- Message:', message);\n\n }\n\n // Event: Connected\n i.onMessage = function(message) {\n\n // log\n console.log('Class: socketioService', '- Event: onMessage', '- Message:', message);\n\n // send to listeners\n var callback = i.callbacks[message.objectName];\n if(typeof callback === 'function'){\n\n // execute\n callback(message.data);\n\n }\n\n }\n\n // be done\n moduleStore.serviceRepository()[\"socketioService\"] = i;\n return i;\n\n});\nangular.module('stwo.core').factory('overlayService', function(smarttrackerService) {\n\n // constants\n var max = 100;\n var updateInProgress = false;\n\n var TIMESTAMP_KEY = \"OverlayPreviousCheckTS\";\n var OVERLAYS_KEY = \"OverlaysWhenPreviousCheck\";\n var OVERLAYS_CID_KEY = \"OverlayPreviousCustomerID\";\n\n // reload overlays\n var reloadOverlays = function(offset, elements, fn) {\n\n // don't proceed when updating\n if (updateInProgress && offset == 0) {\n\n try {\n\n // parse current cache\n fn(JSON.parse(localStorage[OVERLAYS_KEY]));\n\n } catch (e) {\n\n // fallback\n fn([])\n\n }\n return;\n\n };\n\n // set to updating\n updateInProgress = true;\n\n // defaults\n if (!elements) {\n elements = []\n }\n\n // get overlays from smarttracker\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/document/?select=@&type:equals=ACR_OVERLAY&max=\" + max + \"&offset=\" + offset + \"&sort=name&order=asc\")\n .then(function(response) {\n\n // define constants\n var data = response.data;\n elements = elements.concat(response.data.result);\n\n // paging\n if (elements.length < data.total && response.data.result.length > 0) {\n\n reloadOverlays(offset + max + 1, elements, fn);\n\n } else {\n\n // return elements\n localStorage[OVERLAYS_KEY] = JSON.stringify(elements);\n localStorage[TIMESTAMP_KEY] = Date.now();\n localStorage[OVERLAYS_CID_KEY] = smarttrackerService.getCustomerId();\n updateInProgress = false;\n\n if (fn) {\n\n fn(elements);\n\n }\n\n }\n\n });\n }\n\n // get overlays\n var i = {};\n i.getOverlays = function(fn) {\n\n // retrieve access rights\n var access = smarttrackerService.getAccessRights();\n\n // check access\n if (access['document']['get']) {\n\n // make sure keys are defined\n if (!localStorage[TIMESTAMP_KEY]) {\n localStorage[TIMESTAMP_KEY] = new Date();\n localStorage[OVERLAYS_KEY] = [];\n localStorage[OVERLAYS_CID_KEY] = smarttrackerService.getCustomerId();\n }\n\n console.log(\"DIff: \", Date.now() - localStorage[TIMESTAMP_KEY], Date.now(), localStorage[TIMESTAMP_KEY]);\n\n // check localStorage keys\n if (Date.now() - localStorage[TIMESTAMP_KEY] > 3600 * 1000 ||  localStorage[OVERLAYS_CID_KEY] != smarttrackerService.getCustomerId()) {\n\n reloadOverlays(0, [], fn);\n\n } else {\n\n try {\n\n return fn(JSON.parse(localStorage[OVERLAYS_KEY]));\n\n } catch (e) {\n\n console.log('Parsing OverlaysWhenPrevisousCheck failed, reloading overlays');\n reloadOverlays(0, [], fn);\n \n }\n\n }\n\n } else {\n\n return fn([])\n\n }\n }\n\n return i;\n});\nangular.module('stwo.core').factory('mapService', function($http, $location, smarttrackerService, overlayService) {\r\n // change these URLs accordingly\r\n\r\n var availableLayers = {\r\n osm : {\r\n code : \"osm\",\r\n name : 'OpenStreetMap',\r\n url : 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',\r\n type : 'xyz',\r\n transitionEffect: 'resize',\r\n layerParams : {\r\n maxZoom: 21,\r\n maxNativeZoom: 19,\r\n attribution: '© OpenStreetMap contributors, CC-BY-SA'\r\n }\r\n }\r\n //otm : {\r\n // code : \"otm\",\r\n // name : 'Thunderforest.Transport',\r\n // type : 'xyz',\r\n // url : 'https://{s}.tile.thunderforest.com/transport/{z}/{x}/{y}.png',\r\n // layerParams : {\r\n // attribution: '© OpenCycleMap, © OpenStreetMap contributors, CC-BY-SA'\r\n // }\r\n //},\r\n //nsk : {\r\n // code : \"nsk\",\r\n // name : 'Statens Kartverk',\r\n // url : 'https://opencache.statkart.no/gatekeeper/gk/gk.open_gmaps?layers=topo2&zoom={z}&x={x}&y={y}',\r\n // type : 'xyz',\r\n // layerParams : {\r\n // attribution: '© Kartverket'\r\n // }\r\n //},\r\n //ocm : {\r\n // code : \"ocm\",\r\n // name : 'Thunderforest.OpenCycleMap',\r\n // type : 'xyz',\r\n // url : 'https://{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png',\r\n // layerParams : {\r\n // attribution: '© OpenCycleMap, © OpenStreetMap contributors, CC-BY-SA'\r\n // }\r\n //}\r\n\r\n };\r\n\r\n\r\n var _chosenLayer = localStorage[\"mapLayer\"] ? localStorage[\"mapLayer\"] : \"osm\";\r\n\r\n var i = {};\r\n\r\n i.getAvailableLayers = function() {\r\n return availableLayers;\r\n }\r\n\r\n i.chosenLayer = function(layerCode) {\r\n if (layerCode) {\r\n _chosenLayer = layerCode;\r\n\r\n localStorage[\"mapLayer\"] = layerCode;\r\n }\r\n return _chosenLayer;\r\n }\r\n\r\n i.basicMapDesign = function(scope, leafletData, mapId){\r\n scope.layers = {\r\n baselayers : angular.fromJson(angular.toJson(i.getAvailableLayers()))\r\n };\r\n scope.savedCenters = {\r\n osloCenter : { //Changed to The Netherlands coordinates\r\n lat: 52.386617,\r\n lng: 5.799990,\r\n zoom: 8\r\n }\r\n };\r\n\r\n if (navigator.geolocation) {\r\n navigator.geolocation.getCurrentPosition(function(position) {\r\n if (position.coords) {\r\n scope.savedCenters.osloCenter.lat = position.coords.latitude;\r\n scope.savedCenters.osloCenter.lng = position.coords.longitude;\r\n }\r\n })\r\n }\r\n\r\n leafletData.getMap(mapId).then(function (map) {\r\n /*map.zoomControl.setPosition(\"bottomright\");*/\r\n\r\n var l = i.getAvailableLayers();\r\n\r\n for (var k in l) {\r\n if (!scope.layers.baselayers[k]) {\r\n scope.layers.baselayers[k] = l[k];\r\n }\r\n }\r\n\r\n var layersToDelete = [];\r\n for (var k in scope.layers.baselayers) {\r\n if (k !== _chosenLayer) {\r\n layersToDelete.push(k);\r\n }\r\n }\r\n for (var n = 0; n < layersToDelete.length; n++) {\r\n delete scope.layers.baselayers[layersToDelete[n]]\r\n }\r\n\r\n });\r\n };\r\n\r\n var SELECTED_OVERLAY_KEY = \"selectedOverlayLevel\";\r\n i.selectedOverlayLevel = function() {\r\n var selectedOverlayLevel = localStorage[SELECTED_OVERLAY_KEY];\r\n if(!selectedOverlayLevel) {\r\n localStorage[SELECTED_OVERLAY_KEY] = \"0\";\r\n selectedOverlayLevel = \"0\";\r\n }\r\n return selectedOverlayLevel;\r\n }\r\n \r\n i.loadOverlays = function(map, level) {\r\n if(level && level != \"\") {\r\n localStorage[SELECTED_OVERLAY_KEY] = level;\r\n } else {\r\n level = i.selectedOverlayLevel();\r\n }\r\n\r\n overlayService.getOverlays(function (overlaysList) {\r\n if(map.overlayLayer) {\r\n map.overlayLayer.setLevel(level);\r\n } else {\r\n L.layerGroup.overlay(overlaysList, level).addTo(map);\r\n }\r\n })\r\n }\r\n\r\n i.makeNamedIcon = function(name, color, icon, colorDark){\r\n if(!color){\r\n color = \"#1972B9\";\r\n }\r\n if(!colorDark){\r\n colorDark = \"#005f9e\";\r\n }\r\n if (!icon) {\r\n icon = \"mdi mdi-map-marker\";\r\n }\r\n var micon = L.divIcon({\r\n type: 'div',\r\n iconAnchor: [19, 32],\r\n className: 'myleaflet-div-icon',\r\n html: '
' + name + '
',\r\n popupAnchor: [0, 0]\r\n });\r\n return micon;\r\n };\r\n\r\n return i;\r\n}); \nangular.module('stwo.core').factory('contentCacheService', function($q, smarttrackerService) {\n var cache = {};\n \n var i = {};\n \n i.put = function(clazz, id, obj) {\n if (!cache[clazz]) {\n cache[clazz] = {};\n }\n if (cache[clazz][id]) {\n var scrubbedOfAngularVars = angular.fromJson(angular.toJson(obj));\n for (var k in scrubbedOfAngularVars) {\n cache[clazz][id][k] = scrubbedOfAngularVars[k];\n }\n } else {\n cache[clazz][id] = angular.fromJson(angular.toJson(obj));\n }\n }\n \n i.putMany = function(clazz, arr, idField) {\n var f = idField ? idField : \"id\";\n for (var n = 0; n < arr.length; n++) {\n i.put(clazz, arr[n][f], arr[n]);\n }\n }\n \n i.get = function(clazz, id) {\n if (cache[clazz] && cache[clazz][id]) {\n return cache[clazz][id];\n }\n return null;\n }\n \n var downloadCache = {};\n \n var beginDownloading = function(url, initialPromise, opts) {\n var now = (new Date()).getTime();\n var cacheId = url + (opts ? opts.max : \"\");\n var defer = $q.defer();\n \n downloadCache[cacheId] = {expiry: now + (opts && opts.timeToLive ? opts.timeToLive : 60000), url: url, inProgress: true, data: [], promises: [], downloadPromise: defer, offset: 0, max: opts && opts.max ? opts.max : 15};\n downloadCache[cacheId].promises.push(initialPromise);\n \n doDownload(downloadCache[cacheId]);\n \n return defer.promise;\n }\n \n var doDownload = function(cacheData) {\n smarttrackerService.authGet(cacheData.url + (cacheData.url.indexOf(\"?\") > 0 ? '&' : '?') + 'offset=' + cacheData.offset + '&max=' + cacheData.max).then(function(response) {\n for (var n = 0; n < response.data.result.length; n++) {\n cacheData.data.push(response.data.result[n]);\n }\n if (response.data.result.length < cacheData.max) {\n cacheData.inProgress = false;\n cacheData.downloadPromise.resolve(cacheData);\n } else {\n cacheData.offset += cacheData.max;\n doDownload(cacheData);\n }\n }, function() {\n cacheData.inProgress = false;\n cacheData.expiry = 0;\n cacheData.downloadPromise.reject();\n });\n }\n \n i.download = function(url, opts) {\n var now = (new Date()).getTime();\n var defer = $q.defer();\n var cacheId = url + (opts ? opts.max : \"\");\n \n if (downloadCache[cacheId] && !downloadCache[cacheId].inProgress && downloadCache[cacheId].expiry > now) {\n //console.log(\"Content cache hit for \" + cacheId)\n defer.resolve(downloadCache[cacheId].data);\n } else {\n //console.log(\"Content cache MISS for \" + cacheId, now, downloadCache[cacheId])\n if (downloadCache[cacheId] && downloadCache[cacheId].inProgress) {\n //console.log(\"Content cache IN PROGRESS for \" + cacheId)\n downloadCache[cacheId].promises.push(defer);\n } else {\n //console.log(\"Content cache request for \" + cacheId)\n beginDownloading(url, defer, opts).then(function(cacheData) {\n //console.log(\"Content cache request complete \" + cacheId + \" for \" + downloadCache[cacheId].promises.length + \" promises\")\n for (var n = 0; n < downloadCache[cacheId].promises.length; n++) {\n downloadCache[cacheId].promises[n].resolve(cacheData.data);\n }\n }, function() {\n //console.log(\"Content cache request fail \" + cacheId)\n for (var n = 0; n < downloadCache[cacheId].promises.length; n++) {\n downloadCache[cacheId].promises[n].reject();\n }\n })\n }\n }\n return defer.promise;\n }\n \n i.fromCache = function(url, opts) {\n var cacheId = url + (opts ? opts.max : \"\");\n \n i.download(url, opts);\n \n if (downloadCache[cacheId] && !downloadCache[cacheId].inProgress) {\n return downloadCache[cacheId].data;\n } else {\n return null;\n }\n }\n \n i.invalidate = function(urlPrefix) {\n for (var k in downloadCache) {\n if (k.indexOf(urlPrefix) === 0) {\n console.log(\"Invalidating: \" + k)\n delete downloadCache[k];\n }\n }\n }\n \n return i;\n});\nangular.module('stwo.core')\r\n .filter('notificationFromModule', function () {\r\n return function (arr, moduleId) {\r\n var out = [];\r\n if(arr) {\r\n for (var n = 0; n < arr.length; n++) {\r\n if (arr[n].module === moduleId) {\r\n out.push(arr[n]);\r\n }\r\n }\r\n return out;\r\n }\r\n };\r\n }).filter('notificationWithLevel', function () {\r\n return function (arr, level) {\r\n var out = [];\r\n if(arr) {\r\n for (var n = 0; n < arr.length; n++) {\r\n if (arr[n].level == level) {\r\n out.push(arr[n]);\r\n }\r\n }\r\n return out;\r\n }\r\n };\r\n });\r\n\r\nangular.module('stwo.core').factory('notificationService', function (moduleStore, $state, smarttrackerService, utilService) {\r\n\r\n var i = {\r\n ignored: {},\r\n changed: {dismissed: 0, added: 0, updated: 0, removed: 0},\r\n audio: {\r\n muted: false, //localStorage[\"stwo-mute\"] === \"true\", // for backwards compability\r\n snoozed: false,\r\n ignoreSnooze: localStorage[\"stwo-ignore-snooze\"] !== \"false\"\r\n }\r\n };\r\n\r\n var notifications = [];\r\n\r\n var sounds = [\r\n {'name':'Alert', 'file':'core/mp3/alarms/Alert.mp3'},\r\n {'name':'Alarm', 'file':'core/mp3/alarms/Alarm.mp3'},\r\n {'name':'What', 'file':'core/mp3/alarms/What.mp3'},\r\n {'name':'Wake Up', 'file':'core/mp3/alarms/WakeUp.mp3'},\r\n {'name':'Mirror', 'file':'core/mp3/alarms/Mirror.mp3'},\r\n {'name':'Beep Beep', 'file':'core/mp3/alarms/BeepBeep.mp3'},\r\n {'name':'Jump', 'file':'core/mp3/alarms/Jump.mp3'},\r\n {'name':'Shake', 'file':'core/mp3/alarms/Shake.mp3'},\r\n {'name':'Gooday', 'file':'core/mp3/alarms/Gooday.mp3'},\r\n {'name':'Done', 'file':'core/mp3/alarms/Done.mp3'},\r\n {'name':'Toss It', 'file':'core/mp3/alarms/TossIt.mp3'},\r\n {'name':'Tornado', 'file':'core/mp3/alarms/Tornado.mp3'},\r\n {'name':'Alarm Clock', 'file':'core/mp3/alarms/AlarmClock.mp3'},\r\n {'name':'Dive', 'file':'core/mp3/alarms/Dive.mp3'}\r\n ];\r\n\r\n i.add = function (notification) {\r\n \r\n var updated = false;\r\n\r\n notification.dismiss = i.dismiss;\r\n notification.view = i.view;\r\n\r\n for (var n = notifications.length - 1; n >= 0; n--) {\r\n if (notifications[n].id === notification.id) {\r\n notifications[n] = notification;\r\n updated = true;\r\n i.changed.updated++;\r\n\r\n if (notifications[n].level == 'warning') {\r\n Push.create(notifications[n].name, {\r\n // body: 'Warning!',\r\n icon: 'customization/images/notification-warning.png',\r\n timeout: 8000,\r\n onClick: function () {\r\n window.focus();\r\n this.close();\r\n $state.go(\"secure.content.alarm-screen-xguard-detail\", {id: notifications[n].alarmId});\r\n }\r\n });\r\n }\r\n else if (notifications[n].level == 'danger') {\r\n Push.create(notifications[n].name, {\r\n // body: 'Alarm! ID: ' + notifications[n].alarmId,\r\n icon: 'customization/images/notification-danger.png',\r\n timeout: 8000,\r\n onClick: function () {\r\n window.focus();\r\n this.close();\r\n $state.go(\"secure.content.alarm-screen-xguard-detail\", {id: notifications[n].alarmId});\r\n }\r\n });\r\n }\r\n else if (notifications[n].level == 'notification') {\r\n Push.create(notifications[n].name, {\r\n // body: 'Notification!',\r\n icon: 'customization/images/notification-normal.png',\r\n timeout: 8000,\r\n onClick: function () {\r\n window.focus();\r\n this.close();\r\n $state.go(\"secure.content.alarm-screen-xguard-detail\", {id: notifications[n].alarmId});\r\n }\r\n });\r\n }\r\n\r\n /*console.log(notifications[n]);*/\r\n break;\r\n }\r\n }\r\n if (!updated) {\r\n notifications.push(notification);\r\n i.changed.added++;\r\n }\r\n notifications.sort(function (a, b) {\r\n return a.time > b.time ? 1 : -1;\r\n })\r\n }\r\n\r\n i.remove = function (notification) {\r\n for (var n = notifications.length - 1; n >= 0; n--) {\r\n if (notifications[n].id === notification.id) {\r\n notifications.splice(n, 1);\r\n i.changed.removed++;\r\n }\r\n }\r\n }\r\n\r\n i.clear = function () {\r\n notifications.splice(0, notifications.length);\r\n i.changed.removed++;\r\n }\r\n\r\n i.silentDismiss = function (notificationId) {\r\n for (var n = notifications.length - 1; n >= 0; n--) {\r\n if (notifications[n].id === notificationId) {\r\n notifications[n].dismissed = true;\r\n i.changed.dismissed++;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n i.snooze = function() {\r\n i.audio.snoozed = true;\r\n for(var u in notifications) {\r\n console.log(\"Snoozing: \" + notifications[u].id);\r\n i.ignore(notifications[u].id);\r\n }\r\n }\r\n\r\n i.dismiss = function (notification) {\r\n var dismissFunction = function () {\r\n for (var n = notifications.length - 1; n >= 0; n--) {\r\n if (notifications[n].id === notification.id) {\r\n notifications[n].dismissed = true;\r\n i.changed.dismissed++;\r\n }\r\n }\r\n }\r\n\r\n var notificationsHandlers = moduleStore.notificationHandlers();\r\n\r\n if (notification.module && notificationsHandlers[notification.module].dismiss) {\r\n notificationsHandlers[notification.module].dismiss(notification, dismissFunction);\r\n } else {\r\n dismissFunction();\r\n }\r\n }\r\n\r\n i.view = function (notification) {\r\n\r\n var notificationsHandlers = moduleStore.notificationHandlers();\r\n\r\n if (notification.module && notificationsHandlers[notification.module].view) {\r\n notificationsHandlers[notification.module].view(notification);\r\n } else {\r\n alert(\"Viewing notifications not implemented for module \" + notification.module);\r\n }\r\n }\r\n\r\n i.poll = function () {\r\n var notificationsHandlers = moduleStore.notificationHandlers();\r\n for (var k in notificationsHandlers) {\r\n if (notificationsHandlers[k].poll) {\r\n notificationsHandlers[k].poll();\r\n }\r\n }\r\n }\r\n \r\n i.ignore = function(notificationId) {\r\n i.ignored[notificationId] = true;\r\n }\r\n\r\n i.push = function (data, util) {\r\n var notificationsHandlers = moduleStore.notificationHandlers();\r\n for (var k in notificationsHandlers) {\r\n if (notificationsHandlers[k].push) {\r\n notificationsHandlers[k].push(data, util);\r\n }\r\n }\r\n }\r\n\r\n i.list = function () {\r\n return notifications;\r\n }\r\n i.undismissed = function () {\r\n var out = [];\r\n for (var n = 0; n < notifications.length; n++) {\r\n if (!notifications[n].dismissed) {\r\n out.push(notifications[n]);\r\n }\r\n }\r\n return out;\r\n }\r\n\r\n i.getSounds = function() {\r\n return sounds;\r\n }\r\n\r\n i.checkSoundData = function(soundData) {\r\n\r\n var ret = {\r\n redAlarmSound: {muted:false, sound:sounds[0]},\r\n orangeAlarmSound: {muted:false, sound:sounds[5]},\r\n greenAlarmSound: {muted:true, sound:sounds[9]},\r\n cpAlarmSound: {muted:false, sound:sounds[2]}\r\n }\r\n\r\n if(soundData && soundData[\"redAlarmSound\"]){\r\n ret[\"redAlarmSound\"] = soundData[\"redAlarmSound\"];\r\n }\r\n\r\n if(soundData && soundData[\"orangeAlarmSound\"]){\r\n ret[\"orangeAlarmSound\"] = soundData[\"orangeAlarmSound\"]\r\n }\r\n\r\n if(soundData && soundData[\"greenAlarmSound\"]){\r\n ret[\"greenAlarmSound\"] = soundData[\"greenAlarmSound\"]\r\n } \r\n\r\n if(soundData && soundData[\"cpAlarmSound\"]){\r\n ret[\"cpAlarmSound\"] = soundData[\"cpAlarmSound\"]\r\n } \r\n\r\n return ret;\r\n\r\n }\r\n\r\n /** Test code for custom notifications*/\r\n var customNotifications = false;\r\n var ceMetaKey = 'customNotifications';\r\n\r\n\r\n i.registerNotification = function(type, message, object, params) {\r\n if(!customNotifications) {\r\n customNotifications = utilService.checkNestedProperty(smarttrackerService.getUserData() ,'user', 'preferences', 'meta', ceMetaKey)?smarttrackerService.getUserData().user.preferences.meta[ceMetaKey]:[]\r\n }\r\n customNotifications = customNotifications?customNotifications:[];\r\n for(var i = 0; i < customNotifications.length;i++){\r\n var n = customNotifications[i];\r\n if(n.message == message &&(object&&n.object&&object.id===n.object.id)) {\r\n return; // Already added\r\n }\r\n }\r\n var ev = {\r\n createdDate: moment().utc().format(\"YYYY-MM-DDTHH:mm:ss.SSS\"), \r\n object:object, \r\n type:type, \r\n message:message, \r\n messageValues:params\r\n };\r\n customNotifications.push(ev);\r\n saveCustomNotifications();\r\n i.changed.added++;\r\n }\r\n\r\n i.dismissCustomNotification = function(notification, preventSave) {\r\n var index = customNotifications.indexOf(notification);\r\n if(index > -1) {\r\n i.changed.dismissed++;\r\n customNotifications =customNotifications.length == 1?[]: customNotifications.splice(index, 1); // splice doesn't work for arrays with on element for some reason\r\n if(!preventSave) {\r\n saveCustomNotifications();\r\n }\r\n }\r\n }\r\n\r\n i.dismissCustomNotifiactionsForObject = function(object) {\r\n var cn = utilService.clone(customNotifications);\r\n angular.forEach(cn, function (notification){\r\n i.dismissCustomNotification(notification, true);\r\n });\r\n saveCustomNotifications();\r\n \r\n }\r\n var saveCustomNotifications = function() {\r\n var data = smarttrackerService.getUserData();\r\n if(data.user&&data.user.preferences&&data.user.preferences.meta) {\r\n data.user.preferences.meta[ceMetaKey] = customNotifications;\r\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + \"/index\", {user:data.user});\r\n }\r\n }\r\n\r\n i.customNotifications = function() {\r\n if(!customNotifications) {\r\n customNotifications = utilService.checkNestedProperty(smarttrackerService.getUserData() ,'user', 'preferences', 'meta', ceMetaKey)?smarttrackerService.getUserData().user.preferences.meta[ceMetaKey]:[]\r\n }\r\n return customNotifications;\r\n }\r\n\r\n i.notificationTypes = function() {\r\n return {\r\n invitation:{icon:'mdi mdi-account-switch', state:'secure.user', title:'NOTIFICATION_TYPE_INVITATION'}\r\n };\r\n }\r\n /** End Test code for custom notifications*/\r\n\r\n moduleStore.serviceRepository()[\"notificationService\"] = i;\r\n return i;\r\n});\nangular.module('stwo.core').factory('favoritesService',\n function($localStorage) {\n\n\n // if favorites do not exist, create it\n if (!$localStorage.favorites) {\n $localStorage.favorites = {};\n }\n\n // at the end just take the favorites from the local storage\n var favorite = $localStorage.favorites;\n\n var i = {};\n\n i.favorites = function() {\n return favorite;\n }\n\n i.favoritesOfClazz = function(clazz) {\n if (!favorite[clazz]) {\n favorite[clazz] = {};\n }\n\n return favorite[clazz];\n }\n\n i.toggle = function(clazz, id) {\n // create any piece of favorites which does not exist\n if (!favorite[clazz]) {\n favorite[clazz] = {};\n }\n\n favorite[clazz][id] = !(true && favorite[clazz][id]);\n }\n\n i.isFavorite = function(clazz, id) {\n if (!favorite[clazz]) {\n favorite[clazz] = {};\n }\n\n return (true && $localStorage.favorites[clazz][id]);\n }\n\n //return the favorites of clazz as an array (use .join if string is needed)\n i.getListOfFavorites = function(clazz) {\n if (!favorite[clazz]) {\n favorite[clazz] = {};\n }\n\n var outArray = [];\n\n for (var k in favorite[clazz]) {\n if (favorite[clazz][k]) {\n outArray.push(k);\n }\n }\n\n return outArray;\n }\n\n return i;\n });\nangular.module('stwo.core').service('colorService', function () {\n\n return {\n toUpper: function (item) {\n return item.toUpperCase()\n },\n\n alarmColor: function (item) {\n\n // First one is the log level and the\n // second one is the class what needs to be added\n var danger = [\n 'red_alert',\n 'text-danger'\n ],\n warning = [\n 'warning',\n 'text-warning'\n ],\n success = [\n 'notification',\n 'text-success'\n ];\n\n if (item.logLevelFormatted == null) {\n return danger[1]\n }\n\n else {\n if (item.logLevelFormatted == success[0]) {\n return success[1]\n }\n else if (item.logLevelFormatted == danger[0]) {\n return danger[1]\n }\n else if (item.logLevelFormatted == warning[0]) {\n return warning[1]\n }\n }\n },\n\n rangeColor: function (item) {\n var success = [\n 0, 15,\n 'text-success'\n ],\n warning = [\n 15, 40,\n 'text-warning'\n ],\n danger = [\n 'text-danger'\n ];\n\n if (item.logLevelFormatted == null) {\n if (item.lastValidPosition.source.type == 'beacon') {\n return success[2]\n }\n else {\n if (item.lastValidPosition.accuracy > success[0] && item.lastValidPosition.accuracy <= success[1]) {\n return success[2]\n }\n else if (item.lastValidPosition.accuracy > warning[0] && item.lastValidPosition.accuracy <= warning[1]) {\n return warning [2]\n }\n else {\n return danger[0]\n }\n }\n }\n\n else {\n if (item.position.source.type == 'beacon') {\n return success[2]\n }\n else {\n if (item.position.accuracy > success[0] && item.position.accuracy <= success[1]) {\n return success[2]\n }\n else if (item.position.accuracy > warning[0] && item.position.accuracy <= warning[1]) {\n return warning [2]\n }\n else {\n return danger[0]\n }\n }\n }\n }\n };\n});\nangular.module('stwo.core').service('googlemapsService', function () {\n return {\n googleMaps: function (lat, lng, address) {\n\n var addressString = lat + ',' + lng;\n if (typeof address === 'string') {\n\n addressString = encodeURIComponent(address);\n\n }\n\n var isiOS = stwoPushNotificationInfo !== null && stwoPushNotificationInfo.type === 'IOS_DEVICE';\n\n if (isiOS || (/iPad|iPhone|iPod|iPad Simulator|iPhone Simulator|iPod Simulator/.test(navigator.userAgent) && !window.MSStream)) {\n\n console.log('opening Apple maps popup to', addressString)\n return window.location.assign('maps://maps.apple.com/maps?daddr=' + addressString + '&ll=');\n \n } else {\n\n console.log('opening Google maps popup to', addressString)\n return window.location.assign('http://maps.google.com?daddr=' + addressString + '&ll=');\n\n }\n }\n };\n});\nangular.module('stwo.core').service('indoorService', function () {\n\n return {\n toUpper: function (item) {\n return item.toUpperCase()\n },\n\n indoor: function (item) {\n var icons = [\n 'mdi-home',\n 'mdi-earth'\n ]\n\n if (item.position.source == null) {\n return\n }\n\n else {\n if (item.position.source.type == 'beacon') {\n return icons[0]\n }\n else {\n return icons[1]\n }\n }\n }\n };\n});\nangular.module('stwo.core').factory('dialogService', function($modal) {\n\n var i = {};\n\n i.prompt = function(title, text, config) {\n var cfg = {title: title, text: text};\n\n for (var k in config) {\n cfg[k] = config[k];\n }\n\n\n return $modal.open({\n templateUrl: 'core/html/prompt.html',\n controller: stwoCoreDialogPromptModalController,\n size: \"md\",\n resolve: {\n promptConfiguration: function() { return cfg }\n }\n }).result;\n }\n\n i.raiseAlarm = function(title, text, config) {\n var cfg = {title:title, text:text};\n for (var k in config) {\n cfg[k] = config[k];\n }\n\n cfg[\"alarmType\"] = \"0\";\n\n return $modal.open({\n templateUrl: 'core/html/raise_alarm.html',\n controller: stwoCoreDialogRaiseAlarmModalController,\n size: \"md\",\n resolve: {\n promptConfiguration: function() { return cfg }\n }\n }).result;\n }\n\n i.getPosition = function(title, text, config) {\n cfg = {title:title, text:text};\n angular.forEach(config, function (v, k) {\n cfg[k] = v;\n });\n console.log(cfg, config);\n return $modal.open({\n templateUrl: 'core/html/positionPicker.html', \n controller: stwoCoreDialogPositionPickerModalController, \n size:'lg', \n resolve: {\n promptConfiguration: function() {return cfg;}\n }\n });\n }\n\n i.alert = function(title, text, config) {\n cfg = {title:title, text:text};\n angular.forEach(config, function (v, k) {\n cfg[k] = v;\n });\n return $modal.open({\n templateUrl: 'core/html/alertDialog.html', \n controller: stwoDialogAlertModalController, \n size:'md', \n resolve: {\n configuration: function() {return cfg;}\n }\n }).result;\n }\n\n i.wait = function(title, text, config ) {\n var cfg = {title: title, text: text, showWaitButtons:false};\n\n for (var k in config) {\n cfg[k] = config[k];\n }\n return $modal.open({\n templateUrl: 'core/html/working.html',\n controller: stwoCoreDialogPromptModalController,\n size: \"md\",\n resolve: {\n promptConfiguration: function() { return cfg }\n }\n });\n }\n\n return i;\n});\n\nvar stwoCoreDialogPromptModalController = function ($scope, $modalInstance, promptConfiguration) {\n\n $scope.title = promptConfiguration.title;\n $scope.text = promptConfiguration.text;\n $scope.multiline = promptConfiguration.multiline;\n $scope.disablePromptText = promptConfiguration.disablePromptText;\n $scope.nullAllowed = promptConfiguration.nullAllowed;\n $scope.prompt = {text: promptConfiguration.promptText ? promptConfiguration.promptText : \"\"};\n $scope.placeHolder = promptConfiguration.placeHolder ? promptConfiguration.placeHolder : \"\";\n\n $scope.cancelButtonText = promptConfiguration.cancelButtonText ? promptConfiguration.cancelButtonText : \"DIALOG_PROMPT_CANCEL\";\n $scope.cancelButton = promptConfiguration.cancelButton;\n\n $scope.okButtonText = promptConfiguration.okButtonText ? promptConfiguration.okButtonText : \"DIALOG_PROMPT_OK\";\n $scope.nullButtonText = promptConfiguration.nullButtonText ? promptConfiguration.nullButtonText : \"DIALOG_PROMPT_NULL\";\n\n $scope.emptyRestricted = promptConfiguration.emptyRestricted;\n\n $scope.deleteButtonText = promptConfiguration.deleteButtonText ? promptConfiguration.deleteButtonText : \"DIALOG_PROMPT_DELETE\";\n $scope.deleteButton = promptConfiguration.deleteButton;\n\n $scope.cancelDisallowed = promptConfiguration.cancelDisallowed;\n\n $scope.genericData = promptConfiguration.data;\n\n $scope.pickNull = function() {\n $modalInstance.close({data: $scope.genericData, promptText: null});\n }\n\n $scope.ok = function() {\n $modalInstance.close({data: $scope.genericData, promptText: $scope.prompt.text});\n }\n\n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n};\n\n\n\nvar stwoCoreDialogPositionPickerModalController = function($scope, $modalInstance, promptConfiguration, leafletData, mapService, $http, $timeout, addressService, smarttrackerService) {\n\n mapService.basicMapDesign($scope, leafletData);\n $scope.title = promptConfiguration.title;\n $scope.text = promptConfiguration.text;\n \n $scope.paths = [];\n \n $scope.TCAString = \"\";\n $scope.addressSelected = function(data) {\n var pos = data.point;\n $scope.map.setView(pos, 17);\n if($scope.marker){\n $scope.marker.setLatLng(pos);\n } else{\n createMarker(pos);\n $scope.marker.addTo($scope.map);\n }\n $scope.TCAString = data.TCAString;\n }\n \n\n var createMarker = function(loc){\n var micon = L.divIcon({\n type: 'div',\n iconAnchor: [18, 32],\n className: 'myleaflet-div-icon',\n html: '
'\n });\n $scope.marker = new L.Marker(loc, {icon:micon, draggable:true});\n }\n\n $scope.mapData = {\n center:{\n lat: 52.386617,\n lng: 5.799990,\n zoom: 8\n },\n defaults : {\n dragging: true,\n maxZoom: 21\n },\n events: {\n map: {\n enable:['dragstart', 'zoomstart', 'click'], \n logic:'emit'\n }\n }\n };\n leafletData.getMap().then(function (map){\n $scope.map = map;\n var customerMapData = smarttrackerService.getUserData().customer.map.center;\n map.setView(new L.LatLng(promptConfiguration.position?promptConfiguration.position.latitude:customerMapData.latitude,\n promptConfiguration.position?promptConfiguration.position.longitude:customerMapData.longitude), customerMapData.zoom);\n \n console.log(promptConfiguration.position);\n console.log(smarttrackerService.getUserData());\n \n if(promptConfiguration.position) {\n var pos = promptConfiguration.position;\n var loc = new L.LatLng(pos.latitude, pos.longitude);\n createMarker(loc);\n $scope.marker.addTo(map);\n } \n map.on('click', function mapClickListen(e){\n var loc = new L.LatLng(e.latlng.lat, e.latlng.lng);\n\n if($scope.marker){\n $scope.marker.setLatLng(loc);\n } else {\n createMarker(loc);\n $scope.marker.addTo(map);\n }\n addressService.addressByCoordinates(loc.lat, loc.lng).then(function (address){\n //$scope.addressData.selectedAddress = address;\n var a = address.address;\n // Tellu Cloud Address String\n $scope.TCAString = (a.road?a.road + \" \" :'') + (a.house_number?a.house_number:'') + \", \" + a.county + \", \" + a.postcode + \", \" + a.country_code;\n }, function (error){\n console.error(\"Something went wrong when communicateing with address api\", error);\n });\n });\n $timeout(function () {\n map.invalidateSize();\n }, 200);\n });\n\n $scope.ok = function() {\n var loc = $scope.marker.getLatLng();\n console.log(loc);\n $modalInstance.close({data:{position:loc, address:$scope.TCAString}});\n }\n\n $scope.cancel = function() {\n $modalInstance.dismiss('cancel');\n }\n}\n\nvar stwoDialogAlertModalController = function($scope, $modalInstance, configuration) {\n $scope.title = configuration.title;\n $scope.text = configuration.text;\n $scope.okButtonText = configuration.okButtonText ? configuration.okButtonText : \"DIALOG_PROMPT_OK\";\n $scope.cancelButtonText = configuration.cancelButtonText ? configuration.cancelButtonText : 'DIALOG_PROMPT_CANCEL';\n $scope.cancelButton = configuration.cancelButton;\n\n $scope.cancel = function() {\n $modalInstance.dismiss('cancel');\n }\n\n $scope.ok = function() {\n $modalInstance.close({'title':$scope.title, 'text':$scope.text});\n }\n}\n\nvar stwoCoreDialogRaiseAlarmModalController = function ($scope, $modalInstance, promptConfiguration) {\n\n $scope.title = promptConfiguration.title;\n $scope.text = promptConfiguration.text;\n $scope.multiline = true && promptConfiguration.multiline;\n $scope.disablePromptText = true && promptConfiguration.disablePromptText;\n $scope.nullAllowed = true && promptConfiguration.nullAllowed;\n $scope.prompt = {text: promptConfiguration.promptText ? promptConfiguration.promptText : \"\", alarmType:promptConfiguration.alarmType?promptConfiguration.alarmType:\"\"};\n $scope.placeHolder = promptConfiguration.placeHolder ? promptConfiguration.placeHolder : \"\";\n $scope.cancelButtonText = promptConfiguration.cancelButtonText ? promptConfiguration.cancelButtonText : \"DIALOG_PROMPT_CANCEL\";\n $scope.okButtonText = promptConfiguration.okButtonText ? promptConfiguration.okButtonText : \"DIALOG_PROMPT_OK\";\n $scope.nullButtonText = promptConfiguration.nullButtonText ? promptConfiguration.nullButtonText : \"DIALOG_PROMPT_NULL\";\n\n $scope.genericData = promptConfiguration.data;\n\n $scope.pickNull = function() {\n $modalInstance.close({data: $scope.genericData, promptText: null});\n }\n\n $scope.ok = function() {\n $modalInstance.close({data: $scope.genericData, promptText: $scope.prompt.text, alarmType:$scope.prompt.alarmType});\n }\n\n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n};\nangular.module('stwo.core').factory('decorationService', function(moduleStore) {\n\n var i = {};\n \n var decorations = [];\n var temporaryDecorations = [];\n var status = {downloading: false};\n var offset = 0;\n \n var colors = [\"aqua\", \"aquamarine\", \"darkturquoise\", \"lightseagreen\", \"mediumaquamarine\", \"mediumturquoise\", \"paleturquoise\", \"turquoise\", \"aliceblue\", \"blue\", \"blueviolet\", \"cornflowerblue\", \"darkblue\", \"deepskyblue\", \"dodgerblue\", \"lightblue\", \"lightskyblue\", \"lightsteelblue\", \"mediumblue\", \"midnightblue\", \"navy\", \"powderblue\", \"royalblue\", \"skyblue\", \"steelblue\", \"bisque\", \"blanchedalmond\", \"brown\", \"burlywood\", \"chocolate\", \"cornsilk\", \"darkgoldenrod\", \"goldenrod\", \"maroon\", \"peru\", \"rosybrown\", \"saddlebrown\", \"sandybrown\", \"sienna\", \"tan\", \"wheat\", \"cadetblue\", \"cyan\", \"darkcyan\", \"lightcyan\", \"teal\", \"dimgray\", \"gray\", \"antiquewhite\", \"azure\", \"beige\", \"black\", \"darkgray\", \"darkgrey\", \"darkslategray\", \"darkslategrey\", \"dimgrey\", \"floralwhite\", \"gainsboro\", \"ghostwhite\", \"grey\", \"honeydew\", \"ivory\", \"lavenderblush\", \"lightgrey\", \"lightslategrey\", \"linen\", \"mintcream\", \"mistyrose\", \"navajowhite\", \"oldlace\", \"seashell\", \"silver\", \"slategray\", \"slategrey\", \"snow\", \"white\", \"whitesmoke\", \"chartreuse\", \"darkgreen\", \"darkolivegreen\", \"darkseagreen\", \"forestgreen\", \"green\", \"greenyellow\", \"lawngreen\", \"lightgreen\", \"lime\", \"limegreen\", \"mediumseagreen\", \"mediumspringgreen\", \"olive\", \"olivedrab\", \"palegreen\", \"seagreen\", \"springgreen\", \"yellowgreen\", \"lightgray\", \"lightslategray\", \"coral\", \"darkorange\", \"gold\", \"orange\", \"orangered\", \"tomato\", \"deeppink\", \"hotpink\", \"lightpink\", \"mediumvioletred\", \"palevioletred\", \"pink\", \"darkmagenta\", \"darkorchid\", \"darkslateblue\", \"darkviolet\", \"fuchsia\", \"indigo\", \"lavender\", \"magenta\", \"mediumorchid\", \"mediumpurple\", \"mediumslateblue\", \"orchid\", \"plum\", \"purple\", \"slateblue\", \"thistle\", \"violet\", \"crimson\", \"darkred\", \"darksalmon\", \"firebrick\", \"indianred\", \"lightcoral\", \"red\", \"salmon\", \"lightsalmon\", \"darkkhaki\", \"khaki\", \"lemonchiffon\", \"lightgoldenrodyellow\", \"lightyellow\", \"moccasin\", \"palegoldenrod\", \"papayawhip\", \"peachpuff\", \"yellow\"];\n \n function changeCSS(sheetId, selector, property, value){\n var s = document.getElementById(sheetId).sheet;\n var rules = s.cssRules || s.rules;\n for(var i = rules.length - 1, found = false; i >= 0 && !found; i--){\n var r = rules[i];\n if(r.selectorText == selector){\n r.style.setProperty(property, value);\n found = true;\n }\n }\n if(!found){\n s.insertRule(selector + '{' + property + ':' + value + ';}', rules.length);\n }\n }\n \n for (var n = 0; n < colors.length; n++) {\n var tc = tinycolor(colors[n]);\n changeCSS(\"decoration-styles\", '.decorative-color-' + colors[n],\"background-color\", colors[n]);\n changeCSS(\"decoration-styles\", '.decorative-color-' + colors[n],\"border-color\", colors[n]);\n changeCSS(\"decoration-styles\", '.decorative-color-' + colors[n],\"color\", \n tinycolor.mostReadable(colors[n], [\"#FFF\"],{includeFallbackColors:true,level:\"AAA\",size:\"small\"}).toHexString()\n );\n }\n \n i.colors = function() {\n return colors;\n }\n \n i.find = function(itemType, item, partType, specificPart) {\n if (itemType === \"location\") {\n if (item.connectedTo && item.connectedTo.length > 0) {\n for (var n = 0; n < item.connectedTo.length; n++) {\n if (item.connectedTo[n].from.type === \"asset\" || item.connectedTo[n].from._type === \"asset\") {\n return i.find(\"asset\", item.connectedTo[n].from, partType, specificPart);\n } else if (item.connectedTo[n].to.type === \"asset\" || item.connectedTo[n].to._type === \"asset\") {\n return i.find(\"asset\", item.connectedTo[n].to, partType, specificPart);\n }\n }\n }\n } else {\n var effect = null;\n \n var mergeInDecoration = function(effect, decoration) {\n if (!effect) {\n effect = {behaviour: null, color: null, image: null};\n }\n if (decoration.image && !effect.image) {\n effect.image = decoration.image;\n }\n if (decoration.behaviour && !effect.behaviour) {\n effect.behaviour = decoration.behaviour;\n }\n if (decoration.color && !effect.color) {\n effect.color = decoration.color;\n }\n \n return effect;\n }\n \n for (var n = 0; n < decorations.length; n++) {\n var d = decorations[n];\n\n if (d.type === \"tag\" && item.tags && (!partType || partType === \"tag\")) {\n for (var nt = 0; nt < item.tags.length; nt++) {\n if (item.tags[nt].name === d.filter.value && (!partType || (!specificPart || specificPart === item.tags[nt].name))) {\n effect = mergeInDecoration(effect, d);\n }\n }\n } else if (d.type === \"property\" && item.properties && (!partType || partType === \"property\")) {\n for (var nt = 0; nt < item.properties.length; nt++) {\n var p = item.properties[nt];\n\n if (p.name === d.filter.key && (!partType || (!specificPart || specificPart.typePropertyIdentifier === p.typePropertyIdentifier))) {\n if (angular.isDefined(p.numberValue) && p.numberValue !== null && !isNaN(p.numberValue)) {\n if (d.filter.value !== null) {\n try {\n if (parseFloat(d.filter.value) === p.numberValue) {\n effect = mergeInDecoration(effect, d);\n }\n } catch (err) {\n\n }\n }\n if (d.filter.minimum === null && d.filter.maximum !== null) {\n if (p.numberValue <= d.filter.maximum) {\n effect = mergeInDecoration(effect, d);\n }\n } else if (d.filter.minimum !== null && d.filter.maximum === null) {\n if (p.numberValue >= d.filter.minimum) {\n effect = mergeInDecoration(effect, d);\n }\n } else if (d.filter.minimum !== null && d.filter.maximum !== null) {\n if (p.numberValue >= d.filter.minimum && p.numberValue <= d.filter.maximum) {\n effect = mergeInDecoration(effect, d);\n }\n }\n }\n if (angular.isDefined(p.value) && p.value !== null) {\n if (d.filter.value === p.value) {\n effect = mergeInDecoration(effect, d);\n }\n }\n }\n }\n } else if (d.type === \"battery\" && (!partType || partType === \"battery\")) {\n if (item.battery || item.battery === 0) {\n if (d.filter.minimum === null && d.filter.maximum !== null) {\n if (item.battery <= d.filter.maximum) {\n effect = mergeInDecoration(effect, d);\n }\n } else if (d.filter.minimum !== null && d.filter.maximum === null) {\n if (item.battery >= d.filter.minimum) {\n effect = mergeInDecoration(effect, d);\n }\n } else if (d.filter.minimum !== null && d.filter.maximum !== null) {\n if (item.battery >= d.filter.minimum && item.battery <= d.filter.maximum) {\n effect = mergeInDecoration(effect, d);\n }\n }\n }\n }\n }\n \n return effect;\n }\n }\n \n i.decorations = function() {\n return decorations;\n }\n \n i.status = function() {\n return status;\n }\n \n i.refresh = function() {\n if (status.downloading) {\n return;\n } else {\n status.downloading = true;\n temporaryDecorations = [];\n }\n \n var sts = moduleStore.serviceRepository()[\"smarttrackerService\"];\n \n var max = 100;\n sts.authGet(sts.getCustomerId() + '/decoration?select=*&max=' + max + \"&offset=\" + offset + \"&sort=priority&order=desc\", {onErrorDoNotRedirect: true}).then(function(response) {\n if (response && response.data && response.data.result) {\n for (var n = 0; n < response.data.result.length; n++) {\n temporaryDecorations.push(response.data.result[n]);\n }\n\n if (response.data.result.length >= max) {\n offset += max;\n downloadDecorations();\n } else {\n status.downloading = false;\n decorations.splice(0, decorations.length);\n for (var n = 0; n < temporaryDecorations.length; n++) {\n decorations.push(temporaryDecorations[n]);\n }\n }\n } else {\n status.downloading = false;\n }\n \n }, function() {\n status.downloading = false;\n });\n }\n \n moduleStore.serviceRepository()[\"decorationService\"] = i;\n return i;\n});\nangular.module('stwo.core').factory('deploymentApiService', function($http, moduleStore) {\r\n\r\n // init\r\n var i = {};\r\n var config = {\r\n base: stwoGlobal.deploymentApiUrl,\r\n }\r\n\r\n // post\r\n i.post = function(path, data){\r\n\r\n return i.request('POST', path, data);\r\n\r\n }\r\n\r\n // get\r\n i.get = function(path, data){\r\n\r\n return i.request('GET', path, data);\r\n\r\n }\r\n\r\n // delete\r\n i.delete = function(path, data){\r\n\r\n return i.request('DELETE', path, data);\r\n\r\n }\r\n\r\n // request\r\n i.request = function(method, path, data) {\r\n return $http({\r\n method : method,\r\n url : config.base + path,\r\n headers : {\r\n \"X-Auth-Token\" : localStorage.getItem('authToken'),\r\n },\r\n data: data,\r\n })\r\n }\r\n\r\n moduleStore.serviceRepository()[\"deploymentApiService\"] = i;\r\n return i;\r\n\r\n});\r\n\n\nangular.module('stwo.core').directive(\"indoorLocationViewer\", function ($injector, $modal, $timeout, smarttrackerService, indoorLocationViewerDataService, indoorLocationViewerRenderService)\n {\n return {\n restrict: 'EA',\n scope: {\n data: '='\n },\n /*\n template: \"\" + \n \"
\" +\n '' +\n '' +\n '' +\n '' +\n \"
\" + \n \"
\" + '

{{data.basePath}}

' + \"
\" + \n \"
\" + \n '
' +\n '{{marker.marker.name }}'+\n ' {{marker.marker.lastValidPosition.location.name }}' +\n '' +\n '' +\n '' +\n '' +\n '
' +\n \"
\",\n */\n \n template: \"\" + \n \"
\" +\n '' +\n '' +\n '' +\n '' +\n \"
\" + \n \"
\" + '

{{data.basePath}}

' + \"
\" + \n \"
\" + \n '
' +\n '
' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '{{marker.marker.name }}'+\n '{{marker.markerPosition.location.name }}' +\n '
' +\n '
' +\n \"
\",\n link: function(scope, element, attrs) {\n \n scope.zoomIn = function() {\n rx.ppm *= 1.5;\n drawModel();\n }\n scope.zoomOut = function() {\n rx.ppm *= 0.66667;\n if (rx.ppm < 2) {\n rx.ppm = 2;\n }\n drawModel();\n }\n scope.fitToModel = function() {\n indoorLocationViewerDataService.calculateBoundingBox(rx, mx);\n indoorLocationViewerDataService.fitToBoundingBox(rx, mx, mx.boundingBox);\n scope.zoomOut();\n drawModel();\n }\n scope.pickFloor = function() {\n var floors = [];\n \n var findFloors = function(l, floorList) {\n if (l.id && l.structureType === \"floor\") {\n floorList.push(l);\n }\n if (l._children) {\n for (var n = 0; n < l._children.length; n++) {\n findFloors(l._children[n], floorList);\n }\n }\n }\n \n findFloors(mx.hierarchy, floors);\n \n floors.sort(function(a, b) {\n if (a.path < b.path)\n return -1;\n if (a.path > b.path)\n return 1;\n return 0;\n })\n \n var modalInstance = $modal.open({\n templateUrl: 'core/js/indoorViewer/indoor-location-floor-picker-modal.html',\n controller: stwoCoreIndoorLocationFloorPickerModalController,\n size: \"lg\",\n resolve: {\n floors: function() { return floors }\n }\n });\n\n modalInstance.result.then(function (data) {\n console.log(\"new floor\", data.floor);\n \n mx.baseLocation = data.floor ? data.floor : mx.hierarchy;\n mx.rawData.basePath = data.floor ? data.floor.path : '';\n indoorLocationViewerDataService.calculateBoundingBox(rx, mx);\n indoorLocationViewerDataService.fitToBoundingBox(rx, mx, mx.boundingBox);\n\n }, function() {\n\n });\n }\n\n var dx = {progress: 0, error: null};\n \n var rx = {ctx: element.find('canvas')[0].getContext('2d'),\n canvas: element.find('canvas')[0],\n ppm: 10, centeredOnFirstMarkers: false,\n center: {x: 0, y: 0}};\n \n var mx = {locationsWithMarkers: {},\n locationsById: {},\n hierarchy: {_children: []},\n baseLocation: null,\n processedMarkers: {},\n clusteredMarkers: {},\n locationModelReady: false,\n boundingBox: null,\n rawData: scope.data\n };\n mx.baseLocation = mx.hierarchy;\n \n scope.indoorMarkers = mx.processedMarkers;\n scope.clusteredMarkers = mx.clusteredMarkers;\n \n var lastMousePosition = {x: 0, y: 0};\n \n var tappedMarker = null;\n \n var updateDimension = function() {\n $(rx.canvas)[0].width = $(rx.canvas).parent().width();\n $(rx.canvas).css(\"width\", $(rx.canvas).parent().width() + \"px\");\n $(rx.canvas)[0].height = $(rx.canvas).parent().height();\n $(rx.canvas).css(\"height\", $(rx.canvas).parent().height() + \"px\");\n drawModel();\n }\n \n var drawModel = function() {\n var now = (new Date()).getTime();\n var ctx = rx.ctx;\n if (!mx.locationModelReady) {\n if (dx.error) {\n ctx.fillStyle = \"#00F\";\n ctx.fillRect(0, 0, rx.canvas.width, rx.canvas.height);\n ctx.fillStyle = \"#FFF\";\n ctx.fillText(dx.error,10,20);\n } else if (dx.progress === 0) {\n ctx.fillStyle = \"#0F0\";\n ctx.fillRect(0, 0, rx.canvas.width, rx.canvas.height);\n ctx.fillStyle = \"#FFF\";\n ctx.fillRect(2, 2, rx.canvas.width - 4, rx.canvas.height - 4);\n\n ctx.fillStyle = \"#0F0\";\n ctx.fillRect(4, rx.canvas.height - 4, dx.progress * (rx.canvas.width - 8), 20);\n ctx.fillText(\"Waiting to download...\",10,20);\n } else {\n ctx.fillStyle = \"#00F\";\n ctx.fillRect(0, 0, rx.canvas.width, rx.canvas.height);\n ctx.fillStyle = \"#FFF\";\n ctx.fillRect(2, 2, rx.canvas.width - 4, rx.canvas.height - 4);\n\n ctx.fillStyle = \"#00F\";\n ctx.fillRect(4, rx.canvas.height - 24, dx.progress * (rx.canvas.width - 8), 20);\n ctx.fillText(\"Downloading...\",10,20);\n }\n } else {\n ctx.save();\n ctx.fillStyle = \"#FFF\";\n ctx.fillRect(0, 0, rx.canvas.width, rx.canvas.height);\n\n \n ctx.translate(rx.canvas.width / 2, rx.canvas.height / 2);\n ctx.translate(rx.center.x * rx.ppm, rx.center.y * rx.ppm);\n \n for (var n = 0; n < mx.hierarchy._children.length; n++) {\n indoorLocationViewerRenderService.overlay(rx, mx.hierarchy._children[n]);\n }\n indoorLocationViewerRenderService.grid(rx);\n\n if (mx.baseLocation.id) {\n indoorLocationViewerRenderService.location(rx, mx, false, mx.baseLocation);\n } else {\n for (var n = 0; n < mx.baseLocation._children.length; n++) {\n indoorLocationViewerRenderService.location(rx, mx, false, mx.baseLocation._children[n]);\n }\n }\n if (mx.baseLocation.id) {\n indoorLocationViewerRenderService.location(rx, mx, true, mx.baseLocation);\n } else {\n for (var n = 0; n < mx.baseLocation._children.length; n++) {\n indoorLocationViewerRenderService.location(rx, mx, true, mx.baseLocation._children[n]);\n }\n }\n \n for (var markerId in mx.processedMarkers) {\n indoorLocationViewerRenderService.marker(rx, mx, mx.processedMarkers[markerId]);\n }\n \n ctx.restore();\n }\n }\n \n scope.data.centerOnLocationId = function(locationId) {\n indoorLocationViewerDataService.updateCenterLocation(rx, mx, locationId);\n drawModel();\n }\n \n scope.$watch(\"data.location\", function(newVal) {\n indoorLocationViewerDataService.updateCenterLocation(rx, mx, newVal);\n drawModel();\n });\n \n scope.$watch(\"data.state.selected.id\", function(newVal) {\n indoorLocationViewerDataService.processMarkers(rx, mx);\n });\n scope.$watch(\"data.state.hovered.id\", function(newVal) {\n console.log(\"hovered change\", newVal)\n indoorLocationViewerDataService.processMarkers(rx, mx);\n });\n \n indoorLocationViewerDataService.updateCenterLocation(rx, mx, mx.rawData.location);\n \n var findMarkerUnderMouse = function(x, y) {\n /*\n x = x * rx.ppm + rx.center.x * rx.ppm + rx.canvas.width / 2;\n y = y * rx.ppm + rx.center.x * rx.ppm + rx.canvas.height / 2;\n */\n \n var distanceTo = function(x, y, ox, oy) {\n return Math.sqrt(Math.pow(x - ox, 2) + Math.pow(y - oy, 2));\n }\n var closest = null;\n var distance = 99999999;\n for (var markerId in mx.processedMarkers) {\n var m = mx.processedMarkers[markerId];\n var d = distanceTo(x, y, m.position.px, m.position.py);\n \n if (d < 30 && d < distance) {\n closest = m;\n distance = d;\n }\n }\n if (closest) {\n return closest;\n }\n }\n \n scope.markerClick = function(m) {\n mx.rawData.onMarkerClick(m.marker._marker ? m.marker._marker : m.marker);\n }\n \n var initialize = function(baseUrl, token, customerId) {\n console.log(\"indoorLocationViewerDirective\", \"token\", token);\n console.log(\"indoorLocationViewerDirective\", \"customerId\", customerId);\n indoorLocationViewerDataService.downloadModel(rx, mx, dx, baseUrl, token, customerId);\n drawModel();\n \n element.bind('mousedown', function (e) {\n if (e.which > 0) {\n lastMousePosition.x = e.offsetX;\n lastMousePosition.y = e.offsetY;\n \n var m = findMarkerUnderMouse(lastMousePosition.x, lastMousePosition.y);\n if (m && mx.rawData.onMarkerClick) {\n mx.rawData.onMarkerClick(m.marker._marker ? m.marker._marker : m.marker);\n }\n \n }\n });\n element.bind('mousemove', function (e) {\n \n if ((!angular.isDefined(e.buttons) && e.which) || (e.buttons && e.buttons > 0)) {\n rx.center.x += (e.offsetX - lastMousePosition.x) / rx.ppm;\n rx.center.y += (e.offsetY - lastMousePosition.y) / rx.ppm;\n e.preventDefault();\n drawModel();\n }\n \n lastMousePosition.x = e.offsetX;\n lastMousePosition.y = e.offsetY;\n \n var m = findMarkerUnderMouse(lastMousePosition.x, lastMousePosition.y);\n if (m) {\n if (!scope.data.state.hovered || scope.data.state.hovered !== m.marker) {\n $timeout(function() {\n scope.data.state.hovered = m.marker;\n indoorLocationViewerDataService.processMarkers(rx, mx);\n })\n }\n } else {\n if (scope.data.state.hovered) {\n $timeout(function() {\n scope.data.state.hovered = null;\n indoorLocationViewerDataService.processMarkers(rx, mx);\n })\n }\n }\n });\n element.bind('touchstart', function (e) {\n if (e.touches.length > 0 && e.touches[0].target.tagName === \"CANVAS\") {\n lastMousePosition.x = e.touches[0].offsetX;\n lastMousePosition.y = e.touches[0].offsetY;\n }\n e.offsetX = e.targetTouches[0].pageX - e.touches[0].target.clientTop;\n e.offsetY = e.targetTouches[0].pageY - e.touches[0].target.clientLeft;\n tappedMarker = findMarkerUnderMouse(lastMousePosition.x, lastMousePosition.y);\n });\n element.bind('touchend', function (e) {\n if (e.touches.length > 0 && e.touches[0].target.tagName === \"CANVAS\") {\n lastMousePosition.x = e.touches[0].offsetX;\n lastMousePosition.y = e.touches[0].offsetY;\n \n e.offsetX = e.targetTouches[0].pageX - e.touches[0].target.clientTop;\n e.offsetY = e.targetTouches[0].pageY - e.touches[0].target.clientLeft;\n var touchMarker = findMarkerUnderMouse(lastMousePosition.x, lastMousePosition.y);\n if (tappedMarker && touchMarker && touchMarker === tappedMarker) {\n if (mx.rawData.onMarkerClick) {\n mx.rawData.onMarkerClick(touchMarker.marker);\n }\n }\n }\n });\n element.bind('touchmove', function (e) {\n if (e.touches.length > 0 && e.touches[0].target.tagName === \"CANVAS\") {\n rx.center.x += (e.touches[0].offsetX - lastMousePosition.x) / rx.ppm;\n rx.center.y += (e.touches[0].offsetY - lastMousePosition.y) / rx.ppm;\n e.preventDefault();\n drawModel();\n \n lastMousePosition.x = e.touches[0].offsetX;\n lastMousePosition.y = e.touches[0].offsetY;\n \n e.offsetX = e.targetTouches[0].pageX - e.touches[0].target.clientTop;\n e.offsetY = e.targetTouches[0].pageY - e.touches[0].target.clientLeft;\n \n var touchMarker = findMarkerUnderMouse(lastMousePosition.x, lastMousePosition.y);\n if (!touchMarker || touchMarker !== tappedMarker) {\n tappedMarker = null;\n }\n }\n });\n \n indoorLocationViewerDataService.processMarkers(rx, mx);\n \n scope.$watch(\"data.changeCounter\", function() {\n indoorLocationViewerDataService.processMarkers(rx, mx);\n drawModel();\n });\n scope.$watch(\"data.drawCounter\", function() {\n drawModel();\n });\n }\n \n scope.data.drawCounter = 0;\n if ($injector.has(\"moduleStore\")) {\n var moduleStore = $injector.get(\"moduleStore\");\n moduleStore.serviceRepository()[\"smarttrackerService\"].isLoggedInDelayed().then(function() {\n var customerId = moduleStore.serviceRepository()[\"smarttrackerService\"].getCustomerId(); \n var token = moduleStore.serviceRepository()[\"smarttrackerService\"].getToken(); \n var baseUrl = moduleStore.serviceRepository()[\"smarttrackerService\"].url(); \n if (customerId && token) {\n initialize(baseUrl, token, customerId);\n }\n });\n }\n \n drawModel();\n \n updateDimension();\n $(window).resize(updateDimension);\n \n \n // shim layer with setTimeout fallback\n var requestAnimFrame = (function(){\n return window.requestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n function( callback ){\n window.setTimeout(callback, 1000 / 30);\n };\n })();\n\n\n // usage:\n // instead of setInterval(render, 16) ....\n \n var keepAnimating = true;\n scope.$on('$destroy', function() {\n keepAnimating = false;\n });\n var animate = function() {\n if (!keepAnimating) {\n return;\n }\n drawModel();\n requestAnimFrame(function() {\n animate();\n });\n }\n animate();\n // place the rAF *before* the render() to assure as close to\n // 60fps with the setTimeout fallback.\n } \n };\n});\nangular.module('stwo.core').factory('indoorLocationViewerDataService', function($http, pushService, decorationService) {\n \n var i = {};\n \n var assetsConnectedToLocations = {};\n \n /*\n * \n if (mx.baseLocation.id) {\n indoorLocationViewerRenderService.location(rx, mx, true, mx.baseLocation);\n } else {\n for (var n = 0; n < mx.baseLocation._children.length; n++) {\n indoorLocationViewerRenderService.location(rx, mx, true, mx.baseLocation._children[n]);\n }\n }\n */\n \n i.calculateBoundingBox = function(r, m, location, box) {\n if (!location) {\n location = m.baseLocation;\n }\n if (!box) {\n m.boundingBox = {left: 9999999, right: -9999999, top: 9999999, bottom: -9999999};\n box = m.boundingBox;\n }\n \n var shell = i.getShellRecursive(location);\n if (location && shell && shell.length) {\n for (var n = 0; n < shell.length; n++) {\n var p = i.calculateBasePosition(r, m, location, shell[n].x, shell[n].y)\n box.left = Math.min(box.left, p.x);\n box.right = Math.max(box.right, p.x);\n box.top = Math.min(box.top, p.y);\n box.bottom = Math.max(box.bottom, p.y);\n }\n }\n if (location && location._children) {\n for (var ln = 0; ln < location._children.length; ln++) {\n i.calculateBoundingBox(r, m, location._children[ln], box)\n }\n }\n }\n \n i.fitToBoundingBox = function(r, m, box) {\n var cx = -(box.left + box.right) / 2;\n var cy = -(box.top + box.bottom) / 2;\n \n var width = Math.abs(box.left - box.right);\n var height = Math.abs(box.bottom - box.top);\n \n r.center.x = cx;\n r.center.y = cy;\n \n r.ppm = Math.min((r.canvas.width - 40) / width, (r.canvas.height - 40) / height);\n }\n \n i.pushHandler = function(data, util) {\n if (data && data.object && data.object.type === \"asset\" && assetsConnectedToLocations[data.object.info.id]) {\n util.mergeState(assetsConnectedToLocations[data.object.info.id], data.object.info)\n }\n }\n \n pushService.listen(i.pushHandler);\n \n i.getShellRecursive = function(location) {\n if (location && location.shape && location.shape.shell && location.shape.shell.length > 2) {\n return location.shape.shell;\n } else {\n if (location._parent) {\n return i.getShellRecursive(location._parent);\n } else {\n return null;\n }\n }\n }\n \n i.getHeightRecursive = function(location) {\n if (location && location.shape && location.shape.height) {\n return location.shape.height;\n } else {\n if (location._parent) {\n return i.getHeightRecursive(location._parent);\n } else {\n return null;\n }\n }\n }\n i.getHolesRecursive = function(location) {\n if (location && location.shape) {\n if (location.shape.holes && location.shape.holes.length > 0) {\n return location.shape.holes;\n } else {\n return null;\n }\n } else {\n if (location._parent) {\n return i.getHolesRecursive(location._parent);\n } else {\n return null;\n }\n }\n }\n \n \n i.updateCenterLocation = function(r, m, newVal) {\n if (newVal && m.locationsById[newVal]) {\n \n if (m.baseLocation.id) {\n var potentialFloor = m.locationsById[newVal];\n \n while (potentialFloor && potentialFloor.id) {\n if (potentialFloor.structureType === \"floor\") {\n break;\n } else {\n potentialFloor = potentialFloor._parent;\n }\n }\n if (potentialFloor.structureType === \"floor\") {\n m.baseLocation = potentialFloor;\n } else {\n m.baseLocation = m.hierarchy;\n }\n }\n \n console.log(\"Center on \", m.locationsById[newVal])\n\n var newPosition = {x: 0, y: 0};\n\n var shell = i.getShellRecursive(m.locationsById[newVal]);\n if (shell) {\n var p = {x: 0, y: 0};\n var c = 0;\n for (var n = 0; n < shell.length; n++) {\n c++;\n p.x += shell[n].x;\n p.y += shell[n].y;\n }\n newPosition.x = p.x / c;\n newPosition.y = p.y / c;\n\n var p = i.calculateBasePosition(r, m, m.locationsById[newVal], newPosition.x, newPosition.y);\n newPosition.x = p.x;\n newPosition.y = p.y;\n\n r.center.x = -newPosition.x;\n r.center.y = -newPosition.y;\n }\n }\n }\n \n i.calculateBasePosition = function(r, m, location, x, y, skipTransformForParent) {\n\n\n var p = {x: x, y: y};\n\n if (!skipTransformForParent) {\n\n if (location.transformation && location.transformation.rotation && location.transformation.rotation !== 0) {\n var m = Math.sqrt(Math.pow(p.x, 2) + Math.pow(p.y, 2));\n var r = Math.atan2(p.y, p.x);\n r += ((location.transformation.rotation / 180) * Math.PI);\n p.x = Math.cos(r) * m;\n p.y = Math.sin(r) * m;\n }\n if (location.transformation &&\n location.transformation.coordinate &&\n (location.transformation.coordinate.x !== 0 || location.transformation.coordinate.y !== 0 || location.transformation.coordinate.z !== 0)) {\n p.x += location.transformation.coordinate.x;\n p.y += location.transformation.coordinate.y;\n p.z += location.transformation.coordinate.z;\n }\n }\n\n\n\n if (location && location._parent && (!m.baseLocation || location._parent.locationId !== m.baseLocation.locationId)) {\n p = i.calculateBasePosition(r, m, location._parent, p.x, p.y);\n }\n\n return p;\n }\n \n i.processMarkers = function(r, m) {\n for (var markerId in m.locationsWithMarkers) {\n delete m.locationsWithMarkers[markerId];\n }\n\n var markerFound = {};\n\n for (var markerId in m.rawData.markers) {\n\n var a = m.rawData.markers[markerId];\n \n var markerPosition = (a.logLevel || a.logLevel === 0) ? a.position : a.lastValidPosition;\n \n if (markerPosition && markerPosition.location &&\n markerPosition.location.locationId &&\n m.locationsById[markerPosition.location.locationId]) {\n\n\n markerFound[markerId] = true;\n var createdThisProcess = false;\n\n if (!m.processedMarkers[markerId]) {\n m.processedMarkers[markerId] = {};\n m.processedMarkers[markerId].position = {};\n createdThisProcess = true;\n }\n m.processedMarkers[markerId].marker = a;\n\n var newPosition = {locationId: markerPosition.location.locationId, x: markerPosition.coordinate.x, y: markerPosition.coordinate.y};\n\n if (newPosition.x === 0 && newPosition.y === 0) {\n var shell = i.getShellRecursive(m.locationsById[markerPosition.location.locationId]);\n if (shell) {\n var p = {x: 0, y: 0};\n var c = 0;\n for (var n = 0; n < shell.length; n++) {\n c++;\n p.x += shell[n].x;\n p.y += shell[n].y;\n }\n newPosition.x = p.x / c;\n newPosition.y = p.y / c;\n }\n }\n\n var p = i.calculateBasePosition(r, m, m.locationsById[markerPosition.location.locationId], newPosition.x, newPosition.y);\n newPosition.x = p.x;\n newPosition.y = p.y;\n m.processedMarkers[markerId].markerStrokeColor = a.markerStrokeColor;\n m.processedMarkers[markerId].markerPosition = markerPosition;\n\n if (createdThisProcess) {\n console.log(\"new marker\", a);\n if (!m.locationsWithMarkers[markerPosition.location.locationId]) {\n m.locationsWithMarkers[markerPosition.location.locationId] = {};\n }\n m.locationsWithMarkers[markerPosition.location.locationId][markerId] = a;\n\n m.processedMarkers[markerId].position.locationId = newPosition.locationId;\n m.processedMarkers[markerId].position.x = newPosition.x;\n m.processedMarkers[markerId].position.y = newPosition.y;\n m.processedMarkers[markerId].position.time = (new Date()).getTime();\n m.processedMarkers[markerId].previousPosition = angular.fromJson(angular.toJson(m.processedMarkers[markerId].position));\n\n } else if (m.processedMarkers[markerId]) {\n if (angular.toJson(newPosition) === angular.toJson(m.processedMarkers[markerId].position)) {\n console.log(\"same position\");\n } else {\n console.log(\"new position\");\n if (m.locationsWithMarkers[m.processedMarkers[markerId].locationId]) {\n delete m.locationsWithMarkers[m.processedMarkers[markerId].locationId][markerId];\n }\n if (!m.locationsWithMarkers[newPosition.locationId]) {\n m.locationsWithMarkers[newPosition.locationId] = {};\n }\n m.locationsWithMarkers[newPosition.locationId][markerId] = a;\n\n m.processedMarkers[markerId].previousPosition = angular.fromJson(angular.toJson(m.processedMarkers[markerId].position));\n m.processedMarkers[markerId].position.locationId = newPosition.locationId;\n m.processedMarkers[markerId].position.x = newPosition.x;\n m.processedMarkers[markerId].position.y = newPosition.y;\n m.processedMarkers[markerId].position.time = (new Date()).getTime();\n }\n }\n \n\n m.processedMarkers[markerId]._decoration = decorationService.find(\"asset\", m.processedMarkers[markerId].marker);\n console.log(\"DECO FOR \" + m.processedMarkers[markerId].marker.name, m.processedMarkers[markerId].marker , m.processedMarkers[markerId]._decoration)\n }\n \n\n\n \n if (m.processedMarkers[markerId] && markerPosition && !markerPosition.location) {\n if (m.locationsWithMarkers[newPosition.locationId]) {\n delete m.locationsWithMarkers[newPosition.locationId][markerId];\n }\n delete m.processedMarkers[markerId];\n console.log(\"remove marker\");\n }\n }\n\n\n for (var markerId in m.processedMarkers) {\n if (!markerFound[markerId]) {\n delete m.processedMarkers[markerId];\n }\n }\n \n var markersPerSpot = {};\n var spotToString = function(marker) {\n return marker.position.locationId + \"-\" + marker.position.x + \"-\" + marker.position.y\n \n }\n for (var clusterId in m.clusteredMarkers) {\n delete m.clusteredMarkers[clusterId]\n }\n for (var markerId in m.processedMarkers) {\n var s = spotToString(m.processedMarkers[markerId]);\n if (!markersPerSpot[s]) {\n markersPerSpot[s] = [];\n m.clusteredMarkers[s] = {selected: false, hovered: false, position: m.processedMarkers[markerId].position, markers: markersPerSpot[s]};\n }\n markersPerSpot[s].push(m.processedMarkers[markerId]);\n \n if (m.rawData.state.selected && m.processedMarkers[markerId].marker.id === m.rawData.state.selected.id ) {\n m.clusteredMarkers[s].selected = true;\n }\n if (m.rawData.state.hovered && m.processedMarkers[markerId].marker.id === m.rawData.state.hovered.id ) {\n m.clusteredMarkers[s].hovered = true;\n }\n }\n \n for (var spotId in markersPerSpot) {\n if (markersPerSpot[spotId].length > 1) {\n var meanC = {x: 0, y: 0};\n for (var n = 0; n < markersPerSpot[spotId].length; n++) {\n meanC.x += markersPerSpot[spotId][n].position.x;\n meanC.y += markersPerSpot[spotId][n].position.y;\n }\n for (var n = 0; n < markersPerSpot[spotId].length; n++) {\n markersPerSpot[spotId][n]._cluster = {index: n, x: meanC.x / markersPerSpot[spotId].length, y: meanC.y / markersPerSpot[spotId].length};\n }\n } else {\n for (var n = 0; n < markersPerSpot[spotId].length; n++) {\n delete markersPerSpot[spotId][n][\"_cluster\"];\n }\n }\n }\n \n // console.log(\"clusters\", m.clusteredMarkers, m.rawData.state.selected, m.rawData.state.hovered);\n }\n \n \n i.postProcess = function(r, m, flatList) {\n\n for (var n = 0; n < flatList.length; n++) {\n m.locationsById[flatList[n].locationId] = flatList[n];\n m.locationsById[flatList[n].locationId]._children = [];\n }\n\n for (var n = 0; n < flatList.length; n++) {\n var l = flatList[n];\n if (m.locationsById[l.parentLocationId]) {\n l._parent = m.locationsById[l.parentLocationId];\n l._parent._children.push(l);\n } else {\n l._parent = null;\n m.hierarchy._children.push(l);\n }\n \n if (l.connectedTo && l.connectedTo.length > 0) {\n for (var nn = 0; nn < l.connectedTo.length; nn++) {\n if (l.connectedTo[nn].from.type === \"asset\" && assetsConnectedToLocations[l.connectedTo[nn].from.id]) {\n l.connectedTo[nn].from = assetsConnectedToLocations[l.connectedTo[nn].from.id];\n l.connectedTo[nn].from[\"_type\"] = \"asset\";\n } else if (l.connectedTo[nn].to.type === \"asset\" && assetsConnectedToLocations[l.connectedTo[nn].to.id]) {\n l.connectedTo[nn].to = assetsConnectedToLocations[l.connectedTo[nn].to.id];\n l.connectedTo[nn].to[\"_type\"] = \"asset\";\n }\n }\n }\n }\n\n i.updateCenterLocation(r, m, m.rawData.location);\n m.locationModelReady = true;\n i.processMarkers(r, m);\n \n i.calculateBoundingBox(r, m);\n \n i.fitToBoundingBox(r, m, m.boundingBox);\n\n r.ppm *= 0.66667;\n if (r.ppm < 2) {\n r.ppm = 2;\n }\n\n m.rawData.drawCounter++;\n }\n \n i.downloadAssets = function(r, m, d, baseUrl, token, customerId, flatLocationList, remainingAssetsToDownloadList) {\n \n if (!remainingAssetsToDownloadList) {\n var assetIds = {};\n for (var nn = 0; nn < flatLocationList.length; nn++) {\n if (flatLocationList[nn].connectedTo && flatLocationList[nn].connectedTo.length > 0) {\n for (var n = 0; n < flatLocationList[nn].connectedTo.length; n++) {\n if (flatLocationList[nn].connectedTo[n].from.type === \"asset\") {\n assetIds[flatLocationList[nn].connectedTo[n].from.id] = true;\n } else if (flatLocationList[nn].connectedTo[n].to.type === \"asset\") {\n assetIds[flatLocationList[nn].connectedTo[n].to.id] = true;\n }\n }\n }\n }\n remainingAssetsToDownloadList = [];\n for (var k in assetIds) {\n remainingAssetsToDownloadList.push(k);\n }\n }\n \n if (remainingAssetsToDownloadList.length > 0) {\n var assetsToDownloadThisTime = [];\n for (var n = remainingAssetsToDownloadList.length - 1; n >= 0; n--) {\n if (assetsToDownloadThisTime.length >= 20) {\n break;\n }\n if (!assetsConnectedToLocations[remainingAssetsToDownloadList[n]]) {\n assetsToDownloadThisTime.push(remainingAssetsToDownloadList[n]);\n }\n remainingAssetsToDownloadList.splice(n, 1);\n }\n if (assetsToDownloadThisTime.length > 0) {\n $http.get(baseUrl + \"api3/\" + customerId + \"/asset?select=tags%2Bproperties&id:equals=\" + assetsToDownloadThisTime.join(\"%2B\"), {\n headers : {\n \"X-Auth-Token\" : token\n }\n }).then(\n function(response) {\n for (var n = 0; n < response.data.result.length; n++) {\n assetsConnectedToLocations[response.data.result[n].id] = response.data.result[n];\n }\n i.downloadAssets(r, m, d, baseUrl, token, customerId, flatLocationList, remainingAssetsToDownloadList)\n },\n function(response) {\n d.error = \"Error during load of assets\";\n }\n );\n } else {\n i.postProcess(r, m, flatLocationList);\n }\n } else {\n i.postProcess(r, m, flatLocationList);\n }\n }\n \n i.downloadModel = function(r, m, d, baseUrl, token, customerId, flatList) {\n\n if (!flatList) {\n if (sessionStorage && sessionStorage[\"stwo-location-model-cache\"]) {\n var cachedLocModel = angular.fromJson(sessionStorage[\"stwo-location-model-cache\"]);\n if (cachedLocModel[customerId]) {\n flatList = angular.fromJson(cachedLocModel[customerId]);\n i.downloadAssets(r, m, d, baseUrl, token, customerId, flatList);\n return;\n }\n }\n flatList = [];\n d.progress = 0;\n }\n \n m.rawData.drawCounter++;\n\n\n $http.get(baseUrl + \"api3/\" + customerId + \"/location?select=*&offset=\" + flatList.length + \"&max=100\", {\n headers : {\n \"X-Auth-Token\" : token\n }\n }).then(\n function(response) {\n for (var n = 0; n < response.data.result.length; n++) {\n flatList.push(response.data.result[n]);\n }\n d.progress = flatList.length / response.data.total;\n \n if (response.data.result.length === 0 || flatList.length >= response.data.total) {\n var cachedLocModel = {};\n if (sessionStorage && sessionStorage[\"stwo-location-model-cache\"]) {\n cachedLocModel = angular.fromJson(sessionStorage[\"stwo-location-model-cache\"]);\n }\n if (sessionStorage) {\n cachedLocModel[customerId] = flatList;\n sessionStorage[\"stwo-location-model-cache\"] = angular.toJson(cachedLocModel);\n }\n i.downloadAssets(r, m, d, baseUrl, token, customerId, flatList);\n } else {\n i.downloadModel(r, m, d, baseUrl, token, customerId, flatList);\n }\n \n m.rawData.drawCounter++;\n },\n function(response) {\n d.error = \"Error during load\";\n }\n );\n }\n\n return i;\n}); \nangular.module('stwo.core').factory('indoorLocationViewerRenderService', function(indoorLocationViewerDataService, decorationService) {\n \n var i = {};\n \n var overlayImages = {};\n \n \n i.grid = function(r) {\n if (stwoGlobal && stwoGlobal.indoorViewer && stwoGlobal.indoorViewer.doNotDrawGrid) {\n return;\n }\n \n var top = -r.center.y * r.ppm - r.canvas.height / 2;\n var left = -r.center.x * r.ppm - r.canvas.width / 2;\n\n r.ctx.beginPath();\n for (var x = r.ppm * Math.floor(left / r.ppm); x < (left + r.canvas.width); x += r.ppm) {\n r.ctx.moveTo(x, top);\n r.ctx.lineTo(x, r.canvas.height + top);\n }\n for (var y = r.ppm * Math.floor(top / r.ppm); y < (top + r.canvas.height); y += r.ppm) {\n r.ctx.moveTo(left, y);\n r.ctx.lineTo(left + r.canvas.width, y);\n }\n r.ctx.strokeStyle = \"rgba(0, 0, 0, 0.15)\";\n r.ctx.stroke();\n }\n \n i.text = function(r, text, x, y, fontStyle, fillStyle, shadowStyle) {\n if (fontStyle) {\n r.ctx.font = fontStyle;\n } else {\n r.ctx.font = \"bold 12px Verdana\"\n }\n if (shadowStyle) {\n r.ctx.fillStyle = shadowStyle;\n } else {\n r.ctx.fillStyle = \"rgba(255, 255, 255, 0.5)\";\n }\n r.ctx.translate(-2, -2);\n r.ctx.fillText(text, x, y);\n r.ctx.translate(4, 0);\n r.ctx.fillText(text, x, y);\n r.ctx.translate(0, 4);\n r.ctx.fillText(text, x, y);\n r.ctx.translate(-4, 0);\n r.ctx.fillText(text, x, y);\n r.ctx.translate(2, -2);\n\n r.ctx.translate(0, -2);\n r.ctx.fillText(text, x, y);\n r.ctx.translate(0, 4);\n r.ctx.fillText(text, x, y);\n r.ctx.translate(0, -2);\n\n if (fillStyle) {\n r.ctx.fillStyle = fillStyle;\n } else {\n r.ctx.fillStyle = \"#000\";\n }\n r.ctx.fillText(text, x, y);\n }\n \n \n \n i.overlay = function(r, location) {\n r.ctx.save();\n\n if (location.transformation) {\n r.ctx.translate(location.transformation.coordinate.x * r.ppm, location.transformation.coordinate.y * r.ppm);\n r.ctx.rotate((location.transformation.rotation / 180) * Math.PI);\n }\n\n if (location._children && location._children.length) {\n for (var n = 0; n < location._children.length; n++) {\n i.overlay(r, location._children[n]);\n }\n }\n\n\n if (location.meta && location.meta.overlays) {\n for (var m = 0; m < location.meta.overlays.length; m++) {\n var overlay = location.meta.overlays[m];\n\n\n\n var imageObj = overlayImages[overlay.image.url];\n if (!imageObj) {\n imageObj = new Image();\n imageObj.src = overlay.image.url;\n\n imageObj.onload = function() {\n console.log(\"Image downloaded\", imageObj.width, this);\n };\n\n overlayImages[overlay.image.url] = imageObj;\n }\n\n r.ctx.save();\n\n r.ctx.translate(overlay.transformation.coordinate.x * r.ppm, overlay.transformation.coordinate.y * r.ppm);\n r.ctx.rotate((overlay.transformation.rotation / 180) * Math.PI);\n\n\n\n if (overlay.transformation.scale > 0) {\n r.ctx.scale(r.ppm * overlay.transformation.scale, r.ppm * overlay.transformation.scale);\n }\n r.ctx.drawImage(imageObj, -imageObj.width / 2, -imageObj.height / 2);\n\n r.ctx.restore();\n }\n }\n\n r.ctx.restore();\n }\n\n\n i.marker = function(r, m, markerPosition) {\n r.ctx.save();\n \n var now = (new Date()).getTime();\n\n var p = {x: markerPosition.position.x, y: markerPosition.position.y};\n var movementTime = 200;\n\n if (now - markerPosition.position.time < movementTime) {\n var d = (now - markerPosition.position.time) / movementTime;\n //d = d * d;\n p.x = markerPosition.position.x * d + (1 - d) * markerPosition.previousPosition.x;\n p.y = markerPosition.position.y * d + (1 - d) * markerPosition.previousPosition.y;\n }\n \n var r1 = ((now % 2000) / 2000);\n var r2 = (((now + 1000) % 2000) / 2000);\n r.ctx.beginPath();\n r.ctx.arc(p.x * r.ppm, p.y * r.ppm, 15 * r1, 0, 2 * Math.PI, false);\n r.ctx.lineWidth = 3;\n if (markerPosition.markerStrokeColor && markerPosition.markerStrokeColor.indexOf(\" 1)\")) {\n r.ctx.strokeStyle = markerPosition.markerStrokeColor.replace(\" 1)\", (1 - r1));\n } else {\n r.ctx.strokeStyle = 'rgba(0, 0, 255, ' + (1 - r1) + \")\";\n }\n r.ctx.stroke();\n r.ctx.beginPath();\n r.ctx.arc(p.x * r.ppm, p.y * r.ppm, 15 * r2, 0, 2 * Math.PI, false);\n r.ctx.lineWidth = 3;\n if (markerPosition.markerStrokeColor && markerPosition.markerStrokeColor.indexOf(\" 1)\")) {\n r.ctx.strokeStyle = markerPosition.markerStrokeColor.replace(\" 1)\", (1 - r2));\n } else {\n r.ctx.strokeStyle = 'rgba(100, 150, 255, ' + (1 - r2) + \")\";\n }\n r.ctx.stroke();\n \n if (markerPosition._cluster) {\n p.y = p.y - markerPosition._cluster.index * 40 / r.ppm;\n }\n\n r.ctx.font = \"bold 12px Verdana\"\n\n var yScale = 1;\n \n var textMeasurement = r.ctx.measureText(markerPosition.marker.name);\n r.ctx.beginPath();\n \n markerPosition.position.px = markerPosition.position.x * r.ppm + r.center.x * r.ppm + r.canvas.width / 2;\n markerPosition.position.py = markerPosition.position.y * r.ppm + r.center.y * r.ppm + r.canvas.height / 2;\n markerPosition.position.style = {left: markerPosition.position.px, top: markerPosition.position.py};\n\n r.ctx.restore();\n }\n\n i.location = function(r, m, textOnly, location, depth) {\n r.ctx.save();\n \n var now = (new Date()).getTime();\n\n if (!location._lastDecoRuleCheck || (now - location._lastDecoRuleCheck) > 5000) {\n location._decoration = decorationService.find(\"location\", location);\n location._gradient = null;\n location._lastDecoRuleCheck = now;\n }\n\n if (!depth) {\n depth = \"above\";\n }\n\n var locationHasMarkers = false\n for (var k in m.locationsWithMarkers[location.locationId]) {\n depth = \"current\";\n locationHasMarkers = true\n }\n\n if (location.transformation) {\n r.ctx.translate(location.transformation.coordinate.x * r.ppm, location.transformation.coordinate.y * r.ppm);\n r.ctx.rotate((location.transformation.rotation / 180) * Math.PI);\n }\n\n var shell = indoorLocationViewerDataService.getShellRecursive(location);\n var holes = indoorLocationViewerDataService.getHolesRecursive(location);\n\n\n\n if (!textOnly) {\n if (shell && shell.length) {\n\n var colorFillStyle = null;\n if (location._decoration && location._decoration.color) {\n colorFillStyle = location._decoration.color;\n if (true || !location._gradient) {\n var bound = {};\n for (var n = 0; n < shell.length; n++) {\n bound[\"l\"] = Math.min(bound[\"l\"] ? bound[\"l\"] : 0, shell[n].x * r.ppm);\n bound[\"r\"] = Math.max(bound[\"r\"] ? bound[\"r\"] : 0, shell[n].x * r.ppm);\n bound[\"t\"] = Math.min(bound[\"t\"] ? bound[\"t\"] : 0, shell[n].y * r.ppm);\n bound[\"b\"] = Math.max(bound[\"b\"] ? bound[\"b\"] : 0, shell[n].y * r.ppm);\n }\n location._gradient=r.ctx.createRadialGradient((bound[\"l\"] + bound[\"r\"]) / 2,(bound[\"t\"] + bound[\"b\"]) / 2,\n 5,\n (bound[\"l\"] + bound[\"r\"]) / 2,(bound[\"t\"] + bound[\"b\"]) / 2,\n Math.max(Math.abs(bound[\"l\"] - bound[\"r\"]), Math.abs(bound[\"t\"] - bound[\"b\"]))\n );\n location._gradient.addColorStop(0,\"transparent\");\n location._gradient.addColorStop(1, location._decoration.color);\n }\n colorFillStyle = location._gradient;\n }\n\n r.ctx.beginPath();\n r.ctx.moveTo(shell[0].x * r.ppm, shell[0].y * r.ppm);\n for (var n = 1; n < shell.length; n++) {\n r.ctx.lineTo(shell[n].x * r.ppm, shell[n].y * r.ppm);\n }\n r.ctx.lineTo(shell[0].x * r.ppm, shell[0].y * r.ppm);\n\n\n r.ctx.lineWidth = 1;\n r.ctx.strokeStyle = \"#000\";\n r.ctx.fillStyle = \"rgba(240, 240, 240, 0.1)\";\n\n if (colorFillStyle) {\n r.ctx.fillStyle = colorFillStyle;\n }\n\n if (location.structureType === \"floor\") {\n r.ctx.lineWidth = 6;\n r.ctx.fillStyle = \"rgba(240, 240, 240, 0.3)\";\n } else if (location.structureType === \"room\") {\n r.ctx.lineWidth = 2;\n r.ctx.strokeStyle = \"#666\";\n } else {\n r.ctx.strokeStyle = \"#666\";\n }\n\n /*\n if (depth === \"current\") {\n r.ctx.lineWidth = 3;\n r.ctx.strokeStyle = \"#00F\";\n r.ctx.fillStyle = colorFillStyle ? colorFillStyle : \"rgba(200, 200, 200, 0.0)\";\n } else if (depth === \"below\") {\n r.ctx.strokeStyle = \"#000\";\n r.ctx.fillStyle = colorFillStyle ? colorFillStyle : \"rgba(255, 255, 255, 0.2)\";\n } else {\n r.ctx.strokeStyle = \"rgba(0, 0, 0, 0.2)\";\n r.ctx.fillStyle = colorFillStyle ? colorFillStyle : \"rgba(200, 200, 200, 0.00)\";\n }\n */\n r.ctx.fill();\n \n if (locationHasMarkers) {\n r.ctx.lineWidth = 3;\n r.ctx.strokeStyle = \"#00F\";\n }\n \n if (!stwoGlobal || !stwoGlobal.indoorViewer || !stwoGlobal.indoorViewer.doNotDrawLocationBorder) {\n r.ctx.stroke();\n }\n \n if (location._decoration && location._decoration.image) {\n var rct_l = 999999;\n var rct_r = -999999;\n var rct_t = 999999;\n var rct_b = -999999;\n \n for (var n = 0; n < shell.length; n++) {\n rct_l = Math.min(rct_l, shell[n].x * r.ppm);\n rct_r = Math.max(rct_r, shell[n].x * r.ppm);\n rct_t = Math.min(rct_t, shell[n].y * r.ppm);\n rct_b = Math.max(rct_b, shell[n].y * r.ppm);\n }\n \n var cx = (rct_l + rct_r) / 2;\n var cy = (rct_t + rct_b) / 2;\n \n \n\n if (overlayImages[location._decoration.image] && overlayImages[location._decoration.image].width) {\n var w = overlayImages[location._decoration.image].width;// Math.abs(rct_l - rct_r) * 0.9;\n var dw = Math.abs(rct_l - rct_r) * 0.5;\n var h = overlayImages[location._decoration.image].height; //Math.abs(rct_t - rct_b) * 0.9;\n var dh = Math.abs(rct_t - rct_b) * 0.5;\n \n if (w > dw) {\n var scale = dw / w;\n w = w * scale;\n h = h * scale;\n }\n if (h > dh) {\n var scale = dh / h;\n w = w * scale;\n h = h * scale;\n }\n \n r.ctx.drawImage(overlayImages[location._decoration.image], rct_r - w - 10, rct_b - h - 10, w, h);\n } else {\n var imageObj = overlayImages[location._decoration.image];\n if (!imageObj) {\n imageObj = new Image();\n imageObj.src = location._decoration.image;\n\n imageObj.onload = function() {\n console.log(\"Overlay decoration image downloaded\", imageObj.width, this);\n };\n\n overlayImages[location._decoration.image] = imageObj;\n }\n }\n }\n }\n if (holes) {\n for (var m = 0; m < holes.length; m++) {\n if (holes[m].length > 2) {\n r.ctx.beginPath();\n r.ctx.moveTo(holes[m][0].x * r.ppm, holes[m][0].y * r.ppm);\n for (var n = 1; n < holes[m].length; n++) {\n r.ctx.lineTo(holes[m][n].x * r.ppm, holes[m][n].y * r.ppm);\n }\n r.ctx.lineTo(holes[m][0].x * r.ppm, holes[m][0].y * r.ppm);\n r.ctx.lineWidth = 1;\n if (depth === \"current\") {\n r.ctx.strokeStyle = \"#333\";\n r.ctx.fillStyle = \"rgba(0, 0, 0, 0.7)\";\n } else if (depth === \"below\") {\n r.ctx.strokeStyle = \"rgba(0, 0, 0, 0.3)\";\n r.ctx.fillStyle = \"rgba(0, 0, 0, 0.3)\";\n } else {\n r.ctx.strokeStyle = \"rgba(0, 0, 0, 0.1)\";\n r.ctx.fillStyle = \"rgba(0, 0, 0, 0.1)\";\n }\n r.ctx.fill();\n r.ctx.stroke();\n }\n }\n }\n } else {\n if (shell || holes) {\n\n var p = {x: 0, y: 0};\n var c = 0;\n for (var n = 0; n < shell.length; n++) {\n c++;\n p.x += shell[n].x * r.ppm;\n p.y += shell[n].y * r.ppm;\n }\n\n r.ctx.font = \"12px Verdana\";\n if (depth === \"current\") {\n r.ctx.font = \"bold 14px Verdana\";\n i.text(r, location.name, p.x / c - r.ctx.measureText(location.name).width / 2, p.y / c + 10, r.ctx.font, \"rgba(0, 0, 0, 1)\", \"rgba(255, 255, 255, 1)\");\n } else if (depth === \"below\") {\n i.text(r, location.name, p.x / c - r.ctx.measureText(location.name).width / 2, p.y / c + 10, r.ctx.font, \"rgba(0, 0, 0, 1)\", \"rgba(255, 255, 255, 1)\");\n } else {\n i.text(r, location.name, p.x / c - r.ctx.measureText(location.name).width / 2, p.y / c + 10, r.ctx.font, \"rgba(0, 0, 0, 1)\", \"rgba(255, 255, 255, 1)\");\n }\n }\n }\n\n\n\n if (location._children && location._children.length) {\n for (var n = 0; n < location._children.length; n++) {\n i.location(r, m, textOnly, location._children[n], depth === \"current\" ? \"below\" : depth);\n }\n }\n\n r.ctx.restore();\n }\n\n return i;\n}); \n\n\t\nvar stwoCoreIndoorLocationFloorPickerModalController = function ($scope, $modalInstance, floors) {\n \n $scope.floors = floors;\n \n $scope.ok = function (floor) {\n $modalInstance.close({floor: floor});\n };\n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n};\nangular.module('stwo.core').directive('deviceCommands', function() {\n return {\n restrict: 'AE',\n scope: {\n commands: '=commands'\n },\n templateUrl: 'core/html/sent_command_list.html',\n controller: function($scope, $modal) {\n $scope.moreInfo = function(command) {\n $modal.open({\n templateUrl: 'core/html/sent_command_modal.html',\n controller: stwoCommonSentCommandDetailsModalController,\n size: \"lg\",\n resolve: {\n sentCommandConfiguration: function() { return {command: command} }\n }\n });\n }\n }\n };\n });\n\n\nvar stwoCommonSendCommandModalController = function ($scope, $modal, $controller, $modalInstance, smarttrackerService, sendCommandConfiguration) {\n $scope.item = null;\n $scope.itemType = null;\n $scope.availableCommands = [];\n \n $scope.chosenCommand = null;\n $scope.commandData = {};\n \n $scope.commandSent = false;\n \n if (sendCommandConfiguration.asset) {\n $scope.item = sendCommandConfiguration.asset;\n $scope.itemType = \"asset\";\n smarttrackerService.isLoggedInDelayed().then(function() {\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/asset/' + $scope.item.id + '?select=name+deviceCommands').then(function(response) {\n $scope.item = response.data.result[0];\n $scope.availableCommands = $scope.item.deviceCommands;\n });\n });\n }\n \n if (sendCommandConfiguration.device) {\n $scope.item = sendCommandConfiguration.device;\n $scope.itemType = \"device\";\n smarttrackerService.isLoggedInDelayed().then(function() {\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/device/' + $scope.item.id + '?select=name+deviceCommands').then(function(response) {\n $scope.item = response.data.result[0];\n $scope.availableCommands = $scope.item.deviceCommands;\n });\n });\n }\n \n $scope.chooseCommand = function(command) {\n $scope.chosenCommand = command;\n $scope.numParamsInChosen = 0;\n \n for (var k in $scope.commandData) {\n delete $scope.commandData[k];\n }\n if (command && command.parameters) {\n for (var k in command.parameters) {\n $scope.numParamsInChosen++;\n }\n }\n }\n \n $scope.sendCommand = function () {\n \n var dataToSend = {command: $scope.chosenCommand.name, parameters: $scope.commandData};\n if ($scope.itemType === \"asset\") {\n dataToSend[\"asset\"] = $scope.item;\n }\n if ($scope.itemType === \"device\") {\n dataToSend[\"device\"] = $scope.item;\n }\n \n $scope.commandSent = true;\n smarttrackerService.authPost(smarttrackerService.getCustomerId() + '/deviceCommand',\n [dataToSend]\n )\n .then(function(response) {\n $modalInstance.close({});\n \n $modal.open({\n templateUrl: 'core/html/sent_command_modal.html',\n controller: stwoCommonSentCommandDetailsModalController,\n size: \"lg\",\n resolve: {\n sentCommandConfiguration: function() { return {command: response.data.result[0]} }\n }\n });\n }, function(response) {\n $scope.commandSent = false;\n console.log(\"Error while posting command\", response)\n alert(\"Error while posting command\");\n });\n };\n \n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n \n \n if (sendCommandConfiguration.command) {\n $scope.chooseCommand(sendCommandConfiguration.command);\n $scope.sendCommand();\n }\n}\n\nvar stwoCommonSentCommandDetailsModalController = function ($scope, $controller, $modalInstance, smarttrackerService, sentCommandConfiguration) {\n $scope.shown = {moreInfo: false};\n\n $scope.command = sentCommandConfiguration.command;\n $scope.downloadCommand = function() {\n $scope.downloadingCommandData = true;\n return smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/deviceCommand/' + $scope.command.id + '?select=*').then(function(response) {\n $scope.command = response.data.result[0];\n $scope.lastDownload = new Date();\n $scope.downloadingCommandData = false;\n });\n }\n \n smarttrackerService.isLoggedInDelayed().then(function() {\n $scope.downloadCommand();\n });\n \n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n};\n\n\n\t\nvar stwoCommonFilterModalController = function ($scope, $timeout, $modalInstance, availableFilters, filterValues) {\n\n $scope.availableFilters = availableFilters;\n $scope.filterValues = {};\n \n for (var k in filterValues) {\n $scope.filterValues[k] = filterValues[k];\n }\n $timeout(function() {\n $('.filter-form select:first-of-type').focus();\n $('.filter-form input:first-of-type').focus();\n },100)\n \n \n for (var n = 0; n < $scope.availableFilters.length; n++) {\n var f = $scope.availableFilters[n];\n var v = $scope.filterValues[f.id];\n\n var valueFound = false;\n if (v && v !== \"\") {\n if (f.type === \"list\") {\n for (var m = 0; m < f.list.length; m++) {\n if (f.list[m].value === v) {\n valueFound = true;\n $scope.filterValues[f.id] = f.list[m];\n break;\n }\n }\n }\n }\n if (f.type === \"list\" && !valueFound) {\n $scope.filterValues[f.id] = f.list[0];\n }\n }\n \n $scope.ok = function () {\n var filterUrlString = \"\";\n \n for (var n = 0; n < $scope.availableFilters.length; n++) {\n var f = $scope.availableFilters[n];\n var v = $scope.filterValues[f.id];\n \n if (v && v !== \"\") {\n if (f.type === \"string\") {\n filterUrlString += \"&\" + f.field + \":\" + f.comparator + \"=\" + encodeURI(v);\n } else if (f.type === \"list\") {\n if (v.value && v.value !== \"\") {\n filterUrlString += \"&\" + f.field + \":\" + f.comparator + \"=\" + encodeURI(v.value);\n }\n $scope.filterValues[f.id] = v.value;\n }\n }\n }\n \n \n $modalInstance.close({filterValues: $scope.filterValues, filterUrlString: filterUrlString});\n };\n\n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n};\n\t\nvar stwoCommonMapModalController = function ($scope, $modalInstance, mapService, leafletData, mapData) {\n\n $scope.markers = mapData.markers ? mapData.markers : {};\n $scope.mapData = {\n center : (mapData.center ? mapData.center : {\n lat : 0,\n lng : 0,\n zoom : 1\t\t\t\n })\n };\n mapService.basicMapDesign($scope, leafletData);\n\n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n};\n\nangular.module('stwo.core').directive('infiniteScroll', function($timeout, $window) {\n var isAtBottom = function() {\n if ($(document).height() - 500 < this.scrollY + $window.innerHeight) {\n return true;\n } else {\n return false;\n }\n }\n \n return {\n template: '',\n restrict: \"EA\",\n scope: {\n infiniteProgress: \"=\"\n },\n link: function(scope, element, attr) {\n \n scope.$watch(\"infiniteProgress.bottom\", function(a, b) {\n if (scope.infiniteProgress && !a) {\n $timeout(function(){\n scope.infiniteProgress.bottom = isAtBottom();\n });\n } \n });\n \n if (scope.infiniteProgress) {\n $timeout(function(){\n scope.infiniteProgress.bottom = isAtBottom();\n });\n }\n //var raw = element[0]; // this should be the element handling the scrool. But in my case it seams we need the window to handle the scroll.\n angular.element($window).bind('scroll', function() {\n if (scope.infiniteProgress) {\n $timeout(function(){\n scope.infiniteProgress.bottom = isAtBottom();\n });\n }\n });\n }\n };\n});\n\nangular.module('stwo.core').controller('BaseListContentController', function ($scope, $state, $stateParams, $modal, moduleStore, favoritesService, smarttrackerService, contentCacheService) {\n $scope.filterValues = {};\n\t$scope.filterUrlString = \"\";\n\t$scope.filterChanged = 0;\n\t$scope.itemsChanged = 0;\n \n $scope.availableFilters = [];\n $scope.predefinedFilters = {};\n $scope.filterMessage = \"\";\n $scope.filterMessage2 = \"\";\n \n \n $scope.selectedItems = [];\n $scope.selectedItemsMap = {};\n $scope.favorites = {};\n \n $scope.infiniteScrollHandler = null;\n $scope.downloadProgress = {active: false};\n $scope.infiniteScrollProgress = {bottom: false};\n \n $scope.startDownload = function() {\n $scope.downloadProgress.active = true;\n }\n $scope.finishDownload = function() {\n $scope.downloadProgress.active = false;\n $scope.infiniteScrollProgress.bottom = false;\n }\n $scope.downloading = function() {\n return $scope.downloadProgress.active;\n }\n \n $scope.items = [];\n $scope.pagination = {offset: 0, total: -1, max: 30, complete: false};\n $scope.clazz = null;\n $scope.downloadUrl = null;\n\t\n $scope.refresh = function() {\n $scope.clearItems();\n $scope.downloadMore();\n }\n \n $scope.clearItems = function() {\n $scope.items.splice(0, $scope.items.length);\n $scope.pagination.offset = 0;\n $scope.pagination.next = $scope.pagination.max;\n $scope.pagination.total = -1;\n $scope.pagination.left = -1;\n $scope.pagination.complete = false;\n $scope.itemsChanged++;\n }\n $scope.downloadMore = function() {\n if (!$scope.downloadUrl) {\n return;\n }\n if ($scope.downloading()) { \n return;\n }\n if (!smarttrackerService.getCustomerId()) { \n return;\n }\n if ($scope.pagination.total === 0 || $scope.pagination.complete) { \n return;\n }\n $scope.startDownload();\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + $scope.downloadUrl + '&offset=' + $scope.pagination.offset + '&max=' + $scope.pagination.max + $scope.filterUrlString, {onErrorDoNotRedirect: true}).then(function(response) {\n for (var n = 0; n < response.data.result.length; n++) {\n $scope.items.push(response.data.result[n]);\n }\n $scope.itemsChanged++;\n $scope.pagination.offset += response.data.result.length;\n $scope.pagination.total = response.data.total;\n $scope.pagination.next = Math.min($scope.pagination.max, $scope.pagination.total - $scope.pagination.offset);\n $scope.pagination.left = $scope.pagination.total - $scope.pagination.offset;\n if (response.data.total <= $scope.pagination.offset) {\n $scope.pagination.complete = true;\n }\n contentCacheService.putMany($scope.clazz, response.data.result);\n $scope.clearSelection();\n $scope.finishDownload();\n }, function() {\n $scope.finishDownload();\n });\n }\n \n /*$scope.$watch(\"infiniteScrollProgress.bottom\", function(a, b){\n if (a && !b) {\n $scope.downloadMore();\n }\n });*/\n \n $scope.toggleSelect = function(item) {\n if ($scope.selectedItemsMap[item.id]) {\n delete $scope.selectedItemsMap[item.id];\n for (var n = $scope.selectedItems.length - 1; n >= 0; n--) {\n if ($scope.selectedItems[n].id === item.id) {\n $scope.selectedItems.splice(n, 1);\n }\n }\n } else {\n $scope.selectedItemsMap[item.id] = item;\n $scope.selectedItems.push(item);\n }\n }\n \n $scope.showFavorites = function(){\n var favoritesListAsString = favoritesService.getListOfFavorites($scope.clazz).join(\"%2B\");\n $scope.clearFilter();\n $scope.clearSelection();\n $scope.filterUrlString = \"&id:equals=\" + (favoritesListAsString.length > 0 ? favoritesListAsString : \"-1\");\n $scope.filterMessage = \"FAVORITE_ITEMS\";\n }\n\n $scope.toggleFavorite = function(id) {\n \tfavoritesService.toggle($scope.clazz, id);\n }\n $scope.isFavorite = function(id) {\n \tfavoritesService.isFavorite($scope.clazz, id);\n }\n \n $scope.clearFilter = function() {\n $scope.filterValues = {};\n $scope.filterUrlString = \"\";\n $scope.filterMessage = \"\";\n $scope.filterMessage2 = \"\";\n }\n \n $scope.clearSelection = function() {\n $scope.selectedItems = [];\n $scope.selectedItemsMap = {};\n }\n\n $scope.openFilter = function() {\n var modalInstance = $modal.open({\n templateUrl: 'core/html/filter_modal.html',\n controller: stwoCommonFilterModalController,\n size: \"lg\",\n resolve: {\n availableFilters: function() { return $scope.availableFilters },\n filterValues: function() { return $scope.filterValues }\n }\n });\n \n modalInstance.result.then(function (newFilterData) {\n $scope.filterValues = newFilterData.filterValues;\n $scope.filterUrlString = newFilterData.filterUrlString;\n }, function() {\n \n });\n }\n \n $scope.addPredefinedFilter = function(predefinedIdentifier, listOfFilterValues, filterUrlString) {\n //filterIdentifier, filterValues\n var predefinedFilterStructure = {'filterValues': {}, 'filterUrlString': {}};\n for (var n = 0; n < listOfFilterValues.length; n++) {\n predefinedFilterStructure[\"filterValues\"][listOfFilterValues[n].filterId] = listOfFilterValues[n].value;\n }\n predefinedFilterStructure[\"filterUrlString\"] = filterUrlString;\n \n $scope.predefinedFilters[predefinedIdentifier] = predefinedFilterStructure;\n }\n \n $scope.addAvailableFilter = function(identifier, fieldDescription) {\n fieldDescription.id = identifier;\n $scope.availableFilters.push(fieldDescription);\n }\n \n \n $scope.super = function(setup) {\n if (!setup || !setup.clazz) {\n alert(\"Base Data Controller is missing setup and/or setup.clazz\");\n }\n \n $scope.clazz = setup.clazz;\n \n if (setup.pagination && setup.pagination.max) {\n $scope.pagination.max = setup.pagination.max;\n }\n \n var moduleDefinedFilters = moduleStore.getPossibleFiltersForClazz(setup.clazz);\n if (moduleDefinedFilters) {\n for (var n = 0; n < moduleDefinedFilters.length; n++) {\n $scope.addAvailableFilter(moduleDefinedFilters[n].id, moduleDefinedFilters[n]);\n }\n }\n \n smarttrackerService.isLoggedInDelayed().then(function() {\n if ($stateParams.filter && $scope.predefinedFilters[$stateParams.filter]) {\n $scope.filterValues = $scope.predefinedFilters[$stateParams.filter].filterValues;\n $scope.filterUrlString = $scope.predefinedFilters[$stateParams.filter].filterUrlString;\n }\n if ($stateParams.filter === \"favorites\") {\n $scope.showFavorites();\n }\n \n if ($stateParams.filter && $stateParams.filter.indexOf(\"~\") && $stateParams.filter.split(\"~\").length === 4) {\n var advancedFilter = $stateParams.filter.split(\"~\");\n $scope.clearFilter();\n $scope.clearSelection();\n $scope.filterUrlString = \"&\" + advancedFilter[1] + \"=\" + advancedFilter[3];\n $scope.filterMessage = advancedFilter[0];\n $scope.filterMessage2 = advancedFilter[2];\n }\n \n if (setup && setup.clazz && setup.downloadUrl) {\n $scope.downloadUrl = setup.downloadUrl;\n }\n \n $scope.favorites = favoritesService.favoritesOfClazz(setup.clazz);\n \n $scope.downloadMore();\n });\n }\n \n \n \n $scope.$watch(\"filterUrlString\", function(newVal, oldVal) {\n if (newVal !== oldVal) {\n $scope.filterChanged++;\n $scope.clearItems();\n $scope.downloadMore();\n }\n });\n\n\n});\n\nangular.module('stwo.core').controller('BaseDetailContentController', function ($scope, $state, favoritesService, smarttrackerService) {\n \n $scope.favorites = {};\n \n $scope.go = function(state, params) {\n $state.go(state, params);\n }\n \n $scope.toggleFavorite = function(id) {\n \tfavoritesService.toggle($scope.clazz, id);\n }\n $scope.isFavorite = function(id) {\n \tfavoritesService.isFavorite($scope.clazz, id);\n }\n \n $scope.super = function(setup) {\n if (!setup || !setup.clazz) {\n alert(\"Base Detail Data Controller is missing setup and/or setup.clazz\");\n }\n \n $scope.clazz = setup.clazz;\n \n smarttrackerService.isLoggedInDelayed().then(function() {\n $scope.favorites = favoritesService.favoritesOfClazz(setup.clazz);\n });\n }\n\n});\n\n\nvar stwoCommonPickerModalController = function ($scope, $controller, $modalInstance, pickerConfiguration) {\n\n $controller('BaseListContentController', {$scope: $scope});\n \n \n\n $scope.pickMultipleMode = true && pickerConfiguration.multiple;\n $scope.fieldsToShow = pickerConfiguration.fieldsToShow ? pickerConfiguration.fieldsToShow : [\"id\"];\n \n $scope.genericData = pickerConfiguration.data;\n $scope.title = pickerConfiguration.title;\n \n $scope.pickNullAllowed = true && pickerConfiguration.nullAllowed;\n $scope.pickNullButtonText = pickerConfiguration.nullButtonText;\n \n $scope.disabledIDs = pickerConfiguration.disabledIDs?pickerConfiguration.disabledIDs:[];\n\n //map of items who are disabled. key value is .id for quick lookup\n $scope.disabledItems = pickerConfiguration.disabledItems ? pickerConfiguration.disabledItems : {};\n $scope.downloadUrl = pickerConfiguration.downloadUrl;\n $scope.pagination.max = pickerConfiguration.max?pickerConfiguration.max:30;\n \n\n \n $scope.filters = pickerConfiguration.filters ? pickerConfiguration.filters : {};\n var index = 0;\n var filterString = '';\n var filterValues = {};\n angular.forEach($scope.filters, function (filter) {\n filterValues[filter.id] = \"\";\n filterString += (index++==0&&$scope.downloadUrl.indexOf('?')<0?'?':'&') + filter.value;\n });\n if(filterString != '') {\n $scope.filterUrlString = filterString;\n $scope.filterValues = filterValues;\n }\n $scope.super({clazz: pickerConfiguration.clazz, downloadUrl: $scope.downloadUrl});\n\n $scope.$watch(\"itemsChanged\", function() {\n if($scope.itemsChanged > 0) {\n if(pickerConfiguration.fieldsToShow.indexOf('assets') > -1) {\n angular.forEach($scope.items, function (v){\n if(!v.processed) {\n var assets = [];\n angular.forEach(v.assets, function (vv) {\n console.log(vv);\n assets.push(vv.name);\n });\n v.assets = assets.join();\n v.processed = true;\n }\n });\n }\n }\n });\n\n $scope.itemClicked = function(item) {\n if (!$scope.pickMultipleMode) {\n $scope.pickOne(item);\n } else {\n $scope.toggleSelect(item);\n item.selected = !item.selected\n }\n }\n \n $scope.pickNull = function() {\n $modalInstance.close({data: $scope.genericData, selectedItems: [null]});\n }\n \n $scope.pickOne = function(item) {\n $scope.toggleSelect(item);\n $modalInstance.close({data: $scope.genericData, selectedItems: $scope.selectedItems});\n }\n\n $scope.pickMultiple = function () {\n $modalInstance.close({data: $scope.genericData, selectedItems: $scope.selectedItems});\n };\n\n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n\n $scope.textInput = {nameSearchValue: \"\"};\n $scope.applyNameSearch = function($event) {\n var keyCode = $event.which || $event.keyCode;\n if(keyCode === 13){\n $scope.filterValues = {\"name\":$scope.textInput.nameSearchValue};\n $scope.filterUrlString = \"&name:contains=\" + $scope.textInput.nameSearchValue;\n }\n };\n};\nangular.module('stwo.core').directive('phoneField', function ($compile) {\n return {\n restrict: 'E',\n scope: {\n phone: '=',\n callback: '&',\n phonePlaceHolder: '='\n //bindAttr: '='\n },\n\n templateUrl: 'core/html/phone-field.html',\n controller: ['$scope', '$translate', '$timeout', function MyTabsController($scope, $translate, $timeout) {\n\n\n\n $translate([\"COUNTRY_CODE_EMPTY\", \"COUNTRY_CODE_NORWAY\", \"COUNTRY_CODE_NETHERLANDS\", \"COUNTRY_CODE_ROMANIA\", \"COUNTRY_CODE_HUNGARY\", \"COUNTRY_CODE_CZECH_REPUBLIC\",\n \"COUNTRY_CODE_SWEDEN\", \"COUNTRY_CODE_MALAYSIA\", \"COUNTRY_CODE_THAILAND\", \"COUNTRY_CODE_UNITDED_KINGDOM\", \"COUNTRY_CODE_GERMANY\",\n \"COUNTRY_CODE_PERU\", \"COUNTRY_CODE_BONAIRE\", \"COUNTRY_CODE_CHINA\", \"COUNTRY_CODE_FINLAND\", \"COUNTRY_CODE_DENMARK\",\n \"COUNTRY_CODE_IRELAND\", \"COUNTRY_CODE_POLAND\", \"COUNTRY_CODE_MADAGASCAR\", \"COUNTRY_CODE_FRANCE\", \"COUNTRY_CODE_UKRAINE\",\n \"COUNTRY_CODE_BELGIUM\", \"COUNTRY_CODE_AUSTRALIA\"\n ])\n .then(function (data) {\n console.log(data);\n $scope.translations = {\n Netherlands: data['COUNTRY_CODE_NETHERLANDS'],\n Norway: data['COUNTRY_CODE_NORWAY'],\n Romania: data['COUNTRY_CODE_ROMANIA'],\n Hungary: data['COUNTRY_CODE_HUNGARY'],\n Czech: data['COUNTRY_CODE_CZECH_REPUBLIC'],\n Sweden: data['COUNTRY_CODE_SWEDEN'],\n Malaysia: data['COUNTRY_CODE_MALAYSIA'],\n Thailand: data['COUNTRY_CODE_THAILAND'],\n UK: data['COUNTRY_CODE_UNITDED_KINGDOM'],\n Germany: data['COUNTRY_CODE_GERMANY'],\n Peru: data['COUNTRY_CODE_PERU'],\n Bonaire: data['COUNTRY_CODE_BONAIRE'],\n China: data['COUNTRY_CODE_CHINA'],\n Finland: data['COUNTRY_CODE_FINLAND'],\n Denmark: data['COUNTRY_CODE_DENMARK'],\n Ireland: data['COUNTRY_CODE_IRELAND'],\n Poland: data['COUNTRY_CODE_POLAND'],\n Madagascar: data['COUNTRY_CODE_MADAGASCAR'],\n France: data['COUNTRY_CODE_FRANCE'],\n Ukraine: data['COUNTRY_CODE_UKRAINE'],\n Belgium: data['COUNTRY_CODE_BELGIUM'],\n Australia: data['COUNTRY_CODE_AUSTRALIA'],\n Empty: data['COUNTRY_CODE_EMPTY']\n };\n\n\n $scope.countryCodes = [{\n 'label': $scope.translations.Netherlands,\n 'code': '+31',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Norway,\n 'code': '+47',\n 'mask': '99999999'\n }, {\n 'label': $scope.translations.Romania,\n 'code': '+40',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Hungary,\n 'code': '+36',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Czech,\n 'code': '+420',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Sweden,\n 'code': '+46',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Malaysia,\n 'code': '+60',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Thailand,\n 'code': '+66',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.UK,\n 'code': '+44',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Germany,\n 'code': '+49',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Peru,\n 'code': '+51',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Bonaire,\n 'code': '+599',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.China,\n 'code': '+86',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Finland,\n 'code': '+358',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Denmark,\n 'code': '+45',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Ireland,\n 'code': '+353',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Poland,\n 'code': '+48',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Madagascar,\n 'code': '+261',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.France,\n 'code': '+33',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Ukraine,\n 'code': '+380',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Belgium,\n 'code': '+32',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Australia,\n 'code': '+61',\n 'mask': '9999999999'\n }, {\n 'label': $scope.translations.Empty,\n 'code': ' ',\n 'mask': '9999999999'\n }];\n $scope.currentCC = $scope.countryCodes[0];\n\n $scope.phoneNbrPlaceHolder = $scope.phonePlaceHolder ? $scope.phonePlaceHolder : 'PHONE_FIELD_PHONE_PLACEHOLDER';\n parseNbr();\n\n });\n $scope.uniqueID = \"ccdd\" + Math.floor(Math.random() * 1000000);\n $scope.ccSearch = \"\";\n $scope.selectedCCIndex = 0;\n $scope.ccExpanded = function ($event) {\n $timeout(function () {\n console.log($scope.uniqueID, $(\"#\" + $scope.uniqueID));\n $(\"#\" + $scope.uniqueID).focus();\n }, 50);\n }\n\n $scope.searchFieldKeyPressed = function ($event, maxIndex, cc) {\n var keyCode = $event.which || $event.keyCode;\n if (keyCode === 13 && cc) {\n $scope.changeCC(cc);\n $scope.ccSearch = \"\";\n $scope.selectedCCIndex = 0;\n $(\"#\" + $scope.uniqueID).parent().click();\n } else if (keyCode == 38 /*UpArrow*/ ) {\n $scope.selectedCCIndex = Math.max(0, $scope.selectedCCIndex - 1);\n } else if (keyCode == 40 /*Down Arrow*/ ) {\n $scope.selectedCCIndex = Math.min(maxIndex - 1, $scope.selectedCCIndex + 1);\n } else {\n $scope.selectedCCIndex = 0;\n }\n }\n\n $scope.getCountryCodes = function (callback) {\n callback($scope.countryCodes);\n }\n\n var parseNbr = function () {\n console.log(\"Parse number called for number\" + $scope.phone);\n if ($scope.phone) {\n for (var i in $scope.countryCodes) {\n if ($scope.phone.indexOf($scope.countryCodes[i].code) == 0) {\n $scope.currentCC = $scope.countryCodes[i];\n break;\n }\n }\n if ($scope.currentCC) {\n $scope.nbr = $scope.phone.substring($scope.currentCC.code.length);\n }\n }\n }\n\n $scope.changeCC = function (cc) {\n\n $scope.currentCC = cc;\n console.log(\"changeCC\", cc, $scope.currentCC);\n $scope.phone = $scope.nbr && $scope.nbr != '' ? $scope.currentCC.code + $scope.nbr : '';\n }\n\n $scope.$watch('phone', function (newValue, oldValue) {\n if ($scope.callback) {\n $scope.callback();\n }\n parseNbr(); // in case it has been updated from outside\n });\n\n $scope.nbrChanged = function () {\n $scope.phone = $scope.nbr && $scope.nbr != '' ? $scope.currentCC.code + $scope.nbr : '';\n }\n\n\n }],\n replace: true,\n //require: 'ngModel',\n link: function ($scope, elem, attr, ctrl) {\n console.debug(\"link\" + $scope);\n //var textField = $('input', elem).attr('ng-model', 'myDirectiveVar');\n // $compile(textField)($scope.$parent);\n }\n };\n});\n\nangular.module('stwo.core').directive('contactEditor', function ($compile, dialogService) {\n return {\n restrict: 'E',\n scope: {\n type: '@',\n readonly: '=',\n object: '=',\n callback: '&'\n },\n templateUrl: 'core/html/directives/contact-editor.html',\n controller: ['$scope', '$translate', 'smarttrackerService', 'utilService', '$timeout', function MyTabsController($scope, $translate, smarttrackerService, utilService, $timeout) {\n\n\n var translations = {};\n $translate([\"MANAGEMENT_ASSET_WORKHOUR_DAY_MON\", \"MANAGEMENT_ASSET_WORKHOUR_DAY_TUE\", \"MANAGEMENT_ASSET_WORKHOUR_DAY_WED\", \"MANAGEMENT_ASSET_WORKHOUR_DAY_THU\",\n \"MANAGEMENT_ASSET_WORKHOUR_DAY_FRI\", \"MANAGEMENT_ASSET_WORKHOUR_DAY_SAT\", \"MANAGEMENT_ASSET_WORKHOUR_DAY_SUN\", \"MANAGEMENT_ASSET_WORKHOUR_DAY_WORKWEEK\", \"MANAGEMENT_ASSET_WORKHOUR_DAY_WHOLEWEEK\",\n \"MANAGEMENT_ASSET_WORKHOUR_DAY_SELECT\", \"MANAGEMENT_ASSET_WORKHOUR_ERROR_INCONSISTENT\", \"MANAGEMENT_ASSET_WORKHOUR_ERROR_NODAY\"\n ]).then(function (data) {\n angular.forEach(data, function (value, key) {\n var formattedKey = key.substring(key.lastIndexOf(\"_\") + 1, key.length);\n translations[formattedKey] = value;\n });\n var days = {};\n days[translations.WHOLEWEEK] = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'];\n days[translations.WORKWEEK] = ['MON', 'TUE', 'WED', 'THU', 'FRI'];\n angular.forEach(days[translations.WHOLEWEEK], function (value) {\n days[translations[value]] = [value];\n });\n\n\n $scope.workhoursData = {\n days: days,\n fromHours: ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'],\n fromMinutes: ['00', '15', '30', '45'],\n toHours: ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24'],\n toMinutes: ['00', '15', '30', '45'],\n errors: {\n 'inconsistent': translations['INCONSISTENT'],\n 'noday': translations['NODAY']\n }\n };\n });\n\n var correctWHOrder = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'];\n var failedContacts = [];\n var prepareContactsFor = function () {\n if (!$scope.object) return;\n $scope.object.contacts = [];\n var index = 0;\n $scope.object.originalContacts = {};\n console.log(\"Asset initiated\", $scope.object);\n\n angular.forEach($scope.object.labels, function (v, k) {\n if (v.code == 'ACR_CONTACT') {\n var contact = prepareContact($scope.object, v, k);\n if (contact) {\n $scope.object.contacts.push(contact);\n }\n }\n });\n console.log(\"Contacts added\", $scope.object.contacts);\n\n if (failedContacts.length > 0) {\n var fcString = \"\";\n angular.forEach(failedContacts, function (value) {\n fcString += \"
  • \" + value + \"
  • \";\n });\n $translate(['MANAGEMENT_ASSET_CONTACT_ERROR_TITLE', 'MANAGEMENT_ASSET_CONTACT_ERROR_CONTACT', 'MANAGEMENT_ASSET_CONTACT_ERROR_CONTACTS',\n 'MANAGEMENT_ASSET_CONTACT_ERROR_RESOLVED_TITLE', 'MANAGEMENT_ASSET_CONTACT_ERROR_RESOLVED_CONTACT', 'MANAGEMENT_ASSET_CONTACT_ERROR_RESOLVED_CONTACTS'\n ], {\n contacts: fcString\n }).then(function (data) {\n\n var message = failedContacts.length > 1 ? data['MANAGEMENT_ASSET_CONTACT_ERROR_CONTACTS'] : data['MANAGEMENT_ASSET_CONTACT_ERROR_CONTACT'];\n var promise = dialogService.prompt('MANAGEMENT_ASSET_CONTACT_ERROR_TITLE', message, {\n promptText: \"\",\n disablePromptText: true,\n deleteButton: true\n });\n promise.then(function () {\n var labels = utilService.clone($scope.object.labels);\n angular.forEach($scope.object.labels, function (value, name) {\n if (failedContacts.indexOf(name) > -1) {\n delete labels[name];\n }\n });\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + '/' + $scope.type + '/' + $scope.object.id, {\n 'labels': labels\n }).then(function (response) {\n $scope.object.labels = response.data.result[0].labels;\n //$scope.assetClicked(asset);\n dialogService.alert('MANAGEMENT_ASSET_CONTACT_ERROR_RESOLVED_TITLE', failedContacts.length > 1 ? data['MANAGEMENT_ASSET_CONTACT_ERROR_RESOLVED_CONTACTS'] : data['MANAGEMENT_ASSET_CONTACT_ERROR_RESOLVED_CONTACT']);\n });\n });\n });\n }\n\n $scope.object.contacts.sort(function (a, b) {\n return a.priority - b.priority;\n });\n\n };\n\n var prepareContact = function (asset, label, name) {\n var contact = false;\n try {\n contact = JSON.parse(label.value);\n } catch (e) {\n failedContacts.push(name);\n }\n contact.index = name;\n contact.name = name;\n asset.originalContacts[contact.index] = utilService.clone(contact);\n\n angular.forEach(contact.workhours, function (wh) {\n if (!wh.hours) {\n wh.hours = \"0000-2400\";\n contact.dirty = true;\n }\n var whFormatted = {\n fromHours: wh.hours.substring(0, 2),\n fromMinutes: wh.hours.substring(2, 4),\n toHours: wh.hours.substring(5, 7),\n toMinutes: wh.hours.substring(7, 9),\n error: ''\n };\n\n wh.weekday.sort(function (a, b) {\n return correctWHOrder.indexOf(a) - correctWHOrder.indexOf(b);\n });\n\n if (checkWeek(wh.weekday, false)) {\n whFormatted.day = translations.WORKWEEK;\n } else if (checkWeek(wh.weekday, true)) {\n whFormatted.day = translations.WHOLEWEEK;\n } else {\n var tmpWH = [];\n angular.forEach(wh.weekday, function (day) {\n tmpWH.push(translations[day]);\n });\n whFormatted.day = tmpWH.join();\n }\n wh.formatted = whFormatted;\n });\n return contact;\n };\n\n var checkWeek = function (wh, wholeWeek) {\n var test = ['MON', 'TUE', 'WED', 'THU', 'FRI'];\n if (wholeWeek) {\n test.push('SAT');\n test.push('SUN');\n }\n for (var i = 0; i < test.length; i++) {\n if (wh.indexOf(test[i]) < 0)\n return false;\n }\n return true;\n };\n\n\n $scope.expandContact = function (contact) {\n $scope.currentContact = $scope.currentContact == contact ? false : contact;\n $scope.currentContact.workhours = $scope.currentContact.workhours ? $scope.currentContact.workhours : [];\n $scope.animateEditor(contact);\n };\n\n $scope.updatePriority = function () {\n if ($scope.newContactInProgress) return;\n var priority = 1;\n var save = true;\n var labels = $scope.object.labels;\n\n angular.forEach($scope.object.contacts, function (v) {\n v.priority = priority++;\n var json = JSON.parse(labels[v.index].value);\n json.priority = v.priority;\n labels[v.index].value = JSON.stringify(json);\n });\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + \"/\" + $scope.type + \"/\" + $scope.object.id, {\n \"labels\": labels\n }).then(function (response) {\n // already updated clientside\n });\n };\n\n $scope.newContact = function () {\n $scope.object.contacts.push({\n name: '',\n phone: '',\n sms: '',\n email: '',\n priority: $scope.object.contacts.length + 1,\n dirty: true,\n new: true,\n workhours: []\n });\n $scope.currentContact = $scope.object.contacts[$scope.object.contacts.length - 1];\n $scope.newContactInProgress = true;\n $scope.animateEditor($scope.currentContact);\n };\n\n $scope.moveContactPriority = function (direction, contact) {\n var cs = $scope.object.contacts;\n var index = cs.indexOf(contact);\n var newIndex = index + direction;\n if (newIndex >= 0 && newIndex < cs.length) {\n $scope.object.contacts.splice(index, 1);\n cs.splice(newIndex, 0, contact);\n $scope.updatePriority();\n }\n };\n\n $scope.removeContact = function (contact) {\n\n $translate([\"MANAGEMENT_ASSET_CONFIRM_REMOVE_CONTACT\"], {\n contactName: contact.index\n }).then(function (data) {\n var promise = dialogService.prompt(\"MANAGEMENT_ASSET_REMOVE_CONTACT\", \"MANAGEMENT_ASSET_CONFIRM_REMOVE_CONTACT\", {\n promptText: \"\",\n disablePromptText: true,\n deleteButton: true\n });\n promise.then(function (data) {\n var labels = $scope.object.labels;\n delete labels[contact.index];\n $scope.object.contacts.splice($scope.object.contacts.indexOf(contact), 1);\n $scope.updatePriority();\n });\n });\n\n //$translate([\"MANAGEMENT_ASSET_CONFIRM_REMOVE_CONTACT\"], {contactName:contact.index}).then(function (data){\n //if(confirm(data.MANAGEMENT_ASSET_CONFIRM_REMOVE_CONTACT)) {\n // var labels = $scope.object.labels;\n // delete labels[contact.index];\n // $scope.object.contacts.splice($scope.object.contacts.indexOf(contact), 1);\n // $scope.updatePriority();\n //}\n //});\n };\n\n $scope.toggleDrag = function (drag) {\n console.log(\"disableDrag\");\n console.log($('.cecontainer'));\n $('.cecontainer').attr(\"draggable\", drag);\n console.log($('.cecontainer').attr('draggable'));\n };\n\n $scope.selected = {\n value: null\n };\n $scope.animateEditor = function (contact) {\n var index = $scope.object.contacts.indexOf(contact);\n\n if ($scope.selected.value == index) {\n TweenLite.set(\"#editor-\" + index + \"-\" + $scope.object.resourceId, {\n overflow: \"hidden\"\n });\n TweenLite.to(\"#editor-\" + index + \"-\" + $scope.object.resourceId, 0.5, {\n height: \"0px\",\n opacity: 0,\n ease: \"Quart.easeInOut\"\n });\n TweenLite.set(\"#editor-\" + index + \"-\" + $scope.object.resourceId, {\n overflow: \"hidden\",\n delay: 0.5\n });\n $scope.selected.value = null;\n } else {\n $timeout(function () {\n TweenLite.set(\"#editor-\" + index + \"-\" + $scope.object.resourceId, {\n height: \"auto\",\n opacity: 1\n });\n TweenLite.from(\"#editor-\" + index + \"-\" + $scope.object.resourceId, 0.5, {\n height: \"0px\",\n opacity: 0,\n ease: \"Quart.easeInOut\"\n });\n TweenLite.set(\"#editor-\" + index + \"-\" + $scope.object.resourceId, {\n overflow: \"visible\",\n delay: 0.5\n });\n }, 20);\n $scope.selected.value = index;\n }\n if ($scope.selected.value != $scope.previous) {\n TweenLite.set(\"#editor-\" + $scope.previous + \"-\" + $scope.object.resourceId, {\n overflow: \"hidden\"\n });\n TweenLite.to(\"#editor-\" + $scope.previous + \"-\" + $scope.object.resourceId, 0.5, {\n height: \"0px\",\n opacity: 0,\n ease: \"Quart.easeInOut\"\n });\n TweenLite.set(\"#editor-\" + $scope.previous + \"-\" + $scope.object.resourceIdß, {\n overflow: \"hidden\",\n delay: 0.5\n });\n }\n $scope.previous = $scope.selected.value;\n\n };\n\n $scope.checkContact = function (contact) {\n if (contact == $scope.currentContact) {\n $scope.saveContact(contact, true);\n } else {\n $scope.expandContact(contact)\n }\n };\n\n $scope.validateWorkHours = function (wh) {\n var f = wh.formatted;\n var start = f.fromHours + f.fromMinutes;\n var end = f.toHours + f.toMinutes;\n if (f.day == translations.SELECT || !$scope.workhoursData.days[f.day]) {\n f.error = $scope.workhoursData.errors.noday;\n errors = true;\n } else if (Number(end) - Number(start) <= 0 && (end != '0000')) {\n f.error = $scope.workhoursData.errors.inconsistent;\n errors = true;\n } else {\n f.error = false;\n }\n };\n\n $scope.saveContact = function (contact, save) {\n if (!contact || !contact.dirty) {\n $scope.expandContact(contact);\n return;\n }\n if (save) {\n if (!contact.name || contact.name.trim() == '') {\n $translate([\"MANAGEMENT_ASSET_NAME_EMPTY\"]).then(function (data) {\n contact.errors = [data.MANAGEMENT_ASSET_NAME_EMPTY];\n });\n return;\n }\n delete contact.errors;\n\n var verified = [];\n var errors = false;\n angular.forEach(contact.workhours, function (wh) {\n $scope.validateWorkHours(wh);\n if (wh.formatted.error) {\n errors = true;\n } else {\n var f = wh.formatted;\n verified.push({\n \"weekday\": $scope.workhoursData.days[f.day],\n \"hours\": f.fromHours + f.fromMinutes + \"-\" + f.toHours + f.toMinutes\n })\n }\n });\n if (errors) return;\n\n\n var data = {\n phone: contact.phone,\n sms: contact.sms,\n email: contact.email,\n workhours: verified,\n priority: contact.priority,\n contactCode: contact.contactCode\n };\n var labels = $scope.object.labels;\n if (!contact.new) {\n delete labels[contact.index];\n }\n if (name != contact.index) {\n delete labels[contact.index];\n }\n labels[contact.name] = {\n code: 'ACR_CONTACT',\n value: data\n };\n var updateAsset = $scope.object;\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + \"/\" + $scope.type + \"/\" + $scope.object.id, {\n 'labels': labels\n }).then(function (response) {\n\n\n if (!contact.new && contact.name != contact.index) {\n delete updateAsset.originalContacts[contact.index];\n }\n contact.dirty = false;\n contact.new = false;\n\n updateAsset.originalContacts[contact.name] = utilService.clone(contact);\n contact.index = contact.name;\n updateAsset.labels = response.data.result[0].labels;\n updateAsset.contacts.sort(function (a, b) {\n return a.priority - b.priority;\n });\n\n $scope.newContactInProgress = false;\n $scope.expandContact(contact)\n });\n } else {\n if (contact.new) {\n var index = $scope.object.contacts.indexOf(contact);\n if (index >= 0) $scope.object.contacts.splice(index, 1);\n $scope.newContactInProgress = false;\n $scope.expandContact(contact)\n } else {\n var cl = $scope.object.contacts;\n if (cl.indexOf(contact) >= 0) {\n var nc = utilService.clone($scope.object.originalContacts[contact.index]);\n cl[cl.indexOf(contact)] = nc;\n $scope.currentContact = nc;\n $timeout(function () {\n $scope.currentContact.dirty = false;\n }, 500);\n }\n $scope.expandContact(contact)\n }\n }\n };\n\n $scope.workhoursChanged = function () {\n if ($scope.currentContact)\n $scope.currentContact.dirty = true;\n };\n\n $scope.checkContactChanged = function () {\n console.log(\"currentContact \", $scope.currentContact);\n if ($scope.currentContact && $scope.currentContact.index) {\n var a = $scope.currentContact;\n var b = $scope.object.originalContacts[$scope.currentContact.index];\n var checks = ['name', 'email', 'phone', 'sms', 'contactCode'];\n $scope.currentContact.dirty = false;\n angular.forEach(checks, function (v) {\n if (a[v] != b[v]) {\n $scope.currentContact.dirty = true;\n }\n });\n\n }\n };\n\n /** Workhours related methods*/\n\n\n\n\n $scope.whSelect = function (key, value, wh) {\n var index = $scope.currentContact.workhours.indexOf(wh);\n $scope.currentContact.workhours[index].formatted[key] = value;\n $scope.currentContact.dirty = true;\n $scope.validateWorkHours(wh)\n };\n\n $scope.addWorkhour = function () {\n $scope.currentContact.workhours.push({\n \"weekday\": [],\n \"hours\": \"\",\n formatted: {\n day: translations.SELECT,\n fromHours: '00',\n fromMinutes: '00',\n toHours: '24',\n toMinutes: '00',\n error: ''\n }\n });\n $scope.currentContact.dirty = true;\n };\n\n $scope.removeWorkhour = function (index) {\n $scope.currentContact.workhours.splice(index, 1);\n $scope.currentContact.dirty = true;\n };\n /** End workhours related methods*/\n\n\n\n $scope.$watch(function () {\n return $scope.object\n }, function (newValue, oldValue) {\n prepareContactsFor();\n });\n\n }],\n replace: true\n };\n});\n\nangular.module('stwo.core').directive('addressField', function ($compile) {\n return {\n restrict: 'E',\n scope: {\n callback: '&',\n placeholder: '@',\n awaitingNavigation: '=',\n searchOverlay: '='\n },\n\n templateUrl: 'core/html/directives/address-field.html',\n controller: ['$scope', 'addressService', '$timeout', function MyTabsController($scope, addressService, $timeout) {\n\n $scope.addressData = {\n addressSearch: '',\n addressLoading: false,\n addresses: [],\n selectedIndex: 0,\n selectedAddress: '',\n expanded: false\n };\n $scope.$watch(\"addressData.addressSearch\", function (newVal, oldVal) {\n performAddressRequest();\n }, true);\n\n $scope.setAddressExpanded = function () {\n $timeout(function () {\n $scope.addressData.expanded = true\n }, 200);\n }\n\n var requestString = \"\";\n var performAddressRequest = function () {\n if ($scope.addressData.addressSearch != '' && !$scope.addressData.addressLoading) {\n $scope.addressData.addressLoading = true;\n var requestString = $scope.addressData.addressSearch;\n addressService.addressListBySearch(requestString).then(function (addressList) {\n $scope.addressData.addressLoading = false;\n $scope.addressData.addresses = addressList;\n if (requestString != $scope.addressData.addressSearch) {\n console.log(requestString + \"!=\" + $scope.addressData.addressSearch);\n performAddressRequest();\n }\n }, function (error) {\n console.error(\"Error when fetching address\", error);\n $scope.addressData.addressLoading = false;\n });\n }\n }\n\n $scope.addressFieldKeyPressed = function ($event) {\n var keyCode = $event.which || $event.keyCode;\n if (keyCode === 13 /*Enter*/ ) {\n $scope.selectAddress($scope.addressData.addresses[$scope.addressData.selectedIndex]);\n } else if (keyCode == 38 /*Up Arrow*/ ) {\n $scope.addressData.selectedIndex = Math.max(0, $scope.addressData.selectedIndex - 1);\n } else if (keyCode == 40 /*Down Arrow*/ ) {\n $scope.addressData.selectedIndex = Math.min($scope.addressData.addresses.length - 1, $scope.addressData.selectedIndex + 1);\n } else {\n $scope.addressData.selectedIndex = 0;\n }\n }\n\n var addressSearchKey = \"RecentAddressSearches\";\n $scope.recentSearches = localStorage[addressSearchKey] ? JSON.parse(localStorage[addressSearchKey]) : [];\n $scope.selectAddress = function (address) {\n $scope.addressData.addresses = [];\n $scope.addressData.addressSearch = \"\";\n $scope.searchOverlay.toggle = false;\n console.log(address);\n addressService.addressDetails(address).then(function (detailedAddress) {\n $scope.addressData.selectedAddress = detailedAddress;\n var a = detailedAddress.address;\n // Tellu Cloud Address String\n console.log(detailedAddress);\n $scope.addressData.selectedAddress.TCAString = (a.road ? a.road + \" \" : '') + (a.house_number ? a.house_number : '') + (a.road ? \", \" : '') + (a.county ? a.country + \", \" : '') + (a.postcode ? a.postcode + \", \" : '') + a.country_code;\n var data = {\n point: new L.latLng(address.lat, address.lon),\n address: $scope.addressData.selectedAddress,\n TCAString: $scope.addressData.selectedAddress.TCAString\n };\n\n $scope.recentSearches.splice(0, 0, data);\n if ($scope.recentSearches.length > 5) {\n $scope.recentSearches.splice(5, ($scope.recentSearches.length - 5));\n }\n localStorage[addressSearchKey] = JSON.stringify($scope.recentSearches);\n\n if ($scope.callback) {\n $scope.callback({\n data: data\n });\n }\n }, function (error)  {\n console.error(\"Something went wrong when communicating with address api\", error);\n });\n }\n\n $scope.searchSelected = function (index) {\n var data = $scope.recentSearches[index];\n if (data) {\n $scope.callback({\n data: data\n });\n }\n $scope.searchOverlay.toggle = false;\n }\n }],\n replace: true,\n //require: 'ngModel',\n link: function ($scope, elem, attr, ctrl) {\n console.debug(\"link\" + $scope);\n }\n };\n});\n\nangular.module('stwo.core').directive('addressInfo', function ($compile) {\n return {\n restrict: 'E',\n scope: {\n position: '=',\n },\n templateUrl: 'modules/alarm-screen-xguard/directives/address-info.html',\n controller: ['$scope', '$timeout', function MyTabsController($scope, $timeout) {\n\n $scope.result = false;\n return;\n\n var geocoder = new google.maps.Geocoder;\n var service = new google.maps.places.PlacesService(document.createElement('div'));\n geocoder.geocode({\n location: {\n lat: $scope.position.latitude,\n lng: $scope.position.longitude,\n }\n }, function(results, status) {\n if (status === 'OK') {\n\n service.getDetails({\n placeId: results[0].place_id,\n\n // fields: ['name', 'rating', 'formatted_phone_number', 'geometry']\n }, function callback(place, status) {\n if (status == google.maps.places.PlacesServiceStatus.OK) {\n\n // done\n $scope.result = place;\n\n }\n });\n }\n });\n\n }],\n replace: true,\n link: function ($scope, elem, attr, ctrl) {\n console.debug(\"link addressInfo\", { $scope: $scope, elem: elem, attr: attr, ctrl: ctrl });\n }\n };\n});\n\nangular.module('stwo.core').directive('durationTime', function ($compile) {\n return {\n restrict: 'E',\n scope: {\n time: '=',\n },\n templateUrl: 'modules/alarm-screen-xguard/directives/durationTime.html',\n controller: ['$scope', '$interval', function MyTabsController($scope, $interval) {\n\n var start = new Date($scope.time).getTime();\n $interval(function(){\n\n var duration = moment.duration(new Date().getTime() - start).format(\"hh:mm:ss\", {\n stopTrim: \"mm\"\n });\n $scope.timestring = duration;\n\n }, 100);\n\n }],\n replace: true,\n link: function ($scope, elem, attr, ctrl) {\n console.debug(\"link durationTime\", { $scope: $scope, elem: elem, attr: attr, ctrl: ctrl });\n }\n };\n});\n\n\n//how to use\n\n//
    \n\n//watch the variable and persist as needed\n\nangular.module('stwo.core').factory('timeRestrictionService', function(smarttrackerService) {\n\n var i = {};\n\n var weekdays = {\"MON\": 0, \"TUE\": 1, \"WED\": 2, \"THU\": 3, \"FRI\": 4, \"SAT\": 5, \"SUN\": 6};\n\n i.weekdays = function() {\n return weekdays;\n };\n\n i.evaluate = function(timeRestrictionJson) {\n\n var d = timeRestrictionJson && timeRestrictionJson.constructor === Array ? timeRestrictionJson : angular.fromJson(timeRestrictionJson);\n var anyOk = false;\n\n var wd = moment().isoWeekday();\n var hour = moment().hour() * 100 + moment().minute();\n\n if (d && d.constructor === Array) {\n for (var n = 0; n < d.length; n++) {\n var wdOk = false;\n var hourOk = false;\n\n if (d[n].weekday) {\n for (var n2 = 0; n2 < d[n].weekday.length; n2++) {\n if ((weekdays[d[n].weekday[n2]] + 1) === wd) {\n wdOk = true;\n }\n }\n }\n\n if (d[n].hours && d[n].hours.indexOf(\"-\") === 4) {\n var a = d[n].hours.split(\"-\")[0];\n var b = d[n].hours.split(\"-\")[1];\n\n if (parseInt(a) <= hour && parseInt(b) >= hour) {\n hourOk = true;\n }\n }\n\n if (wdOk && hourOk) {\n anyOk = true;\n break;\n }\n }\n }\n\n return anyOk;\n };\n\n return i;\n});\nangular.module('stwo.core')\n .filter('isWithinTimeRestriction', function (timeRestrictionService) {\n return function (obj) {\n return timeRestrictionService.evaluate(obj);\n };\n });\nangular.module('stwo.core')\n .filter('isOutsideTimeRestriction', function (timeRestrictionService) {\n return function (obj) {\n return !timeRestrictionService.evaluate(obj);\n };\n });\n\nangular.module('stwo.core').directive(\"timeRestriction\", function ($injector, $modal, $timeout, smarttrackerService, indoorLocationViewerDataService, indoorLocationViewerRenderService, timeRestrictionService)\n {\n return {\n restrict: 'EA',\n scope: {\n data: '=',\n edit: '=',\n waiting: '=',\n callback: '&'\n },\n templateUrl: 'core/js/timeRestriction/time-restriction-table.html',\n link: function(scope, element, attrs) {\n console.log(\"directive data \" + scope.data);\n },\n controller: function($scope) {\n var weekdays = timeRestrictionService.weekdays();\n\n var updateInternalData = function() {\n $scope.rows = []\n\n var d = angular.fromJson($scope.data);\n\n if (d) {\n for (var n = 0; n < d.length; n++) {\n var minWeekday = 7;\n var minHour = 24;\n d[n][\"weekdayToTranslate\"] = [];\n\n if (d[n].weekday) {\n for (var n2 = 0; n2 < d[n].weekday.length; n2++) {\n d[n][\"weekdayToTranslate\"].push({\"key\": \"DAYS_\" + d[n].weekday[n2], \"_sort\": weekdays[d[n].weekday[n2]]})\n minWeekday = Math.min(weekdays[d[n].weekday[n2]], minWeekday)\n }\n }\n\n d[n][\"weekdayToTranslate\"].sort(function(a, b) {\n return a._sort - b._sort;\n });\n\n if (d[n].hours) {\n minHour = Math.min(parseInt(d[n].hours.split(\"-\")[0]), parseInt(d[n].hours.split(\"-\")[1]));\n }\n\n d[n][\"_sort\"] = minWeekday * 100000 + minHour;\n\n $scope.rows.push(d[n]);\n }\n }\n\n $scope.rows.sort(function(a, b) {\n return a._sort - b._sort;\n });\n }\n\n var updateExternalData = function() {\n var d = [];\n\n for (var n = 0; n < $scope.rows.length; n++) {\n d.push({weekday: $scope.rows[n].weekday, hours: $scope.rows[n].hours});\n }\n\n $scope.data = angular.toJson(d);\n }\n\n updateInternalData();\n\n $scope.removeRow = function(idx) {\n $scope.rows.splice(idx, 1);\n updateExternalData();\n }\n\n var modalController = function ($scope, $modalInstance, row) {\n $scope.state = {mode: row ? 'edit' : 'add'};\n\n $scope.rowData = {weekday: {}, hoursStart: \"\", hoursEnd: \"\"};\n\n if (row) {\n for (var wd in weekdays.length) {\n $scope.rowData.weekday[wd] = false;\n }\n for (var n2 = 0; n2 < row.weekday.length; n2++) {\n $scope.rowData.weekday[row.weekday[n2]] = true;\n }\n $scope.rowData.hoursStart = row.hours.split(\"-\")[0];\n $scope.rowData.hoursEnd = row.hours.split(\"-\")[1];\n }\n\n $scope.padHours = function() {\n if ($scope.rowData.hoursStart.length === 0) {\n $scope.rowData.hoursStart = \"0000\";\n }\n if ($scope.rowData.hoursStart.length === 1) {\n $scope.rowData.hoursStart = \"0\" + $scope.rowData.hoursStart + \"00\";\n }\n if ($scope.rowData.hoursStart.length === 2) {\n $scope.rowData.hoursStart = $scope.rowData.hoursStart + \"00\";\n }\n if ($scope.rowData.hoursStart.length === 3) {\n $scope.rowData.hoursStart = \"0\" + $scope.rowData.hoursStart;\n }\n if ($scope.rowData.hoursEnd.length === 0) {\n $scope.rowData.hoursEnd = \"2400\";\n }\n if ($scope.rowData.hoursEnd.length === 1) {\n $scope.rowData.hoursEnd = \"0\" + $scope.rowData.hoursEnd + \"00\";\n }\n if ($scope.rowData.hoursEnd.length === 2) {\n $scope.rowData.hoursEnd = $scope.rowData.hoursEnd + \"00\";\n }\n if ($scope.rowData.hoursEnd.length === 3) {\n $scope.rowData.hoursEnd = \"0\" + $scope.rowData.hoursEnd;\n }\n }\n\n $scope.ok = function (floor) {\n $scope.padHours();\n var returnRow = {weekday: [], hours: $scope.rowData.hoursStart + \"-\" + $scope.rowData.hoursEnd}\n\n for (var wd in $scope.rowData.weekday) {\n if ($scope.rowData.weekday[wd]) {\n returnRow.weekday.push(wd);\n }\n }\n\n $modalInstance.close({row: returnRow});\n };\n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n };\n\n $scope.editRow = function(idx) {\n var modalInstance = $modal.open({\n templateUrl: 'core/js/timeRestriction/time-restriction-picker-modal.html',\n controller: modalController,\n size: \"lg\",\n resolve: {\n row: function() { return $scope.rows[idx] }\n }\n });\n\n modalInstance.result.then(function (data) {\n $scope.rows[idx] = data.row;\n updateExternalData();\n updateInternalData();\n\n }, function() {\n\n });\n }\n\n $scope.addRow = function() {\n var modalInstance = $modal.open({\n templateUrl: 'core/js/timeRestriction/time-restriction-picker-modal.html',\n controller: modalController,\n size: \"lg\",\n resolve: {\n row: function() { return null }\n }\n });\n\n modalInstance.result.then(function (data) {\n $scope.rows.push(data.row);\n updateExternalData();\n updateInternalData();\n }, function() {\n\n });\n }\n\n $scope.$watch(\"data\", function() {\n updateInternalData();\n console.log(\"directive data changed \", $scope.data);\n if($scope.callback) {\n $scope.callback();\n }\n\n });\n\n\n }\n };\n});\nangular.module('stwo.core').factory('messageService', function ($modal, smarttrackerService, $translate) {\n\tvar i = {};\n\n \t\tvar messageDataValues = [\n \"email_name\",\n \"email_tags\",\n \"email_insideZones\",\n \"email_properties\",\n \"email_links\",\n \"email_type\",\n \"email_position\",\n \"email_rule\",\n \"email_messageTime\",\n \"email_positionTime\"\n ];\n\n\tvar getTableRow = function (col1, col2) {\n\t return \"\" + col1 + \"\" + col2 + \"\";\n\t}\n\tvar getGoogleMapsLink = function (lat, lon) {\n \treturn \"http://maps.google.com/maps?q=\"+lat+\"%2C\" + lon;\n }\n\n var data = {};\n $translate(['MESSAGE_SERVICE_EMAIL_ASSET_NAME', 'MESSAGE_SERVICE_EMAIL_ASSET_IMAGE', 'MESSAGE_SERVICE_EMAIL_ASSET_EXTERNAL_ID', 'MESSAGE_SERVICE_EMAIL_ASSET_LAST_MESSAGE', \n\t\t\t'MESSAGE_SERVICE_EMAIL_ASSET_CURRENT_POSITION', 'MESSAGE_SERVICE_EMAIL_ASSET_LABELS', 'MESSAGE_SERVICE_EMAIL_ASSET_GOOLE_LINK', 'MESSAGE_SERVICE_EMAIL_ASSET_INSIDE_ZONES_NONE', \n\t\t\t'MESSAGE_SERVICE_EMAIL_ASSET_SUBJECT', 'MESSAGE_SERVICE_SMS_ASSET_NAME', 'MESSAGE_SERVICE_SMS_ASSET_EXTERNAL_ID', 'MESSAGE_SERVICE_SMS_ASSET_LATEST_POSITION_UPDATE', 'MESSAGE_SERVICE_SMS_ASSET_CURRENT_POSITION',\n\t\t\t'MESSAGE_SERVICE_SMS_ASSET_INSIDE_ZONES', 'MESSAGE_SERVICE_SMS_ASSET_INSIDE_ZONES_NONE', 'MESSAGE_SERVICE_SMS_ASSET_TYPE', 'MESSAGE_SERVICE_SMS_ASSET_PHONE', 'MESSAGE_SERVICE_SMS_ASSET_SMS', \n\t\t\t'MESSAGE_SERVICE_SMS_ASSET_EMAIL', 'MESSAGE_SERVICE_SMS_ASSET_GOOGLE_MAPS_LINK'])\n \t\t.then(function (translations){\n \t\tdata = translations;\n });\n\n var trimPhoneNumber = function (nbr) {\n return nbr ? nbr.replace(/\\+/, \"00\").replace(/\\s/g, \"\") : nbr;\n }\n\n var getAssetInformationTable = function(asset, messageData) {\n \t\n\t\t\t\n\t\t\tvar zones = [];\n\t\t\tangular.forEach(asset.insideZones, function (zone) {\n\t\t\t\tzones.push(zone.name);\n\t\t\t});\n\t\t\tvar insideZonesString = zones.lengh>0?zones.join():data['MESSAGE_SERVICE_EMAIL_ASSET_INSIDE_ZONES_NONE'];\n\n\t\t\tvar assetTable = \"\" + \n\t\t\tgetTableRow(data['MESSAGE_SERVICE_EMAIL_ASSET_IMAGE'] + \":\", \"\") + \n\t\t\tgetTableRow(data['MESSAGE_SERVICE_EMAIL_ASSET_NAME'] + \":\", asset.name) + \n\t\t\tgetTableRow(data['MESSAGE_SERVICE_EMAIL_ASSET_EXTERNAL_ID'] + \":\", asset.externalId) + \n\t\t\tgetTableRow(data['MESSAGE_SERVICE_EMAIL_ASSET_LAST_MESSAGE'] + \": \", asset.lastValidPosition.timestampFormatted) + \n\t\t\tgetTableRow(data['MESSAGE_SERVICE_EMAIL_ASSET_CURRENT_POSITION'] + \": \", asset.lastValidPosition.address) + \n\t\t\tgetTableRow(data['MESSAGE_SERVICE_EMAIL_ASSET_INSIDE_ZONES_NONE'] + \":\", zones);\n\n\t\t\tangular.forEach(asset.properties, function (property) {\n\t\t\t\tassetTable += getTableRow(property.name + \":\", property.value);\n\t\t\t})\n\t\t\ttry{\n\t\t\t\tassetTable += getTableRow(data['MESSAGE_SERVICE_EMAIL_ASSET_LABELS'] + \":\", JSON.stringify(asset.labels));\n\t\t\t} catch(e) {\n\t\t\t\tconsole.error(\"Error when parsing labels for email: \" + e);\n\t\t\t} \n\t\t\tassetTable += getTableRow(data['MESSAGE_SERVICE_EMAIL_ASSET_GOOLE_LINK'] + \":\", getGoogleMapsLink(asset.lastValidPosition.latitude, asset.lastValidPosition.longitude));\n\t\t\tassetTable += \"
    \";\n\t\t\treturn assetTable;\n\t\t\n\t // Check highest priority RA to see if it has custom message data\n\t \n } \n\n var getAssetSMSContent = function(asset, messageData) {\n \tvar zones = [];\n \tangular.forEach(asset.insideZones, function (zone) {\n \t\tzones.push(zone.name);\n \t})\n \tvar insideZones = zones.length>0?zones.join():data['MESSAGE_SERVICE_SMS_ASSET_INSIDE_ZONES_NONE'];\n\n \tvar assetInfo = \n \t\n \t\tdata[\"MESSAGE_SERVICE_SMS_ASSET_NAME\"] + \": \" + asset.name + \"\\n\" +\n \t\tdata[\"MESSAGE_SERVICE_SMS_ASSET_EXTERNAL_ID\"] + \": \" + asset.externalId + \"\\n\" +\n \t\tdata[\"MESSAGE_SERVICE_SMS_ASSET_LATEST_POSITION_UPDATE\"] + \": \" + asset.lastValidPosition.timestampFormatted + \"\\n\" +\n \t\tdata[\"MESSAGE_SERVICE_SMS_ASSET_CURRENT_POSITION\"] + \": \" + asset.lastValidPosition.address + \"\\n\" +\n \t\tdata[\"MESSAGE_SERVICE_SMS_ASSET_INSIDE_ZONES\"] + \": \" + insideZones + \"\\n\" +\n \t\t(asset.type ? data[\"MESSAGE_SERVICE_SMS_ASSET_TYPE\"] + \": \" + asset.type.name + \"\\n\" : '') +\n \t\t(asset.phone ? data[\"MESSAGE_SERVICE_SMS_ASSET_PHONE\"] + \": \" + asset.phone + \"\\n\" : \"\") +\n \t\t(asset.sms ? data[\"MESSAGE_SERVICE_SMS_ASSET_SMS\"] + \": \" + asset.sms + \"\\n\" : \"\") +\n \t\t(asset.email ? data[\"MESSAGE_SERVICE_SMS_ASSET_EMAIL\"] + \": \" + asset.email + \"\\n\" : \"\") +\n \t\tdata[\"MESSAGE_SERVICE_SMS_ASSET_GOOGLE_MAPS_LINK\"] + \": \" + getGoogleMapsLink(asset.lastValidPosition.latitude, asset.lastValidPosition.longitude) + \"\\n\";\n\n\t\treturn assetInfo;\n }\n\n\ti.sendAssetByMail = function(message, asset, mail, messageData) {\n\t\t\tvar mailContent = \"

    \" + asset.name + \"

    \" + message + \"

    \";\n\t\t\tmailContent += getAssetInformationTable(asset, messageData);\n\t\t\tmailContent += \"
    \";\n\t \n\t var mailBody = {\n\t \t\"to\": mail,\n\t \t\"subject\": data['MESSAGE_SERVICE_EMAIL_ASSET_SUBJECT'].replace(\"\", asset.name),//lan['XGUARD_SEND_MAIL_SUBJECT'],\n\t \t\"message\": mailContent\n\t };\n\n\t return smarttrackerService.authPost(smarttrackerService.getCustomerId() + \"/mail/\", mailBody);\n \t\n\t}\n\n\ti.sendAssetBySMS = function(message, asset, number, messageData) {\n\t\tvar smsContent = message + \"\\n\";\n\t\tsmsContent += getAssetSMSContent(asset, messageData);\n\t\tvar formatNumber = false;\n\t\t try {\n formatNumber = trimPhoneNumber(number);\n } catch (e) {\n \talert(\"The number: \" + number + \" is not a valid phone number \" + formatNumber);\n \treturn;\n }\n\n\t\tvar smsBody = {\n\t\t\t\"to\": formatNumber,\n \"message\": smsContent\n\t\t};\n\t\t\n return smarttrackerService.authPost(smarttrackerService.getCustomerId() + \"/sms/\", smsBody);\n\t}\n\n\treturn i;\n});\nangular.module('stwo.core').factory('addressService', function ($modal, $http) {\n\n var i = {};\n\n var baseUrl = \"https://api.pickpoint.io/v1/\";\n var apiKey = \"WsxLCvmfN8D8wjJzPzNd\";\n\n i.addressListBySearch = function(searchTerm) {\n return new Promise (function (resolve, reject) {\n $http({\n method:'GET', \n url: baseUrl + \"forward?key=\" + apiKey + \"&q=\" + searchTerm\n }).then(function (response){\n resolve(response.data);\n }, function (response){\n reject(response);\n });\n });\n }\n\n i.addressDetails = function(address) {\n return new Promise (function (resolve, reject){\n $http({\n method:'GET', \n url:baseUrl + 'lookup/?key=' + apiKey + '&osm_ids=' + address.osm_type.substring(0,1).toUpperCase() + address.osm_id\n }).then(function (response){\n resolve(response.data[0]);\n }, function (response){\n reject(respons);\n });\n });\n }\n\n i.addressByCoordinates = function(latitude, longitude) {\n return new Promise (function (resolve, reject){\n $http({\n method:'GET', \n url:baseUrl + 'reverse/?key=' + apiKey + '&lat=' + latitude + '&lon=' + longitude\n }).then(function (response){\n resolve(response.data);\n }, function (response){\n reject(response);\n });\n });\n }\n\n return i;\n});\nangular.module('stwo.core').factory('IPSService', function ($http, smarttrackerService) {\n\n // radians and degrees helper\n function toRadians(angle) {\n return angle * (Math.PI / 180);\n }\n\n function toDegrees(rad) {\n return rad * 180 / Math.PI;\n }\n\n function getLatLngCenter(latLngInDegr) {\n\n // init\n var sumX = 0;\n var sumY = 0;\n var sumZ = 0;\n\n for (var i = 0; i < latLngInDegr.length; i++) {\n\n // get the latlng\n var lat = toRadians(latLngInDegr[i].lat);\n var lng = toRadians(latLngInDegr[i].lng);\n\n // sum of cartesian coordinates\n sumX += Math.cos(lat) * Math.cos(lng);\n sumY += Math.cos(lat) * Math.sin(lng);\n sumZ += Math.sin(lat);\n\n }\n\n var avgX = sumX / latLngInDegr.length;\n var avgY = sumY / latLngInDegr.length;\n var avgZ = sumZ / latLngInDegr.length;\n\n // convert average x, y, z coordinate to latitude and longtitude\n var lng = Math.atan2(avgY, avgX);\n var hyp = Math.sqrt(avgX * avgX + avgY * avgY);\n var lat = Math.atan2(avgZ, hyp);\n\n return {\n lat: toDegrees(lat),\n lng: toDegrees(lng)\n };\n }\n\n function getDistance(lat1, lon1, lat2, lon2, unit) {\n\n var radlat1 = Math.PI * lat1 / 180\n var radlat2 = Math.PI * lat2 / 180\n var theta = lon1 - lon2\n var radtheta = Math.PI * theta / 180\n var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);\n dist = Math.acos(dist)\n dist = dist * 180 / Math.PI\n dist = dist * 60 * 1.1515\n if (unit == \"K\") {\n dist = dist * 1.609344\n }\n if (unit == \"N\") {\n dist = dist * 0.8684\n }\n return dist\n\n }\n\n // function boundingBoxAroundPolyCoords(coords) {\n\n // var latAll = [],\n // lngAll = []\n\n // for (var i = 0; i < coords.length; i++) {\n // latAll.push(coords[i].lat)\n // lngAll.push(coords[i].lng)\n // }\n\n // latAll = latAll.sort(function (a, b) {\n // return a - b\n // })\n // lngAll = lngAll.sort(function (a, b) {\n // return a - b\n // })\n\n // return [\n // [latAll[0], lngAll[0]],\n // [latAll[latAll.length - 1], lngAll[lngAll.length - 1]]\n // ]\n\n // }\n\n function returnBestMatchWay(elements, point) {\n\n // loopt elements\n var bestMatch = null;\n for (var k in elements) {\n\n // only ways are relevant\n if (elements[k].type === 'way') {\n\n // try catch because incomplete ways will cause errors (not all nodes are resolved to coordinates)\n try {\n\n // calculate center\n elements[k].center = getLatLngCenter(elements[k].nodes);\n //elements[k].centerDistance = getDistance(elements[k].center.lat, elements[k].center.lng, point.lat, point.lng);\n\n // calculate lowest distance\n //var lowestDistance = Infinity,\n var averageDistance = [];\n for (var n in elements[k].nodes) {\n\n averageDistance.push(getDistance(elements[k].nodes[n].lat, elements[k].nodes[n].lng, point.lat, point.lng));\n\n // if (dist < lowestDistance) {\n\n // lowestDistance = dist;\n\n // }\n\n }\n\n averageDistance = averageDistance.sort(function (a, b) {\n return a - b\n }).splice(0, 5);\n\n var avgSum = 0;\n for (var p in averageDistance) {\n\n avgSum += averageDistance[p]\n\n }\n\n\n // save\n // elements[k].lowestDistance = lowestDistance\n elements[k].averageDistance = avgSum / averageDistance.length\n\n } catch (e) {\n\n // better be safe, right?\n elements[k].distance = Infinity;\n\n }\n\n // check best match\n if (bestMatch === null) {\n\n bestMatch = elements[k];\n\n } else\n if (elements[k].averageDistance < bestMatch.averageDistance) {\n\n // if (elements[k].lowestDistance == bestMatch.lowestDistance && elements[k].averageDistance < bestMatch.averageDistance) {\n\n bestMatch = elements[k];\n\n // }\n\n }\n\n }\n\n }\n\n return (bestMatch !== null && bestMatch.nodes) || false;\n\n }\n\n function resolveNode(elements, nodeId) {\n\n // loop through elements\n for (var b in elements) {\n\n // check if this is the node we are looking for\n if (elements[b].type === 'node' && elements[b].id === nodeId) {\n\n // return lat/lng (written as lon in overpass api)\n return {\n lat: elements[b].lat,\n lng: elements[b].lon\n }\n\n }\n\n }\n\n }\n\n // init\n var i = {\n defaultRadius: 35,\n smallRadius: 1\n };\n\n // get bounding box of building\n i.getBuildingBoundsData = {\n point: {\n lat: 0,\n lng: 0\n },\n callback: function () {},\n radius: 0,\n radiusStep: 5\n };\n i.getBuildingBounds = function (point, callback, radius) {\n\n // temp disable\n return callback([]);\n // stop temp disable\n //\n //\n //\n //\n //\n //\n //\n //\n //\n //\n //\n //\n\n if (typeof radius === 'undefined') {\n\n radius = 2;\n\n }\n\n var script = '[out:json][timeout:25];';\n script += '(';\n script += ' node(around:' + radius + ',' + point.lat + ',' + point.lng + ');';\n script += ' way(around:' + radius + ',' + point.lat + ',' + point.lng + ');';\n script += ');';\n script += 'out;';\n script += '>;';\n script += 'out skel qt;';\n\n i.getBuildingBoundsData = {\n point: point,\n callback: callback,\n radius: radius,\n radiusStep: i.getBuildingBoundsData.radiusStep\n };\n\n $http\n .get('https://overpass-api.de/api/interpreter?data=' + encodeURIComponent(script))\n .then(function (response) {\n\n // init\n var elements = response.data.elements;\n\n var foundNode = false,\n foundWay = false;\n\n for (var node in elements) {\n\n // way\n if (elements[node].type === 'way') {\n\n // add all points\n for (var p in elements[node].nodes) {\n\n elements[node].nodes[p] = resolveNode(elements, elements[node].nodes[p])\n\n }\n\n // mark as found\n foundWay = true;\n\n } else\n if (elements[node].type === 'node') {\n\n foundNode = true;\n\n }\n\n }\n\n\n var wayPoints = returnBestMatchWay(elements, i.getBuildingBoundsData.point);\n\n console.log('foundNode', foundNode)\n console.log('foundWay', foundWay)\n console.log('wayPoints', wayPoints)\n\n // console.log('boundingBoxAroundPolyCoords', boundingBoxAroundPolyCoords(wayPoints))\n // return;\n\n // var geod = GeographicLib.Geodesic.WGS84;\n // (function (g) {\n // \"use strict\";\n\n // /*\n // * Compute the area of a polygon\n // */\n // g.Geodesic.prototype.Area = function (points, polyline) {\n\n // var poly = this.Polygon(polyline),\n // i;\n\n // for (i = 0; i < points.length; ++i){\n // poly.AddPoint(points[i].lat, points[i].lng);\n // }\n\n // return poly.Compute(false, true);\n\n // };\n\n // })(GeographicLib.Geodesic);\n\n // console.log('AreaCalc', Math.abs(geod.Area(wayPoints, false).area));\n\n // return;\n\n if (foundNode && foundWay && wayPoints && wayPoints.length > 2) {\n\n return i.getBuildingBoundsData.callback(wayPoints);\n\n } else\n if (radius < 50) {\n\n return i.getBuildingBounds(i.getBuildingBoundsData.point, i.getBuildingBoundsData.callback, i.getBuildingBoundsData.radius + i.getBuildingBoundsData.radiusStep)\n\n } else {\n\n return i.getBuildingBoundsData.callback([], {\n notice: 'No points found'\n });\n\n }\n\n }, function (err) {\n\n return i.getBuildingBoundsData.callback(null, err)\n\n })\n\n }\n\n i.checkAddressZoneExists = function(address){\n return new Promise(function (resolve, reject) {\n\n // check if a zone already exists on this address\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/zone/?name:equals=\" + encodeURIComponent(address.address)).then(function (existingZone) {\n if (typeof existingZone.data !== 'undefined' && existingZone.data.total === 0) {\n\n resolve(false)\n\n } else {\n\n resolve(true)\n\n }\n\n }, function (errorResponse) {\n\n response(false)\n\n })\n\n });\n }\n\n i.changeArcSize = function(zoneResourceId, map){\n return new Promise(function (resolve, reject) {\n\n // get the zone\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/zone/\"+encodeURIComponent(zoneResourceId)+\"?select=@\").then(function (response) {\n if (typeof response.data !== 'undefined' && response.data.total === 1) {\n\n var zone = response.data.result[0];\n if(zone.labels.shapeMeta.code === 'ACR_ZCIRCLE'){\n\n var p = JSON.parse(zone.labels.shapeMeta.value);\n var points = [];\n var labels = {};\n\n //new arc\n // angle that will be increased each loop\n var theta = 0;\n\n // zoom to level 8\n map.setZoom(8)\n\n // create circle on leaflet map\n var h = p.lat; // x coordinate of circle center\n var k = p.lng; // y coordinate of circle center\n var circ = L.circle([h, k], {\n radius: i.smallRadius\n });\n circ.addTo(map);\n\n // get steps from circle\n var step = 360 / 20; // amount to add to theta each time (degrees)\n var rx = circ.getBounds().getNorthEast().lat - h;\n var ry = circ.getBounds().getNorthEast().lng - k;\n circ.remove();\n var p1 = {\n 'latitude': h + rx * Math.cos(toRadians(theta)),\n 'longitude': k - ry * Math.sin(toRadians(theta))\n };\n while (theta < 360) {\n var lat = h + rx * Math.cos(toRadians(theta));\n var lng = k - ry * Math.sin(toRadians(theta))\n points.push({\n 'latitude': lat,\n 'longitude': lng\n });\n theta += step;\n }\n points.push(p1);\n\n // save steps meta\n labels['shapeMeta'] = {\n code: 'ACR_ZCIRCLE',\n value: JSON.stringify({\n 'lat': p.lat,\n 'lng': p.lng,\n 'radius': i.smallRadius\n })\n };\n\n // send to tellu cloud\n var body = {\n 'labels': labels,\n 'points': points\n };\n\n // update\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + \"/zone/\"+encodeURIComponent(zoneResourceId), body).then(function (response) {\n\n resolve(response);\n\n }, function (errorResponse) {\n\n reject(errorResponse);\n\n });\n\n }else{\n\n return reject();\n\n }\n\n }else{\n\n return reject();\n\n }\n });\n\n });\n\n }\n\n // create new ips points on addresses\n i.newIPSPoint = function (address, map, level) {\n return new Promise(function (resolve, reject) {\n\n // check if a zone already exists on this address\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/zone/?name:equals=\" + encodeURIComponent(address.address)).then(function (existingZone) {\n if (typeof existingZone.data !== 'undefined' && existingZone.data.total === 0) {\n\n // check if we are able to create zones with rssi-90\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/zoneType/?name:contains=Rssi-90\").then(function (response) {\n if (response && response.data && response.data.result && response.data.result.length > 0) {\n\n i.getBuildingBounds(address.point, function (buildingBounds, err) {\n\n // temp\n buildingBounds = [];\n\n // set coordinates from point\n var p = address.point;\n var points = [];\n\n // init labels\n labels = {};\n\n // console.log('debug stop')\n // return;\n\n if (buildingBounds.length > 0) {\n\n for (var j in buildingBounds) {\n\n points.push({\n 'latitude': buildingBounds[j].lat,\n 'longitude': buildingBounds[j].lng\n });\n\n }\n\n\n } else {\n\n // angle that will be increased each loop\n var theta = 0;\n\n // zoom to level 8\n map.setZoom(8)\n\n // create circle on leaflet map\n var h = p.lat; // x coordinate of circle center\n var k = p.lng; // y coordinate of circle center\n var circ = L.circle([h, k], {\n radius: i.defaultRadius\n });\n circ.addTo(map);\n\n // get steps from circle\n var step = 360 / 20; // amount to add to theta each time (degrees)\n var rx = circ.getBounds().getNorthEast().lat - h;\n var ry = circ.getBounds().getNorthEast().lng - k;\n circ.remove();\n var p1 = {\n 'latitude': h + rx * Math.cos(toRadians(theta)),\n 'longitude': k - ry * Math.sin(toRadians(theta))\n };\n while (theta < 360) {\n var lat = h + rx * Math.cos(toRadians(theta));\n var lng = k - ry * Math.sin(toRadians(theta))\n points.push({\n 'latitude': lat,\n 'longitude': lng\n });\n theta += step;\n }\n points.push(p1);\n\n // save steps meta\n labels['shapeMeta'] = {\n code: 'ACR_ZCIRCLE',\n value: JSON.stringify({\n 'lat': p.lat,\n 'lng': p.lng,\n 'radius': i.defaultRadius\n })\n };\n\n }\n\n // format address\n var formattedAddress = address.address;\n if(formattedAddress.match(new RegExp('^'+address.placeName, 'i')) === null){\n\n formattedAddress = address.placeName + ', ' + address.address;\n\n }\n\n // send to tellu cloud\n var body = {\n 'name': address.address,\n 'address': formattedAddress, //address.placeName + address.address, //address.address,\n 'description': 'IPS_SecureNavigation',\n 'labels': labels,\n 'points': points,\n //'shareLevel': 'public', // temp\n 'floor': (level ? level : 0),\n 'type': {\n 'id': response.data.result[0].id\n },\n };\n smarttrackerService.authPost(smarttrackerService.getCustomerId() + \"/zone/\", body).then(function (response) {\n resolve(response);\n }, function (errorResponse) {\n console.log('Something went wrong creating ips point', errorResponse)\n reject(errorResponse);\n });\n\n })\n }else{\n\n smarttrackerService.authPost(smarttrackerService.getCustomerId() + \"/zoneType/\", {\n 'name': 'RSSI-90',\n 'icon': 'https://www.smarttracker.no/web/images/map_icons/house.png'\n }).then(function (response) {\n\n i.newIPSPoint(address, map, level).then(function(response){\n\n resolve(response)\n\n }, function(){\n\n alert('RSSI-90 Zone is missing for your account. Please contact X-Guard about this error.\\n\\ninfo@x-guard.nl or call 088 126 12 12');\n reject(response)\n\n })\n\n }, function (errorResponse) {\n\n alert('RSSI-90 Zone is missing for your account. Please contact X-Guard about this error.\\n\\ninfo@x-guard.nl or call 088 126 12 12');\n reject(errorResponse);\n\n });\n\n }\n\n }, function (errorResponse) {\n console.log('Something went wrong creating ips point', errorResponse)\n reject(errorResponse)\n })\n\n } else {\n\n // it already exists so we just resolve with the existing address\n console.log('A zone on this address already exists, we are skipping the creation', existingZone.data.result[0]);\n resolve(existingZone.data.result[0] || {});\n\n }\n\n }, function (errorResponse) {\n\n // rejection, something went wrong\n console.log('Something went wrong creating ips point', errorResponse)\n reject(errorResponse)\n\n })\n }); // End promise\n }\n\n return i;\n\n});\n//# sourceMappingURL=stwo_app-core.js.map","angular.module('stwo.glue', [\"stwo.core\", \"ui.bootstrap\", \"angularMoment\", \"ngAudio\"])\r\n .constant('angularMomentConfig', {\r\n preprocess: 'utc',\r\n timezone: jstz.determine().name() // e.g. 'Europe/London'\r\n })\r\n .config(function ($stateProvider, $urlRouterProvider, moduleStoreProvider) {\r\n\r\n setTimeout(function (i) {\r\n console.log('=== Reloading AM after 1 hour ===')\r\n window.location.reload();\r\n }, 1000 * 60 * 30);\r\n\r\n moduleStoreProvider.states().missingCustomer = \"secure.user\";\r\n moduleStoreProvider.states().notLoggedIn = \"login.box\";\r\n\r\n $urlRouterProvider.otherwise(\"/login\");\r\n\r\n $stateProvider\r\n .state(\"login\", {\r\n url: \"/\",\r\n abstract: true,\r\n views: {\r\n \"loginheader\": {\r\n templateUrl: \"glue/login/header.html\"\r\n },\r\n 'logincontent': {\r\n templateUrl: \"glue/login/content.html\"\r\n }\r\n }\r\n })\r\n\r\n .state('login.box', {\r\n url: \"login\",\r\n views: {\r\n 'logincontent@': {\r\n templateUrl: 'glue/login/views/login.html'\r\n }\r\n },\r\n menu: {\r\n name: 'Login',\r\n tag: \"main\"\r\n }\r\n })\r\n\r\n .state(\"login-with-credentials\", {\r\n url: \"login/:username/:password\",\r\n views: {\r\n 'logincontent@': {\r\n templateUrl: 'glue/login/views/login.html'\r\n }\r\n }\r\n })\r\n\r\n .state('login.demo', {\r\n url: \"demo\",\r\n views: {\r\n 'logincontent@': {\r\n templateUrl: 'glue/login/views/demo.html'\r\n }\r\n },\r\n menu: {\r\n name: 'Demo',\r\n tag: 'main'\r\n }\r\n })\r\n\r\n .state('login.contact', {\r\n url: \"contact\",\r\n views: {\r\n 'logincontent@': {\r\n templateUrl: 'glue/login/views/contact.html'\r\n }\r\n },\r\n menu: {\r\n name: 'Contact',\r\n tag: 'main'\r\n }\r\n })\r\n\r\n .state(\"login.logout\", {\r\n url: \"logout/:reason\",\r\n views: {\r\n 'logincontent@': {\r\n templateUrl: 'glue/login/views/login.html',\r\n controller: \"LogoutController\"\r\n }\r\n }\r\n })\r\n .state(\"secure\", {\r\n url: \"/secure\",\r\n templateUrl: \"glue/secure.html\",\r\n controller: \"SecureController\"\r\n })\r\n .state(\"secure.notifications\", {\r\n url: \"/notifications\",\r\n templateUrl: \"glue/notifications/list.html\",\r\n controller: \"NotificationController\"\r\n })\r\n .state(\"secure.content\", {\r\n url: \"/content\",\r\n templateUrl: \"glue/welcome.html\",\r\n controller: \"ContentController\"\r\n })\r\n .state(\"secure.user\", {\r\n url: \"/user\",\r\n templateUrl: \"glue/user/user.html\",\r\n controller: \"UserController\"\r\n })\r\n })\r\n .config(['$translateProvider', function ($translateProvider) {\r\n $translateProvider.useStaticFilesLoader({\r\n prefix: stwoGlobal.languageUrl,\r\n suffix: '.json?x=812746'\r\n });\r\n\r\n $translateProvider.preferredLanguage(localStorage[\"language\"] && _.find(stwoGlobal.availableLanguages, function (lang) {\r\n return localStorage[\"language\"] === lang.code;\r\n }) ? localStorage[\"language\"] : stwoGlobal.defaultLanguage);\r\n }]);\r\n\r\n\r\nangular.module('stwo.glue').run([\"$rootScope\", \"$anchorScroll\", function ($rootScope, $anchorScroll) {\r\n $rootScope.$on(\"$locationChangeSuccess\", function () {\r\n $anchorScroll();\r\n });\r\n}]);\r\n\r\nangular.module('stwo.glue').controller('SecureController', function ($translate, $timeout, $window, $rootScope, $scope, $state, $modal, pushService, timerService, smarttrackerService, socketioService, notificationService, moduleStore, ngAudio) {\r\n\r\n\r\n // new push\r\n var createSoundFilter = function () {\r\n var sf = {};\r\n sf[getSoundName($scope.soundData.redAlarmSound)] = \"severity:equals=high\";\r\n var n = getSoundName($scope.soundData.greenAlarmSound);\r\n sf[n] = sf[n] ? 'OR( ' + sf[n] + \"; severity:equals=low )\" : \"severity:equals=low\";\r\n n = getSoundName($scope.soundData.orangeAlarmSound);\r\n sf[n] = sf[n] ? (sf[n].indexOf('OR(') == 0 ? sf[n].replace(' )', '; severity:equals=normal; )') : 'OR( ' + sf[n] + '; severity:equals=normal; )') : \"severity:equals=normal\";\r\n // sf[getSoundName($scope.soundData.greenAlarmSound)] =\r\n // sf[getSoundName($scope.soundData.greenAlarmSound)] = \"severity:equals=low\";\r\n // sf[getSoundName($scope.soundData.orangeAlarmSound)] = \"severity:equals=normal\";\r\n return sf;\r\n }\r\n\r\n var getSoundName = function (sound) {\r\n var ss = sound.sound.file;\r\n return sound.muted ? 'silence.wav' : (ss.substring(ss.lastIndexOf(\"/\") + 1, ss.indexOf(\".mp3\")).toLowerCase() + \".wav\");\r\n }\r\n\r\n $rootScope.checkToken = function () {\r\n\r\n if (stwoPushNotificationInfo === null) {\r\n\r\n //$window.alert(\"checktoken delayed\");\r\n return $timeout(function () {\r\n\r\n $rootScope.checkToken();\r\n\r\n }, 1000);\r\n\r\n }\r\n\r\n $rootScope.newPushEnabled = true;\r\n\r\n if (smarttrackerService.getCustomerId()) {\r\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/pushSubscription?select=token+customer+soundFilter\").then(function (response) {\r\n $rootScope.newPushTokens = response.data.result;\r\n $rootScope.newPushActive = false;\r\n if (stwoPushNotificationInfo) {\r\n delete stwoPushNotificationInfo.id\r\n for (var i in response.data.result) {\r\n var sub = response.data.result[i];\r\n //$window.alert(\"Sub \" + i + \":\\n\\n\" + JSON.stringify(sub));\r\n if (sub.token == stwoPushNotificationInfo.token && (sub.customer == null || smarttrackerService.getCustomerId() == sub.customer.id)) {\r\n $rootScope.newPushActive = true;\r\n stwoPushNotificationInfo.id = sub.id;\r\n //DEBUG//$window.alert(\"Push active with id \" + stwoPushNotificationInfo.id);\r\n break;\r\n }\r\n\r\n }\r\n }\r\n //DEBUG//$window.alert(\"checkToken Done\");\r\n $rootScope.newPushWorking = false;\r\n }, function (errorResp) {\r\n $window.alert(\"checktoken failed: \" + errorResp);\r\n $rootScope.newPushWorking = false;\r\n });\r\n }\r\n }\r\n\r\n $translate(['PUSH_OFF', 'PUSH_ON']).then(function (translations) {\r\n $rootScope.enablePush = translations.PUSH_ON;\r\n $rootScope.disablePush = translations.PUSH_OFF;\r\n });\r\n\r\n $rootScope.newPushDebugInfo = JSON.stringify(stwoPushNotificationInfo);\r\n $rootScope.newPushEnabled = stwoPushNotificationInfo ? true : false;\r\n $rootScope.newPushActive = false;\r\n $rootScope.newPushWorking = false;\r\n $rootScope.newPushTokens = [];\r\n\r\n var enablePushLink = \"smarttrackermobile:enablePush:\" + smarttrackerService.getAuthToken() + \":\" + smarttrackerService.getCustomerId();\r\n var disablePushLink = \"smarttrackermobile:disablePush\";\r\n\r\n var ua = $window.navigator.userAgent.toLowerCase();\r\n\r\n $rootScope.isAndroid = /android/.test(ua);\r\n $rootScope.isXguard = /xguard/.test(ua);\r\n $rootScope.isIOS = /iphone|ipod|ipad/.test(ua);\r\n $rootScope.isIOSApp = !/safari/.test(ua); //$window.navigator.standalone;\r\n\r\n $rootScope.pushEnabled = smarttrackerService.isPushSubscriptionEnabled();\r\n $rootScope.btnCaption = $scope.pushEnabled ? $scope.disablePush : $scope.enablePush;\r\n $translate(['XGUARD_USER_PUSH_OFF', 'XGUARD_USER_PUSH_ON']).then(function (translations) {\r\n $rootScope.enablePush = translations['XGUARD_USER_PUSH_ON'];\r\n $rootScope.disablePush = translations['XGUARD_USER_PUSH_OFF'];\r\n $rootScope.btnCaption = $scope.pushEnabled ? $scope.disablePush : $scope.enablePush;\r\n\r\n });\r\n\r\n $rootScope.useragent = $window.navigator.userAgent;\r\n //$scope.displayPushButton = $scope.userAgent.indexOf('iPhone')\r\n\r\n $rootScope.togglePush = function () {\r\n smarttrackerService.togglePushSubscription();\r\n $rootScope.pushEnabled = smarttrackerService.isPushSubscriptionEnabled();\r\n $rootScope.btnCaption = $rootScope.pushEnabled ? $rootScope.disablePush : $rootScope.enablePush;\r\n window.location = $rootScope.pushEnabled ? disablePushLink : enablePushLink;\r\n console.log($rootScope.btnCaption);\r\n }\r\n\r\n $rootScope.toggleNewPush = function () {\r\n\r\n //DEBUG//$window.alert('Toggle started\\n'+JSON.stringify(stwoPushNotificationInfo))\r\n\r\n $rootScope.newPushWorking = true;\r\n if ($rootScope.newPushActive) {\r\n\r\n if (stwoPushNotificationInfo === null) {\r\n //DEBUG//$window.alert('Trying to disable but push Notifications are not enabled for your device.')\r\n return;\r\n }\r\n\r\n if (typeof stwoPushNotificationInfo.id === 'undefined') {\r\n\r\n $rootScope.checkToken();\r\n setTimeout(function () {\r\n\r\n $rootScope.toggleNewPush();\r\n\r\n }, 1000)\r\n return;\r\n\r\n }\r\n\r\n stwoPushNotificationInfo.customer = {\r\n \"id\": smarttrackerService.getCustomerId()\r\n };\r\n\r\n //DEBUG//$window.alert(\"stwoPushNotificationInfo\\n\\n\" +JSON.stringify(stwoPushNotificationInfo))\r\n\r\n smarttrackerService.authDelete(smarttrackerService.getCustomerId() + \"/pushSubscription/\" + stwoPushNotificationInfo.id)\r\n .then(function (response) {\r\n delete stwoPushNotificationInfo.id;\r\n $rootScope.checkToken();\r\n }, function (errorResponse) {\r\n\r\n $rootScope.checkToken();\r\n //DEBUG//$window.alert('Delete failed: '+JSON.stringify(errorResponse))\r\n\r\n\r\n });\r\n } else {\r\n\r\n if (stwoPushNotificationInfo === null) {\r\n //DEBUG//$window.alert('Push Notifications are not enabled for your device.')\r\n return;\r\n }\r\n\r\n // var rs = $scope.soundData.redAlarmSound.sound.file;\r\n // var gs = $scope.soundData.greenAlarmSound.sound.file;\r\n // var os = $scope.soundData.orangeAlarmSound.sound.file;\r\n // rs = getSoundName(rs) + \".wav\";\r\n // gs = getSoundName(gs) + \".wav\";\r\n // os = getSoundName(os) + \".wav\";\r\n if (stwoPushNotificationInfo.labels && stwoPushNotificationInfo.labels[\"version\"] && stwoPushNotificationInfo.labels[\"version\"] == \"2.0\") {\r\n stwoPushNotificationInfo.soundFilter = createSoundFilter();\r\n console.log(stwoPushNotificationInfo);\r\n stwoPushNotificationInfo.labels[\"version\"] = {\r\n value: stwoPushNotificationInfo.labels[\"version\"]\r\n };\r\n }\r\n smarttrackerService.authPost(smarttrackerService.getCustomerId() + \"/pushSubscription/\", stwoPushNotificationInfo)\r\n .then(function (response) {\r\n $rootScope.checkToken();\r\n //DEBUG//$window.alert('checking token after adding')\r\n }, function (errorResponse) {\r\n //DEBUG//$window.alert('error\\n\\n'+JSON.stringify(errorResponse))\r\n if (errorResponse.status == 409) {\r\n $rootScope.notificationError = true;\r\n smarttrackerService.authPost(smarttrackerService.getCustomerId() + \"/pushSubscription/?overwriteIfExists=true\", stwoPushNotificationInfo)\r\n .then(function (response) {\r\n //DEBUG//$window.alert('checking token after adding (overwrite)')\r\n $rootScope.checkToken();\r\n });\r\n }\r\n });\r\n }\r\n }\r\n\r\n $rootScope.checkToken();\r\n\r\n smarttrackerService.isLoggedInDelayed().then(function () {\r\n\r\n console.log('IS LOGGED IN DELAYED OK');\r\n\r\n $scope.userData = smarttrackerService.getUserData();\r\n\r\n $scope.$watch(\"userData.customer.id\", function () {\r\n $rootScope.checkToken();\r\n })\r\n\r\n $scope.sounds = notificationService.getSounds();\r\n $scope.soundData = $scope.userData.user.preferences.meta ? $scope.userData.user.preferences.meta : {};\r\n $scope.soundData = notificationService.checkSoundData($scope.soundData);\r\n\r\n $rootScope.checkToken();\r\n\r\n }, function () {\r\n\r\n console.log('IS LOGGED IN DELAYED NOT OK: Logout');\r\n\r\n $state.go(moduleStore.states().notLoggedIn);\r\n return;\r\n });\r\n // end\r\n\r\n\r\n\r\n //adding underscore lib to scope\r\n $scope[\"_\"] = _;\r\n\r\n $scope[\"hiddenUi\"] = stwoGlobal.hiddenUi;\r\n\r\n $scope.modalContent = {\r\n images: []\r\n };\r\n $scope.openModalImages = function (imageUrlArr) {\r\n $scope.modalContent.images = imageUrlArr;\r\n }\r\n\r\n var lastMouseMove = (new Date()).getTime();\r\n $scope.inactivityState = {\r\n \"enabled\": false,\r\n \"warning\": false,\r\n \"remaining\": 12,\r\n \"remainingPct\": 0.6,\r\n \"warningTime\": 0\r\n };\r\n\r\n if (stwoGlobal.inactivityTimeout > 0) {\r\n $scope.inactivityState.enabled = true;\r\n $scope.inactivityState.warningTime = stwoGlobal.inactivityTimeout * (3 / 4);\r\n document.addEventListener(\r\n 'mousemove',\r\n function () {\r\n lastMouseMove = (new Date()).getTime();\r\n if ($scope.inactivityState.warning) {\r\n $scope.inactivityState.warning = false;\r\n }\r\n },\r\n false\r\n );\r\n }\r\n\r\n\r\n smarttrackerService.isLoggedInDelayed().then(function () {\r\n\r\n // var socketioService = moduleStoreProvider.serviceRepository()[\"socketioService\"];\r\n socketioService.connect();\r\n\r\n moduleStore.serviceRepository()[\"$state\"] = $state;\r\n moduleStore.serviceRepository()[\"$modal\"] = $modal;\r\n pushService.enabled(true);\r\n\r\n $scope.status = {\r\n menuOpen: false,\r\n notificationsOpen: false,\r\n settingsOpen: false\r\n };\r\n\r\n $scope.userData = smarttrackerService.getUserData();\r\n\r\n $scope.timers = timerService.timers();\r\n $scope.links = moduleStore.rootLinks();\r\n $scope.notifications = notificationService.undismissed();\r\n $scope.notificationsChanged = notificationService.changed;\r\n $scope.modules = moduleStore.modules();\r\n $scope.access = smarttrackerService.getAccessRights();\r\n $scope.customNotifications = notificationService.customNotifications();\r\n $scope.notificationTypes = notificationService.notificationTypes();\r\n console.log($scope.notificationTypes);\r\n\r\n $scope.customNotificationClicked = function (notification) {\r\n console.log(\"notification clicked\", notification);\r\n console.log($scope.notificationTypes[notification.type]);\r\n console.log($scope.notificationTypes[notification.type].state);\r\n $state.go($scope.notificationTypes[notification.type].state);\r\n\r\n $scope.notificationCenter = false;\r\n }\r\n\r\n $scope.dismissCustomNotification = function (notification) {\r\n console.log(\"Dismiss notification\");\r\n notificationService.dismissCustomNotification(notification);\r\n $scope.customNotifications = notificationService.customNotifications();\r\n }\r\n\r\n $scope.allLinks = moduleStore.links();\r\n $scope.categories = moduleStore.categories();\r\n\r\n $scope.rebuildLinksPerCategory = function () {\r\n $scope.linksPerCategory = {};\r\n $scope.navigationLinksPerCategory = {};\r\n $scope.navigationLinksCount = 0;\r\n $scope.categoriesWithLinks = 0;\r\n for (var n = 0; n < $scope.allLinks.length; n++) {\r\n var l = $scope.allLinks[n];\r\n\r\n if (!$scope.linksPerCategory[l.category]) {\r\n $scope.linksPerCategory[l.category] = [];\r\n }\r\n if (l.hasAccess(l, $scope.access)) {\r\n $scope.linksPerCategory[l.category].push(l);\r\n if (l.navigation) {\r\n if (!$scope.navigationLinksPerCategory[l.category]) {\r\n $scope.navigationLinksPerCategory[l.category] = [];\r\n $scope.categoriesWithLinks++;\r\n }\r\n $scope.navigationLinksPerCategory[l.category].push(l);\r\n $scope.navigationLinksCount++;\r\n }\r\n }\r\n }\r\n }\r\n\r\n $scope.rebuildLinksPerCategory();\r\n\r\n $scope.$watch(\"allLinks.length\", function () {\r\n $scope.rebuildLinksPerCategory();\r\n })\r\n\r\n $scope.notificationAudio = notificationService.audio;\r\n\r\n $scope.$watch(\"notificationsChanged.dismissed + notificationsChanged.added + notificationsChanged.updated + notificationsChanged.removed\", function () {\r\n $scope.notifications = notificationService.undismissed();\r\n $scope.customNotifications = notificationService.customNotifications();\r\n checkAndPlayNotificationSound();\r\n })\r\n $scope.$watch(\"notificationsChanged.added\", function (newVal, oldVal) {\r\n if (newVal) {\r\n $scope.notificationAudio.snoozed = false;\r\n }\r\n })\r\n\r\n $scope.toggleMute = function () {\r\n notificationService.audio.muted = !notificationService.audio.muted;\r\n localStorage[\"stwo-mute\"] = notificationService.audio.muted;\r\n }\r\n $scope.toggleIgnoreSnooze = function () {\r\n notificationService.audio.ignoreSnooze = !notificationService.audio.ignoreSnooze;\r\n localStorage[\"stwo-ignore-snooze\"] = notificationService.audio.ignoreSnooze;\r\n }\r\n\r\n $scope.stopPlayingNotificationAudio = function () {\r\n $scope.notificationAudio.snoozed = true;\r\n }\r\n\r\n var player = false;\r\n var playingFile = false;\r\n var play = function (color, file) {\r\n if (playingFile === file && player.remaining > 0) {\r\n return;\r\n }\r\n ngAudio.setUnlock(false);\r\n playingFile = file;\r\n if (player) {\r\n player.stop();\r\n player.unbind();\r\n }\r\n player = ngAudio.play(file);\r\n }\r\n\r\n var checkAndPlayNotificationSound = function () {\r\n if ($scope.notifications.length === 0) {\r\n $scope.notificationAudio.snoozed = false;\r\n }\r\n if (!notificationService.audio.muted && $scope.notifications.length) {\r\n var anyRedAlert = false;\r\n var anyOrangeAlerts = false;\r\n var anyGreenAlerts = false;\r\n var anyAlerts = false;\r\n var anyCPEvents = false;\r\n angular.forEach($scope.notifications, function (notification) {\r\n if (!notificationService.ignored[notification.id]) {\r\n if (notification.module == \"alarm\") {\r\n if (notification.level === \"danger\") {\r\n anyRedAlert = true;\r\n } else if (notification.level === \"warning\") {\r\n anyOrangeAlerts = true;\r\n } else if (notification.level === \"success\") {\r\n anyGreenAlerts = true;\r\n }\r\n } else if (notification.module == \"cp\") {\r\n anyCPEvents = true;\r\n }\r\n }\r\n anyAlerts = anyRedAlert || anyOrangeAlerts || anyGreenAlerts || anyCPEvents;\r\n });\r\n\r\n if (anyAlerts && (!notificationService.audio.snoozed || notificationService.audio.ignoreSnooze)) {\r\n var userData = smarttrackerService.getUserData();\r\n var soundData = notificationService.checkSoundData($scope.userData.user.preferences.meta ? $scope.userData.user.preferences.meta : {});\r\n\r\n if (anyRedAlert && !soundData.redAlarmSound.muted) {\r\n play(\"red\", soundData.redAlarmSound.sound.file);\r\n } else if (anyOrangeAlerts && !soundData.orangeAlarmSound.muted) {\r\n play(\"orange\", soundData.orangeAlarmSound.sound.file);\r\n } else if (anyGreenAlerts && !soundData.greenAlarmSound.muted) {\r\n play(\"green\", soundData.greenAlarmSound.sound.file);\r\n } else if (anyCPEvents && !soundData.cpAlarmSound.muted) {\r\n play(\"cp\", soundData.cpAlarmSound.sound.file);\r\n }\r\n }\r\n }\r\n }\r\n\r\n $scope.$watch(\"timers.one\", function () {\r\n pushService.processNewPushMessages();\r\n checkAndPlayNotificationSound();\r\n\r\n if (stwoGlobal.inactivityTimeout > 0) {\r\n var now = (new Date()).getTime();\r\n if (now - lastMouseMove > stwoGlobal.inactivityTimeout * 1000) {\r\n console.log(\"Logged out because of inactivity\")\r\n $state.go(\"logout\", {\r\n reason: \"LOGOUT_INACTIVITY_TIMEOUT\"\r\n });\r\n } else if (now - lastMouseMove > $scope.inactivityState.warningTime * 1000) {\r\n if (!$scope.inactivityState.warning) {\r\n console.log(\"Inactivity warning\")\r\n }\r\n $scope.inactivityState.warning = true;\r\n $scope.inactivityState.remaining = Math.round(((lastMouseMove + stwoGlobal.inactivityTimeout * 1000) - now) / 1000);\r\n $scope.inactivityState.remainingPct = $scope.inactivityState.remaining / (stwoGlobal.inactivityTimeout - $scope.inactivityState.warningTime);\r\n\r\n }\r\n }\r\n\r\n })\r\n\r\n $scope.viewNotification = function (notification) {\r\n notificationService.view(notification);\r\n $scope.status.notificationsOpen = false;\r\n }\r\n\r\n $scope.goToNotifications = function () {\r\n $scope.status.menuOpen = false;\r\n $state.go(\"secure.notifications\");\r\n }\r\n\r\n $scope.$watch(\"timers.ten\", function () {\r\n notificationService.poll();\r\n })\r\n\r\n\r\n $scope.pushChanged = pushService.changed();\r\n $scope.$watch(\"pushChanged.counter\", function () {\r\n pushService.process(function (data, util) {\r\n notificationService.push(data, util);\r\n });\r\n })\r\n\r\n $scope.getSelectedCustomer = function () {\r\n var customer = smarttrackerService.getAvailableCustomers()[index];\r\n if (customer && (!$scope.selectedCustomer || $scope.selectedCustomer.id !== customer.id)) {\r\n for (var index in smarttrackerService.getAvailableCustomers()) {\r\n if (customer.id == smarttrackerService.getCustomerId()) {\r\n $scope.selectedCustomer = customer;\r\n break;\r\n }\r\n }\r\n }\r\n return $scope.selectedCustomer;\r\n }\r\n $scope.getSelectedProvider = function () {\r\n if (!$scope.selectedProvider) {\r\n for (var index in smarttrackerService.getAvailableProviders()) {\r\n var provider = smarttrackerService.getAvailableProviders()[index];\r\n if (provider.id === smarttrackerService.getProviderId()) {\r\n $scope.selectedProvider = provider;\r\n break;\r\n }\r\n }\r\n }\r\n return $scope.selectedProvider;\r\n }\r\n\r\n $scope.getActiveControllerName = function () {\r\n return $state.current.controller;\r\n }\r\n\r\n $scope.getTitleName = function () {\r\n return $state.current.titleName;\r\n }\r\n\r\n $scope.getTitleIcon = function () {\r\n return $state.current.titleIcon;\r\n }\r\n\r\n $scope.getParentControllerName = function () {\r\n return $state.$current.parent.controller;\r\n }\r\n\r\n $scope.getCurrentState = function () {\r\n return $state.current.name;\r\n }\r\n\r\n $scope.getBodyClass = function () {\r\n return $state.current.bodyclass;\r\n }\r\n\r\n $scope.checkCurrentState = function () { //true if it is among the arguments\r\n for (var i = 0; i < arguments.length; i++) {\r\n if ($state.current.name == arguments[i]) return true;\r\n }\r\n return false;\r\n }\r\n\r\n $scope.linkClicked = function (link) {\r\n $scope.status.menuOpen = false;\r\n if (link.stateParams) {\r\n $state.go(link.sref.split(\"(\")[0], link.stateParams);\r\n } else {\r\n $state.go(link.sref);\r\n }\r\n }\r\n\r\n $scope.currentVersion = stwoGlobal.appVersion;\r\n $scope.beta = stwoGlobal.beta;\r\n\r\n if (!localStorage[\"localVersion\"] && (localStorage[\"SidebarMap\"] != null)) {\r\n localStorage[\"localVersion\"] = $scope.currentVersion;\r\n localStorage[\"updateNotification\"] = true;\r\n $scope.showUpdateNotification = true;\r\n }\r\n\r\n if (!localStorage[\"localVersion\"]) {\r\n localStorage[\"localVersion\"] = $scope.currentVersion;\r\n localStorage[\"updateNotification\"] = false;\r\n $scope.showUpdateNotification = false;\r\n }\r\n\r\n if (localStorage[\"localVersion\"] != $scope.currentVersion) {\r\n localStorage[\"localVersion\"] = $scope.currentVersion;\r\n localStorage[\"updateNotification\"] = true;\r\n $scope.showUpdateNotification = true;\r\n }\r\n\r\n if (localStorage[\"updateNotification\"] == 'true') {\r\n $scope.showUpdateNotification = true;\r\n }\r\n\r\n $scope.closeUpdateNotification = function () {\r\n localStorage[\"updateNotification\"] = false;\r\n $scope.showUpdateNotification = false;\r\n }\r\n\r\n\r\n }, function () {\r\n $state.go(moduleStore.states().notLoggedIn);\r\n return;\r\n });\r\n\r\n\r\n});\r\nangular.module('stwo.glue').controller('ContentController', function ($scope, $state, smarttrackerService, moduleStore) {\r\n smarttrackerService.isLoggedInDelayed().then(function () {\r\n if (!smarttrackerService.getCustomerId()) {\r\n $state.go(moduleStore.states().missingCustomer);\r\n return;\r\n }\r\n });\r\n});\r\nangular.module('stwo.glue').controller('UserController', function ($rootScope, $scope, $state, smarttrackerService, mapService, moduleStore, $translate, $window, ngAudio, utilService, notificationService) {\r\n\r\n $scope.state = {\r\n tab: \"settings\"\r\n };\r\n $scope.selected = {};\r\n\r\n // $translate(['PUSH_OFF', 'PUSH_ON']).then(function (translations) {\r\n // $scope.enablePush = translations.PUSH_ON;\r\n // $scope.disablePush = translations.PUSH_OFF;\r\n // });\r\n\r\n // $scope.newPushEnabled = stwoPushNotificationInfo?true:false;\r\n // $scope.newPushActive = false;\r\n // $scope.newPushWorking = false;\r\n // $scope.newPushTokens = [];\r\n\r\n smarttrackerService.isLoggedInDelayed().then(function () {\r\n // checkToken();\r\n $scope.fieldsPerView = 7;\r\n readInvitations();\r\n });\r\n\r\n var readInvitations = function () {\r\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/userInvitation?select=customer&type:equals=customer&status:equals=pending\").then(function (response) {\r\n $scope.invitations = response.data.result;\r\n });\r\n }\r\n $scope.updateInvitation = function (invitation, status) {\r\n console.log(\"Will update invitation\");\r\n invitation.status = status;\r\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + \"/userInvitation/\" + invitation.id, {\r\n status: status\r\n }).then(function () {\r\n readInvitations();\r\n notificationService.dismissCustomNotifiactionsForObject(invitation);\r\n });\r\n }\r\n\r\n $scope.showMoreCustomers = function () {\r\n $scope.fieldsPerView += 10;\r\n }\r\n $scope.showAllCustomers = function () {\r\n $scope.fieldsPerView = $scope.availableCustomers.length;\r\n }\r\n\r\n $scope.availableCustomers = smarttrackerService.getAvailableCustomers();\r\n $scope.availableProviders = smarttrackerService.getAvailableProviders();\r\n\r\n $scope.availableMapProviders = mapService.getAvailableLayers();\r\n\r\n // var enablePushLink = \"smarttrackermobile:enablePush:\" + smarttrackerService.getAuthToken() + \":\" + smarttrackerService.getCustomerId();\r\n // var disablePushLink = \"smarttrackermobile:disablePush\";\r\n\r\n // var ua = $window.navigator.userAgent.toLowerCase();\r\n\r\n // $scope.isAndroid = /android/.test(ua);\r\n // $scope.isXguard = /xguard/.test(ua);\r\n // $scope.isIOS = /iphone|ipod|ipad/.test(ua);\r\n // $scope.isIOSApp = !/safari/.test(ua);//$window.navigator.standalone;\r\n\r\n // $scope.pushEnabled = smarttrackerService.isPushSubscriptionEnabled();\r\n // $scope.btnCaption = $scope.pushEnabled ? $scope.disablePush : $scope.enablePush;\r\n // $translate(['XGUARD_USER_PUSH_OFF', 'XGUARD_USER_PUSH_ON']).then(function (translations) {\r\n // $scope.enablePush = translations['XGUARD_USER_PUSH_ON'];\r\n // $scope.disablePush = translations['XGUARD_USER_PUSH_OFF'];\r\n // $scope.btnCaption = $scope.pushEnabled ? $scope.disablePush : $scope.enablePush;\r\n\r\n // });\r\n\r\n // $scope.useragent = $window.navigator.userAgent;\r\n //$scope.displayPushButton = $scope.userAgent.indexOf('iPhone')\r\n\r\n // $scope.togglePush = function () {\r\n // smarttrackerService.togglePushSubscription();\r\n // $scope.pushEnabled = smarttrackerService.isPushSubscriptionEnabled();\r\n // $scope.btnCaption = $scope.pushEnabled ? $scope.disablePush : $scope.enablePush;\r\n // window.location = $scope.pushEnabled ? disablePushLink : enablePushLink;\r\n // console.log($scope.btnCaption);\r\n // }\r\n\r\n $scope.openDialog = \"\";\r\n $scope.openSoundSelector = function (color) {\r\n $scope.openDialog = color;\r\n }\r\n\r\n $scope.closeAudioSelector = function ($event) {\r\n var cl = $event.target.classList;\r\n if ($event.target.id != $scope.openDialog && !cl.contains(\"sound\")) {\r\n $scope.openDialog = \"\";\r\n $scope.activeSound = null;\r\n if (audio) {\r\n audio.stop();\r\n audio.unbind();\r\n }\r\n }\r\n };\r\n\r\n var audio = false;\r\n $scope.selectSound = function (sound, color) {\r\n // var data = utilService.clone($scope.soundData);\r\n // data[color + \"AlarmSound\"].sound = sound;\r\n // updateSoundPrefs(data);\r\n $scope.activeSound = sound;\r\n if (audio) {\r\n audio.stop();\r\n audio.unbind();\r\n }\r\n ngAudio.setUnlock(false);\r\n audio = ngAudio.load(sound.file);\r\n audio.play();\r\n }\r\n\r\n $scope.saveSound = function (color) {\r\n var data = {};\r\n angular.forEach($scope.soundData, function (value, key) {\r\n data[key] = utilService.clone(value);\r\n });\r\n if ($scope.soundData[color + \"AlarmSound\"].sound.file == $scope.activeSound.file) {\r\n return;\r\n }\r\n data[color + \"AlarmSound\"].sound = $scope.activeSound;\r\n updateSoundPrefs(data);\r\n $('.toggle-sounds').parent().removeClass('open');\r\n $scope.activeSound = null;\r\n }\r\n\r\n var updatePushSound = function () {\r\n angular.forEach($scope.newPushTokens, function (token, key) {\r\n if (token.soundFilter && Object.keys(token.soundFilter).length > 0) {\r\n var body = {\r\n 'soundFilter': createSoundFilter()\r\n }\r\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + \"/pushSubscription/\" + token.id, body);\r\n }\r\n })\r\n }\r\n\r\n var updateSoundPrefs = function (data) {\r\n $scope.soundDataUpdating = true;\r\n var body = {\r\n \"user\": {\r\n \"preferences\": {\r\n \"meta\": data\r\n }\r\n }\r\n };\r\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + \"/index\", body).then(function (response) {\r\n console.log(\"ALLES IN ORDNUNG\");\r\n $scope.userData.user.preferences.meta = response.data.user.preferences.meta;\r\n $scope.soundData = notificationService.checkSoundData($scope.userData.user.preferences.meta);\r\n $scope.soundDataUpdating = false;\r\n updatePushSound();\r\n }, function () {\r\n console.log(\"Nicht So Gut :(\");\r\n $scope.soundDataUpdating = false;\r\n });\r\n }\r\n $scope.toggleMuted = function (color) {\r\n var data = utilService.clone($scope.soundData);\r\n data[color + \"AlarmSound\"].muted = !data[color + \"AlarmSound\"].muted;\r\n updateSoundPrefs(data);\r\n }\r\n\r\n var getSoundName = function (sound) {\r\n var ss = sound.sound.file;\r\n return sound.muted ? 'silence.wav' : (ss.substring(ss.lastIndexOf(\"/\") + 1, ss.indexOf(\".mp3\")).toLowerCase() + \".wav\");\r\n }\r\n\r\n var createSoundFilter = function () {\r\n var sf = {};\r\n sf[getSoundName($scope.soundData.redAlarmSound)] = \"severity:equals=high\";\r\n var n = getSoundName($scope.soundData.greenAlarmSound);\r\n sf[n] = sf[n] ? 'OR( ' + sf[n] + \"; severity:equals=low )\" : \"severity:equals=low\";\r\n n = getSoundName($scope.soundData.orangeAlarmSound);\r\n sf[n] = sf[n] ? (sf[n].indexOf('OR(') == 0 ? sf[n].replace(' )', '; severity:equals=normal; )') : 'OR( ' + sf[n] + '; severity:equals=normal; )') : \"severity:equals=normal\";\r\n // sf[getSoundName($scope.soundData.greenAlarmSound)] =\r\n // sf[getSoundName($scope.soundData.greenAlarmSound)] = \"severity:equals=low\";\r\n // sf[getSoundName($scope.soundData.orangeAlarmSound)] = \"severity:equals=normal\";\r\n return sf;\r\n }\r\n\r\n // $scope.toggleNewPush = function() {\r\n // $scope.newPushWorking = true;\r\n // if($scope.newPushActive){\r\n // stwoPushNotificationInfo.customer = {\"id\":smarttrackerService.getCustomerId()};\r\n // smarttrackerService.authDelete(smarttrackerService.getCustomerId() + \"/pushSubscription/\" + stwoPushNotificationInfo.id)\r\n // .then(function (response){\r\n // delete stwoPushNotificationInfo.id;\r\n // checkToken();\r\n // });\r\n // } else {\r\n // // var rs = $scope.soundData.redAlarmSound.sound.file;\r\n // // var gs = $scope.soundData.greenAlarmSound.sound.file;\r\n // // var os = $scope.soundData.orangeAlarmSound.sound.file;\r\n // // rs = getSoundName(rs) + \".wav\";\r\n // // gs = getSoundName(gs) + \".wav\";\r\n // // os = getSoundName(os) + \".wav\";\r\n // if(stwoPushNotificationInfo.labels&&stwoPushNotificationInfo.labels[\"version\"]&&stwoPushNotificationInfo.labels[\"version\"]==\"2.0\") {\r\n // stwoPushNotificationInfo.soundFilter = createSoundFilter();\r\n // console.log(stwoPushNotificationInfo);\r\n // stwoPushNotificationInfo.labels[\"version\"] = {value:stwoPushNotificationInfo.labels[\"version\"]};\r\n // }\r\n // smarttrackerService.authPost(smarttrackerService.getCustomerId() + \"/pushSubscription/\", stwoPushNotificationInfo)\r\n // .then(function (response){\r\n // checkToken();\r\n // }, function (errorResponse){\r\n // if(errorResponse.status == 409) {\r\n // $scope.notificationError = true;\r\n // smarttrackerService.authPost(smarttrackerService.getCustomerId() + \"/pushSubscription/?overwriteIfExists=true\", stwoPushNotificationInfo)\r\n // .then(function (response){\r\n // checkToken();\r\n // }); \r\n // }\r\n // });\r\n // }\r\n // }\r\n\r\n // var checkToken = function() {\r\n // if(smarttrackerService.getCustomerId()) {\r\n // smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/pushSubscription?select=token+customer+soundFilter\").then(function (response){\r\n // $scope.newPushTokens = response.data.result;\r\n // $scope.newPushActive = false;\r\n // if(stwoPushNotificationInfo){\r\n // delete stwoPushNotificationInfo.id\r\n // for(var i in response.data.result){\r\n // var sub = response.data.result[i];\r\n // if(sub.token == stwoPushNotificationInfo.token && (sub.customer == null || smarttrackerService.getCustomerId() == sub.customer.id)){\r\n // $scope.newPushActive = true;\r\n // stwoPushNotificationInfo.id = sub.id;\r\n // break;\r\n // }\r\n\r\n // }\r\n // }\r\n // $scope.newPushWorking = false;\r\n // }, function(errorResp){\r\n // alert(\"failed: \" + errorResp);\r\n // $scope.newPushWorking = false;\r\n // });\r\n // }\r\n // }\r\n\r\n\r\n $scope.getCurrentCustomerId = function () {\r\n return smarttrackerService.getCustomerId();\r\n }\r\n $scope.selectedCustomerIndex = 0;\r\n $scope.customerName = '';\r\n\r\n $scope.customerSearch = function ($event, maxSearch, customerId) {\r\n if ($scope.customerName == '') return;\r\n var keyCode = $event.which || $event.keyCode;\r\n if (keyCode === 13) {\r\n console.log(customerId);\r\n if (customerId) {\r\n $scope.chooseCustomer(customerId);\r\n }\r\n } else if (keyCode == 38 /*UpArrow*/ ) {\r\n if ($scope.selectedCustomerIndex > 0) $scope.selectedCustomerIndex--;\r\n } else if (keyCode == 40 /*Down Arrow*/ ) {\r\n $scope.selectedCustomerIndex = Math.min(maxSearch - 1, $scope.selectedCustomerIndex + 1);\r\n } else {\r\n $scope.selectedCustomerIndex = 0;\r\n }\r\n }\r\n\r\n $scope.getCurrentCustomerName = function () {\r\n if (smarttrackerService.getCustomerId()) {\r\n for (var n = 0; n < $scope.availableCustomers.length; n++) {\r\n if ($scope.availableCustomers[n].id === smarttrackerService.getCustomerId()) {\r\n return $scope.availableCustomers[n].name;\r\n }\r\n }\r\n return null;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n $scope.getCurrentProviderId = function () {\r\n return smarttrackerService.getProviderId();\r\n }\r\n\r\n $scope.getCurrentProviderName = function () {\r\n if (smarttrackerService.getProviderId()) {\r\n for (var n = 0; n < $scope.availableProviders.length; n++) {\r\n if ($scope.availableProviders[n].id === smarttrackerService.getProviderId()) {\r\n return $scope.availableProviders[n].name;\r\n }\r\n }\r\n return null;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n $scope.customerSelectWorking = false;\r\n $scope.chooseCustomer = function (customerId) {\r\n if ($scope.customerSelectWorking || customerId == smarttrackerService.getCustomerId()) return;\r\n $scope.customerSelectWorking = true;\r\n smarttrackerService.changeCustomer(customerId).then(function (response) {\r\n $scope.customerSelectWorking = false;\r\n });\r\n }\r\n $scope.chooseProvider = function (providerId) {\r\n smarttrackerService.changeProvider(providerId);\r\n }\r\n\r\n $scope.availableLanguages = stwoGlobal.availableLanguages;\r\n\r\n\r\n $scope.mapDefaultStates = [{\r\n key: \"auto\",\r\n label: \"MAP_DEFAULT_AUTO\"\r\n }, {\r\n key: \"indoor\",\r\n label: \"MAP_DEFAULT_INDOOR\"\r\n }, {\r\n key: \"outdoor\",\r\n label: \"MAP_DEFAULT_OUTDOOR\"\r\n }]\r\n\r\n $translate(['MAP_DEFAULT_AUTO', 'MAP_DEFAULT_INDOOR', 'MAP_DEFAULT_OUTDOOR']).then(function (translations) {\r\n $scope.mapDefaultStates[0].label = translations.MAP_DEFAULT_AUTO;\r\n $scope.mapDefaultStates[1].label = translations.MAP_DEFAULT_INDOOR;\r\n $scope.mapDefaultStates[2].label = translations.MAP_DEFAULT_OUTDOOR;\r\n });\r\n\r\n smarttrackerService.isLoggedInDelayed().then(function () {\r\n for (var n = 0; n < stwoGlobal.availableLanguages.length; n++) {\r\n if (stwoGlobal.availableLanguages[n].code === smarttrackerService.language()) {\r\n $scope.selected[\"language\"] = stwoGlobal.availableLanguages[n];\r\n }\r\n }\r\n if (!$scope.selected[\"language\"]) {\r\n $scope.selected[\"language\"] = stwoGlobal.availableLanguages[0];\r\n }\r\n $scope.selected[\"mapProvider\"] = $scope.availableMapProviders[mapService.chosenLayer()];\r\n\r\n\r\n $scope.selected[\"mapDefaultState\"] = $scope.mapDefaultStates[0];\r\n for (var n = 0; n < $scope.mapDefaultStates.length; n++) {\r\n if ($scope.mapDefaultStates[n].key === localStorage[\"mapDefaultState\"]) {\r\n $scope.selected[\"mapDefaultState\"] = $scope.mapDefaultStates[n];\r\n }\r\n }\r\n $scope.$watch(\"selected.mapDefaultState.key\", function () {\r\n localStorage[\"mapDefaultState\"] = $scope.selected[\"mapDefaultState\"].key;\r\n });\r\n\r\n $scope.$watch(\"selected.language.code\", function (newVal, oldVal) {\r\n if (oldVal && oldVal !== newVal) {\r\n console.log(\"Lang changed in user controller\")\r\n\r\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + '/index', {\r\n user: {\r\n language: $scope.selected.language.code\r\n }\r\n })\r\n .then(function (response) {\r\n\r\n }, function (response) {\r\n\r\n });\r\n\r\n smarttrackerService.language($scope.selected[\"language\"].code);\r\n }\r\n });\r\n $scope.$watch(\"selected.mapProvider.name\", function () {\r\n mapService.chosenLayer($scope.selected[\"mapProvider\"].code);\r\n });\r\n\r\n $scope.$watch(\"userData.customer.id\", function () {\r\n $rootScope.checkToken();\r\n })\r\n $scope.sounds = notificationService.getSounds();\r\n $scope.soundData = $scope.userData.user.preferences.meta ? $scope.userData.user.preferences.meta : {};\r\n $scope.soundData = notificationService.checkSoundData($scope.soundData);\r\n\r\n }, function () {\r\n $state.go(moduleStore.states().notLoggedIn);\r\n return;\r\n });\r\n\r\n\r\n\r\n});\r\n\r\n\r\nangular.module('stwo.glue').controller('LogoutController', function ($scope, $state, $timeout, $stateParams, smarttrackerService, moduleStore) {\r\n smarttrackerService.logout();\r\n\r\n $timeout(function () {\r\n if ($stateParams.reason) {\r\n moduleStore.flags()[\"logoutReason\"] = $stateParams.reason;\r\n } else {\r\n delete moduleStore.flags()[\"logoutReason\"];\r\n }\r\n $state.go(moduleStore.states().notLoggedIn);\r\n }, 100);\r\n});\nangular.module('stwo.glue').controller('LoginController', function ($scope, $state, $http, $translate, moduleStore, $stateParams, smarttrackerService, notificationService, $timeout) {\r\n\t$scope.alerts = [];\r\n $scope.user = {};\r\n \r\n if (moduleStore.flags()[\"logoutReason\"]) {\r\n $scope.alerts.push({type: \"danger\", textToTranslate: moduleStore.flags()[\"logoutReason\"]});\r\n }\r\n \r\n $scope.login = {state: \"login\", language: null, working: false, rememberLogin: true, renewPassword: false, credentialsMode: true};\r\n\r\n $translate(['LOGIN_FORGOT_PASSWORD_MAIL_TEMPLATE']).then(function (translations) {\r\n $scope.login.mailTemplate = translations['LOGIN_FORGOT_PASSWORD_MAIL_TEMPLATE'];\r\n });\r\n \r\n $scope.availableLanguages = stwoGlobal.availableLanguages;\r\n for (var n = 0; n < stwoGlobal.availableLanguages.length; n++) {\r\n if (stwoGlobal.availableLanguages[n].code === smarttrackerService.language()) {\r\n $scope.login[\"language\"] = stwoGlobal.availableLanguages[n];\r\n }\r\n }\r\n if (!$scope.login[\"language\"]) {\r\n $scope.login[\"language\"] = stwoGlobal.availableLanguages[0];\r\n }\r\n $scope.setLanguage = function(languageCode) {\r\n for (var n = 0; n < stwoGlobal.availableLanguages.length; n++) {\r\n if (stwoGlobal.availableLanguages[n].code === languageCode) {\r\n $scope.login[\"language\"] = stwoGlobal.availableLanguages[n];\r\n smarttrackerService.language(languageCode);\r\n }\r\n }\r\n };\r\n \r\n console.log(\"Language\", $scope.login[\"language\"]);\r\n \r\n\t$scope.sendRecoveryMail = function(usernameToRecover) {\r\n \r\n $scope.login.working = true;\r\n $http.post(smarttrackerService.url() + \"api2/passwordRecovery\", {\"action\":\"requestRecovery\", \"html\": $scope.login.mailTemplate, \"username\": usernameToRecover}).then(function(response) {\r\n $scope.login.working = false;\r\n $scope.login.modalAlert = \"LOGIN_FORGOT_PASSWORD_RECOVERY_REQUEST_SENT_TEXT\"\r\n }, function() {\r\n $scope.login.working = false;\r\n $scope.login.modalAlert = \"LOGIN_FORGOT_PASSWORD_RECOVERY_REQUEST_ERROR_TEXT\"\r\n });\r\n\t};\r\n\t$scope.performRecovery = function(recoveryKey) {\r\n $scope.login.working = true;\r\n $http.post(smarttrackerService.url() + \"api2/passwordRecovery\", {\"action\":\"performRecovery\", \"recoveryKey\": recoveryKey}).then(function(response) {\r\n $scope.login.working = false;\r\n $scope.login.modalAlert = \"LOGIN_FORGOT_PASSWORD_PASSWORD_RESET_SUCCESS_TEXT\";\r\n $scope.login.credentialsMode = true;\r\n $scope.login.renewPassword = false;\r\n $scope.login.state = \"login\";\r\n }, function() {\r\n $scope.login.working = false;\r\n $scope.login.modalAlert = \"LOGIN_FORGOT_PASSWORD_PASSWORD_RESET_ERROR_TEXT\"\r\n });\r\n\t};\r\n \r\n \r\n\t$scope.cancelRenew = function() {\r\n\t\t$scope.login.renewPassword = false;\r\n\t}\r\n\t$scope.storedUsers = smarttrackerService.getUsers();\r\n \r\n $scope.login.credentialsMode = $scope.storedUsers.length == 0;\r\n $scope.$watch(\"storedUsers.length\", function() {\r\n $scope.login.credentialsMode = !$scope.login.credentialsMode ? $scope.storedUsers.length == 0 : $scope.login.credentialsMode;\r\n });\r\n\t$scope.doLogout = function() {\r\n\t\tsmarttrackerService.logout();\r\n\t}\r\n\r\n\t$scope.closeAlert = function (idx) {\r\n\t\t$scope.alerts.splice(idx, 1);\r\n\t}\r\n\t$scope.removeUser = function (username) {\r\n\t\tsmarttrackerService.removeUser(username);\r\n\t}\r\n\t$scope.selectUser = function(username) {\r\n\t\t$scope.login.working = true;\r\n\t\t\r\n\t\tsmarttrackerService.selectUser(username).then(function (response) {\r\n if (!response||response.status!=200) {\r\n \r\n if (response.status == 402) {\r\n $scope.alerts.push({type: \"danger\", textToTranslate:\"LOGIN_ERROR_GETTING_INFO\"});\r\n } else if(response.data.tokenNotFound || response.data.tokenExpired || response.status == 401 ){\r\n smarttrackerService.removeUser(username);\r\n $scope.alerts.push({type: \"danger\", textToTranslate:\"LOGIN_ERROR_AUTHENTICATION_TOKEN_NOT_FOUND\"});\r\n } else if (response.status == 403) {\r\n $scope.alerts.push({type: \"danger\", textToTranslate:\"LOGIN_ERROR_WRONG_CREDENTIALS\"});\r\n } else {\r\n $scope.alerts.push({type: \"danger\", textToTranslate:\"LOGIN_ERROR_UNKNOWN_TRY_AGAIN\"});\r\n } \r\n $scope.login.working = false;\r\n } else {\r\n console.log(response);\r\n $scope.alerts = [];\r\n $timeout( function() {\r\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/userInvitation/?select=customer&type:equals=customer&status:equals=pending\", {onErrorDoNotRedirect:true}).then(function (re) {\r\n console.log(\"got invitations \" , re);\r\n angular.forEach(re.data.result, function (invitation) {\r\n notificationService.registerNotification('invitation', 'NOTIFICATION_MESSAGE_INVITATION', invitation, {customerName:invitation.customer.name});\r\n });\r\n\r\n }, function (error) {\r\n });\r\n }, 200);\r\n\r\n \r\n $state.go(stwoGlobal.stateAfterLogin ? stwoGlobal.stateAfterLogin : \"secure.dashboard\");\r\n\r\n\r\n }\r\n\t\t}, function(response) {\r\n $scope.login.working = false;\r\n if (response.status == 402) {\r\n $scope.alerts.push({type: \"danger\", textToTranslate:\"LOGIN_ERROR_GETTING_INFO\"});\r\n } else if (response.status == 403) {\r\n $scope.alerts.push({type: \"danger\", textToTranslate:\"LOGIN_ERROR_WRONG_CREDENTIALS\"});\r\n } else {\r\n $scope.alerts.push({type: \"danger\", textToTranslate:\"LOGIN_ERROR_UNKNOWN\"});\r\n }\r\n\t\t});\r\n\t}\r\n\t\r\n\t$scope.doLogin = function() {\r\n $scope.alerts = [];\r\n console.log(\"user: \" + $scope.user);\r\n if (!$scope.user || !$scope.user.username) {\r\n $scope.alerts.push({type: \"danger\", textToTranslate:\"LOGIN_ERROR_MISSING_USERNAME\"});\r\n return;\r\n }\r\n \r\n if ($scope.login.renewPassword) {\r\n \r\n if (!$scope.user.passwordNew || $scope.user.passwordNew.length === 0 || $scope.user.passwordNew !== $scope.user.passwordNewRepeat) {\r\n $scope.alerts.push({type: \"danger\", textToTranslate:\"LOGIN_ERROR_NEW_PASSWORD_ERROR\"});\r\n return;\r\n }\r\n \r\n }\r\n\r\n\r\n if (!$scope.user.password) {\r\n $scope.alerts.push({type: \"danger\", textToTranslate:\"LOGIN_ERROR_MISSING_PASSWORD\"});\r\n return;\r\n }\r\n $scope.working = true;\r\n\r\n var newUserInfo = {username: $scope.user.username.toLowerCase(), password: $scope.user.password, replacementPassword: $scope.user.passwordNew, persist: $scope.login.rememberLogin};\r\n var r = smarttrackerService.login(newUserInfo, $scope.login.renewPassword).then(function (response) {\r\n\r\n $scope.selectUser(newUserInfo.username);\r\n $scope.login.renewPassword = false;\r\n }, function(response) {\r\n $scope.working = false;\r\n if (response.status == 402) {\r\n $scope.alerts.push({type: \"danger\", textToTranslate:\"LOGIN_ERROR_WRONG_CREDENTIALS\"});\r\n } else if (response.status == 403) {\r\n $scope.alerts.push({type: \"danger\", textToTranslate:\"LOGIN_ERROR_WRONG_CREDENTIALS\"});\r\n } else if (response.status == 406) {\r\n $scope.alerts.push({type: \"warning\", textToTranslate:\"LOGIN_ERROR_MUST_RENEW_PASSWORD\"});\r\n $scope.login.renewPassword = true;\r\n } else {\t\r\n $scope.alerts.push({type: \"danger\", textToTranslate:\"LOGIN_ERROR_UNKNOWN\"});\r\n }\r\n });\r\n\t}\r\n\r\n if ($stateParams.username && $stateParams.password) {\r\n $scope.user.username = $stateParams.username;\r\n $scope.user.password = $stateParams.password;\r\n $scope.doLogin();\r\n }\r\n\r\n /*var cookieNotice = localStorage.getItem('cookieNotice');\r\n\r\n if (cookieNotice === null) {\r\n $scope.showCookieNotice = true;\r\n localStorage.setItem(\"cookieNotice\", \"false\");\r\n }\r\n else if (cookieNotice == 'true') {\r\n $scope.showCookieNotice = true;\r\n }\r\n else {\r\n $scope.showCookieNotice = false;\r\n }\r\n $scope.hideCookieNotice = function () {\r\n if (!$scope.showCookieNotice) {\r\n $scope.showCookieNotice = true;\r\n localStorage.setItem(\"cookieNotice\", \"true\");\r\n }\r\n else {\r\n $scope.showCookieNotice = false;\r\n localStorage.setItem(\"cookieNotice\", \"false\");\r\n }\r\n };*/\r\n\r\n $scope.DemoLogin = function() {\r\n $scope.user.username = \"demo@x-guard.nl\";\r\n $scope.user.password = \"demo\";\r\n $scope.doLogin();\r\n }\r\n \r\n});\n\nangular.module('stwo.glue').controller('NotificationController', function ($scope, notificationService) {\n\t\n\t$scope.notifications = notificationService.undismissed();\n\t$scope.notificationsChanged = notificationService.changed;\n console.log($scope.notifications)\n\n notificationService.audio.snoozed = true;\n \n $scope.$watch(\"notificationsChanged.dismissed + notificationsChanged.added + notificationsChanged.removed\", function() {\n $scope.notifications = notificationService.undismissed();\n })\n});\nangular.module('stwo.dashboard', [\"stwo.glue\"])\r\n .config(function($stateProvider, $urlRouterProvider, moduleStoreProvider) {\r\n\r\n moduleStoreProvider.registerModule({\r\n name: \"dashboard\",\r\n links: [{\r\n name:\"DASHBOARD\",\r\n category: \"navigation\",\r\n icon: \"fa fa-tachometer\",\r\n sref: \"secure.dashboard\",\r\n sort: 5,\r\n color: \"success\",\r\n controllers: [\"DashboardController\"]\r\n }]\r\n });\r\n\r\n $stateProvider\r\n .state(\"secure.dashboard\",\r\n {\r\n url: \"/dashboard\",\r\n templateUrl: \"glue/dashboard/dashboard.html\",\r\n controller: \"DashboardController\"\r\n })\r\n });\r\n\t\r\n\t\r\nangular.module('stwo.dashboard').controller('DashboardController', function ($scope, $state, notificationService, moduleStore) {\r\n $scope.notifications = notificationService.undismissed();\r\n $scope.notificationsChanged = notificationService.changed;\r\n\r\n $scope.$watch(\"notificationsChanged.dismissed + notificationsChanged.added + notificationsChanged.removed\", function() {\r\n $scope.notifications = notificationService.undismissed();\r\n })\r\n \r\n $scope.linkClicked = function(link) {\r\n if (link.stateParams) {\r\n $state.go(link.sref.split(\"(\")[0], link.stateParams);\r\n } else {\r\n $state.go(link.sref);\r\n }\r\n }\r\n \r\n});\n/**\n * angular-ui-router state derived menu, nav, navbar, tab and other navigation tools\n * @version v0.2.1-dev-2014-10-30\n * @link https://github.com/nitintutlani/angular-ui-router-menus\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\n!function(a,b){\"use strict\";function c(a){var b=a.replace(/[.+^$()|{}]/g,function(a,b,c){return\"\\\\\"===c[b-1]?a:\"\\\\\"+a});return b=b.replace(/[?*]/g,function(a,b,c){return\"\\\\\"===c[b-1]?a:\"?\"===a?\".\":\".*\"}),b=b.replace(/\\\\([dDsSwWtrnvfbB0cxu])/g,\"$1\"),\"^\"+b+\"$\"}function d(a){var b=[];if(g(a)&&(a=a.split(\" \")),h(a))for(var d=0;dmax){\r\n max = response.data.total;\r\n pollingForAlarms = false;\r\n pollSmarttrackerForAlarms();\r\n return;\r\n }\r\n var ns = moduleStoreProvider.serviceRepository()[\"notificationService\"];\r\n\r\n var notificationIdsSeen = {};\r\n for (var n = 0; n < response.data.result.length; n++) {\r\n notificationIdsSeen[\"alarm-\" + response.data.result[n].id] = true;\r\n ns.add({\r\n id : \"alarm-\" + response.data.result[n].id,\r\n time : response.data.result[n].lastUpdated,\r\n level : (response.data.result[n].logLevelFormatted === \"warning\" ? 'warning' : (response.data.result[n].logLevelFormatted === \"notification\" ? 'success' : \"danger\")), //success, info, warning, danger\r\n name : response.data.result[n].name,\r\n module: \"alarm\",\r\n dismissable: true,\r\n dismissed: false,\r\n access : [\"alarm\", \"put\"],\r\n alarmId: response.data.result[n].id\r\n });\r\n }\r\n\r\n var nss = ns.list();\r\n for (var nn = 0; nn < nss.length; nn++) {\r\n if (nss[nn].module === \"alarm\" && !notificationIdsSeen[nss[nn].id]) {\r\n ns.silentDismiss(nss[nn].id);\r\n }\r\n }\r\n } else {\r\n console.log(\"Empty response from smarttracker\", response)\r\n }\r\n\r\n pollingForAlarms = false;\r\n }, function() {\r\n pollingForAlarms = false;\r\n });\r\n }\r\n }\r\n\r\n\tmoduleStoreProvider.registerModule({\r\n\t\tname : \"alarm\",\r\n categories : [{\r\n name : \"ALARMS\",\r\n icon : \"map\",\r\n color: \"info\",\r\n sort : 5\r\n }],\r\n\t\tlinks : [{\r\n name:\"ALARMS_NAV\",\r\n category: \"navigation\",\r\n icon: \"map\",\r\n sref: \"secure.content.alarm\",\r\n access: moduleStoreProvider.access(\"stwo.alarm\", [\"alarm\", \"get\"]),\r\n sort: 9,\r\n color: \"danger\",\r\n badge: \"notificationCount\",\r\n controllers: [\"AlarmListController\", \"AlarmDetailController\"]\r\n }\r\n // ,{\r\n\t\t\t// name : \"ALARMS_ALL\",\r\n\t\t\t// category : \"ALARMS\",\r\n\t\t\t// sref : \"secure.content.alarm\",\r\n // access : [\"alarm\", \"get\"],\r\n\t\t\t// icon : \"format-list-bulleted\",\r\n // controllers: [\"AlarmListController\", \"AlarmDetailController\"],\r\n // color: \"danger\",\r\n // badge: \"notificationCount\",\r\n\t\t\t// sort : 25\r\n // }\r\n // ,{\r\n\t\t// \tname : \"ALARMS_UNACK\",\r\n\t\t// \tcategory : \"ALARMS\",\r\n\t\t// \tsref : \"secure.content.alarm({filter: 'unacked'})\",\r\n // access : [\"alarm\", \"get\"],\r\n\t\t// \tstateParams : {\r\n\t\t// \t\tfilter : 'unacked'\r\n\t\t// \t},\r\n // color: \"danger\",\r\n\t\t// \ticon : \"alert\",\r\n\t\t// \tsort : 20\r\n\t\t// }\r\n\t\t],\r\n \r\n notificationHandlers: {\r\n view: function(notification) {\r\n moduleStoreProvider.serviceRepository()[\"$state\"].go(\"secure.content.alarm.detail\", {id:notification.alarmId});\r\n },\r\n push: function(data, util) {\r\n if (data && data.type === \"alarm\") {\r\n pollSmarttrackerForAlarms();\r\n }\r\n },\r\n poll: function() {\r\n pollSmarttrackerForAlarms();\r\n },\r\n dismiss: function(notification, dismissFn) {\r\n var m = moduleStoreProvider.serviceRepository()[\"$modal\"];\r\n \r\n\r\n var modalInstance = m.open({\r\n templateUrl: 'modules/alarm/ack_modal.html',\r\n controller: stwoAlarmAcknowledgeModalController,\r\n size: \"lg\",\r\n resolve: {\r\n alarm: function() { return null },\r\n notification: function() { return notification }\r\n }\r\n });\r\n\r\n modalInstance.result.then(function (newFilterData) {\r\n dismissFn();\r\n }, function() {\r\n\r\n });\r\n }\r\n }\r\n\t});\r\n\r\n\t$stateProvider.state(\"secure.content.alarm\", {\r\n\t\turl : \"/alarm/:filter\",\r\n\t\ttemplateUrl : \"modules/alarm/list.html\",\r\n\t\tcontroller : \"AlarmListController\",\r\n titleName: 'ALARM_LIST',\r\n titleIcon: \"format-list-bulleted\"\r\n\t}).state(\"secure.content.alarm.detail\", {\r\n\t\turl : \"/alarm-detail/:id\",\r\n\t\ttemplateUrl : \"modules/alarm/detail.html\",\r\n\t\tcontroller : \"AlarmDetailController\",\r\n titleName: 'ALARM_DETAIL',\r\n titleIcon: \"identification-card\"\r\n\t});\r\n \r\n \r\n moduleStoreProvider.addPossibleFilter(\"alarm\", {id: \"name\", label: \"ALARMS_FILTER_NAME\", type: \"string\", field: \"name\", comparator: \"contains\"});\r\n moduleStoreProvider.addPossibleFilter(\"alarm\", {id: \"asset\", label: \"ALARMS_FILTER_ASSET\", type: \"string\", field: \"asset.name\", comparator: \"contains\"});\r\n moduleStoreProvider.addPossibleFilter(\"alarm\", {id: \"ack_needed\", label: \"ALARMS_FILTER_ACK_NEEDED\", comparator: \"equals\", type: \"list\", list: [{label: \"-\", value: \"\"}, {label: \"ALARMS_FILTER_ACK_NEEDED_TRUE\", value: \"true\"}, {label: \"ALARMS_FILTER_ACK_NEEDED_FALSE\", value: \"false\"}], field: \"ackNeeded\"});\r\n moduleStoreProvider.addPossibleFilter(\"alarm\", {id: \"acked_by\", label: \"ALARMS_FILTER_ACKED\", comparator: \"null\", type: \"list\", list: [{label: \"-\", value: \"\"}, {label: \"ALARMS_FILTER_ACKED_FALSE\", value: \"false\"}, {label: \"ALARMS_FILTER_ACKED_TRUE\", value: \"true\"}], field: \"ackedBy\"});\r\n \r\n});\r\n\r\nangular.module('stwo.alarm').controller('AlarmListController', function($scope, $controller, $state, $modal, smarttrackerService, notificationService) {\r\n $controller('BaseListContentController', {$scope: $scope});\r\n \r\n $scope.alarmWarning = {newAlarms: false};\r\n notificationService.audio.snoozed = true;\r\n \r\n $scope.addPredefinedFilter(\"unacked\", [{filterId: \"ack_needed\", label: \"ALARMS_FILTER_ACK_NEEDED\", value: \"true\"},{filterId: \"acked_by\", label: \"ALARMS_FILTER_ACKED\", value: \"true\"}], \"&ackNeeded:equals=true&ackedBy:null=true\");\r\n \r\n $scope.super({clazz: 'alarm', downloadUrl: '/alarm?select=dateCreated+lastUpdated+rule+logLevel+name+asset.name+asset.image+asset.properties+asset.tags+ackedBy+ackNeeded+comment&sort=lastUpdated&order=desc'});\r\n \r\n $scope.notificationsChanged = notificationService.changed;\r\n $scope.$watch(\"notificationsChanged.dismissed + notificationsChanged.added + notificationsChanged.updated + notificationsChanged.removed\", function() {\r\n var notifications = notificationService.list();\r\n \r\n for (var n = 0; n < notifications.length; n++) {\r\n for (var m = 0; m < $scope.items.length; m++) {\r\n var not = notifications[n];\r\n var alm = $scope.items[m];\r\n if (not.alarmId && alm.id && not.alarmId === alm.id) {\r\n if (not.dismissed && alm.ackNeeded && !alm.ackedBy) {\r\n alm.ackedBy = {id: -1, name: \"...\"};\r\n }\r\n }\r\n }\r\n }\r\n })\r\n \r\n \r\n $scope.$watch(\"items.length\", function() {\r\n if ($scope.items.length === 0) {\r\n $scope.alarmWarning.newAlarms = false;\r\n } \r\n });\r\n $scope.$watch(\"notificationsChanged.added\", function() {\r\n if ($scope.items.length > 0) {\r\n $scope.alarmWarning.newAlarms = true;\r\n } \r\n });\r\n \r\n $scope.alarmClicked = function(alarm) {\r\n $state.go(\"secure.content.alarm-screen-xguard-detail\", {id:alarm.id});\r\n }\r\n \r\n $scope.ackAlarm = function(alarm) {\r\n\r\n var modalInstance = $modal.open({\r\n templateUrl: 'modules/alarm/ack_modal.html',\r\n controller: stwoAlarmAcknowledgeModalController,\r\n size: \"lg\",\r\n resolve: {\r\n alarm: function() { return alarm },\r\n notification: function() { return null }\r\n }\r\n });\r\n\r\n modalInstance.result.then(function (data) {\r\n \r\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/alarm/' + alarm.id + '?select=ackedBy+comment').then(function(response) {\r\n for (var n = 0; n < $scope.items.length; n++) {\r\n if (response.data.result.length > 0 && $scope.items[n].id === response.data.result[0].id) {\r\n $scope.items[n].ackedBy = response.data.result[0].ackedBy;\r\n $scope.items[n].comment = response.data.result[0].comment;\r\n }\r\n }\r\n });\r\n }, function() {\r\n\r\n });\r\n }\r\n});\r\n\r\nangular.module('stwo.alarm').controller('AlarmDetailController', function($scope, $controller, $stateParams, $modal, $window, smarttrackerService, contentCacheService, notificationService, mapService, leafletData, pushService) {\r\n\t\r\n $controller('BaseDetailContentController', {$scope: $scope});\r\n \r\n $scope.indoorViewer = {location: null, markers: {}, changeCounter: 0};\r\n $scope.alarm = contentCacheService.get(\"alarm\", $stateParams.id);\r\n\r\n\r\n mapService.basicMapDesign($scope, leafletData);\r\n $scope.markers = {};\r\n\r\n $scope.mapData = {\r\n center : {\r\n lat : 0,\r\n lng : 0,\r\n zoom : 1\t\t\t\r\n },\r\n defaults : {'dragging': true}\r\n };\r\n\r\n\r\n $scope.events = {\r\n marker : {enable: ['click'],\r\n logic :'emit'}\r\n };\r\n\r\n $scope.updateMarkers = function(fitToBounds) {\r\n if (!$scope.alarm) {\r\n return;\r\n }\r\n\r\n var boundsMarkerArray = [];\r\n $scope.markerCount = 0;\r\n\r\n \r\n $scope.indoorViewer.markers[\"alarm\"] = $scope.alarm;\r\n $scope.indoorViewer.markers[\"alarm\"].markerStrokeColor = ($scope.alarm.logLevelFormatted === 'notification' ? 'rgba(0, 255, 0, 1)' : ($scope.alarm.logLevelFormatted === 'warning' ? 'rgba(255, 128, 0, 1)' : 'rgba(255, 0, 0, 1)' ) );\r\n \r\n if ($scope.alarm.position && $scope.alarm.position.location && $scope.alarm.position.location.locationId) {\r\n $scope.indoorViewer.location = $scope.alarm.position.location.locationId;\r\n }\r\n \r\n $scope.indoorViewer.markers[\"asset\"] = $scope.alarm.asset;\r\n \r\n if ($scope.alarm.position && $scope.alarm.position.valid) {\r\n boundsMarkerArray.push(new L.latLng($scope.alarm.position.latitude, $scope.alarm.position.longitude));\r\n $scope.markers[\"alarm\"] = {\r\n id : \"alarm\",\r\n lat : $scope.alarm.position.latitude,\r\n lng : $scope.alarm.position.longitude,\r\n icon: mapService.makeNamedIcon($scope.alarm.name, \"danger\"),\r\n focus : false, //just add them on the map. not in focus\r\n draggable : false\r\n }\r\n $scope.markerCount++;\r\n \r\n }\r\n \r\n if ($scope.alarm.asset && $scope.alarm.asset.lastValidPosition && $scope.alarm.asset.lastValidPosition.valid) {\r\n boundsMarkerArray.push(new L.latLng($scope.alarm.asset.lastValidPosition.latitude, $scope.alarm.asset.lastValidPosition.longitude));\r\n $scope.markers[\"asset\"] = {\r\n id : \"asset\",\r\n lat : $scope.alarm.asset.lastValidPosition.latitude,\r\n lng : $scope.alarm.asset.lastValidPosition.longitude,\r\n icon: mapService.makeNamedIcon($scope.alarm.asset.name),\r\n //message : \"message\",\r\n focus : false, //just add them on the map. not in focus\r\n draggable : false\r\n }\r\n $scope.markerCount++;\r\n }\r\n\r\n delete $scope.markers[\"merged\"];\r\n if ($scope.markers[\"alarm\"] && $scope.markers[\"asset\"]) {\r\n var distanceBetweenTheMarkers = Math.sqrt(Math.pow($scope.markers[\"asset\"].lat - $scope.markers[\"alarm\"].lat, 2) + Math.pow($scope.markers[\"asset\"].lng - $scope.markers[\"alarm\"].lng, 2))\r\n if (distanceBetweenTheMarkers < 0.0005) { //magic number, decrease if group occurs prematurely\r\n delete $scope.markers[\"asset\"];\r\n delete $scope.markers[\"alarm\"];\r\n\r\n $scope.markers[\"merged\"] = {\r\n id : \"merged\",\r\n lat : $scope.alarm.asset.lastValidPosition.latitude,\r\n lng : $scope.alarm.asset.lastValidPosition.longitude,\r\n icon: mapService.makeNamedIcon($scope.alarm.name + \", \" + $scope.alarm.asset.name, \"danger\"),\r\n //message : \"message\",\r\n focus : false, //just add them on the map. not in focus\r\n draggable : false\r\n }\r\n $scope.markerCount = 1;\r\n }\r\n }\r\n\r\n if (fitToBounds && boundsMarkerArray.length > 0) {\r\n var bounds = new L.latLngBounds(boundsMarkerArray);\r\n\r\n leafletData.getMap().then(function(map) {\r\n map.fitBounds(bounds);\r\n map.zoomOut(1);\r\n });\r\n }\r\n \r\n \r\n $scope.indoorViewer.changeCounter++;\r\n }\r\n\r\n $scope.updateMarkers(true);\r\n \r\n $scope.notificationsChanged = notificationService.changed;\r\n \r\n $scope.$watch(\"notificationsChanged.dismissed + notificationsChanged.added + notificationsChanged.updated + notificationsChanged.removed\", function() {\r\n var notifications = notificationService.list();\r\n \r\n for (var n = 0; n < notifications.length; n++) {\r\n var not = notifications[n];\r\n var alm = $scope.alarm;\r\n if (alm && not.alarmId && alm.id && not.alarmId === alm.id) {\r\n if (not.dismissed && alm.ackNeeded && !alm.ackedBy) {\r\n $scope.downloadAlarm();\r\n }\r\n }\r\n }\r\n })\r\n \r\n $scope.downloadAlarm = function() {\r\n return smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/alarm/' + $stateParams.id + '?select=*').then(function(response) {\r\n $scope.alarm = response.data.result[0];\r\n if ($scope.alarm) {\r\n contentCacheService.put(\"alarm\", $scope.alarm.id, $scope.alarm);\r\n }\r\n $scope.updateMarkers(true);\r\n });\r\n }\r\n\t\r\n\t$scope.googleMaps = function(alarm) {\r\n\t\t$window.open('http://maps.google.com/maps?q='+alarm.position.latitude+','+alarm.position.longitude);\t\t \t\t \r\n }\r\n\r\n $scope.ackAlarm = function(alarm) {\r\n\r\n var modalInstance = $modal.open({\r\n templateUrl: 'modules/alarm/ack_modal.html',\r\n controller: stwoAlarmAcknowledgeModalController,\r\n size: \"lg\",\r\n resolve: {\r\n alarm: function() { return alarm },\r\n notification: function() { return null }\r\n }\r\n });\r\n\r\n modalInstance.result.then(function (data) {\r\n $scope.downloadAlarm().then(function() {\r\n // Iterates over parent scope data. Not very elegant, and makes assumptions about parent controller's data structure. Redo if possible. Magnus.\r\n if ($scope.items) {\r\n for (var n = 0; n < $scope.items.length; n++) {\r\n if ($scope.alarm && $scope.items[n].id === $scope.alarm.id) {\r\n $scope.items[n].ackedBy = $scope.alarm.ackedBy;\r\n $scope.items[n].comment = $scope.alarm.comment;\r\n }\r\n }\r\n }\r\n });\r\n });\r\n }\r\n \r\n smarttrackerService.isLoggedInDelayed().then(function() {\r\n $scope.downloadAlarm();\r\n \r\n $scope.pushChanged = pushService.changed();\r\n \r\n $scope.$watch(\"pushChanged.counter\", function() {\r\n pushService.process(function(data, util) {\r\n if (data.type === \"observation\" && $scope.alarm && $scope.alarm.asset && data.object && data.object.type === \"asset\" && data.object.info.id === $scope.alarm.asset.id) {\r\n util.mergePosition($scope.alarm.asset, data);\r\n $scope.updateMarkers();\r\n $scope.indoorViewer[\"markers\"][\"asset\"] = $scope.alarm.asset;\r\n $scope.indoorViewer.changeCounter++;\r\n }\r\n });\r\n });\r\n });\r\n \r\n $scope.super({clazz: 'alarm'});\r\n \r\n});\r\n\r\n\r\nvar stwoAlarmAcknowledgeModalController = function ($scope, $modalInstance, contentCacheService, notificationService, smarttrackerService, alarm, notification) {\r\n\r\n $scope.impossibleToAck = true;\r\n $scope.downloadingAlarm = true;\r\n $scope.data = {comment: \"\"};\r\n var setAlarm = function(alarm) {\r\n $scope.alarm = alarm;\r\n $scope.downloadingAlarm = false;\r\n $scope.impossibleToAck = (alarm.alarmCenter && alarm.alarmCenter.id !== alarm.owner.id) || !smarttrackerService.getAccessRights()[\"alarm\"][\"put\"];\r\n }\r\n if (alarm) {\r\n $scope.alarm = contentCacheService.get(\"alarm\", alarm.id);\r\n\r\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/alarm/' + alarm.id + '?select=*').then(function(response) {\r\n setAlarm(response.data.result[0]);\r\n });\r\n } else {\r\n $scope.alarm = contentCacheService.get(\"alarm\", notification.alarmId);\r\n\r\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/alarm/' + notification.alarmId + '?select=*').then(function(response) {\r\n setAlarm(response.data.result[0]);\r\n });\r\n }\r\n\r\n $scope.ok = function () {\r\n \r\n var user = smarttrackerService.getLoggedInUser();\r\n \r\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + '/alarm/' + $scope.alarm.id,\r\n [{id: $scope.alarm.id, comment: $scope.data.comment, ackedBy: {id: user.user.id}}]\r\n )\r\n .then( function(response) {\r\n notificationService.silentDismiss(\"alarm-\" + $scope.alarm.id)\r\n $modalInstance.close({});\r\n }, function(response) {\r\n alert(\"Error while acking\");\r\n });\r\n \r\n };\r\n\r\n $scope.cancel = function () {\r\n $modalInstance.dismiss('cancel');\r\n };\r\n};\nangular.module(\"stwo.alarm-screen-xguard\", [\"stwo.core\", \"ui.bootstrap.datetimepicker\"]).config(function ($stateProvider, $urlRouterProvider, moduleStoreProvider) {\n\n moduleStoreProvider.registerModule({\n name: \"alarm-screen-xguard\",\n links: [{\n name: \"XGUARD_ALARMMANAGER_TITLE\",\n category: \"navigation\",\n icon: \"alert\",\n sref: \"secure.content.alarm-screen-xguard\",\n categoryDependency: \"ALARMS\",\n sort: 5,\n color: \"info\",\n controllers: [\"AlarmScreenXGuardController\"]\n }, {\n name: \"XGUARD_ALARMMANAGER_TITLE\",\n category: \"ALARMS\",\n sref: \"secure.content.alarm-screen-xguard\",\n access: [\"alarm\", \"get\"],\n icon: \"alert\",\n controllers: \"AlarmScreenXGuardController\",\n color: \"danger\",\n sort: 5\n }\n /*, {\n name: \"ALARMS_UNACK\",\n category: \"ALARMS\",\n sref: \"secure.content.alarm-screen-xguard({filter: 'unacked'})\",\n access: [\"alarm\", \"get\"],\n stateParams: {\n filter: 'unacked'\n },\n color: \"danger\",\n icon: \"alert\",\n sort: 20\n }*/\n ]\n });\n\n $stateProvider.state(\"secure.content.alarm-screen-xguard\", {\n url: \"/alarm-manager/:filter\",\n templateUrl: \"modules/alarm-screen-xguard/alarm-screen-xguard.html\",\n controller: \"AlarmScreenXGuardController\",\n titleName: 'XGUARD_ALARMMANAGER_TITLE',\n titleIcon: \"alert\"\n\n\n }).state(\"secure.content.alarm-screen-xguard-detail\", {\n url: \"/alarm-manager-detail/:id\",\n templateUrl: \"modules/alarm-screen-xguard/alarm-screen-xguard-detail.html\",\n controller: \"AlarmScreenXGuardDetailController\",\n titleName: 'XGUARD_ALARMMANAGER_TITLE',\n titleIcon: \"alert\"\n\n }).state(\"secure.content.alarm-screen-xguard-asset\", {\n url: \"/alarm-manager-asset/:assetID\",\n templateUrl: \"modules/alarm-screen-xguard/alarm-screen-xguard-asset.html\",\n controller: \"AlarmScreenXGuardAssetController\",\n titleName: 'XGUARD_ALARMMANAGER_TITLE',\n titleIcon: \"alert\"\n }).state(\"secure.content.alarm-screen-xguard-externalid\", {\n url: \"/alarm-manager-extern/:externalId\",\n templateUrl: \"modules/alarm-screen-xguard/alarm-screen-xguard-externalid.html\",\n controller: \"AlarmScreenXGuardExternalIdController\",\n titleName: 'XGUARD_ALARMMANAGER_TITLE',\n titleIcon: \"alert\"\n }).state(\"secure.content.alarm-screen-xguard-alert\", {\n url: \"/alarm-manager-alert/:assetID\",\n templateUrl: \"modules/alarm-screen-xguard/alarm-screen-xguard-alert.html\",\n controller: \"AlarmScreenXGuardAlertController\",\n titleName: 'XGUARD_ALARMMANAGER_TITLE',\n titleIcon: \"alert\"\n });\n\n moduleStoreProvider.addPossibleFilter(\"alarm\", {\n id: \"name\",\n label: \"ALARMS_FILTER_NAME\",\n type: \"string\",\n field: \"name\",\n comparator: \"contains\"\n });\n moduleStoreProvider.addPossibleFilter(\"alarm\", {\n id: \"asset\",\n label: \"ALARMS_FILTER_ASSET\",\n type: \"string\",\n field: \"asset.name\",\n comparator: \"contains\"\n });\n moduleStoreProvider.addPossibleFilter(\"alarm\", {\n id: \"ack_needed\",\n label: \"ALARMS_FILTER_ACK_NEEDED\",\n comparator: \"equals\",\n type: \"list\",\n list: [{\n label: \"-\",\n value: \"\"\n }, {\n label: \"ALARMS_FILTER_ACK_NEEDED_TRUE\",\n value: \"true\"\n }, {\n label: \"ALARMS_FILTER_ACK_NEEDED_FALSE\",\n value: \"false\"\n }],\n field: \"ackNeeded\"\n });\n moduleStoreProvider.addPossibleFilter(\"alarm\", {\n id: \"acked_by\",\n label: \"ALARMS_FILTER_ACKED\",\n comparator: \"null\",\n type: \"list\",\n list: [{\n label: \"-\",\n value: \"\"\n }, {\n label: \"ALARMS_FILTER_ACKED_FALSE\",\n value: \"false\"\n }, {\n label: \"ALARMS_FILTER_ACKED_TRUE\",\n value: \"true\"\n }],\n field: \"ackedBy\"\n });\n\n\n}).filter('commentsWithLabelKey', function () {\n return function (arr, key) {\n var out = [];\n if (arr) {\n angular.forEach(arr, function (comment) {\n if (comment.labels && comment.labels[key]) {\n out.push(comment);\n }\n });\n return out;\n }\n }\n}).filter('contactWithUserId', function () {\n return function (arr, id) {\n angular.forEach(arr, function (contact) {\n if (contact.connectedTo) {\n angular.forEach(contact.connectedTo, function (conn) {\n if (conn.type == \"user\" && conn.to.id == id) {\n return contact;\n }\n });\n }\n });\n return false;\n }\n});; // End Module definition\n\nangular.module('stwo.alarm-screen-xguard').controller('AlarmScreenXGuardController', function ($scope, $controller, $state, $modal, smarttrackerService, notificationService, $interval, pushService, $filter) {\n $controller('BaseListContentController', {\n $scope: $scope\n });\n\n //$scope.addPredefinedFilter(\"unacknowledged\", [{\n // filterId: \"ack_needed\",\n // label: \"ALARMS_FILTER_ACK_NEEDED\",\n // value: \"true\"\n //}, {\n // filterId: \"acked_by\",\n // label: \"ALARMS_FILTER_ACKED\",\n // value: \"true\"\n //}], \"&ackNeeded:equals=true&ackedBy:null=true\");\n\n $scope.super({\n clazz: 'alarm',\n downloadUrl: '/alarm?select=asset.owner+dateCreated+lastUpdated+positionProvider+rule+logLevel+name+zone+asset.name+asset.image+asset.properties+asset.tags+ackedBy+ackNeeded+comment&sort=dateCreated&order=desc&active:false=true'\n\n });\n\n /**FILTERS*/\n var acfKey = \"AlarmCenterFilter\";\n\n $scope.endDateBeforeRender = endDateBeforeRender\n $scope.endDateOnSetTime = endDateOnSetTime\n $scope.startDateBeforeRender = startDateBeforeRender\n $scope.startDateOnSetTime = startDateOnSetTime\n var map = false;\n\n function startDateOnSetTime() {\n $scope.$broadcast('start-date-changed');\n }\n\n function endDateOnSetTime() {\n $scope.$broadcast('end-date-changed');\n }\n\n function startDateBeforeRender($dates) {\n if ($scope.filters.dateRange.end) {\n var activeDate = moment($scope.filters.dateRange.end);\n\n $dates.filter(function (date) {\n return date.localDateValue() >= activeDate.valueOf()\n }).forEach(function (date) {\n date.selectable = false;\n });\n $scope.applyFilter();\n }\n }\n\n function endDateBeforeRender($view, $dates) {\n if ($scope.filters.dateRange.start) {\n var ts = moment($scope.filters.dateRange.start).format(\"YYYY-MM-DDThh:mm:ss.SSS\");\n console.log(ts);\n var activeDate = moment($scope.filters.dateRange.start).subtract(1, $view).add(1, 'minute');\n\n $dates.filter(function (date) {\n return date.localDateValue() <= activeDate.valueOf()\n }).forEach(function (date) {\n date.selectable = false;\n });\n $scope.applyFilter();\n }\n }\n\n $scope.clearFilters = function (refresh) {\n $scope.filters = {\n 'externalId': {\n 'value': '',\n 'list': []\n },\n 'triggeringAsset': {\n 'value': '',\n 'list': []\n },\n 'logLevel': {\n 'list': {\n 'RED_ALERT': {\n selected: true\n },\n \"WARNING\": {\n selected: true\n },\n \"NOTIFICATION\": {\n selected: true\n }\n },\n 'allSelected': true\n },\n 'resolution': {\n 'acked': true,\n 'active': true\n },\n 'dateRange': {\n 'start': '',\n 'end': ''\n }\n }\n if (refresh) {\n $scope.filterUrlString = '';\n $scope.applyFilter();\n }\n }\n $scope.clearFilters(false);\n\n $scope.changeAlarmTypeFilter = function (val) {\n $scope.filters.logLevel.value = val;\n $scope.applyFilter();\n }\n $scope.addExternalIdFilter = function ($event) {\n if ($event && ($event.which || $event.keyCode) && ($event.which != 13 && $event.keyCode != 13)) {\n return;\n }\n var o = $scope.filters.externalId;\n if (o.value != '' && o.list.indexOf(o.value) < 0) {\n o.list.push(o.value);\n }\n o.value = '';\n $scope.applyFilter();\n }\n\n $scope.addTriggeringAsset = function ($event) {\n if ($event && ($event.which || $event.keyCode) && ($event.which != 13 && $event.keyCode != 13)) {\n return;\n }\n var o = $scope.filters.triggeringAsset;\n if (o.value != '' && o.list.indexOf(o.value) < 0) {\n o.list.push(o.value);\n }\n o.value = '';\n $scope.applyFilter();\n }\n\n $scope.removeFilter = function (field, value) {\n switch (field) {\n case 'externalId':\n case 'triggeringAsset':\n $scope.filters[field].list.splice($scope.filters[field].list.indexOf(value), 1);\n $scope.applyFilter();\n break;\n case 'logLevel':\n angular.forEach($scope.filters.logLevel.list, function (value, key) {\n value.selected = true;\n });\n $scope.filters.logLevel.allSelected = true;\n $scope.applyFilter();\n break;\n case 'dateRange':\n $scope.filters[field][value] = '';\n $scope.applyFilter();\n break;\n }\n }\n\n $scope.applyFilter = function () {\n var filterString = \"\";\n angular.forEach($scope.filters.externalId.list, function (value) {\n filterString += \"&asset.externalId:equals=\" + value;\n });\n angular.forEach($scope.filters.triggeringAsset.list, function (value) {\n filterString += \"&asset.name:contains=\" + value;\n });\n var o = $scope.filters.logLevel.list;\n var llFilters = (o.RED_ALERT.selected ? '1' : '0') + (o.WARNING.selected ? '1' : '0') + (o.NOTIFICATION.selected ? '1' : '0');\n switch (llFilters) {\n case '111':\n break;\n case '110':\n filterString += \"&logLevel:greater=-10\";\n break;\n case '101':\n filterString += \"&logLevel:equals=0&logLevel:equals=-15&logLevel:equals=-20\";\n break;\n case '100':\n filterString += \"&logLevel:equals=0\";\n break;\n case '011':\n filterString += \"&logLevel:less=0\";\n break;\n case '001':\n filterString += \"&logLevel:less=-9\";\n break;\n case '010':\n filterString += \"&logLevel:less=0&logLevel:greater=-10\";\n break;\n }\n $scope.filters.logLevel.allSelected = (o.RED_ALERT.selected && o.WARNING.selected && o.NOTIFICATION.selected);\n // if(!(o.RED_ALERT.selected&&o.WARNING.selected&&o.NOTIFICATION.selected)) {\n // angular.forEach(o, function (value, key){\n // if(value.selected) {\n // filterString += value.value;\n // }\n // });\n // }\n\n if ($scope.filters.dateRange.end != '') {\n filterString += \"&dateCreated:less=\" + moment($scope.filters.dateRange.end).utc().format(\"YYYY-MM-DDTHH:mm:ss.SSS\");\n }\n if ($scope.filters.dateRange.start != '') {\n filterString += \"&dateCreated:greater=\" + moment($scope.filters.dateRange.start).utc().format(\"YYYY-MM-DDTHH:mm:ss.SSS\");\n }\n\n // if(!($scope.filters.resolution.active&&$scope.filters.resolution.acked)) {\n // filterString += \"&ackedBy:null=\" + ($scope.filters.resolution.active?'true':'false');\n // }\n\n console.log($scope.filters);\n downloadActiveAlarms(filterString);\n $scope.filterUrlString = filterString;\n if (filterString == \"\") {\n $scope.refresh();\n }\n // store filter\n localStorage[acfKey] = JSON.stringify($scope.filters);\n\n\n }\n\n var performUpdate = false;\n $scope.$watch(\"downloadProgress.active\", function () {\n if (performUpdate && $scope.downloadProgress.active == false) {\n $scope.refresh();\n performUpdate = false;\n }\n });\n /**END Filters*/\n var ninit = 0;\n $scope.$watch(\"(notifications | notificationFromModule : 'alarm').length\", function (val, val2) {\n console.log(\"Notification changed\", val, val2, ninit);\n\n if (ninit++ > 2) { // initially it will be undefined and length,0. Ignore these.\n console.log(\"Notification triggered\");\n $scope.applyFilter();\n // console.log(\"Notification triggered\");\n // var filterString = $scope.filterUrlString + ($scope.activeAlarms&&$scope.activeAlarms.length>0?'&dateCreated:less=' + $scope.activeAlarms[0].dateCreated:'');\n // var downloadUrl = '/alarm?select=dateCreated+lastUpdated+positionProvider+rule+logLevel+name+zone+asset.name+asset.image+asset.properties+asset.tags+ackedBy+ackNeeded+comment&sort=lastUpdated&order=desc&ackedBy:null=true&&ackNeeded:equals=true' + (filterString?filterString:'');\n // smarttrackerService.authGet(smarttrackerService.getCustomerId() + downloadUrl).then(function (response){\n // for(var i = response.data.result.length-1;i >=0;i--) {\n // $scope.activeAlarms.unshift(response.data.result[i]);\n // }\n // $scope.nbrActiveAlarms = $scope.activeAlarms.length;\n // });\n }\n })\n // $scope.pushChanged = pushService.changed();\n // $scope.$watch(\"pushChanged.counter\", function () {\n // console.log(\"Push triggered\");\n // pushService.process(function (data, util) {\n // console.log(\"Push message\", data, util);\n // if (data.type === \"alarm\") {\n // //$scope.items.unshift(data);\n // // smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/alarm?select=dateCreated+lastUpdated+rule+logLevel+name+asset.name+asset.image+asset.properties+asset.tags+ackedBy+ackNeeded+comment&sort=lastUpdated&order=desc&ackedBy:null=true').then(function (response) {\n // // for (var i in response.data.result) {\n // // var alarm = response.data.result[i];\n // // var list = alarm.ackNeeded?$scope.activeAlarms:$scope.items;\n // // var found = false;\n // // angular.forEach(list, function (val, key){\n // // if(val.id == alarm.id) found = true;\n // // })\n // // if(found)break;\n // // list.unshift(alarm);\n // // if(alarm.ackNeeded)$scope.nbrActiveAlarms++;\n // // }\n // // });\n // $scope.refresh();\n // }\n // });\n // });\n\n $scope.nbrActiveAlarms = 0;\n $scope.nbrAckedAlarms = 0;\n\n $scope.toggleFilters = function (scroll) {\n if ($scope.filterExpanded) {\n $scope.filterExpanded = false;\n TweenLite.set(\"#filters\", {\n overflow: \"hidden\"\n });\n TweenLite.to(\"#filters\", 0.5, {\n height: \"45px\",\n ease: \"Quart.easeInOut\"\n });\n TweenLite.set(\"#filters\", {\n overflow: \"hidden\",\n delay: 0.5\n });\n if (scroll) {\n TweenLite.to(\"#view\", 0.5, {\n scrollTo: \"#scrollAnchor\",\n ease: \"Quart.easeInOut\"\n });\n }\n } else {\n $scope.filterExpanded = true;\n TweenLite.set(\"#filters\", {\n height: \"auto\"\n });\n TweenLite.from(\"#filters\", 0.5, {\n height: \"45px\",\n ease: \"Quart.easeInOut\"\n });\n TweenLite.set(\"#filters\", {\n overflow: \"visible\",\n delay: 0.5\n });\n }\n };\n\n $scope.showFilters = function () {\n if ($(window).width() > 768) {\n $scope.filterExpanded = true;\n TweenLite.set(\"#filters\", {\n height: \"auto\",\n overflow: \"visible\"\n });\n }\n };\n\n $(window).width(function () {\n $scope.showFilters();\n });\n\n $(window).resize(function () {\n $scope.showFilters();\n });\n\n $scope.$watch(\"itemsChanged\", function () {\n if ($scope.itemsChanged > 0) {\n $scope.nbrAckedAlarms = 0;\n }\n });\n\n $scope.activeAlarms = [];\n $scope.downloadActiveInProgress = true;\n\n function downloadActiveAlarms(filterString, offset) {\n if (!offset) offset = 0;\n if (offset == 0) {\n $scope.activeAlarms = [];\n $scope.nbrActiveAlarms = 0;\n $scope.downloadActiveInProgress = true;\n }\n var downloadUrl = '/alarm?select=asset.owner+dateCreated+lastUpdated+positionProvider+rule+logLevel+name+zone+asset.name+asset.image+asset.properties+asset.tags+ackedBy+ackNeeded+comment&sort=dateCreated&order=desc&ackedBy:null=true&&ackNeeded:equals=true&offset=' + offset + \"\" + (filterString ? filterString : '');\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + downloadUrl).then(function (response) {\n $scope.activeAlarms = $scope.activeAlarms.concat(response.data.result);\n $scope.nbrActiveAlarms = response.data.total;\n if (response.data.max + offset < response.data.total) {\n downloadActiveAlarms(filterString, offset + response.data.max);\n } else {\n $scope.downloadActiveInProgress = false\n }\n });\n }\n\n smarttrackerService.isLoggedInDelayed().then(function () {\n if (localStorage.getItem(acfKey)) {\n try {\n $scope.filters = JSON.parse(localStorage.getItem(acfKey));\n } catch (error) {\n console.error(\"error when parsing stored filter. \", error);\n $scope.clearFilters(false);\n }\n } else {\n $scope.clearFilters(false);\n }\n //downloadActiveAlarms();\n $scope.applyFilter();\n performUpdate = $scope.downloadProgress.active && $scope.filterUrlString != \"\";\n\n notificationService.poll();\n });\n\n $scope.alarmClicked = function (alarm) {\n $state.go(\"secure.content.alarm-screen-xguard-detail\", {\n id: alarm.id\n });\n }\n}); // End Module alarm-screen\n\nangular.module('stwo.alarm-screen-xguard').controller('AlarmScreenXGuardDetailController', function ($http, $scope, deploymentApiService, $controller, $stateParams, $translate, socketioService, $timeout, $state, timerService, $modal, smarttrackerService, mapService, leafletData, notificationService, contentCacheService, $location, dialogService, $filter, utilService, $window) {\n $controller('BaseListContentController', {\n $scope: $scope\n });\n\n var PageOpenedDate = new Date().toISOString();\n var debugMode = false;\n\n var translations = [];\n $scope.responseAreas = [];\n\n $scope.handleCameraClick = function ($event, url) {\n\n if (url && url.indexOf('localhost:10283') !== -1) {\n\n // stop\n $event.stopPropagation();\n $event.preventDefault();\n\n // call xhr instead\n $http.get(url).then(function (result) {\n\n\n\n });\n\n }\n\n }\n\n // $translate('XGUARD_ASSETS_NAV', null, null, \"nl\", \"nl\").then(function (data){\n // alert(data);\n // })\n\n $scope.commentTemplateList = [];\n $translate([\"COMMENT_TEMPLATE_NO_VOICE_INITIATED\",\n \"COMMENT_TEMPLATE_NO_VOICE_AUDIO\",\n \"COMMENT_TEMPLATE_NO_VOICE_RESPONSE\",\n \"COMMENT_TEMPLATE_NO_VOICE_ONE_WAY\",\n \"COMMENT_TEMPLATE_VOICE_CORRECT\",\n \"COMMENT_TEMPLATE_OUTGOING_CALL_INITIATED\",\n \"COMMENT_TEMPLATE_OUTGOING_CALL_BUSY\",\n \"COMMENT_TEMPLATE_OUTGOING_CALL_VOICEMAIL\",\n \"COMMENT_TEMPLATE_OUTGOING_CALL_NO_VOICEMAIL\",\n \"COMMENT_TEMPLATE_RESPONDER_NOT_AVAILABLE\",\n \"COMMENT_TEMPLATE_OUTCOME_ALL_OK\",\n \"COMMENT_TEMPLATE_OUTCOME_EMERGENCY\",\n \"COMMENT_TEMPLATE_OUTCOME_TEST_OK\",\n \"COMMENT_TEMPLATE_OUTCOME_TEST_NOK\",\n \"COMMENT_TEMPLATE_RESPONSE_ONSITE_SECURITY\",\n \"COMMENT_TEMPLATE_RESPONSE_PRIVATE_SECURITY\",\n \"COMMENT_TEMPLATE_POLICE_NEEDED\",\n \"COMMENT_TEMPLATE_POLICE_SENT\",\n \"COMMENT_TEMPLATE_UNIT_EXTPOWER\",\n \"COMMENT_TEMPLATE_RESPONSE_IN_ACTION\",\n \"COMMENT_TEMPLATE_DUPLICATE\",\n \"COMMENT_TEMPLATE_OUTGOING_CALL_NO_AUDIO\",\n ])\n .then(function (data) {\n\n angular.forEach(data, function (value, key) {\n\n $scope.commentTemplateList.push({\n \"text\": value\n })\n\n });\n\n $scope.commentTemplateList.sort(function (a, b) {\n\n if (a.text < b.text) {\n\n return -1;\n\n } else\n if (a.text > b.text) {\n\n return 1;\n\n }\n\n return 0;\n\n });\n\n\n })\n\n\n $scope.openDialog = \"\";\n $scope.openToggle = function (toggle) {\n $scope.openDialog = toggle;\n }\n\n $scope.closeToggle = function ($event) {\n var cl = $event.target.classList;\n if ($event.target.id != $scope.openDialog && !cl.contains(\"dropdownItem\")) {\n $scope.openDialog = \"\";\n }\n };\n\n $scope.modes = {\n isDoubt: true\n }\n\n var codes = {\n customer: 0, // Customer, subject of the alarm\n qr: 1, // Quick Response\n ra: 4, // Response Area\n nqr: 3, // National Quick Response\n pc: 2, // Personal Contacts\n pd: 6, // Police Department\n bz: 5 // Backup zone\n };\n\n $translate([\"XGUARD_MINUTES\", \"XGUARD_MINUTE\", \"XGUARD_HOUR\", \"XGUARD_HOURS\", \"XGUARD_TIME_MEASURE_TEMPLATE\", \"XGUARD_TIMESTAMP_TODAY\", \"ALARM_MANAGER_NOTIFICATION_MESSAGE\",\n \"ALARM_MANAGER_NOTIFICATION_SUBJECT\"\n ])\n .then(function (data) {\n $scope.translations = {\n hour: data['XGUARD_HOUR'],\n hours: data['XGUARD_HOURS'],\n minute: data['XGUARD_MINUTE'],\n minutes: data['XGUARD_MINUTES'],\n timeTemplate: data['XGUARD_TIME_MEASURE_TEMPLATE'],\n today: data['XGUARD_TIMESTAMP_TODAY'],\n notificationMessage: data['ALARM_MANAGER_NOTIFICATION_MESSAGE'],\n notificationSubject: data['ALARM_MANAGER_NOTIFICATION_SUBJECT']\n };\n });\n\n\n\n var alarmID = $stateParams.id ? $stateParams.id : \"67645959\";\n var securityGuardID = \"67566425\";\n var employeeID = \"67566364\";\n\n\n\n var syntax = {\n ZMTag: \"ACR_ZM\",\n QRTag: \"ACR_QR\",\n NQRTag: \"ACR_NQR\",\n PDTag: \"ACR_PD\",\n BZTag: \"ACR_BZ\",\n RATag: \"ACR_RA\",\n CLTag: \"ACR_CL\",\n ContactTag: \"ACR_CONTACT\",\n email: \"email\",\n phone: \"phone\",\n sms: \"sms\",\n allowContact: \"allowContact\",\n allowContactNQR: \"allowContactNQR\",\n allowEmergencyContact: \"allowEmergencyContact\",\n allowNQR: \"allowNQR\",\n updateIntervalSeconds: \"sixty\"\n };\n\n\n $scope.$watch(\"timers.five\", function () {\n if ($scope.alarm) {\n $scope.refreshEvents(0);\n }\n });\n\n $scope.timers = timerService.timers();\n $scope.$watch(\"timers.sixty\", function () {\n if ($scope.alarm) {\n getTimeString();\n }\n });\n var killAlarmUpdater = $scope.$watch(\"timers.\" + syntax.updateIntervalSeconds, function () {\n if ($scope.alarm && ($scope.alarm.asset || $scope.alarm.zone)) {\n\n //var object = $scope.alarm.asset?'asset':'zone';\n downloadContacts($scope.alarm.asset ? $scope.alarm.asset : $scope.alarm.zone);\n\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/alarm/\" + $scope.alarm.id + \"?select=meta+ackedBy\", {\n onErrorDoNotRedirect: true\n }).then(function (response) {\n if (response.data.result != undefined) {\n var alarm = response.data.result[0];\n console.log(\"killAlarmUpdater > Succesfull\")\n } else {\n //alert(\"Error: No response data available\");\n console.log(\"killAlarmUpdater > FAILED\");\n }\n\n if (alarm.meta && alarm.meta.actionStatus) {\n $scope.actionStatus = alarm.meta.actionStatus;\n }\n if (alarm.ackedBy)\n $scope.downloadAlarm();\n\n });\n\n $scope.refreshEvents(0);\n\n }\n });\n\n\n $scope.mapViewAltered = false;\n $scope.selectedMarker = '';\n $scope.selectedMarkerName = \"\";\n $scope.markers = {};\n $scope.mapSidebar = {\n 'visible': false\n };\n $scope.indoorViewer = {\n location: null,\n markers: {},\n changeCounter: 0\n };\n mapService.basicMapDesign($scope, leafletData, \"amMap\");\n\n var updateBZVisibility = function () {\n var nbrOfContacts = 0;\n var allElseFailed = true;\n var totalNbrOfContacts = 0;\n for (var i in $scope.responseAreas) {\n var ra = $scope.responseAreas[i];\n if (ra.visible && ra.code != codes.bz && ra.code != codes.pd) {\n if (allElseFailed) {\n for (var i in ra.contacts) {\n var c = ra.contacts[i];\n var key = getActionStatusKey(c);\n if (!$scope.actionStatus.hasOwnProperty(key) || $scope.getActionStatus(c)) {\n allElseFailed = false;\n }\n }\n }\n if (ra.code != codes.pd && ra.code != codes.customer) {\n nbrOfContacts += ra.contacts.length;\n }\n }\n }\n\n updateRAPropertyForCode(codes.bz, \"visible\", nbrOfContacts == 0 || allElseFailed);\n }\n\n var clipboard = new Clipboard('.clipBtn');\n clipboard.on('success', function (e) {\n console.log(e);\n });\n clipboard.on('error', function (e) {\n console.log(e);\n });\n\n\n $scope.order = 0;\n $scope.actionStatus = {};\n $scope.setOrder = function (order) {\n $scope.responseAreas.sort(function (a, b) {\n if (order == 1 && b.code == codes.pc) return -1; // Exception for personal Contacts. They should not be reversed in order, but remain on the end. Maybe not the best solution. \n if (a.code == b.code) {\n return a.priority - b.priority;\n }\n return (order == 0) ? a.code - b.code : b.code - a.code;\n });\n $scope.order = order;\n }\n\n $scope.isAlarmCenter = false;\n\n $scope.downloadAlarm = function () {\n\n return smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/alarm/' + alarmID + '?select=@', {\n onErrorDoNotRedirect: true\n }).then(function (response) {\n if (!response) return;\n $scope.alarm = response.data.result[0];\n $scope.isAlarmCenter = $scope.alarm.alarmCenter && $scope.alarm.alarmCenter.id == smarttrackerService.getCustomerId();\n if ($scope.alarm) {\n contentCacheService.put(\"alarm\", $scope.alarm.id, $scope.alarm);\n currentAlarm();\n }\n console.log(\"downloading alarm ALARM ALARM !!\", $scope.alarm);\n if (!$scope.alarm) return;\n\n if ($scope.alarm.meta.commentsMeta) {\n $scope.commentsMeta = $scope.alarm.meta.commentsMeta;\n }\n console.log(\"Lets check meta\", $scope.alarm.meta);\n if ($scope.alarm.meta[notificationStatusKey]) {\n $scope.notificationStatus = $scope.alarm.meta[notificationStatusKey];\n }\n if ($scope.alarm.meta.order) {\n $scope.order = $scope.alarm.meta.order;\n }\n $scope.actionStatus = $scope.alarm.meta.actionStatus ? $scope.alarm.meta.actionStatus : {};\n getTimeString();\n\n if ($scope.alarm.ackedBy != null) { // Stop updating. Everything we need is persisted with the alarm on the meta JSON object. \n var meta = $scope.alarm.meta;\n if (meta.responseAreas)\n $scope.responseAreas = meta.responseAreas;\n if (meta.comments) {\n $scope.events = meta.comments;\n for (var i in $scope.events) {\n var dd = moment.tz($scope.events[i].dateCreated, \"YYYY-MM-DDTHH:mm:ss.SSS\", \"UTC\");\n if (new Date() - dd.toDate() < 43200000)\n $scope.events[i].dateCreatedFormatted = $scope.translations.today + \", \" + $filter(\"amDateFormat\")($scope.events[i].dateCreated, 'HH:mm:ss');\n else\n $scope.events[i].dateCreatedFormatted = $filter(\"amDateFormat\")($scope.events[i].dateCreated, 'YYYY-DD-MM, HH:mm:ss');\n }\n } else {\n $scope.events = [];\n }\n // update map\n if (meta.asset) {\n $scope.alarm.asset = meta.asset;\n } else if (meta.zone) {\n $scope.alarm.zone = meta.zone;\n }\n\n addCustomerMarker($scope.alarm.asset);\n addAlarmMarker($scope.alarm);\n renderLineBetween();\n\n if (typeof $scope.alarm.comment === 'string') {\n $scope.alarm.comment = $scope.alarm.comment.replace(/\\*\\*([\\s\\S]+?)\\*\\*/gm, '$1');\n }\n\n for (var i in $scope.responseAreas) {\n var ra = $scope.responseAreas[i];\n if (ra.code == codes.qr || ra.code == codes.nqr) {\n for (var x in ra.contacts) {\n var contact = ra.contacts[x];\n if (ra.code == codes.nqr) {\n addNQRMarker(contact);\n } else {\n addQRMarker(contact);\n }\n }\n }\n }\n\n $scope.chat = [];\n setupChat();\n\n if (killAlarmUpdater)\n killAlarmUpdater();\n\n $scope.initMap();\n $scope.ackedTS = utilService.getFormattedDateFromTimestamp($scope.alarm.lastUpdated);\n return;\n }\n\n var asset = $scope.alarm.asset;\n\n setupConferenceCalls($scope.alarm);\n\n $scope.chat = [];\n setupChat();\n\n if (asset /* && $scope.alarm.position /*&& asset.type && asset.type.id==employeeID*/ ) {\n\n addCustomerMarker($scope.alarm.asset);\n addAlarmMarker($scope.alarm);\n\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/asset/' + $scope.alarm.asset.id + '?select=@&crossAccount=true', {\n onErrorDoNotRedirect: true\n }).then(function (resp) {\n if (resp.data.result.length == 0) return;\n $scope.alarm.asset = resp.data.result[0];\n var asset = $scope.alarm.asset;\n var nqrEnabled = $scope.getPropertyValue(asset, syntax.allowNQR);\n\n getAssetContactList();\n\n $scope.contactInfo = {\n \"id\": asset.id,\n \"name\": asset.name,\n \"image\": asset.image,\n \"phone\": $scope.getPropertyValue(asset, syntax.phone),\n \"phoneFormatted\": $scope.trimPhoneNumber($scope.getPropertyValue(asset, syntax.phone)),\n \"sms\": $scope.getPropertyValue(asset, syntax.sms),\n \"email\": $scope.getPropertyValue(asset, syntax.email),\n \"allowEmergencyContact\": $scope.getPropertyValue(asset, syntax.allowEmergencyContact),\n \"nqrEnabled\": nqrEnabled && nqrEnabled == \"true\"\n }\n\n addContactsForCode([$scope.contactInfo], codes.customer);\n getResponseAreaForCode(codes.nqr).visible = $scope.contactInfo.nqrEnabled;\n\n if ($scope.contactInfo.allowEmergencyContact == \"false\") {\n updateRAPropertyForCode(codes.customer, \"visible\", false);\n }\n downloadZones(asset.insideZones);\n downloadContacts(asset);\n })\n\n renderLineBetween();\n //$scope.updateMarkers(true);\n $timeout(function () {\n $scope.initMap();\n }, 300);\n } else if ($scope.alarm.zone) {\n var zone = $scope.alarm.zone;\n //addAlarmMarker($scope.alarm);\n // TODO Add marker to the center of the zone\n\n // Set Contact Info?\n addMarker(zone, \"glyphicon glyphicon-map-marker\", \"#FF0000\", \"Current Position\", true, codes.customer);\n\n for (var i in zone.labels) {\n var label = zone.labels[i];\n if (label.code == syntax.ZMTag) {\n try {\n var json = JSON.parse(label.value);\n $scope.contactInfo = {\n \"nqrEnabled\": (json.showNQR && json.showNQR == true)\n }\n } catch (e) {\n console.error(e);\n }\n }\n }\n\n\n $scope.contactInfo = {\n 'name': $scope.alarm.zone.name\n };\n downloadZonesForZone(zone);\n downloadContacts(zone);\n $scope.initMap();\n\n } else {\n normalMode();\n }\n $scope.refreshEvents(0);\n\n }, function (response) {\n alert(\"Something went very wrong on this one, GEt alarm\");\n });\n } // End Download Alarm\n\n $scope.contactStatus = 0;\n var mapInitiated = false;\n var maximumDistances = {\n 'total': 0\n };\n\n function uniq_fast(a) {\n var seen = {};\n var out = [];\n var len = a.length;\n var j = 0;\n for (var i = 0; i < len; i++) {\n var item = a[i]\n if (seen[item.id] !== 1) {\n seen[item.id] = 1;\n out[j++] = item;\n }\n }\n return out;\n }\n\n var conferenceParseParticipants = function(alarm, rawParticipants) {\n\n // filter participants\n var participants = [];\n $scope.alarmAssetConnected = false;\n $scope.alarmAssetConnectedStartTime = null;\n $scope.conferenceOthersConnected = false;\n $scope.conferenceSelfConnected = false;\n $scope.mutedHintClicked = false;\n if(typeof rawParticipants !== 'undefined'){\n\n for (var i = 0; i < rawParticipants.length; i++) {\n\n var participant = rawParticipants[i];\n\n // parse away app_ prefix\n participant.client = participant.client.replace(/^app_/i, '');\n\n // check connected\n if(participant.status !== 'connected'){\n continue;\n }\n\n if(participant.client != alarm.asset.id){\n\n // check\n if(participant.userId == $scope.userResourceId) {\n\n participant.isSelf = true;\n $scope.conferenceSelfConnected = true;\n\n } else {\n\n $scope.conferenceOthersConnected = true;\n\n }\n\n participants.push(participant);\n\n } else {\n\n $scope.alarmAssetConnected = true;\n $scope.alarmAssetConnectedStartTime = participant.startTime;\n\n }\n\n }\n\n participants.sort(function(a, b) {\n\n if(a.isSelf === true) {\n\n return -1;\n\n }\n\n return 1;\n\n });\n\n }\n\n return participants;\n }\n\n var setupConferenceCalls = function(alarm) {\n\n if (alarm.ackedBy != null) {\n\n // log and done\n console.log('Tag: Conference', '- Not setting up conference calls, already acked so no call will come in')\n return;\n\n }\n\n // log\n console.log('Tag: Conference', '- Setting up websocket');\n $scope.dccPhoneNumber = stwoGlobal.dccPhoneNumber;\n $scope.conferenceEnded = false;\n $scope.alarmAssetConnected = false;\n $scope.conferenceSelfConnected = false;\n $scope.conferenceOthersConnected = false;\n $scope.conferenceParticipants = [];\n\n $scope.checkboxes = {\n dccJoinMuted: alarm.logLevel === 0,\n };\n\n $scope.$watch('checkboxes.dccJoinMuted', setJoinMuted);\n\n console.log('Tag: conference', 'Alarmdata', alarm)\n\n // $scope.conferenceCallCode = 444;\n // $timeout(function(){\n\n // // filter participants\n // var participants = [];\n // var message = {\n // participants: [\n // {\n // \"client\": \"+31881261206\",\n // \"status\": \"connected\",\n // \"muted\": false,\n // \"hold\": false,\n // \"endConferenceOnExit\": true\n // },\n // {\n // \"client\": \"8232gfd44f0698\",\n // \"status\": \"connected\",\n // \"muted\": false, \n // \"hold\": false,\n // \"endConferenceOnExit\": true\n // },\n // {\n // \"client\": \"+3188j1261207\",\n // \"status\": \"connected\",\n // \"muted\": false,\n // \"hold\": false,\n // \"endConferenceOnExit\": true\n // }]\n // }\n // for (var i = 0; i < message.participants.length; i++) {\n\n // var participant = message.participants[i];\n // if(participant.client != alarm.asset.id && participant.client.match(/[a-z]/gi) === null) {\n\n // participants.push(participant);\n\n // }\n\n // }\n\n // $scope.conferenceParticipants = participants;\n\n // }, 5000);\n\n // check if there is a call active now\n deploymentApiService.get('/v1/conference/find/'+alarm.asset.id+'?joinMuted='+$scope.checkboxes.dccJoinMuted).then(function(response){\n\n console.log('Tag: Conference', '- Set code to', response, response.data.code);\n if(response.status !== 200){\n return;\n }\n\n $scope.conferenceSid = response.data.conferenceSid;\n $scope.conferenceCallCode = response.data.code;\n\n if(typeof response.data.participants !== 'undefined'){\n\n $scope.conferenceParticipants = conferenceParseParticipants(alarm, response.data.participants);\n\n }\n\n // if-provider\n if($scope.isServiceProvider !== true) {\n\n $scope.registerEvent('(Waargenomen)\\nTelefoongesprek aangeboden door gebruiker');\n\n }\n\n });\n\n // connect to socket\n socketioService.subscribe('asset/'+alarm.asset.id, function(message){\n\n console.log('Tag: Conference', '- Received message about asset', message);\n\n var participants = conferenceParseParticipants(alarm, message.participants);\n\n // new\n if(message.event === 'conference/create'){\n\n // set conference ended to not false\n $scope.conferenceEnded = false;\n $scope.conferenceCallCode = \"...\";\n\n $timeout(function() {\n\n // get the code\n getConferenceCallCode(alarm);\n\n }, 1000)\n\n // if-provider\n if($scope.isServiceProvider !== true) {\n\n $scope.registerEvent('(Waargenomen)\\nTelefoongesprek aangeboden door gebruiker');\n\n }\n\n }else\n if(message.event === 'conference/event/conference-end'){\n\n if($scope.isServiceProvider !== true) {\n\n $scope.registerEvent('(Waargenomen)\\nTelefoongesprek is opgehangen');\n\n }\n \n $scope.conferenceEnded = true;\n $scope.conferenceSelfConnected = false;\n $scope.alarmAssetConnected = false;\n\n }else\n if(message.event === 'conference/event/participant-join'){\n\n $scope.conferenceParticipants = participants;\n\n }else\n if(message.event === 'conference/event/participant-leave'){\n\n $scope.conferenceParticipants = participants;\n\n }else\n if(message.event === 'conference/event/participant-mute' || message.event === 'conference/event/participant-unmute'){\n\n // only update the muted variable\n angular.forEach($scope.conferenceParticipants, function(participant) {\n\n // loop and adjust\n for (var i = 0; i < participants.length; i++) {\n\n if(participants[i].callSid === participant.callSid) {\n\n participant.muted = participants[i].muted;\n break;\n\n }\n\n }\n\n });\n\n }\n\n\n })\n\n }\n\n $scope.setMuted = function(participant, muted) {\n\n console.log('Tag: Conference', '- setMuted', participant, muted);\n\n participant.muted = muted;\n\n // perform update on server\n deploymentApiService.post('/v1/conference/participant/mute', {\n callSid: participant.callSid,\n muted: muted,\n });\n\n }\n\n $scope.setMutedHintClicked = function() {\n\n $scope.mutedHintClicked = true;\n \n }\n\n function setJoinMuted(muted) {\n\n if(!$scope.conferenceSid) {\n return;\n }\n\n console.log('Tag: Conference', '- setJoinMuted', muted);\n\n // get the code\n deploymentApiService.post('/v1/conference/join-options/mute', {\n conferenceSid: $scope.conferenceSid,\n muted: muted,\n }).then(function(response){\n\n console.log('Tag: Conference', '- setJoinMuted - Result:', response);\n\n });\n\n }\n\n var getConferenceCallCode = function(alarm, attempts){\n\n // check\n if(typeof attempts === 'undefined' ) {\n\n attempts = 0;\n\n }\n\n // reset\n $scope.checkboxes.dccJoinMuted = (alarm.logLevel === 0);\n\n // get the code\n deploymentApiService.get('/v1/conference/find/'+alarm.asset.id+'?joinMuted='+$scope.checkboxes.dccJoinMuted).then(function(response){\n\n console.log('Tag: Conference', '- Set code to', response);\n $scope.conferenceSid = response.data.conferenceSid;\n $scope.conferenceCallCode = response.data.code;\n\n }, function(response) {\n\n if(attempts < 3) {\n\n return getConferenceCallCode(alarm, attempts + 1);\n\n }\n\n });\n\n }\n\n var downloadContacts = function (asset) {\n if (!asset || !$scope.access['type']['get'] || (!asset.position && !asset.lastValidPosition)) return;\n var position = asset.lastValidPosition ? asset.lastValidPosition : asset.position;\n\n var lessLat = position.latitude + 1; // 1 used to be 0.5\n var lessLon = position.longitude + 1;\n var greaterLat = position.latitude - 1;\n var greaterLon = position.longitude - 1;\n\n downloadCloseAssets('/asset?select=properties+lastValidPosition+lastPosition+type+groups+connectedTo&crossAccount=true&type.labels:contains=' + syntax.QRTag + '&owner:equals=' + asset.owner.id +\n '&latitude:less=' + lessLat + '&latitude:greater=' + greaterLat + '&longitude:less=' + lessLon + '&longitude:greater=' + greaterLon + (debugMode ? '' : '&embeddedTimestamp:younger=3900000') + '&max=50', syntax.QRTag,\n function (list) {\n\n downloadCloseAssets('/asset?select=properties+lastValidPosition+lastPosition+type+groups&crossAccount=true&type.labels:contains=ACR_QR_ALWAYS&latitude:less=' + lessLat + '&latitude:greater=' + greaterLat +\n '&longitude:less=' + lessLon + '&longitude:greater=' + greaterLon + '&max=50', 'ACR_QR_ALWAYS',\n function (list_2) {\n\n for (var a in list_2) {\n\n list_2[a].type_label = 'ACR_QR_ALWAYS';\n\n // loop properties\n list_2[a].propertiesFormatted = {}\n for (var p in list_2[a].properties) {\n\n list_2[a].propertiesFormatted[list_2[a].properties[p].code] = list_2[a].properties[p];\n\n }\n\n }\n\n // list = uniq_fast(list.concat(list_2))\n list = uniq_fast(list_2.concat(list))\n list.sort(function (a, b) {\n\n if (a.distance < b.distance) {\n\n return -1;\n\n } else\n if (a.distance > b.distance) {\n\n return 1;\n\n }\n\n return 0;\n\n })\n\n // get types meta\n var usedIDS = [];\n console.log('MERGED LIST 1', list);\n if (list && list.length > 0) {\n var typeIDS = list[0].type.id;\n var anyAvailablePush = false;\n for (var i = 0; i < list.length; i++) {\n var id = list[i].type.id;\n if (usedIDS.indexOf(id) < 0) {\n usedIDS.push(id);\n typeIDS += \"%2B\" + id;\n }\n if (list[i].connectedTo && list[i].connectedTo.length > 0) {\n console.log(\"Check connection for \" + list[i].name);\n angular.forEach(list[i].connectedTo, function (obj) {\n if (obj.to && obj.to.type == \"user\") {\n list[i].user = obj.to;\n list[i].notificationStatus = $scope.notificationStatus[obj.to.id] ? $scope.notificationStatus[obj.to.id].status : $scope.ns.available.status;\n if (obj.to.id == $scope.userID) {\n $scope.me = list[i];\n updateFeedbackVariables();\n }\n }\n });\n anyAvailablePush = anyAvailablePush || list[i].notificationStatus == $scope.ns.available.status;\n } else {\n // console.log(\"Skipping test for \" + list[i].name + \" because there is no connected objects\", list[i].connectedTo);\n }\n if (!list[i].user) {\n list[i].notificationStatus = $scope.ns.unavailable.status;\n }\n\n }\n\n console.log('MERGED LIST 2', list);\n\n $scope.anyAvailablePush = anyAvailablePush;\n if (!maximumDistances || !maximumDistances.qr) {\n getMaxDistancesForCode(list, codes.qr);\n }\n $scope.collegues = list;\n addContactsForCode(list, codes.qr, true);\n\n $scope.contactStatus++;\n updateBZVisibility();\n applyDistanceFilter(codes.qr);\n if (!mapInitiated) {\n $timeout(function () {\n $scope.autoCenter();\n }, 300);\n mapInitiated = true;\n }\n }\n\n });\n\n // end\n });\n // \n\n\n if (($scope.contactInfo.nqrEnabled || $scope.alarm.zone) && $scope.alarm && $scope.alarm.ackedBy == null) {\n downloadCloseAssets('/asset?select=properties+lastValidPosition+lastPosition+type+groups&crossAccount=true&type.labels:contains=' + syntax.NQRTag + '&latitude:less=' + lessLat + '&latitude:greater=' + greaterLat +\n '&longitude:less=' + lessLon + '&longitude:greater=' + greaterLon + (debugMode ? '' : '&embeddedTimestamp:younger=3900000') + '&max=50', syntax.NQRTag,\n function (list) {\n\n $scope.guards = list;\n\n if (!maximumDistances || !maximumDistances[codes.nqr]) {\n getMaxDistancesForCode(list, codes.nqr);\n }\n\n addContactsForCode($scope.guards, codes.nqr, true);\n\n $scope.contactStatus++;\n updateBZVisibility();\n applyDistanceFilter(codes.nqr);\n\n });\n\n }\n if ($scope.alarm && ($scope.alarm.asset || $scope.alarm.zone)) {\n var object = $scope.alarm.asset ? 'asset' : 'zone';\n\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/' + object + '/' + $scope.alarm[object].id + '?crossAccount=true', {\n onErrorDoNotRedirect: true\n }).then(function (response) {\n if (response && response.data && response.data.result && response.data.result.length > 0) {\n $scope.alarm[object] = response.data.result[0];\n\n // Add private contacts\n if (!getResponseAreaForCode(codes.pc) && $scope.alarm[object].labels) {\n var data = parseDataForZone($scope.alarm[object]);\n var contacts = data.contacts.sort(comparePriority);\n if (data.contacts) {\n $scope.responseAreas.push({\n \"name\": translations[\"XGUARD_RESPONSE_AREAS_PRIVATE_CONTACTS\"],\n \"color\": \"ra\",\n \"code\": codes.pc,\n \"contacts\": contacts,\n \"expanded\": false,\n \"visible\": true\n });\n $scope.setOrder($scope.order);\n\n }\n }\n if ($scope.alarm.asset) {\n addCustomerMarker($scope.alarm.asset);\n downloadZones(asset.insideZones);\n }\n }\n }, function () {\n alert(\"Something went wrong with the \" + object + \" request\");\n });\n }\n }\n\n var getLabelWithCode = function (objectWithLabel, code) {\n if (objectWithLabel.labels) {\n for (var i in objectWithLabel.labels) {\n if (objectWithLabel.labels[i].code == code) {\n return objectWithLabel.labels[i];\n }\n }\n }\n }\n\n var getAssetContactList = function () {\n if (!$scope.alarm ||  !$scope.alarm.asset || !$scope.access['alarm']['put']) return;\n var asset = $scope.alarm.asset;\n if ($scope.access['group']['get'] && asset.groups && asset.groups.length > 0) {\n var groupIDs = asset.groups[0].id;\n for (var i = 1; i < asset.groups.length; i++) {\n groupIDs += \"%2B\" + asset.groups[i].id;\n }\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/group/\" + \"?select=labels&id:equals=\" + groupIDs + \"&labels:contains=ACR_CL&crossAccount=true&owner:equals=\" + $scope.alarm.asset.owner.id, {\n onErrorDoNotRedirect: true\n })\n .then(function (response) {\n if (response.data.result.length > 0) {\n var idFilters = \"id:equals=\";\n var usedIDs = [];\n angular.forEach(response.data.result, function (group) {\n var labels = group.labels;\n angular.forEach(labels, function (label, name) {\n if (label.code == syntax.CLTag) {\n try {\n var json = JSON.parse(label.value);\n var id = json.id;\n if (id && usedIDs.indexOf(id) < 0) {\n usedIDs.push(id);\n idFilters += id + \"%2B\";\n }\n } catch (e) {\n console.log(\"Error parsing label \", label, e);\n }\n }\n });\n });\n if (idFilters != \"id:equals=\") {\n idFilters = idFilters.substring(0, idFilters.lastIndexOf(\"%2B\"));\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/contactList?select=@&\" + idFilters + \"&crossAccount=true\", {\n onErrorDoNotRedirect: true\n }).then(function (response) {\n if (response.data.result.length > 0) {\n $scope.contactLists = [];\n angular.forEach(response.data.result, function (cl) {\n $scope.contactLists.push(cl.id);\n });\n }\n console.log(\"Contact Lists are set to: \", $scope.contactLists);\n });\n }\n }\n });\n }\n\n }\n\n\n var getMaxDistancesForCode = function (contacts, code) {\n if (contacts.length > 0) {\n var usedIDS = [];\n var typeIDS = contacts[0].type.id;\n for (var i = 1; i < contacts.length; i++) {\n var id = contacts[i].type.id;\n if (usedIDS.indexOf(id) === -1) {\n usedIDS.push(id);\n typeIDS += \"%2B\" + id;\n }\n }\n if (!maximumDistances || !maximumDistances.qr) {\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/type/?select=labels&id:equals=\" + typeIDS, {\n onErrorDoNotRedirect: true\n })\n .then(function (response) {\n\n var approvedContacts = [];\n maximumDistances[code] = new Date();\n for (var i in response.data.result) {\n var type = response.data.result[i];\n for (var x in type.labels) {\n var label = type.labels[x];\n\n if (label.code === 'ACR_QR_ALWAYS') {\n continue;\n }\n\n if (label.value.indexOf(\"maxDistance\") >= 0) {\n try {\n var value = JSON.parse(label.value);\n maximumDistances[type.id + type.name] = value.maxDistance;\n maximumDistances['total'] = maximumDistances['total'] + 1;\n\n //alert('Set ' + type.id + type.name + ' to ' + value.maxDistance)\n\n } catch (e) {\n console.log(e);\n maximumDistances[type.id + type.name] = 2000;\n maximumDistances['total'] = maximumDistances['total'] + 1\n\n //alert('Set ' + type.id + type.name + ' to default 2000')\n }\n } else {\n maximumDistances[type.id + type.name] = 2000;\n maximumDistances['total'] = maximumDistances['total'] + 1\n\n //alert('Set ' + type.id + type.name + ' to default 2000')\n\n }\n }\n }\n applyDistanceFilter(code);\n });\n }\n }\n }\n\n var applyDistanceFilter = function (code) {\n\n if (maximumDistances && maximumDistances.total > 0) {\n var ra = false;\n for (var i in $scope.responseAreas) {\n if ($scope.responseAreas[i].code == code) {\n ra = $scope.responseAreas[i];\n }\n }\n\n if (ra) {\n var list = [];\n for (var i in ra.contacts) {\n var contact = ra.contacts[i];\n\n console.log('distanceFilter', '['+code+']', contact.distance > maximumDistances[contact.type.id + contact.type.name] ? '🚫 FILTERED' : '🟢 ACCEPTED', contact.type.id, contact.type.name, '=', maximumDistances[contact.type.id + contact.type.name], 'vs', contact.distance, 'for', contact.name)\n\n if (!(contact.type && maximumDistances[contact.type.id + contact.type.name] &&\n contact.distance > maximumDistances[contact.type.id + contact.type.name])) {\n list.push(contact);\n if (code == codes.nqr) addNQRMarker(contact);\n else if (code == codes.qr) addQRMarker(contact);\n\n } else if ($scope.markers[\"marker\" + contact.id]) {\n leafletData.getMap(\"amMap\").then(function (map) {\n map.removeLayer($scope.markers[\"marker\" + contact.id]);\n delete $scope.markers[\"marker\" + contact.id];\n });\n }\n }\n addContactsForCode(list, code, true);\n\n }\n }\n }\n\n\n var downloadCloseAssets = function (url, context, repl) {\n var list = [];\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + url, {\n onErrorDoNotRedirect: true\n }).then(function (response) {\n if (!response || !response.data) return;\n for (var i in response.data.result) {\n var asset = response.data.result[i];\n if (!asset.lastValidPosition || !isContactAllowed(asset, context))\n continue;\n\n if ($scope.alarm.asset && asset.id != $scope.alarm.asset.id || $scope.alarm.zone) {\n\n asset.invisibleResponder = $scope.getPropertyValue(asset, 'invisibleResponder') || 'false';\n asset.phone = $scope.getPropertyValue(asset, syntax.phone);\n asset.phoneFormatted = $scope.trimPhoneNumber($scope.getPropertyValue(asset, syntax.phone));\n asset.sms = $scope.getPropertyValue(asset, syntax.sms);\n asset.email = $scope.getPropertyValue(asset, syntax.email);\n asset.distance = calculateDistance(asset.lastValidPosition, $scope.alarm.asset ? $scope.alarm.asset.lastValidPosition : $scope.alarm.zone.position);\n asset.distanceText = getDistanceText(asset.distance);\n //asset.allowConact = $scope.getPropertyValue(asset, syntax.allowConact);\n\n\n\n // only add when not invisible\n if(('' + asset.invisibleResponder) !== 'true') {\n\n list.push(asset);\n\n }\n\n }\n }\n list.sort(function (a, b) {\n return a.distance - b.distance;\n });\n\n repl(list);\n });\n }\n\n var downloadZonesForZone = function (zone) {\n var maxLat = zone.points[0].latitude;\n var minLat = zone.points[0].latitude;\n var maxLon = zone.points[0].longitude;\n var minLon = zone.points[0].longitude;\n\n for (var i in zone.points) {\n var lat = zone.points[i].latitude;\n var lon = zone.points[i].longitude;\n if (lat > maxLat) maxLat = lat;\n else if (lat < minLat) minLat = lat;\n if (lon > maxLon) maxLon = lon;\n else if (lon < minLon) minLon = lon;\n }\n // maxLat += 0.5;minLat -= 0.5;maxLon += 0.5;minLon -= 0.5;\n smarttrackerService.authGet(smarttrackerService.getCustomerId() +\n '/zone/?maxLatitude:greater=' + maxLat + '&minLatitude:less=' + minLat + '&maxLongitude:greater=' + maxLon + '&minLongitude:less=' + minLon + '&max=100&crossAccount=true&owner:equals=' + $scope.alarm.zone.owner.id + ($scope.alarm.alarmCenter ? '&owner:equals=' + $scope.alarm.alarmCenter.id : '', {\n onErrorDoNotRedirect: true\n })).then(function (response) {\n // compile list of ids. \n var zones = response.data.result;\n\n if (zones.length > 1) {\n for (var i = 0; i < zones.length; i++) {\n if (zones[i].id == zone.id) {\n zones.splice(i, 1);\n break;\n }\n }\n downloadZones(zones);\n }\n });\n\n\n }\n\n var downloadZones = function (zones) {\n if (!zones || zones.length < 1) return;\n var zoneIDS = \"\" + zones[0].id;\n for (var i = 1; i < zones.length; i++) {\n zoneIDS += \"%2B\" + zones[i].id;\n }\n\n // remove zones that the asset is no longer inside\n\n\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/zone/?id:equals=' + zoneIDS + \"&select=type+labels+points&crossAccount=true\", {\n onErrorDoNotRedirect: true\n }).then(function (response) {\n var zs = response.data.result;\n // clear old zone contacts\n for (var i in $scope.responseAreas) {\n var ra = $scope.responseAreas[i];\n if (ra.code == codes.pd || ra.code == codes.bz || ra.code == codes.ra) {\n ra.contacts = [];\n }\n }\n\n for (var i in zs) {\n var z = zs[i];\n if (z.labels) {\n for (var l in z.labels) {\n var label = z.labels[l];\n switch (label.code) {\n case syntax.RATag:\n addResponseArea(z);\n break;\n case syntax.PDTag:\n if ($scope.isAlarmCenter || $scope.isServiceProvider)\n addContactsForCode(parseDataForZone(z).contacts, codes.pd);\n break;\n case syntax.BZTag:\n addContactsForCode(parseDataForZone(z).contacts, codes.bz);\n break;\n }\n }\n }\n }\n updateBZVisibility();\n });\n }\n\n var addResponseArea = function (z) {\n var data = parseDataForZone(z);\n var priority = data.priority ? data.priority : 20000;\n var contacts = data.contacts.sort(comparePriority);;\n getResponseAreaTextForZone(z).then(function (text) {\n var ra = {\n \"name\": text,\n \"color\": \"ra\",\n \"code\": codes.ra,\n \"priority\": priority,\n \"contacts\": contacts,\n \"expanded\": false,\n \"visible\": contacts.length > 0\n };\n if (data.messageData) ra.messageData = data.messageData;\n $scope.responseAreas.push(ra);\n $scope.setOrder($scope.order);\n var hp = ra.priority;\n var fp = false;\n for (var i in $scope.responseAreas) {\n var area = $scope.responseAreas[i];\n if (area.code == codes.ra && area.priority && area.priority < hp) {\n fp = true;\n break;\n }\n }\n if (!fp) {\n renderResponseArea(z);\n\n }\n });\n }\n\n $scope.setMode = function (mode) {\n\n $scope.modes.isDoubt = (mode === 'doubt');\n\n }\n\n $scope.centerOnAddress = function (data) {\n leafletData.getMap(\"amMap\").then(function (map) {\n map.setView({\n 'lat': data.point.lat,\n 'lng': data.point.lng\n }, 16);\n });\n }\n\n var renderResponseArea = function (a) {\n leafletData.getMap(\"amMap\").then(function (map) {\n var latlngs = [];\n try {\n angular.forEach(a.points, function (point) {\n latlngs.push({\n 'lat': point['latitude'],\n 'lng': point['longitude']\n });\n });\n } catch (e) {\n console.error(e);\n }\n addPath(\"ResponseArea\", {\n type: \"polygon\",\n fillColor: 'darkgreen',\n color: 'darkgreen',\n latlngs: latlngs,\n clickable: false,\n weight: 2\n });\n if ($scope.polygon) {\n try {\n $scope.polygon.remove();\n } catch (e) {\n console.error(e);\n }\n }\n\n $scope.polygon = L.polygon(latlngs, {\n color: 'darkgreen',\n fillColor: 'darkgreen'\n });\n $scope.polygon.addTo(map);\n $scope.paths[\"responseArea\"] = $scope.polygon;\n });\n }\n\n var getResponseAreaForCode = function (code, priority) {\n for (var i in $scope.responseAreas) {\n if ($scope.responseAreas[i].code == code) {\n var ra = $scope.responseAreas[i];\n if (priority && ra.priority != priority) {\n continue;\n }\n return ra;\n }\n }\n return false;\n }\n\n var updateRAPropertyForCode = function (code, property, value) {\n for (var i in $scope.responseAreas) {\n if ($scope.responseAreas[i].code == code) {\n $scope.responseAreas[i][property] = value;\n break;\n }\n }\n }\n\n var addContactsForCode = function (contacts, code, refresh) {\n var index = false;\n for (var i in $scope.responseAreas) {\n if ($scope.responseAreas[i].code == code) {\n index = i;\n break;\n }\n }\n if (index && index > -1) {\n if (refresh) {\n $scope.responseAreas[index].contacts = [];\n }\n for (var j in contacts) {\n $scope.responseAreas[i].contacts.push(contacts[j]);\n }\n\n }\n if (code == codes.nqr || code == codes.qr)\n $scope.responseAreas[i].contacts = $scope.responseAreas[i].contacts;\n else\n $scope.responseAreas[i].contacts = $scope.responseAreas[i].contacts.sort(comparePriority);\n }\n\n var days = [\"SUN\", \"MON\", \"TUE\", \"WED\", \"THU\", \"FRI\", \"SAT\"];\n\n var parseDataForZone = function (zone) {\n zone.contacts = [];\n var now = new Date();\n\n\n for (var i in zone.labels) {\n var label = zone.labels[i];\n if (label.code == \"ACR_CONTACT\") {\n try {\n var properties = JSON.parse(label.value);\n properties[\"name\"] = i;\n // Check if the contact is available \n if (properties.workhours && properties.workhours.length > 0) {\n properties.working = false;\n whcheck:\n for (var y in properties.workhours) {\n var wh = properties.workhours[y];\n for (var z in wh.weekday) {\n if (days.indexOf(wh.weekday[z]) == now.getDay()) {\n\n var startBound = new Date();\n if (wh.hours) {\n startBound.setHours(wh.hours.substring(0, 2));\n startBound.setMinutes(wh.hours.substring(2, 4));\n var endBound = new Date();\n endBound.setHours(wh.hours.substring(5, 7));\n endBound.setMinutes(wh.hours.substring(7, 9));\n if (endBound == '0000') {\n endBound.setDate(endBound.getDate() + 1);\n }\n }\n\n if (now.getTime() > startBound.getTime() && now.getTime() < endBound.getTime() || !wh.hours) {\n properties.working = true;\n zone.contacts.push(properties);\n break whcheck;\n }\n }\n }\n }\n\n } else {\n properties.working = true;\n zone.contacts.push(properties);\n }\n } catch (e) {\n console.log(e);\n }\n } else if (label.code == \"ACR_RA\") {\n\n try {\n var properties = JSON.parse(label.value);\n var kv = {\n showQR: \"qr\",\n showNQR: \"nqr\",\n showPD: \"pd\"\n };\n for (var k in kv) {\n if (properties.hasOwnProperty(k) && !properties[k]) {\n updateRAPropertyForCode(codes[kv[k]], \"visible\", false);\n }\n }\n zone.priority = properties.priority ? properties.priority : 20000;\n if (properties.messageData) {\n zone.messageData = properties.messageData;\n }\n } catch (e) {\n console.log(e);\n }\n }\n }\n\n\n return zone;\n }\n\n\n $translate([\"XGUARD_RESPONSE_AREAS_CUSTOMER\", \"XGUARD_RESPONSE_AREAS_QUICK_RESPONSE\",\n \"XGUARD_RESPONSE_AREAS_NATIONAL_QUICK_RESPONSE\", \"XGUARD_RESPONSE_AREAS_POLICE_REGION\", \"XGUARD_RESPONSE_AREAS_PRIVATE_CONTACTS\",\n \"XGUARD_RESPONSE_AREAS_BACKUP\"\n ]).then(function (data) {\n translations = data;\n\n $scope.responseAreas = [{\n \"name\": translations[\"XGUARD_RESPONSE_AREAS_CUSTOMER\"],\n \"color\": \"cu\",\n \"code\": codes.customer,\n \"contacts\": [],\n \"expanded\": false,\n \"visible\": true\n }, {\n \"name\": translations[\"XGUARD_RESPONSE_AREAS_QUICK_RESPONSE\"],\n \"color\": \"qr\",\n \"code\": codes.qr,\n \"contacts\": [],\n \"expanded\": false,\n \"visible\": true\n },\n //{\"name\":\"Response Area\", \"color\":\"ra\", \"code\":codes.ra, \"contacts\":[], \"expanded\":false, \"visible\":true},\n {\n \"name\": translations[\"XGUARD_RESPONSE_AREAS_NATIONAL_QUICK_RESPONSE\"],\n \"color\": \"nqr\",\n \"code\": codes.nqr,\n \"contacts\": [],\n \"expanded\": false,\n \"visible\": true\n }, {\n \"name\": translations[\"XGUARD_RESPONSE_AREAS_POLICE_REGION\"],\n \"color\": \"pd\",\n \"code\": codes.pd,\n \"contacts\": [],\n \"expanded\": false,\n \"visible\": true\n }, {\n \"name\": translations[\"XGUARD_RESPONSE_AREAS_BACKUP\"],\n \"color\": \"pd\",\n \"code\": codes.bz,\n \"contacts\": [],\n \"expanded\": false,\n \"visible\": false\n }\n ];\n smarttrackerService.isLoggedInDelayed().then(function () {\n leafletData.getMap(\"amMap\").then(function (otherMap) {\n map = otherMap;\n $(window).width(function () {\n smallScreen();\n setMobileView();\n map.invalidateSize();\n $scope.autoCenter();\n });\n map.on('click', function (event) {\n $scope.selectedMarker = '';\n deselectSelectedMarker();\n });\n map.on('dragstart', function (event) {\n $scope.mapViewAltered = true;\n });\n notificationService.snooze();\n notificationService.ignore(\"alarm-\" + alarmID);\n\n mapService.loadOverlays(map);\n $scope.userID = smarttrackerService.getUserData().user.id;\n $scope.userResourceId = smarttrackerService.getUserData().user.resourceId;\n $scope.isServiceProvider = smarttrackerService.getUserData().flags.isServiceProvider;\n $scope.downloadAlarm();\n $scope.customerID = smarttrackerService.getCustomerId();\n\n });\n });\n });\n //$scope.alarm = contentCacheService.get(\"alarm\", 67523534);\n\n\n var isContactAllowed = function (asset, context) {\n var contactAllowed = true;\n var testValue = context == syntax.NQRTag ? syntax.allowContactNQR : syntax.allowContact;\n\n for (var i in asset.properties) {\n var prop = asset.properties[i];\n if (prop.code == testValue) {\n contactAllowed = prop.value != \"false\";\n break;\n }\n }\n return contactAllowed;\n }\n\n $scope.getPropertyValue = function (asset, code) {\n var value = false;\n if (asset && code) {\n for (var i in asset.properties) {\n var property = asset.properties[i];\n if (property.code == code) {\n value = property.value;\n break;\n }\n }\n }\n return value;\n }\n\n $scope.isNormalMode = false;\n var normalMode = function () {\n $scope.isNormalMode = true;\n\n if ($scope.alarm.asset && $scope.alarm.asset.lastValidPosition)\n addCustomerMarker($scope.alarm.asset);\n if ($scope.alarm && $scope.alarm.position)\n addAlarmMarker($scope.alarm);\n renderLineBetween();\n $scope.toggleMap();\n $timeout(function () {\n $scope.autoCenter();\n }, 1050);\n }\n\n makeNamedIcon = function (name, icon, color) {\n if (!color) {\n color = \"#31708f\";\n }\n if (!icon) {\n icon = \"glyphicon glyphicon-map-marker\";\n }\n var div_icon = {\n type: 'div',\n iconAnchor: [18, 36 - 8], //these numbers come from the fact that we use an icon 36x36 and the leaflet positions this with its top-felt corner. Thus I shift so the the nidle of the icon shows right point in map\n iconSize: [2000, 0],\n className: 'myleaflet-div-icon',\n //html: '' + name + '',\n html: '' + name + '',\n popupAnchor: [0, 0]\n };\n\n\n return div_icon;\n }\n\n /* Map Commands*/\n var coreMarkers = [];\n $scope.securityGuardsVisible = false;\n\n var deselectSelectedMarker = function () {\n if (selectedMarker) {\n selectedMarker._icon.className = selectedMarker._icon.className.replace(\"selected\", \"\");\n }\n selectedMarker = false;\n }\n var selectedMarker = false;\n var addSelectedMarker = function (marker) {\n /*$scope.markers[marker.id] = {\n id: marker.id,\n lat: marker.lat,\n lng: marker.lng,\n icon: makeNamedIcon(marker.item.name, \"glyphicon glyphicon-map-marker\", \"DodgerBlue\"),//(item.logLevelFormatted === 'notification' ? 'success' : (item.logLevelFormatted === 'warning' ? 'warning' : 'danger' ) )),\n //message : \"message\",\n focus: false, //just add them on the map. not in focus\n draggable: false,\n 'item': marker.item,\n 'code': marker.code\n };*/\n if (selectedMarker) {\n deselectSelectedMarker();\n }\n selectedMarker = marker;\n selectedMarker._icon.className += \" selected\";\n }\n var addAlarmMarker = function (alarm) {\n addMarker(alarm, \"mdi mdi-bullseye\", \"#FF0000\", \"#e00000\", \"Alarm Position\", true, null, 18, 18);\n }\n var addQRMarker = function (asset) {\n addMarker(asset, \"mdi mdi-map-marker\", \"#22b573\", \"#1c925d\", asset.name, true, codes.qr);\n }\n\n var addCustomerMarker = function (asset) {\n if (!asset.positionIsFixed) {\n addMarker(asset, \"mdi mdi-map-marker\", \"#FF0000\", \"#e00000\", \"Current Position\", true, codes.customer);\n renderLineBetween();\n }\n }\n\n var addNQRMarker = function (asset) {\n addMarker(asset, \"mdi mdi-marker-check\", \"#0b788a\", \"#095e6d\", asset.name, false, codes.nqr, 15, 29);\n }\n\n var oms = false;\n var addMarker = function (item, icon, color, colorDark, text, core, code, iconAnchorX, iconAnchorY) {\n if (!$scope.slInit) {\n oms = new OverlappingMarkerSpiderfier(map);\n oms.addListener(\"click\", function (marker) {\n if (marker.code == codes.nqr || marker.code == codes.qr || marker.code == codes.customer) {\n\n var ra = getResponseAreaForCode(marker.code);\n if (ra.contacts.indexOf(marker.item) >= 2)\n ra.expanded = true;\n\n deselectSelectedMarker();\n addSelectedMarker(marker);\n\n $scope.selectedMarker = marker.item.id;\n $scope.selectedMarkerName = marker.id;\n }\n });\n $scope.slInit = true;\n }\n\n if (item && item.id && (item.lastValidPosition || item.position)) {\n var positionKey = item.position ? 'position' : 'lastValidPosition';\n /*$scope.markers[\"marker\" + item.id] = {\n id: \"marker\" + item.id,\n lat: item[positionKey].latitude,\n lng: item[positionKey].longitude,\n icon: makeNamedIcon(text, icon, (\"marker\" + item.id == $scope.selectedMarkerName ? \"DodgerBlue\" : color)),//(item.logLevelFormatted === 'notification' ? 'success' : (item.logLevelFormatted === 'warning' ? 'warning' : 'danger' ) )),\n //message : \"message\",\n focus: false, //just add them on the map. not in focus\n draggable: false,\n 'item': item,\n 'code': code\n };*/\n if (oms) {\n L.Icon.Default.imagePath = 'css/images';\n\n if (!iconAnchorX || !iconAnchorY) {\n iconAnchorX = 18;\n iconAnchorY = 32;\n }\n\n var micon = L.divIcon({\n type: 'div',\n iconAnchor: [iconAnchorX, iconAnchorY],\n className: 'myleaflet-div-icon',\n html: '
    ' + text + '
    ',\n popupAnchor: [0, 0]\n });\n var markerId = \"marker\" + item.id;\n\n var marker = $scope.markers[markerId];\n var loc = new L.LatLng(item[positionKey].latitude, item[positionKey].longitude);\n if (marker)  {\n oms.unspiderfy();\n try {\n marker.setLatLng(loc);\n } catch (err) {\n console.log(err);\n }\n } else {\n marker = new L.Marker(loc, {\n icon: micon,\n riseOnHover: true\n });\n map.addLayer(marker);\n oms.addMarker(marker);\n marker.item = item;\n marker.code = code;\n marker.id = markerId;\n marker.iconCode = micon;\n // marker.on('mouseover', function (e){\n // console.log(this);\n // });\n $scope.markers[markerId] = marker;\n }\n }\n\n if (core && coreMarkers.indexOf(\"marker\" + item.id) < 0) {\n coreMarkers.push(\"marker\" + item.id);\n }\n }\n\n }\n\n var clearMarkersForCode = function (code) {\n var markers = {};\n for (var i in $scope.markers) {\n if (i.indexOf(code) != 0) {\n markers[i] = $scope.markers[i];\n }\n }\n $scope.markers = markers;\n }\n\n var addPath = function (name, path) {\n var p = $scope.paths;\n $scope.paths = {};\n for (var i in p) {\n $scope.paths[i] = p[i];\n }\n $scope.paths[name] = path;\n }\n\n var renderLineBetween = function () {\n //if posisjon ulikif()\n if (!$scope.alarm || !$scope.alarm.position || !$scope.alarm.asset || !$scope.alarm.asset.lastValidPosition)\n return;\n var latlngs = [{\n 'lat': $scope.alarm.position.latitude,\n 'lng': $scope.alarm.position.longitude\n }, {\n 'lat': $scope.alarm.asset.lastValidPosition.latitude,\n 'lng': $scope.alarm.asset.lastValidPosition.longitude\n }];\n addPath(\"polyline\", {\n type: \"polyline\",\n color: 'red',\n latlngs: latlngs,\n dashArray: \"5,5\",\n weight: 2\n });\n }\n\n $scope.initialCenterSet = false;\n\n $scope.setCenter = function (newCenter) {\n console.log(\"SetCenter\", newCenter);\n map.setView($scope.mapData.center = new L.LatLng(newCenter.lat, newCenter.lng), newCenter.zoom);\n $scope.mapData.center.lat = newCenter.lat;\n $scope.mapData.center.lng = newCenter.lng;\n\n if (newCenter.zoom) {\n $scope.mapData.center.zoom = newCenter.zoom;\n }\n };\n\n $scope.centerOnItem = function (item) {\n console.log(\"center on item\", item);\n if (item && item.position && item.position.location && item.position.location.locationId) {\n $scope.mapMode.indoor = true;\n $scope.indoorViewer.location = item.position.location.locationId;\n } else if (item && item.position && item.position.valid) {\n $scope.mapMode.indoor = false;\n var newcenter = {\n lat: item.position.latitude,\n lng: item.position.longitude\n };\n\n $scope.setCenter(newcenter);\n }\n };\n\n $scope.toggleMap = function () {\n $scope.mapVisible = !$scope.mapVisible;\n if ($scope.mapVisible) {\n if (!mapInitiated) {\n mapInitiated = true;\n $scope.autoCenter();\n $scope.mapViewAltered = false;\n }\n $timeout(function () {\n map.invalidateSize();\n }, 1050);\n }\n }\n\n $scope.zoomNQR = function () {\n $scope.securityGuardsVisible = true;\n $scope.autoCenter();\n }\n\n $scope.zoomCore = function () {\n\n $scope.securityGuardsVisible = false;\n $scope.autoCenter();\n $scope.mapViewAltered = false;\n }\n\n $scope.autoCenter = function () {\n var activeMarkersPoints = [];\n\n if ($scope.securityGuardsVisible) {\n for (var m in $scope.markers) {\n var item = $scope.markers[m];\n if (item && item.getLatLng()) {\n activeMarkersPoints.push(item.getLatLng());\n }\n }\n } else {\n for (var i in coreMarkers) {\n var item = $scope.markers[coreMarkers[i]];\n if (item && item.getLatLng()) {\n activeMarkersPoints.push(item.getLatLng());\n }\n }\n }\n\n var bounds = new L.latLngBounds(activeMarkersPoints);\n\n if (activeMarkersPoints.length > 0) {\n $timeout(function () {\n map.fitBounds(bounds, {\n padding: [50, 50]\n });\n }, 310);\n }\n };\n\n /*Map Commands*/\n\n var calculateDistance = function (pos1, pos2) {\n var lat1 = pos1.latitude;\n var lat2 = pos2.latitude;\n var lon1 = pos1.longitude;\n var lon2 = pos2.longitude;\n\n var R = 6371e3; // metres\n var φ1 = toRadians(lat1);\n var φ2 = toRadians(lat2);\n var Δφ = toRadians(lat2 - lat1);\n var Δλ = toRadians(lon2 - lon1);\n\n var a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +\n Math.cos(φ1) * Math.cos(φ2) *\n Math.sin(Δλ / 2) * Math.sin(Δλ / 2);\n var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\n var d = R * c;\n return d;\n }\n\n var toRadians = function (deg) {\n return deg * Math.PI / 180.0;\n }\n\n var getDistanceText = function (distance) {\n if (distance > 100) {\n return (Math.round(distance / 100) / 10) + \" km\";\n } else return (Math.round(distance * 10) / 10) + \" m\";\n }\n\n function comparePriority(a, b) {\n return a.priority == b.priority ? 0 : a.priority < b.priority ? -1 : 1;\n }\n\n $scope.commentsMeta = {};\n /** Registers a comment as an event, meta is expandable info in the comment. additionalInfo is labels on comment (*/\n $scope.registerEvent = function (eventText, meta, additionalInfo, editable) {\n\n if ($scope.alarm.ackedBy) return;\n\n socketioService.socket.emit('alarms/'+$scope.alarm.id+'/chat', {\n type: 'user',\n text: eventText,\n notification: {\n title: $scope.alarm.name +' '+$scope.alarm.asset.name,\n }\n });\n\n }\n\n $scope.expandedComment = false;\n $scope.expandComment = function (id) {\n if ($scope.expandedComment == id)\n $scope.expandedComment = false;\n else\n $scope.expandedComment = id;\n }\n\n var eventCommentDelim = \"#$%#$%\";\n\n\n\n $scope.addEditCommentEvent = function (comment, commentText) {\n\n if (typeof commentText === 'undefined') {\n commentText = false;\n }\n\n $translate([\"XGUARD_COMMENT_DIALOG_ADD_TITLE\", \"XGUARD_COMMENT_DIALOG_EDIT_TITLE\", \"XGUARD_COMMENT_DIALOG_EDIT_CONTENT\",\n \"XGUARD_COMMENT_DIALOG_ADD_CONTENT\", \"XGUARD_COMMENT_DIALOG_EDIT_OK_BUTTON\", \"XGUARD_COMMENT_DIALOG_ADD_OK_BUTTON\",\n \"XGUARD_COMMENT_DIALOG_PLACEHOLDER\"\n ]).then(function (data) {\n\n if (comment && comment.name != \"editable\") {\n return;\n }\n var promise = dialogService.prompt(\n comment ? data[\"XGUARD_COMMENT_DIALOG_EDIT_TITLE\"] : data[\"XGUARD_COMMENT_DIALOG_ADD_TITLE\"],\n comment ? data[\"XGUARD_COMMENT_DIALOG_EDIT_CONTENT\"] : data[\"XGUARD_COMMENT_DIALOG_ADD_CONTENT\"], {\n okButtonText: comment ? data[\"XGUARD_COMMENT_DIALOG_EDIT_OK_BUTTON\"] : data[\"XGUARD_COMMENT_DIALOG_ADD_OK_BUTTON\"],\n multiline: true,\n promptText: comment ? comment.text : '',\n placeHolder: data[\"XGUARD_COMMENT_DIALOG_PLACEHOLDER\"]\n })\n .then(function (data) {\n var text = data.promptText;\n \n socketioService.socket.emit('alarms/'+$scope.alarm.id+'/chat', {\n type: 'user',\n text: text,\n notification: {\n title: $scope.alarm.name +' '+$scope.alarm.asset.name,\n }\n });\n\n },\n function (data) {\n //Cancelled\n });\n });\n }\n\n /** Helper functions*/\n $scope.isIndoor = function (item) {\n if (item.position) { // alarma\n return item.position.source && item.position.source.type == \"beacon\";\n } else {\n return item.lastValidPosition && item.lastValidPosition.source && item.lastValidPosition.source.type == \"beacon\";\n }\n }\n\n $scope.isInZone = function (item, zone) {\n\n if (zone && zone.id && (item.insideZones || (item.position && item.position.insideZones))) {\n var zones = item.insideZones ? item.insideZones : item.position.insideZones;\n for (var i in zones) {\n if (zones[i].id == zone.id)\n return true;\n }\n }\n return false;\n }\n\n $scope.isGuardsVisible = function () {\n var nqr = getResponseAreaForCode(codes.nqr);\n return $scope.alarm && $scope.alarm.asset && nqr.visible && nqr.contacts.length > 0;\n }\n\n // $scope.getIconColor = function(item){\n // var clazz = 'badAccuracy';\n // var accuracy = item.position?item.position.accuracy : item.lastValidPosition.accuracy;\n // if($scope.isIndoor(item) || (accuracy>0&&accuracy<=15))\n // clazz = 'goodAccuracy';\n // else if(accuracy>15&&accuracy<=40)\n // clazz = 'medAccuracy';\n // return clazz;\n // }\n\n // $scope.getTimeColor = function(){\n // var clazz = 'badAccuracy';\n // if($scope.alarm){\n // var alarmDate = new Date($scope.alarm.dateCreated)\n // var now = new Date();\n // var diff = now - alarmDate;\n // if(diff < 901*1000){\n // clazz = 'goodAccuracy';\n // } else if(diff < 3900 * 1000) {\n // clazz = 'medAccuracy';\n // }\n // }\n // return clazz;\n // }\n\n $scope.timeString = \"\";\n var getTimeString = function () {\n\n if ($scope.alarm && $scope.translations) {\n\n var time = moment.tz($scope.alarm.dateCreated, \"YYYY-MM-DDTHH:mm:ss.SSS\", \"UTC\").toDate();\n var diff = Math.floor((new Date() - time) / 1000);\n\n if (diff < 86400) {\n var hours = Math.floor(diff / 3600);\n diff = diff = Math.floor(diff % 3600);\n var minutes = Math.floor(diff / 60);\n\n $scope.timeString = $scope.translations.timeTemplate.toString().replace(\"\", hours > 0 ? hours + (hours > 1 ? \" \" + $scope.translations.hours + \" \" : \" \" + $scope.translations.hour + \" \") : \"\")\n .replace(\"\", minutes >= 0 ? (minutes + (minutes == 1 ? \" \" + $scope.translations.minute + \" \" : \" \" + $scope.translations.minutes + \" \")) : \"\");\n\n $scope.timeStringDate = $scope.alarm.dateCreatedFormatted;\n\n } else {\n $scope.timeString = $scope.alarm.dateCreatedFormatted;\n $scope.timeStringDate = '';\n }\n\n }\n };\n\n var getResponseAreaTextForZone = function (zone) {\n return $translate(\"XGUARD_RESPONSE_AREAS_RESPONSE_AREA\", {\n zoneName: zone.name\n });\n };\n\n /**End Helper functions*/\n\n $scope.$on('$locationChangeStart', function( event, next, current ) {\n\n if(current.match(new RegExp('alarm-manager-detail\\/'+$scope.alarm.id+'$')) !== null) {\n\n socketioService.unsubscribe('alarms/'+$scope.alarm.id+'/chat');\n socketioService.unsubscribe('asset/'+alarm.asset.id);\n\n }\n\n });\n\n var setupChat = function(){\n\n $scope.getComments();\n\n // connect to socket\n socketioService.subscribe('alarms/'+$scope.alarm.id+'/chat', function(message){\n\n console.log('new chat message', message);\n\n parseMessage(message);\n\n $scope.chat = [].concat([message], $scope.chat);\n\n });\n\n }\n\n var parseMessage = function(message) {\n\n // fix timestamp\n var date = moment.tz(message.dateCreated, \"YYYY-MM-DDTHH:mm:ss.SSS\", \"UTC\").toDate();\n message.dateCreated = new Date(date).toLocaleString('nl-NL');\n\n }\n\n $scope.getComments = function(offsetId) { \n\n console.log('Getting chat messages with offsetId =', offsetId);\n\n var offset = '';\n if(typeof offsetId !== 'undefined') {\n\n offset = 'offsetId='+offsetId;\n\n }\n\n deploymentApiService.get('/v1/alarms/chat/'+$scope.alarm.id+'?limit=50&order=desc&'+offset).then(function(response) {\n\n // mutate\n for(var i = 0; i < response.data.result.length; i++) {\n\n var message = response.data.result[i];\n\n parseMessage(message);\n\n }\n\n // check if we need to fetch more\n if(response.data.result.length > 0) {\n\n // add earlier results\n $scope.chat = [].concat($scope.chat || [], response.data.result);\n\n // get more\n $scope.getComments(response.data.result[response.data.result.length - 1].id);\n\n } else {\n\n $scope.chat = [].concat($scope.chat || [], []);\n\n }\n\n });\n\n }\n\n $scope.refreshEvents = function (offset) {\n\n return;\n\n /*\n var limit = 50;\n\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/comment?filter:relatedToAlarm=' + $scope.alarm.id + '&sort=dateCreated&order=desc&max=' + limit + '&offset=' + offset + '&crossAccount=true&select=@', {\n onErrorDoNotRedirect: true\n }).then(function (response) {\n if (offset == 0) $scope.events = [];\n if ($scope.events && $scope.events.length > 0) {\n $scope.events = $scope.events.concat(\n response.data.result\n );\n } else if (response.data.result != undefined) {\n $scope.events = response.data.result;\n console.log(\"refreshEvents > Succesfull\")\n } else {\n console.log(\"Error: No response data available\");\n console.log(\"refreshEvents > FAILED\");\n }\n if (response.data.result.length == 50) {\n $scope.refreshEvents(offset + limit)\n } else {\n $scope.events.sort(function (a, b) {\n return new Date(b.dateCreated) - new Date(a.dateCreated)\n });\n if ($scope.access['alarm']['put']) {\n checkNotificationStatusForComments();\n }\n }\n });\n */\n\n // console.log(\"SmartTracker Reequest\" + 1202 + \" Downloading comments\");\n }\n\n /*$scope.googleMapsBackup = function (item) {\n $window.open('http://maps.google.com/maps?q=' + item.lastValidPosition.latitude + ',' + item.lastValidPosition.longitude);\n }*/\n\n $scope.googleMaps = function (item) {\n\n var lat = item.position.latitude;\n var lng = item.position.longitude;\n\n if ((navigator.platform.indexOf(\"iPhone\") !== -1) || (navigator.platform.indexOf(\"iPod\") !== -1)) {\n function iOSversion() {\n if (/iP(hone|od|ad)/.test(navigator.platform)) {\n // supports iOS 2.0 and later: \n var v = (navigator.appVersion).match(/OS (\\d+)_(\\d+)_?(\\d+)?/);\n return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)];\n }\n }\n\n var ver = iOSversion() || [0];\n\n if (ver[0] >= 6) {\n protocol = 'maps://';\n } else {\n protocol = 'http://';\n\n }\n window.location = protocol + 'maps.apple.com/maps?daddr=' + lat + ',' + lng + '&ll=';\n } else {\n window.open('http://maps.google.com?daddr=' + lat + ',' + lng + '&ll=');\n }\n };\n\n var getTableRow = function (col1, col2, addHeader, headerOnly) {\n\n var header = '';\n if(addHeader !== false) {\n\n header = '

    '+col1+'

    ';\n\n }\n\n if(headerOnly === true) {\n\n return header + col2;\n\n }\n\n return header + '
    '+col2+'
    ';\n }\n\n $scope.getTableRow = getTableRow;\n\n $scope.getGoogleMapsLink = function (lat, lon) {\n return \"http://maps.google.com/maps?q=\" + lat + \"%2C\" + lon;\n }\n\n $scope.getAddressHTML = function(position){\n\n var link = \"http://maps.google.com/maps?q=\" + position.latitude + \"%2C\" + position.longitude;\n var button = '
    Open via Google Maps
    ';\n var result = '
    '+position.address+'
    '+button+'
    ';\n\n console.log('debugresult', result);\n\n return result;\n\n }\n\n $scope.acknowledgeText = \"\";\n $scope.acknowledgeAlarm = function (comment, surveyResult) {\n\n var acknowledge = {\n \"comment\": comment,\n \"ackedBy\": {\n \"id\": smarttrackerService.getUserData().user.id\n },\n \"meta\": {\n \"responseAreas\": $scope.responseAreas,\n \"comments\": $scope.events,\n \"asset\": $scope.alarm.asset,\n \"zone\": $scope.alarm.zone,\n \"order\": $scope.order,\n \"actionStatus\": $scope.actionStatus,\n \"commentsMeta\": $scope.commentsMeta,\n \"notificationStatus\": $scope.notificationStatus,\n \"surveyResult\": surveyResult,\n }\n };\n\n\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + \"/alarm/\" + $scope.alarm.id, acknowledge).then(function (response) {\n var alarm = response.data.result[0];\n if (alarm) {\n $scope.alarm.ackedBy = alarm.ackedBy;\n $scope.alarm.comment = alarm.comment;\n\n if (typeof $scope.alarm.comment === 'string') {\n $scope.alarm.comment = $scope.alarm.comment.replace(/\\*\\*([\\s\\S]+?)\\*\\*/gm, '$1');\n }\n\n sendSurveyMail($scope.alarm.id, acknowledge, surveyResult, $scope.contactLists);\n\n getResponseAreaForCode(codes.nqr).visible = false;\n if (killAlarmUpdater){\n killAlarmUpdater();\n }\n\n }\n });\n\n $scope.downloadAlarm();\n \n }\n\n var sendSurveyMail = function (alarmId, acknowledgeData, surveyResult, contactLists) {\n\n $http.post('https://server1.microservices.x-guard.nl/survey/follow-up', {\n alarmId: alarmId,\n data: acknowledgeData,\n surveyResult: surveyResult,\n contactLists: contactLists,\n });\n\n }\n\n var getActionStatusKey = function (contact) {\n return contact.name + \"\" + contact.phone + contact.email;\n }\n\n $scope.getActionStatus = function (contact) {\n var name = getActionStatusKey(contact);\n return $scope.actionStatus[name];\n }\n\n $scope.updateActionStatus = function (contact, status) {\n var name = getActionStatusKey(contact);\n if ($scope.actionStatus.hasOwnProperty(name) && $scope.actionStatus[name] == status) {\n delete $scope.actionStatus[name];\n } else {\n $scope.actionStatus[name] = status;\n }\n\n var meta = $scope.alarm.meta;\n meta[\"actionStatus\"] = $scope.actionStatus;\n\n //var labels = $scope.alarm.labels;\n //labels[\"ALARM_CENTER_ACTIONS\"] = {\"value\":JSON.stringify($scope.actionStatus)};\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + \"/alarm/\" + $scope.alarm.id, {\n \"meta\": meta\n });\n updateBZVisibility();\n // put update\n }\n\n\n $scope.startSurvey = function () {\n\n var modalInstance = $modal.open({\n templateUrl: 'modules/alarm-screen-xguard/alarm-screen-xguard-survey.html',\n controller: function ($scope, $modalInstance, alarm, outerScope) {\n\n console.log('Survey scope alarm', alarm);\n\n\n // translation table\n var translations = {\n audioExpected: 'SURVEY_RESULT_AUDIO_EXPECTED',\n audioQualityOk: 'SURVEY_RESULT_AUDIO_QUALITY_OK',\n audioQualityNotOkReason: 'SURVEY_RESULT_AUDIO_QUALITY_NOT_OK_REASON',\n responseSettingsOk: 'SURVEY_RESULT_REPSONSE_SETTINGS_OK',\n responseSettingsComment: 'SURVEY_RESULT_REPSONSE_SETTINGS_NOT_OK_REASON',\n positionOk: 'SURVEY_RESULT_POSITION_OK',\n locationQualityNotOkReason: 'SURVEY_RESULT_POSITION_NOT_OK_REASON',\n customerHappy: 'SURVEY_RESULT_CUSTOMER_HAPPY',\n acknowledgementComment: 'SURVEY_RESULT_ACK_COMMENT'\n }\n\n // replacements\n var replacements = {\n 'true': 'Yes',\n 'false': 'No',\n '2': 'Unknown',\n '3': 'Not applicable',\n '0': 'No',\n '1': 'Yes',\n 'undefined': 'Left blank',\n }\n\n var possibleConstants = ['true', 'false', '3', '2', '0', '1', 'undefined'];\n var logdataReplacements = {\n 'true': 1,\n 'false': 0,\n '3': -2,\n '2': -1,\n '0': 0,\n '1': 1,\n 'undefined': -1,\n }\n\n var translateArray = ['SURVEY_BUTTON_YES', 'SURVEY_BUTTON_NO', 'SURVEY_BUTTON_NA', 'SURVEY_BUTTON_UNKNOWN', 'SURVEY_BUTTON_NO', 'SURVEY_BUTTON_YES', 'SURVEY_UNDEFINED'];\n for (var i in translations) {\n translateArray.push(translations[i]);\n }\n $translate(translateArray).then(function (transData) {\n\n console.log('survey', 'transdata', transData)\n\n // overwrite\n translations = {\n audioExpected: transData['SURVEY_RESULT_AUDIO_EXPECTED'],\n audioQualityOk: transData['SURVEY_RESULT_AUDIO_QUALITY_OK'],\n audioQualityNotOkReason: transData['SURVEY_RESULT_AUDIO_QUALITY_NOT_OK_REASON'],\n responseSettingsOk: transData['SURVEY_RESULT_REPSONSE_SETTINGS_OK'],\n responseSettingsComment: transData['SURVEY_RESULT_REPSONSE_SETTINGS_NOT_OK_REASON'],\n positionOk: transData['SURVEY_RESULT_POSITION_OK'],\n locationQualityNotOkReason: transData['SURVEY_RESULT_POSITION_NOT_OK_REASON'],\n customerHappy: transData['SURVEY_RESULT_CUSTOMER_HAPPY'],\n acknowledgementComment: transData['SURVEY_RESULT_ACK_COMMENT']\n }\n\n // replacements\n replacements = {\n 'true': transData['SURVEY_BUTTON_YES'],\n 'false': transData['SURVEY_BUTTON_NO'],\n '3': transData['SURVEY_BUTTON_NA'],\n '2': transData['SURVEY_BUTTON_UNKNOWN'],\n '0': transData['SURVEY_BUTTON_NO'],\n '1': transData['SURVEY_BUTTON_YES'],\n 'undefined': transData['SURVEY_UNDEFINED'],\n }\n\n })\n\n // init\n $scope.surveyDone = false;\n $scope.step = 0;\n $scope.lastStep = 8;\n\n $scope.percentage = 0;\n $scope.progressStyle = {\n width: '0%'\n };\n\n // init local\n var result = {};\n\n // set step function\n $scope.setStep = function (step, stepResult) {\n\n // loop and push result\n for (var i in stepResult) {\n\n if (possibleConstants.indexOf(stepResult[i] + '') !== -1) {\n\n // save the result\n result[i] = '%' + stepResult[i] + '%';\n\n } else {\n\n // save the result\n result[i] = stepResult[i];\n\n }\n\n }\n\n console.log('SurveyResult', result);\n\n // check if last step\n if (step > $scope.lastStep) {\n\n // we\n // are\n // done\n $scope.ok();\n\n } else {\n\n // set\n $scope.step = step;\n\n // progress\n var percentage = (($scope.step / $scope.lastStep) * 100);\n $scope.progressStyle = {\n marginTop: 0,\n width: percentage + '%'\n };\n $scope.percentage = Math.round(percentage);\n\n }\n\n }\n\n var beforeTranslations = {};\n $scope.setTranslatedStep = function (step, key, value) {\n\n // translate\n $translate(['' + value]).then(function (data) {\n\n // set\n var object = {};\n object[key] = data[value];\n\n beforeTranslations[data[value]] = value;\n\n // proxy to setStep\n $scope.setStep(step, object);\n\n });\n\n }\n\n // ok\n $scope.ok = function () {\n\n // loop all results\n var message = \"\";\n var originalResult = angular.copy(result);\n for (var i in result) {\n\n // loop replacements\n for (var j in replacements) {\n\n result[i] = (result[i] + '').replace(new RegExp('%' + j + '%', 'gi'), replacements[j]);\n\n }\n\n message += \"**\" + translations[i] + \"**\\n\" + result[i] + \"\\n\\n\";\n\n }\n\n // logdata\n for (var i in originalResult) {\n\n // loop replacements\n for (var j in logdataReplacements) {\n\n originalResult[i] = (originalResult[i] + '').replace(new RegExp(j, 'gi'), logdataReplacements[j]);\n\n }\n\n for (var k in beforeTranslations) {\n\n originalResult[i] = (originalResult[i] + '').replace(k, beforeTranslations[k]);\n\n }\n\n }\n\n originalResult.alarmId = alarmID;\n originalResult.customerId = smarttrackerService.getCustomerId();\n\n try {\n\n originalResult.LocationAccuracy = alarm.position ? alarm.position.accuracy : alarm.lastValidPosition.accuracy;\n\n }catch(e){\n\n originalResult.LocationAccuracy = -1;\n\n }\n\n originalResult.CreatedDate = alarm.dateCreated + 'Z';\n originalResult.AcknowledgeDate = new Date().toISOString();\n originalResult.AlarmSeverity = alarm.logLevelFormatted;\n originalResult.AlarmText = alarm.name;\n\n originalResult.IsAckedByAlarmCenter = outerScope.isAlarmCenter ? 1 : 0;\n\n originalResult.CommentCount = outerScope.events && outerScope.events.length || 0;\n originalResult.FirstCommentDate = outerScope.events && ((outerScope.events.length > 0) ? (outerScope.events[outerScope.events.length - 1].dateCreated + 'Z') : -1) || -1;\n originalResult.HasExternalId = alarm.asset && alarm.asset.externalId && 1 || 0;\n originalResult.PageOpenedDate = PageOpenedDate;\n\n // done\n $modalInstance.close({\n message: message,\n surveyResult: originalResult,\n });\n\n $http.post('https://server1.microservices.x-guard.nl/survey', originalResult);\n\n }\n\n // cancel\n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n\n\n },\n size: \"lg\",\n resolve: {\n alarm: function () {\n return $scope.alarm;\n },\n outerScope: function () {\n return $scope;\n },\n }\n });\n\n modalInstance.result.then(function (data) {\n\n // be done with it\n $scope.acknowledgeAlarm(data.message, data.surveyResult);\n\n });\n\n\n }\n\n\n $scope.trimPhoneNumber = function (nbr) {\n return nbr ? nbr.replace(/\\+/, \"00\").replace(/\\s/g, \"\") : nbr;\n }\n\n $scope.sendEmail = function (name, mail) {\n\n var md_content = \"\";\n\n\n $translate([\"XGUARD_SEND_SMS_DIALOG.EXTERNAL_ID\", \"XGUARD_SMS_SPLASH_TITLE\", \"XGUARD_SMS_SPLASH_CONTENT\",\n \"XGUARD_SMS_ALARM_POSITION\", \"XGUARD_SMS_GOOGLE_MAPS_LINK\", \"XGUARD_SMS_ALARM_POSITION_RECEIVED\", \"XGUARD_SMS_RULE\",\n \"XGUARD_SMS_ASSET\", \"XGUARD_SMS_NAME\", \"XGUARD_SMS_EXTERNAL_ID\", \"XGUARD_SMS_LATEST_POSITION_UPDATE\",\n \"XGUARD_SMS_CURRENT_POSITION\", \"XGUARD_SMS_INSIDE_ZONES\", \"XGUARD_SMS_TYPE\",\n \"XGUARD_SMS_PHONE\", \"XGUARD_SMS_SMS\", \"XGUARD_SMS_EMAIL\", \"XGUARD_SMS_SMS_EVENT_TEXT\", \"XGUARD_SMS_SMS_FAILED_EVENT_TEXT\", \"XGUARD_SEND_MAIL_DIALOG_CONTENT\", \"XGUARD_SEND_MAIL_SUBJECT\",\n \"XGUARD_SEND_MAIL_EVENT_TEXT\", \"XGUARD_SEND_MAIL_FAILED_TEXT\", \"XGUARD_USER_TITLE\", \"ALARM_MANAGER_FILTER_TRIGGERING_ASSET\", \"MESSAGE_SERVICE_EMAIL_ASSET_IMAGE\"\n ], {\n externalId: $scope.alarm.asset ? $scope.alarm.asset.externalId : \"\",\n contact: name,\n name: name,\n email: mail\n }).then(function (langData) {\n var asset = $scope.alarm.asset;\n\n\n\n var properties = \"\";\n angular.forEach(asset.properties, function (prop) {\n properties += getTableRow()\n });\n var ra = getResponseAreaForCode(codes.ra);\n console.log(\"Message Data: \", ra.messageData);\n var md = ra.messageData;\n var messageComponents = {};\n if (!md || (md.includes('email_position') || md.includes('email_links') || md.includes('email_positionTime') || md.includes('email_rule'))) {\n messageComponents.asset = {};\n messageComponents.alarm = {};\n var components = {\n 'email_position': {\n key: 'position',\n value: {\n text: getTableRow(langData['XGUARD_SMS_ALARM_POSITION'], $scope.getAddressHTML($scope.alarm.position), true, true),\n label: langData['XGUARD_SMS_ALARM_POSITION'],\n selected: true\n }\n },\n // 'email_links': {\n // key: 'map_link',\n // value: $scope.alarm.position ? {\n // text: getTableRow(\"Google Maps (\"+langData['XGUARD_SMS_ALARM_POSITION']+\"): \", $scope.getGoogleMapsEmailButton($scope.alarm.position.latitude, $scope.alarm.position.longitude)),\n // selected: true\n // } : false\n // },\n // 'email_positionTime': {\n // key: 'received',\n // value: $scope.alarm.position ? {\n // text: getTableRow(langData[\"XGUARD_SMS_ALARM_POSITION_RECEIVED\"] + \":\", $scope.alarm.position.timestampFormatted),\n // selected: true\n // } : false\n // },\n // 'email_rule': {\n // key: 'rule',\n // value: $scope.alarm.rule ? {\n // text: (getTableRow(langData[\"XGUARD_SMS_RULE\"] + \":\", $scope.alarm.rule.name)),\n // selected: true\n // } : false\n // },\n };\n angular.forEach(components, function (content, component) {\n if ((!md || md.includes(component) && content.value)) {\n messageComponents.alarm[content.key] = content.value\n }\n });\n }\n\n messageComponents.additional = {};\n if ($scope.alarm.zone) {\n messageComponents.additional = {\n zone: {\n text: ($scope.alarm.zone ? getTableRow(langData[\"XGUARD_SMS_NAME\"], $scope.alarm.zone.name) : \"\"),\n selected: true\n }\n };\n }\n if (md && md.includes('email_links')) {\n messageComponents.additional['amlink'] = {\n text: getTableRow('More Info : ', 'Click Here'),\n selected: true\n }\n }\n\n\n\n var insideZones = \"\";\n if (asset) {\n if (asset.insideZones && asset.insideZones.length > 0) {\n insideZones += asset.insideZones[0].name;\n for (var i = 1; i < asset.insideZones.length; i++) {\n insideZones += \", \" + asset.insideZones[i].name;\n }\n }\n var propertiesString = \"

    Properties

    \";\n if (asset.properties) {\n angular.forEach(asset.properties, function (property) {\n propertiesString += getTableRow(property.name + \": \", property.value);\n });\n }\n\n var image = '';\n if(asset.image) {\n image = '\"FotoKlik om te vergroten';\n }\n\n var externalId = '';\n if(asset.externalId) {\n\n externalId = '
    referentie: '+asset.externalId+'
    ';\n\n }\n\n messageComponents.asset.name = {\n text: (!md || md.includes('email_name')) ? getTableRow(langData[\"XGUARD_USER_TITLE\"], \"

    \"+ asset.name+\"

    \" + externalId + image) : false,\n label: langData[\"XGUARD_USER_TITLE\"],\n selected: (!md || md.includes('email_name'))\n };\n\n // messageComponents.asset.position = {\n // text: (asset.lastValidPosition && (!md || md.includes('email_positionTime'))) ? getTableRow(langData[\"XGUARD_SMS_LATEST_POSITION_UPDATE\"] + \":\", asset.lastValidPosition.timestampFormatted) : false,\n // selected: (asset.lastValidPosition && (!md || md.includes('email_positionTime')))\n // };\n // messageComponents.asset.zones = {\n // text: (asset.insideZones && (!md || md.includes('email_position'))) ? getTableRow(langData[\"XGUARD_SMS_INSIDE_ZONES\"] + \":\", insideZones) : false,\n // selected: (asset.insideZones && (!md || md.includes('email_position')))\n // };\n // messageComponents.asset.type = {\n // text: ((asset.type && (!md || md.includes('email_type'))) ? getTableRow(langData[\"XGUARD_SMS_TYPE\"] + \":\", asset.type.name) : false),\n // selected: (asset.type && (!md || md.includes('email_type')))\n // };\n // messageComponents.asset.properties = {\n // text: (asset.properties && (!md || md.includes('email_properties'))) ? propertiesString : false,\n // selected: (asset.properties && (!md || md.includes('email_properties')))\n // };\n\n if(asset.lastValidPosition.latitude !== $scope.alarm.position.latitude || asset.lastValidPosition.longitude !== $scope.alarm.position.longitude){\n\n messageComponents.additional.address = {\n text: (asset.lastValidPosition && (!md || md.includes('email_position'))) ? getTableRow(langData[\"XGUARD_SMS_CURRENT_POSITION\"], $scope.getAddressHTML(asset.lastValidPosition), true, true) : false,\n label: langData[\"XGUARD_SMS_CURRENT_POSITION\"],\n selected: (asset.lastValidPosition && (!md || md.includes('email_position')))\n };\n\n // messageComponents.asset.map_link = {\n // text: (asset.lastValidPosition && (!md || md.includes('email_position'))) ? getTableRow(\"Google Maps (\"+langData['XGUARD_SMS_CURRENT_POSITION']+\"): \", $scope.getGoogleMapsEmailButton(asset.lastValidPosition.latitude, asset.lastValidPosition.longitude)) : false,\n // selected: (asset.lastValidPosition && (!md || md.includes('email_position')))\n // };\n\n }\n\n\n }\n\n\n var title = langData['XGUARD_SEND_MAIL_DIALOG_CONTENT'];\n var modalInstance = $modal.open({\n templateUrl: 'modules/alarm-screen-xguard/message-preview.html',\n controller: function ($scope, $modalInstance, messageComponents, title, alarmId, getTableRow) {\n $scope.messageComponents = messageComponents;\n $scope.customMessage = \"\";\n $scope.title = title;\n $scope.getTableRow = getTableRow;\n $scope.ok = function () {\n\n var message = '';\n\n // add custom message\n if($scope.customMessage.length > 0){\n\n message = getTableRow('Bericht van de centralist', $scope.customMessage);\n\n }\n\n message += '';\n angular.forEach($scope.messageComponents, function (value, key) {\n angular.forEach(value, function (value2, key2) {\n if (value2.selected) {\n message += value2.text;\n }\n });\n });\n \n message += \"
    Alarm ID: \"+alarmId+\"

    \";\n\n $modalInstance.close({\n message: message\n });\n };\n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n },\n size: \"lg\",\n resolve: {\n messageComponents: function () {\n return messageComponents;\n },\n title: function () {\n return title;\n },\n alarmId: function() {\n return $scope.alarm.id;\n },\n getTableRow: function(){\n return $scope.getTableRow;\n }\n }\n });\n\n modalInstance.result.then(function (data) {\n if (data.message) {\n var dialog = dialogService.wait(\"XGUARD_SEND_MAIL_SPLASH_TITLE\", \"XGUARD_SEND_MAIL_SPLASH_CONTENT\", {});\n\n const templateData = '
    \"X-Guard

    Alarmmelding

    U heeft een alarmmelding ontvangen

    In de onderstaande e-mail staat informatie over de maker van een alarm. Deze informatie is u toegezonden door een centralist.


    U kunt deze informatie gebruiken bij de opvolging van het alarm.

    %alarmBody%
    Deze e-mail kan niet worden beantwoord.
    x-guard.nl / +31 88 126 12 12 / info@x-guard.nl
    ';\n const mailBodyTemplated = templateData.replace('%alarmBody%', data.message);\n\n var mailBody = {\n \"to\": mail,\n \"subject\": langData['XGUARD_SEND_MAIL_SUBJECT'],\n \"message\": mailBodyTemplated\n };\n smarttrackerService.authPost(smarttrackerService.getCustomerId() + \"/mail/\", mailBody).then(function () {\n $scope.registerEvent(langData['XGUARD_SEND_MAIL_EVENT_TEXT']);\n dialog.close();\n }, function (response) {\n $scope.registerEvent(langData['XGUARD_SEND_MAIL_FAILED_TEXT'], data.message);\n dialog.close();\n });\n }\n });\n\n });\n }\n\n $scope.contactCalled = function (name) {\n // $translate.use(\"nl\");\n $translate(\"XGUARD_CONTACT_CALLED_EVENT_TEXT\", {\n contact: name\n }).then(function (data) {\n $scope.registerEvent(data);\n // $translate.use(\"en\");\n })\n }\n\n $scope.showContact = function(contact) {\n\n contact.showNumber = true;\n $scope.contactCalled(contact.name);\n\n }\n\n $scope.linkClicked = function (link) {\n $location.path(link);\n };\n\n $scope.sendSMS = function (contact) {\n var formatNumber = false;\n var number = contact.sms;\n try {\n formatNumber = $scope.trimPhoneNumber(number);\n } catch (e) {}\n if (!formatNumber) {\n alert(\"The number: \" + number + \" is not a valid phone number \" + formatNumber);\n return;\n }\n var name = contact.name;\n\n $translate([\"XGUARD_SEND_SMS_DIALOG.EXTERNAL_ID\", \"XGUARD_SMS_SPLASH_TITLE\", \"XGUARD_SMS_SPLASH_CONTENT\",\n \"XGUARD_SMS_ALARM_POSITION\", \"XGUARD_SMS_GOOGLE_MAPS_LINK\", \"XGUARD_SMS_ALARM_POSITION_RECEIVED\", \"XGUARD_SMS_RULE\",\n \"XGUARD_SMS_ASSET\", \"XGUARD_SMS_NAME\", \"XGUARD_SMS_EXTERNAL_ID\", \"XGUARD_SMS_LATEST_POSITION_UPDATE\",\n \"XGUARD_SMS_CURRENT_POSITION\", \"XGUARD_SMS_INSIDE_ZONES\", \"XGUARD_SMS_TYPE\",\n \"XGUARD_SMS_PHONE\", \"XGUARD_SMS_SMS\", \"XGUARD_SMS_EMAIL\", \"XGUARD_SMS_SMS_EVENT_TEXT\", \"XGUARD_SMS_SMS_FAILED_EVENT_TEXT\", \"XGUARD_SEND_SMS_DIALOG_CONTENT\"\n ], {\n externalId: $scope.alarm.asset ? $scope.alarm.asset.externalId : \"\",\n contact: name,\n name: name,\n number: number\n }).then(function (langData) {\n var asset = $scope.alarm.asset;\n var title = langData.XGUARD_SEND_SMS_DIALOG_CONTENT;\n var insideZones = \"\";\n if (asset && asset.insideZones && asset.insideZones.length > 0) {\n insideZones += asset.insideZones[0].name;\n for (var i = 1; i < asset.insideZones.length; i++) {\n insideZones += \", \" + asset.insideZones[i].name;\n }\n }\n // $scope.assetTitle = (langData[\"XGUARD_SMS_ASSET\"] + \"\\n\");\n var messageComponents = {\n asset: {\n name: {\n text: \"\\n\\n[\"+langData[\"XGUARD_SMS_NAME\"] + \"]\\n\" + asset.name,\n label: langData[\"XGUARD_SMS_NAME\"],\n selected: true\n },\n },\n alarm: {\n position: {\n text: \"\\n\\n[\"+langData[\"XGUARD_SMS_ALARM_POSITION\"] + \"]\\n\" + $scope.alarm.position.address,\n label: langData[\"XGUARD_SMS_ALARM_POSITION\"],\n selected: true\n },\n // map_link: {\n // text: langData[\"XGUARD_SMS_GOOGLE_MAPS_LINK\"] + \": \" + $scope.getGoogleMapsLink($scope.alarm.position.latitude, $scope.alarm.position.longitude) + \"\\n\",\n // selected: false\n // },\n // received: {\n // text: langData[\"XGUARD_SMS_ALARM_POSITION_RECEIVED\"] + \": \" + $scope.alarm.position.timestampFormatted + \"\\n\",\n // selected: false\n // },\n // rule: {\n // text: ($scope.alarm.rule ? langData[\"XGUARD_SMS_RULE\"] + \": \" + $scope.alarm.rule.name + \"\\n\" : \"\"),\n // selected: false\n // },\n },\n additional: {\n address: {\n text: \"\\n\\n[\"+langData[\"XGUARD_SMS_CURRENT_POSITION\"] + \"]\\n\" + asset.lastValidPosition.address,\n label: langData[\"XGUARD_SMS_CURRENT_POSITION\"],\n selected: true\n },\n }\n // externalId: {\n // text: langData[\"XGUARD_SMS_EXTERNAL_ID\"] + \": \" + asset.externalId + \"\\n\",\n // selected: false\n // },\n // position: {\n // text: langData[\"XGUARD_SMS_LATEST_POSITION_UPDATE\"] + \": \" + asset.lastValidPosition.timestampFormatted + \"\\n\",\n // selected: false\n // },\n // zones: {\n // text: langData[\"XGUARD_SMS_INSIDE_ZONES\"] + \": \" + insideZones + \"\\n\",\n // selected: false\n // },\n // type: {\n // text: (asset.type ? langData[\"XGUARD_SMS_TYPE\"] + \": \" + asset.type.name + \"\\n\" : ''),\n // selected: false\n // },\n // phone: {\n // text: (asset.phone ? langData[\"XGUARD_SMS_PHONE\"] + \": \" + asset.phone + \"\\n\" : \"\"),\n // selected: false\n // },\n // sms: {\n // text: (asset.sms ? langData[\"XGUARD_SMS_SMS\"] + \": \" + asset.sms + \"\\n\" : \"\"),\n // selected: false\n // },\n // email: {\n // text: (asset.email ? langData[\"XGUARD_SMS_EMAIL\"] + \": \" + asset.email + \"\\n\" : \"\"),\n // selected: false\n // },\n // map_link: {\n // text: langData[\"XGUARD_SMS_GOOGLE_MAPS_LINK\"] + \": \" + $scope.getGoogleMapsLink(asset.lastValidPosition.latitude, asset.lastValidPosition.longitude) + \"\\n\",\n // selected: false\n // }\n // },\n // additional: {\n // zone: {\n // text: ($scope.alarm.zone ? langData[\"XGUARD_SMS_NAME\"] + \": \" + $scope.alarm.zone.name : \"\"),\n // selected: false\n // },\n // amlink: {\n // text: 'More Info : ' + $state.href('secure.content.alarm-screen-xguard-detail', {}, {\n // absolute: true\n // }),\n // selected: false\n // }\n // }\n\n };\n\n\n var modalInstance = $modal.open({\n templateUrl: 'modules/alarm-screen-xguard/message-preview.html',\n controller: function ($scope, $modalInstance, messageComponents, title) {\n $scope.messageComponents = messageComponents;\n $scope.customMessage = \"\";\n $scope.title = title;\n $scope.openToggle = function (toggle) {\n $scope.openDialog = toggle;\n }\n\n $scope.closeToggle = function ($event) {\n var cl = $event.target.classList;\n if ($event.target.id != $scope.openDialog && !cl.contains(\"dropdownItem\")) {\n $scope.openDialog = \"\";\n }\n };\n\n $scope.setText = function(smsTemplateItem) {\n\n $scope.customMessage = smsTemplateItem.value;\n\n }\n\n $scope.smsTemplateList = [{\n label: 'Pand betreden veilig',\n value: 'Alles is veilig. U kunt het pand veilig betreden. Het alarm wordt voor u uitgeschakeld. Succes vandaag.',\n }, {\n label: 'Pand verlaten veilig',\n value: 'Er zijn geen bijzonderheden geconstateerd. U kunt de vestiging verlaten. Het alarm wordt aangezet en is binnen 2 minuten actief. Fijne avond.',\n }, {\n label: 'Bijzonderheden bij vestiging',\n value: 'Er zijn bijzonderheden rondom de vestiging. Er wordt nu contact met u opgenomen voor verdere instructies.',\n }, {\n label: '=================',\n value: '',\n }, {\n label: 'Opening - alarm al gedeactiveerd',\n value: 'Er is al een collega in de vestiging alarm is al gedeactiveerd.',\n }, {\n label: 'Opening - bijzonderheden',\n value: 'Er zijn bijzonderheden er wordt contact met u opgenomen voor instructies.',\n }, {\n label: 'Opening - geen bijzonderheden',\n value: 'De omgeving is gecontroleerd u kunt de vestiging betreden. Alarm is gedeactiveerd.',\n }, {\n label: '=================',\n value: '',\n }, {\n label: 'Sluiting - overbruggingen/storingen',\n value: 'Er zijn overbruggingen/storingen in de vestiging. Er wordt contact opgenomen of u krijgt een bericht voor instructies.',\n }, {\n label: 'Sluiting - brand- en sluitronde',\n value: 'Succes met brand- en sluitronde. Bij bijzonderheden druk op de rode knop om contact te maken met MCR.',\n }, {\n label: 'Sluiting - wacht op controle',\n value: 'U wilt de vestiging sluiten, wacht in de vestiging de omgeving wordt gecontroleerd.',\n }]\n\n\n $scope.ok = function () {\n var message = $scope.customMessage;\n // var assetTitle = {\n // text: (langData[\"XGUARD_SMS_ASSET\"] + \"\\n\"),\n // inserted: false\n // };\n angular.forEach($scope.messageComponents, function (value, key) {\n angular.forEach(value, function (value2, key2) {\n if (value2.selected) {\n // if (key == 'asset' && !assetTitle.inserted) {\n // message += assetTitle.text;\n // assetTitle.inserted = true;\n // }\n message += value2.text;\n }\n });\n })\n\n // add line break in end\n message += \"\\n\";\n\n // remove not needed line breaks\n message = message.replace(/^\\n+/, '');\n\n console.log(message);\n $modalInstance.close({\n message: message\n });\n };\n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n },\n size: \"lg\",\n resolve: {\n messageComponents: function () {\n return messageComponents;\n },\n title: function () {\n return title\n }\n }\n });\n\n modalInstance.result.then(function (data) {\n console.log(\"update alarm done\", data);\n if (data.message) {\n var dialog = dialogService.wait(\"XGUARD_SMS_SPLASH_TITLE\",\n \"XGUARD_SMS_SPLASH_CONTENT\", {});\n var smsBody = {\n \"to\": formatNumber,\n \"message\": data.message\n };\n\n smarttrackerService.authPost(smarttrackerService.getCustomerId() + \"/sms/\", smsBody).then(function () {\n $scope.registerEvent(langData[\"XGUARD_SMS_SMS_EVENT_TEXT\"], data.promptText);\n dialog.close();\n }, function (response) {\n $scope.registerEvent(langData[\"XGUARD_SMS_SMS_FAILED_EVENT_TEXT\"], data.promptText);\n dialog.close();\n });\n }\n });\n });\n }\n\n\n $scope.mapData = {\n center: {\n lat: 52.386617,\n lng: 5.799990,\n zoom: 8\n },\n defaults: {\n dragging: true,\n maxZoom: 21\n },\n events: {\n map: {\n enable: ['dragstart', 'zoomstart', 'click'],\n logic: 'emit'\n }\n }\n };\n\n var smallScreen = function () {\n if ($(this).width() > 1199) {\n $scope.screenSmallitems = false;\n } else {\n $scope.screenSmallitems = true;\n }\n };\n\n $scope.getIconColor = function (item) {\n var clazz = 'text-danger';\n var accuracy = item.position ? item.position.accuracy : item.lastValidPosition.accuracy;\n if ($scope.isIndoor(item) || (accuracy >= 0 && accuracy <= 15))\n clazz = 'text-success';\n else if (accuracy > 15 && accuracy <= 40)\n clazz = 'text-warning';\n return clazz;\n }\n\n $scope.getTimeColor = function () {\n var clazz = 'text-danger';\n if ($scope.alarm) {\n var alarmDate = moment.tz($scope.alarm.dateCreated, \"YYYY-MM-DDTHH:mm:ss.SSS\", \"UTC\").toDate();\n var now = new Date();\n var diff = now - alarmDate;\n if (diff < 901 * 1000) {\n clazz = 'text-success';\n } else if (diff < 3900 * 1000) {\n clazz = 'text-warning';\n }\n }\n return clazz;\n }\n\n var setMobileView = function () {\n if ($(this).width() < 768) {\n $scope.appFormat = true;\n } else {\n $scope.appFormat = false;\n }\n };\n\n $(window).width(function () {\n setMobileView();\n smallScreen();\n });\n\n $(window).resize(function () {\n setMobileView();\n smallScreen();\n });\n\n\n //$scope.currentTab = 1;\n\n //$scope.switchTabs = function (number) {\n // $scope.currentTab = number;\n //};\n\n\n var currentAlarm = function () {\n if (localStorage[\"currentAlarm\"] == $scope.alarm.id) {\n $scope.currentTab = localStorage[\"currentTab\"];\n console.log('localStorage unchanged: ' + localStorage[\"currentAlarm\"]);\n } else {\n $scope.currentTab = 1;\n localStorage[\"currentTab\"] = 1;\n localStorage[\"currentAlarm\"] = $scope.alarm.id;\n console.log('localStorage ID changed to: ' + localStorage[\"currentAlarm\"]);\n }\n };\n\n $scope.switchTabs = function (number) {\n $scope.currentTab = number;\n localStorage[\"currentTab\"] = number;\n };\n $scope.togglePinSidebarMap = function () {\n $scope.localPinSidebarMap = !$scope.localPinSidebarMap;\n localStorage[\"PinSidebarMap\"] = $scope.localPinSidebarMap;\n };\n\n $scope.localAlarmScreenMap = (localStorage[\"AlarmScreenMapSmall\"] === \"true\");\n $scope.toggleAlarmScreenMap = function () {\n $scope.localAlarmScreenMap = !$scope.localAlarmScreenMap;\n localStorage[\"AlarmScreenMapSmall\"] = $scope.localAlarmScreenMap;\n setTimeout(function () {\n $scope.initMap();\n }, 310);\n };\n\n $scope.initMap = function () {\n map.invalidateSize();\n $scope.autoCenter();\n };\n\n $scope.initMapDelayed = function () {\n setTimeout(function () {\n $scope.initMap();\n }, 50);\n };\n\n // Bind a color to the alarm\n $scope.getAlarmColor = function (item) {\n var color = 'text-danger';\n\n if (item.logLevelFormatted == null) {\n color = 'text-danger'\n } else {\n if (item.logLevelFormatted == 'notification') {\n color = 'text-success'\n } else if (item.logLevelFormatted == 'red_alert') {\n color = 'text-danger'\n } else if (item.logLevelFormatted == 'warning') {\n color = 'text-warning'\n }\n }\n return color\n };\n\n $scope.ZoomIn = function () {\n map.zoomIn();\n };\n\n $scope.ZoomOut = function () {\n map.zoomOut();\n };\n\n /** Notification related*/\n\n $scope.ns = {\n available: {\n status: \"available\",\n order: 0,\n messageKey: '',\n titleKey: 'ALARM_MANAGER_NOTIFICATION_TITLE_AVAILABLE'\n },\n unavailable: {\n status: \"unavailable\",\n order: 0,\n messageKey: '',\n titleKey: 'ALARM_MANAGER_NOTIFICATION_TITLE_UNAVAILABLE'\n },\n pending: {\n status: \"pending\",\n order: 1,\n messageKey: 'ALARM_MANAGER_NOTIFICATION_COMMENT_PENDING',\n titleKey: 'ALARM_MANAGER_NOTIFICATION_TITLE_PENDING'\n },\n responded: {\n status: \"responded\",\n order: 2,\n messageKey: 'ALARM_MANAGER_NOTIFICATION_COMMENT_FEEDBACK',\n titleKey: 'ALARM_MANAGER_NOTIFICATION_TITLE_RESPONDED'\n },\n confirmed: {\n status: \"confirmed\",\n order: 3,\n messageKey: 'ALARM_MANAGER_NOTIFICATION_COMMENT_CONFIRMED',\n titleKey: 'ALARM_MANAGER_NOTIFICATION_TITLE_CONFIRMED'\n },\n failed: {\n status: \"failed\",\n order: 5,\n messageKey: 'ALARM_MANAGER_NOTIFICATION_COMMENT_FAILED',\n titleKey: 'ALARM_MANAGER_NOTIFICATION_TITLE_FAILED'\n }\n };\n var nsLabelKeys = {\n event: 'notificationEvent',\n userID: 'notificationEventUserID',\n status: 'notificationEventState',\n contactID: 'notificationEventContactID'\n };\n\n $scope.notificationStatus = {};\n var notificationStatusKey = \"notificationStatus\";\n $scope.notificationStatus[\"ff4d8839-7e6c-4287-89be-760c073a2d7e\"] = {\n 'status': 'pending'\n };\n $scope.notificationStatus[\"2e137984-1f74-4cac-a835-45993881b09d\"] = {\n 'status': 'feedback'\n };\n\n $scope.sendNotifications = function () {\n if ($scope.anyAvailablePush) {\n var validAccess = $scope.access['sendNotification']['post'] && $scope.access['alarm']['put'];\n if (!validAccess) return;\n console.log(\"Trying to send push\");\n var idString = \"\";\n var qrs = getResponseAreaForCode(codes.qr).contacts;\n angular.forEach(qrs, function (contact) {\n if (contact.user) {\n idString += contact.id + \"%2B\"\n }\n });\n idString = idString.replace(/%2B$/, \"\");\n var modalInstance = $modal.open({\n templateUrl: 'core/html/picker.html',\n controller: stwoCommonPickerModalController,\n size: \"md\",\n resolve: {\n pickerConfiguration: function () {\n return {\n title: \"MANAGEMENT_ASSET_TYPE_TITLE\",\n clazz: \"type\",\n fieldsToShow: [\"name\"],\n nullAllowed: false,\n multiple: true,\n nullButtonText: \"MANAGEMENT_ASSET_REMOVE_TYPE\",\n downloadUrl: '/asset?select=name+connectedTo&id:equals=' + idString + '&sort=name&order=asc'\n }\n }\n }\n });\n modalInstance.result.then(function (pickerResult) {\n\n var receivers = [];\n var receiverContacts = [];\n angular.forEach(pickerResult.selectedItems, function (contact) {\n for (var i = 0; i < qrs.length; i++) {\n if (qrs[i].id == contact.id) {\n //updateNotificationStatusForContact(qrs[i], $scope.ns.pending.status);\n receivers.push({\n 'id': qrs[i].user.id\n });\n receiverContacts.push(qrs[i]);\n break;\n }\n }\n });\n\n var body = {\n \"recipients\": receivers,\n \"subject\": $scope.translations.notificationMessage,\n \"message\": $scope.translations.notificationSubject,\n \"object\": {\n \"id\": $scope.alarm.id,\n \"type\": \"alarm\"\n },\n \"type\": \"push\"\n };\n smarttrackerService.authPost(smarttrackerService.getCustomerId() + \"/sendNotification/\", body).then(function (response) {\n console.log(\"response:\", response);\n angular.forEach(receiverContacts, function (contact) {\n var found = false;\n angular.forEach(response.data.recipients, function (recipient) {\n if (recipient.id == contact.user.id) {\n found = true;\n }\n });\n updateNotificationStatusForContact(contact, found ? $scope.ns.pending.status : $scope.ns.failed.status);\n });\n saveNotificationStatus();\n });\n\n //saveNotificationStatus();\n }, function () { /** CANCEL */ });\n }\n };\n\n var updateNotificationStatusForContact = function (contact, newStatus) {\n if (contact.notificationStatus && ($scope.ns[contact.notificationStatus].order > $scope.ns[newStatus].order || contact.notificationStatus == newStatus)) {\n return false;\n }\n contact.notificationStatus = newStatus;\n $translate($scope.ns[newStatus].messageKey, {\n receiver: contact.name\n }).then(function (data) {\n console.log(\"translated\", data);\n // var labels = {\n // 'notificationEvent':{code:'ACR_NE', value:contact.user.id}, \n // 'notificationEventState':{code:'ACR_NES', value:newStatus}, \n // 'notificationEventContactID':{code:'ACR_NECI', value:contact.id}\n // };\n $scope.registerEvent(data, \"\", createCommentLabel(newStatus, contact.user.id, contact.id));\n });\n\n $scope.notificationStatus[contact.user.id] = {\n 'status': newStatus,\n updated: moment().utc().format(\"YYYY-MM-DDTHH:mm:ss.SSS\"),\n contact: contact\n }\n return true;\n }\n\n var saveNotificationStatus = function () {\n var meta = $scope.alarm.meta;\n meta[notificationStatusKey] = $scope.notificationStatus;\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + \"/alarm/\" + $scope.alarm.id, {\n 'meta': meta\n });\n }\n\n /** As the */\n var checkNotificationStatusForComments = function () {\n var elements = $filter('commentsWithLabelKey')($scope.events, 'notificationEvent');\n // angular.forEach($scope.events, function (comment) {\n // if(comment.labels && comment.labels['notificationEvent']) {\n // console.log(\"Adding comment\" + comment.text + \" because labels is \", comment.labels);\n // elements.push(comment);\n // } else {\n // console.log(\"Ignoring comment \" + comment.text + \" because labels is \", comment.labels);\n // }\n // });\n console.log(\"elements:\", elements);\n var qrs = getResponseAreaForCode(codes.qr).contacts;\n var changed = false;\n angular.forEach(elements, function (comment) {\n try {\n var data = JSON.parse(comment.labels[nsLabelKeys.event].value);\n var id = data[nsLabelKeys.userID];\n var contact = $filter('contactWithUserId', qrs, id);\n var state = data[nsLabelKeys.state];\n if ($scope.ns[state].order >= 2 && $scope.ns[state].order > $scope.ns[$scope.notificationStatus[id].status].order) { // Only responded and confirmed are updated by non centralist\n $scope.notificationStatus[id] = {\n 'status': state,\n updated: moment().utc().format(\"YYYY-MM-DDTHH:mm:ss.SSS\"),\n contact: contact\n };\n changed = true;\n }\n // var cid = comment.labels['notificationEventContactID'].value;\n // var currentState = $scope.notificationStatus.id;\n // if(currentState && $scope.ns[currentState.state].order < $scope.ns[state].order){\n\n // var contact = false;\n // for(var i = 0; i < qrs.length;i++) {\n // if(qrs[i].id == cid) {\n // contact = qrs[i];\n // break;\n // }\n // }\n // if(updateNotificationStatusForContact(contact, state)) {\n // changed = true;\n // }\n // }\n } catch (e) {\n console.error(\"Error when parsing comment data for \" + comment.name + \": \" + e);\n }\n });\n if (changed) {\n saveNotificationStatus();\n }\n }\n\n var createCommentLabel = function (eventID, userID, contactID) {\n var label = {};\n var o = {};\n o[nsLabelKeys.userID] = userID;\n o[nsLabelKeys.eventID] = eventID;\n o[nsLabelKeys.contactID] = contactID;\n var label = {};\n label[nsLabelKeys.event] = {\n code: 'ACR_NE',\n value: JSON.stringify(o)\n };\n return label;\n }\n\n $scope.sendNotificationFeedback = function () {\n var currentStatus = $scope.notificationStatus[$scope.userID];\n if (currentStatus && (currentStatus.status == $scope.ns.pending.status || (currentStatus.status == $scope.ns.responded.status && $scope.me && $scope.me.distance <= 40))) {\n var nextStatus = currentStatus.status == $scope.ns.pending.status ? $scope.ns.responded.status : ns.confirmed.status;\n updateNotificationStatusForContact($scope.me, nextStatus);\n updateFeedbackVariables();\n }\n }\n\n var updateFeedbackVariables = function () {\n var currentStatus = $scope.notificationStatus[$scope.userID];\n if (currentStatus) {\n $scope.showFeedbackButton = (currentStatus.status == $scope.ns.pending.status);\n $scope.showConfirmButton = (currentStatus.status == $scope.ns.responded.status);\n }\n }\n\n\n /** End notification related */\n\n\n}); // End Module alarm-screen-xguard-detail\n\nangular.module('stwo.alarm-screen-xguard').controller('AlarmScreenXGuardAssetController', function ($scope, $translate, $controller, $state, $stateParams, $modal, smarttrackerService, notificationService, $interval) {\n $controller('BaseListContentController', {\n $scope: $scope\n });\n\n var assetID = $stateParams.assetID;\n // if(!assetID) {\n // $state.go('secure.content.alarm-screen-xguard');\n // }\n\n var syntax = {\n email: \"email\",\n phone: \"phone\",\n sms: \"sms\",\n allowContact: \"allowContact\",\n allowEmergencyContact: \"allowEmergencyContact\",\n allowNQR: \"allowNQR\",\n updateIntervalSeconds: 60\n };\n\n\n var translations = [];\n $translate([\"XGUARD_MINUTES\", \"XGUARD_MINUTE\", \"XGUARD_HOUR\", \"XGUARD_HOURS\", \"XGUARD_TIME_MEASURE_TEMPLATE\"]).then(function (data) {\n translations = data;\n\n });\n\n $translate([\"XGUARD_ASSET_LABEL_PHONE\", \"XGUARD_ASSET_LABEL_ALLOW_CONTACT\", \"XGUARD_ASSET_LABEL_SHOW_NQR\",\n \"XGUARD_ASSET_LABEL_EMAIL\", \"XGUARD_ASSET_LABEL_SMS\", \"XGUARD_ASSET_LABEL_ALLOW_EMERGENCY_CONTACT\"\n ])\n .then(function (data) {\n $scope.translations = {\n allowNQR: data[\"XGUARD_ASSET_LABEL_SHOW_NQR\"],\n allowEmergencyContact: data[\"XGUARD_ASSET_LABEL_ALLOW_EMERGENCY_CONTACT\"],\n phone: data['XGUARD_ASSET_LABEL_PHONE'],\n email: data['XGUARD_ASSET_LABEL_EMAIL'],\n allowContact: data['XGUARD_ASSET_LABEL_ALLOW_CONTACT'],\n sms: data['XGUARD_ASSET_LABEL_SMS']\n };\n });\n\n smarttrackerService.isLoggedInDelayed().then(function () {\n\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/asset/\" + assetID + \"?select=@&crossAccount=true\").then(function (response) {\n $scope.asset = response.data.result[0];\n\n // sort properties\n sortProperties();\n });\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/alarm?select=@&crossAccount=true&asset.id:equals=\" + assetID + \"&ackedBy:equals=null\")\n .then(function (response) {\n $scope.alarms = response.data.result;\n if ($scope.alarms.length == 0) {\n /*$state.go('secure.content.asset.detail', {'id': assetID})*/\n $scope.noAlarmAvailable = true;\n } else if ($scope.alarms.length == 1) {\n $scope.gotoAlarm($scope.alarms[0].id);\n }\n });\n });\n\n\n\n $scope.gotoAlarms = function () {\n $state.go('secure.content.alarm-screen-xguard');\n }\n $scope.enableProperty = function (index) {\n var properties = $scope.asset.properties;\n if (properties[index].value != \"true\") {\n toggleProperty(index, \"true\");\n }\n }\n $scope.disableProperty = function (index) {\n var properties = $scope.asset.properties;\n if (properties[index].value != \"false\") {\n toggleProperty(index, \"false\");\n }\n }\n var toggleProperty = function (index, action) {\n var property = copyProperty($scope.asset.properties[index]);\n property.value = action;\n var json = {\n \"properties\": [property]\n }\n\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + \"/asset/\" + $scope.asset.id, json)\n .then(function (response) {\n $scope.asset.properties = response.data.result[0].properties;\n sortProperties();\n });\n }\n\n var sortProperties = function () {\n var correctOrder = [\"email\", \"phone\", \"sms\", \"allowNQR\", \"allowEmergencyContact\", \"allowContact\"];\n $scope.asset.properties.sort(function (a, b) {\n return correctOrder.indexOf(a.code) - correctOrder.indexOf(b.code);\n });\n }\n var copyProperty = function (property) {\n var copy = property.constructor();\n for (var attr in property) {\n if (property.hasOwnProperty(attr)) copy[attr] = property[attr];\n }\n return copy;\n }\n\n $scope.gotoAlarm = function (alarmID) {\n $state.go(\"secure.content.alarm-screen-xguard-detail\", {\n id: alarmID\n });\n }\n});\n\nangular.module('stwo.alarm-screen-xguard').controller('AlarmScreenXGuardExternalIdController', function ($scope, $translate, $controller, $state, $stateParams, $modal, smarttrackerService, notificationService, $interval) {\n $controller('BaseListContentController', {\n $scope: $scope\n });\n\n smarttrackerService.isLoggedInDelayed().then(function () {\n\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/alarm?select=asset.externalId%2BdateCreated&max=1&asset.externalId:equals=\" + encodeURIComponent($stateParams.externalId) + \"&sort=dateCreated&order=desc&crossAccount=true\", {\n onErrorDoNotRedirect: true\n }).then(function (response) {\n\n // check result\n if (typeof response.data.result !== 'undefined' && response.data.result.length > 0) {\n\n // alarm is first item\n var alarm = response.data.result[0];\n\n // go to alarm\n $state.go(\"secure.content.alarm-screen-xguard-detail\", {\n id: alarm.id,\n });\n\n } else {\n\n // go to alarm\n $state.go(\"secure.content.alarm-screen-xguard\");\n\n }\n\n });\n\n });\n\n // // go to alarm\n // $state.go(\"secure.content.alarm-screen-xguard-detail\", {\n // id: alarmID\n // });\n\n});\n\nangular.module('stwo.alarm-screen-xguard').controller('AlarmScreenXGuardAlertController', function ($scope, $translate, $controller, $state, $stateParams, smarttrackerService) {\n $controller('BaseListContentController', {\n $scope: $scope\n });\n var assetID = $stateParams.assetID;\n $translate([\"ALARM_CENTER_ALERT_ALARM_NAME\", \"ALARM_CENTER_ALERT_ALARM_ERROR\",\n \"ALARM_CENTER_ALERT_ALARM_PROVIDE_ASSET_ID\"\n ]).then(function (data) {\n smarttrackerService.isLoggedInDelayed().then(function () {\n if (assetID) {\n smarttrackerService.authPost(smarttrackerService.getCustomerId() + \"/alarm/\", {\n 'name': data['ALARM_CENTER_ALERT_ALARM_NAME'],\n 'ackNeeded': true,\n 'asset': {\n 'id': assetID\n }\n }).then(function (response) {\n $state.go(\"secure.content.alarm-screen-xguard-detail\", {\n id: response.data.result[0].id\n });\n }, function (response) {\n $scope.errors = data['ALARM_CENTER_ALERT_ALARM_ERROR'] + response.data.message;\n console.error(\"Error response\", response);\n });\n } else {\n $scope.errors = data['ALARM_CENTER_ALERT_ALARM_PROVIDE_ASSET_ID'];\n }\n });\n });\n});\nangular.module(\"stwo.response-check\", [\"stwo.core\"]).config(function ($stateProvider, $urlRouterProvider, moduleStoreProvider) {\n\n moduleStoreProvider.registerModule({\n name: \"response-check\",\n links: [{\n name: \"XGUARD_ASSET_SITUATION_TITLE\",\n category: \"ASSETS\",\n icon: \"verified\",\n sref: \"secure.content.response-check\",\n categoryDependency: \"ALARMS\",\n sort: 5,\n color: \"info\",\n controllers: [\"AssetSituationListController\"]\n }]\n });\n\n $stateProvider.state(\"secure.content.response-check\", {\n url: \"/response-check/:id\",\n templateUrl: \"modules/response-check/response-check.html\",\n controller: \"AssetSituationListController\",\n titleName: 'ASSET_SITUATION_LIST_TITLE',\n titleIcon: \"verified\"\n }).state(\"secure.content.response-check-detail\", {\n url: \"/response-check-detail/:id\",\n templateUrl: \"modules/response-check/detail.html\",\n controller: \"AssetSituationDetailController\",\n titleName: 'XGUARD_ASSET_SITUATION_TITLE',\n titleIcon: \"verified\"\n });\n\n console.log(\"modulestoreprovider\", moduleStoreProvider);\n\n moduleStoreProvider.addPossibleFilter(\"asset\", {\n id: \"name\",\n label: \"MANAGEMENT_ASSET_EXTERNAL_ID_FILTER\",\n type: \"string\",\n field: \"name\",\n comparator: \"contains\"\n });\n\n}); // End Module definition\n\nangular.module('stwo.response-check').controller('AssetSituationListController', function ($scope, $controller, $stateParams, $translate, $timeout, $state, timerService, $modal, smarttrackerService, mapService, leafletData, notificationService, contentCacheService, $location, dialogService, $filter, messageService) {\n $controller('BaseListContentController', {\n $scope: $scope\n });\n\n $scope.addPredefinedFilter(\"unacknowledged\", [{\n filterId: \"ack_needed\",\n label: \"ALARMS_FILTER_ACK_NEEDED\",\n value: \"true\"\n }, {\n filterId: \"acked_by\",\n label: \"ALARMS_FILTER_ACKED\",\n value: \"true\"\n }], \"&ackNeeded:equals=true&ackedBy:null=true\");\n\n $scope.super({\n clazz: 'alarm',\n pagination: {\n max: 100\n },\n downloadUrl: '/asset?select=name+image+lastValidPosition&sort=name&order=asc'\n });\n\n\n\n $scope.downloadAll = function () {\n var total = $scope.pagination.total;\n //$scope.clearItems();\n\n $scope.super({\n pagination: {\n max: total\n },\n clazz: 'asset',\n downloadUrl: '/asset?select=name+image+lastValidPosition&sort=name&order=asc'\n });\n $scope.downloadMore();\n $scope.downloadProgress.active = true;\n };\n\n $scope.textInput = {\n nameSearchValue: \"\",\n externalIdSearchValue: \"\",\n assetIdSearchValue: \"\"\n };\n $scope.applyNameSearch = function ($event) {\n if (!$scope.textInput.nameSearchValue || $scope.textInput.nameSearchValue == '')\n return;\n var keyCode = $event.which || $event.keyCode;\n if (keyCode === 13) {\n $scope.filterValues = {\n \"name\": $scope.textInput.nameSearchValue\n };\n $scope.filterUrlString = \"&name:contains=\" + $scope.textInput.nameSearchValue + ($scope.isAlarmCenter ? \"&crossAccount=true\" : \"\");\n $scope.textInput = {\n nameSearchValue: \"\",\n externalIdSearchValue: \"\",\n assetIdSearchValue: \"\"\n };\n }\n }\n\n $scope.downloadInProgress = true;\n\n $scope.$watch(\"itemsChanged\", function () {\n console.log(\"Changed\", $scope.items);\n if ($scope.itemsChanged > 0) {\n $scope.downloadInProgress = false;\n }\n });\n\n $scope.assetClicked = function (asset) {\n $scope.currentAssetID = asset.id;\n $scope.downloadAsset();\n $scope.initMapDelayed();\n\n if ($(window).width() < 1400) {\n $scope.Sidebar = false;\n }\n };\n\n\n $scope.closeAsset = function () {\n $scope.currentAssetID = 0;\n $scope.Sidebar = true;\n };\n\n $scope.localSidebarSituation = (localStorage[\"SidebarSituation\"] === \"true\");\n $scope.toggleSidebarSituation = function () {\n $scope.localSidebarSituation = !$scope.localSidebarSituation;\n localStorage[\"SidebarSituation\"] = $scope.localSidebarSituation;\n $scope.initMapDelayed();\n };\n\n $scope.initMap = function () {\n map.invalidateSize();\n $scope.autoCenter();\n };\n\n $scope.initMapDelayed = function () {\n setTimeout(function () {\n $scope.initMap();\n }, 20);\n };\n\n\n var debugMode = true;\n\n var translations = [];\n $scope.responseAreas = [];\n\n // var codes = {\n // customer: 0,\n // qr: 1,\n // ra: 3,\n // nqr: 2,\n // pc: 4,\n // pd: 6,\n // bz: 5\n // };\n\n var codes = {\n customer: 0, // Customer, subject of the alarm\n qr: 1, // Quick Response\n ra: 4, // Response Area\n nqr: 3, // National Quick Response\n pc: 2, // Personal Contacts\n pd: 6, // Police Department\n bz: 5 // Backup zone\n };\n\n $translate([\"XGUARD_MINUTES\", \"XGUARD_MINUTE\", \"XGUARD_HOUR\", \"XGUARD_HOURS\", \"XGUARD_TIME_MEASURE_TEMPLATE\", \"XGUARD_TIMESTAMP_TODAY\"])\n .then(function (data) {\n $scope.translations = {\n hour: data['XGUARD_HOUR'],\n hours: data['XGUARD_HOURS'],\n minute: data['XGUARD_MINUTE'],\n minutes: data['XGUARD_MINUTES'],\n timeTemplate: data['XGUARD_TIME_MEASURE_TEMPLATE'],\n today: data['XGUARD_TIMESTAMP_TODAY']\n };\n });\n\n\n var syntax = {\n ZMTag: \"ACR_ZM\",\n QRTag: \"ACR_QR\",\n NQRTag: \"ACR_NQR\",\n PDTag: \"ACR_PD\",\n BZTag: \"ACR_BZ\",\n RATag: \"ACR_RA\",\n CLTag: \"ACR_CL\",\n ContactTag: \"ACR_CONTACT\",\n email: \"email\",\n phone: \"phone\",\n sms: \"sms\",\n allowContact: \"allowContact\",\n allowContactNQR: \"allowContactNQR\",\n allowEmergencyContact: \"allowEmergencyContact\",\n allowNQR: \"allowNQR\",\n updateIntervalSeconds: \"sixty\"\n };\n\n\n // $scope.timers = timerService.timers();\n // $scope.$watch(\"timers.sixty\", function () {\n // if ($scope.alarm) {\n\n // }\n // });\n var killAlarmUpdater = $scope.$watch(\"timers.\" + syntax.updateIntervalSeconds, function () {\n if ($scope.asset) {\n downloadContacts($scope.asset);\n }\n getTimeString();\n });\n\n $scope.mapViewAltered = false;\n $scope.$on('leafletDirectiveMap.dragstart', function (event) {\n $scope.mapViewAltered = true;\n });\n\n $scope.$on('leafletDirectiveMap.click', function (event) {\n $scope.selectedMarker = '';\n deselectSelectedMarker();\n });\n $scope.selectedMarker = '';\n $scope.selectedMarkerName = \"\";\n\n $scope.markers = {};\n\n\n $scope.mapSidebar = {\n 'visible': false\n };\n $scope.markers = {};\n $scope.paths = {\n popupPath: {\n color: '#FF0000',\n weight: 4,\n latlngs: [],\n }\n };\n\n $scope.indoorViewer = {\n location: null,\n markers: {},\n changeCounter: 0\n };\n mapService.basicMapDesign($scope, leafletData);\n\n var updateBZVisibility = function () {\n var nbrOfContacts = 0;\n var allElseFailed = true;\n var totalNbrOfContacts = 0;\n for (var i in $scope.responseAreas) {\n var ra = $scope.responseAreas[i];\n if (ra.visible && ra.code != codes.bz && ra.code != codes.pd) {\n if (allElseFailed) {\n for (var i in ra.contacts) {\n var c = ra.contacts[i];\n var key = getActionStatusKey(c);\n if (!$scope.actionStatus.hasOwnProperty(key) || $scope.getActionStatus(c)) {\n allElseFailed = false;\n }\n }\n }\n if (ra.code != codes.pd && ra.code != codes.customer) {\n nbrOfContacts += ra.contacts.length;\n }\n }\n }\n\n updateRAPropertyForCode(codes.bz, \"visible\", nbrOfContacts == 0 || allElseFailed);\n }\n\n var clipboard = new Clipboard('.clipBtn');\n clipboard.on('success', function (e) {\n console.log(e);\n });\n clipboard.on('error', function (e) {\n console.log(e);\n });\n\n\n $scope.order = 0;\n $scope.actionStatus = {};\n $scope.setOrder = function (order) {\n $scope.responseAreas.sort(function (a, b) {\n if (a.code == b.code) {\n return a.priority - b.priority;\n }\n return (order == 0) ? a.code - b.code : b.code - a.code;\n });\n $scope.order = order;\n }\n\n smarttrackerService.isLoggedInDelayed().then(function () {\n $scope.customerID = smarttrackerService.getCustomerId();\n if ($stateParams.id) {\n $scope.filterUrlString = \"&id:equals=\" + $stateParams.id;\n $scope.filterMessage = \"SELECTED_ITEMS\";\n $scope.filterMessage2 = \"\";\n $scope.assetClicked({\n id: $stateParams.id\n });\n\n $scope.singleAsset = true;\n $scope.Sidebar = false;\n\n };\n });\n\n $scope.isAlarmCenter = false;\n $scope.downloadStatus = {\n 'NQR': true,\n 'QR': true,\n 'RA': true\n };\n $scope.downloadAsset = function () {\n leafletData.getMap(\"rcmap\").then(function (map) {\n\n map.eachLayer(function (layer) {\n if (layer.hasOwnProperty(\"item\")) {\n layer.remove();\n }\n });\n $scope.markers = {};\n coreMarkers = [];\n $scope.paths = {};\n\n\n\n var assetID = $scope.currentAssetID;\n if (!assetID) {\n $scope.errorMessage = \"Please provide an Asset ID TRANSLATE THIS MESSAGE\";\n return;\n }\n return smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/asset/' + assetID + '?select=@&crossAccount=true', {\n onErrorDoNotRedirect: true\n }).then(function (response) {\n if (!response) return;\n $scope.asset = response.data.result[0];\n\n if ($scope.asset) {\n contentCacheService.put(\"asset\", assetID, $scope.asset);\n }\n\n if (!$scope.asset) return;\n\n getTimeString();\n\n\n var asset = $scope.asset;\n\n if (asset && $scope.asset.lastValidPosition) {\n\n\n\n addCustomerMarker($scope.asset);\n\n if (response.data.result.length == 0) return;\n var asset = $scope.asset;\n var nqrEnabled = $scope.getPropertyValue(asset, syntax.allowNQR);\n\n $scope.contactInfo = {\n \"id\": asset.id,\n \"name\": asset.name,\n \"image\": asset.image,\n \"phone\": $scope.getPropertyValue(asset, syntax.phone),\n \"phoneFormatted\": $scope.trimPhoneNumber($scope.getPropertyValue(asset, syntax.phone)),\n \"sms\": $scope.getPropertyValue(asset, syntax.sms),\n \"email\": $scope.getPropertyValue(asset, syntax.email),\n \"allowEmergencyContact\": $scope.getPropertyValue(asset, syntax.allowEmergencyContact),\n \"nqrEnabled\": nqrEnabled && nqrEnabled == \"true\"\n }\n\n addContactsForCode([$scope.contactInfo], codes.customer, true);\n getResponseAreaForCode(codes.nqr).visible = $scope.contactInfo.nqrEnabled;\n\n if ($scope.contactInfo.allowEmergencyContact == \"false\") {\n updateRAPropertyForCode(codes.customer, \"visible\", false);\n }\n downloadZones(asset.insideZones);\n downloadContacts(asset);\n $timeout(function () {\n $scope.initMap();\n }, 300);\n }\n }); // ENd download asset request\n });\n }\n\n\n $scope.contactStatus = 0;\n var mapInitiated = false;\n var maximumDistances = {\n 'total': 0\n };\n var downloadContacts = function (asset) {\n if (!asset || !$scope.access['type']['get'] || (!asset.position && !asset.lastValidPosition)) return;\n var position = asset.lastValidPosition ? asset.lastValidPosition : asset.position;\n var lessLat = position.latitude + 1;\n var lessLon = position.longitude + 1;\n var greaterLat = position.latitude - 1;\n var greaterLon = position.longitude - 1;\n\n downloadCloseAssets('/asset?select=properties+lastValidPosition+lastPosition+type+groups&crossAccount=true&type.labels:contains=' + syntax.QRTag + '&owner:equals=' + asset.owner.id +\n '&latitude:less=' + lessLat + '&latitude:greater=' + greaterLat + '&longitude:less=' + lessLon + '&longitude:greater=' + greaterLon + (debugMode ? '' : '&embeddedTimestamp:younger=3900000') + '&max=50', syntax.QRTag,\n function (list) {\n // get types meta\n var usedIDS = [];\n if (list && list.length > 0) {\n var typeIDS = list[0].type.id;\n\n for (var i = 1; i < list.length; i++) {\n var id = list[i].type.id;\n if (usedIDS.indexOf(id) < 0) {\n usedIDS.push(id);\n typeIDS += \"%2B\" + id;\n }\n }\n if (!maximumDistances || !maximumDistances.qr) {\n getMaxDistancesForCode(list, codes.qr);\n }\n $scope.collegues = list;\n addContactsForCode(list, codes.qr, true);\n\n $scope.contactStatus++;\n updateBZVisibility();\n applyDistanceFilter(codes.qr);\n if (!mapInitiated) {\n $timeout(function () {\n $scope.autoCenter();\n }, 300);\n mapInitiated = true;\n }\n }\n $scope.downloadStatus['QR'] = false;\n\n });\n if ($scope.contactInfo.nqrEnabled) {\n downloadCloseAssets('/asset?select=properties+lastValidPosition+lastPosition+type+groups&crossAccount=true&type.labels:contains=' + syntax.NQRTag + '&latitude:less=' + lessLat + '&latitude:greater=' + greaterLat +\n '&longitude:less=' + lessLon + '&longitude:greater=' + greaterLon + (debugMode ? '' : '&embeddedTimestamp:younger=3900000') + '&max=50', syntax.NQRTag,\n function (list) {\n\n $scope.guards = list;\n if (!maximumDistances || !maximumDistances[codes.nqr]) {\n getMaxDistancesForCode(list, codes.nqr);\n }\n\n addContactsForCode($scope.guards, codes.nqr, true);\n $scope.contactStatus++;\n updateBZVisibility();\n applyDistanceFilter(codes.nqr);\n $scope.downloadStatus['NQR'] = false;\n });\n\n } else {\n $scope.downloadStatus['NQR'] = false;\n }\n if ($scope.asset) {\n\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/asset/' + $scope.asset.id + '?crossAccount=true', {\n onErrorDoNotRedirect: true\n }).then(function (response) {\n if (response && response.data && response.data.result && response.data.result.length > 0) {\n $scope.asset = response.data.result[0];\n\n // Add private contacts\n if (!getResponseAreaForCode(codes.pc) && $scope.asset.labels) {\n var data = parseDataForZone($scope.asset);\n var contacts = data.contacts.sort(comparePriority);\n if (data.contacts) {\n $scope.responseAreas.push({\n \"name\": translations[\"XGUARD_RESPONSE_AREAS_PRIVATE_CONTACTS\"],\n \"color\": \"ra\",\n \"code\": codes.pc,\n \"contacts\": contacts,\n \"expanded\": false,\n \"visible\": true\n });\n $scope.setOrder($scope.order);\n }\n }\n if ($scope.asset) {\n addCustomerMarker($scope.asset);\n downloadZones(asset.insideZones);\n }\n }\n });\n }\n }\n\n var getLabelWithCode = function (objectWithLabel, code) {\n if (objectWithLabel.labels) {\n for (var i in objectWithLabel.labels) {\n if (objectWithLabel.labels[i].code == code) {\n return objectWithLabel.labels[i];\n }\n }\n }\n }\n\n var getMaxDistancesForCode = function (contacts, code) {\n if (contacts.length > 0) {\n var usedIDS = [];\n var typeIDS = contacts[0].type.id;\n for (var i = 1; i < contacts.length; i++) {\n var id = contacts[i].type.id;\n if (usedIDS.indexOf(id) < 0) {\n usedIDS.push(id);\n typeIDS += \"%2B\" + id;\n }\n }\n if (!maximumDistances || !maximumDistances.qr) {\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + \"/type/?select=labels&id:equals=\" + typeIDS, {\n onErrorDoNotRedirect: true\n })\n .then(function (response) {\n\n var approvedContacts = [];\n \n\n for (var i in response.data.result) {\n var type = response.data.result[i];\n for (var x in type.labels) {\n var label = type.labels[x];\n if (label.value.indexOf(\"maxDistance\") >= 0) {\n try {\n var value = JSON.parse(label.value);\n maximumDistances[type.id + type.name] = value.maxDistance;\n maximumDistances['total'] = maximumDistances['total'] + 1;\n } catch (e) {\n console.log(e);\n maximumDistances[type.id + type.name] = 2000;\n maximumDistances['total'] = maximumDistances['total'] + 1\n }\n } else {\n maximumDistances[type.id + type.name] = 2000;\n maximumDistances['total'] = maximumDistances['total'] + 1\n }\n }\n }\n applyDistanceFilter(code);\n });\n }\n }\n }\n\n var applyDistanceFilter = function (code) {\n if (maximumDistances && maximumDistances.total > 0) {\n var ra = false;\n for (var i in $scope.responseAreas) {\n if ($scope.responseAreas[i].code == code) {\n ra = $scope.responseAreas[i];\n }\n }\n if (ra) {\n var list = [];\n for (var i in ra.contacts) {\n var contact = ra.contacts[i];\n if (!(contact.type && maximumDistances[contact.type.id + contact.type.name] &&\n contact.distance > maximumDistances[contact.type.id + contact.type.name])) {\n list.push(contact);\n if (code == codes.nqr) addNQRMarker(contact);\n else if (code == codes.qr) addQRMarker(contact);\n\n } else if ($scope.markers[\"marker\" + contact.id]) {\n leafletData.getMap(\"rcmap\").then(function (map) {\n map.removeLayer($scope.markers[\"marker\" + contact.id]);\n delete $scope.markers[\"marker\" + contact.id];\n });\n }\n }\n addContactsForCode(list, code, true);\n\n }\n }\n }\n\n\n\n\n var downloadCloseAssets = function (url, context, repl) {\n var list = [];\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + url, {\n onErrorDoNotRedirect: true\n }).then(function (response) {\n if (!response || !response.data) return;\n for (var i in response.data.result) {\n var asset = response.data.result[i];\n\n if (!asset.lastValidPosition || !isContactAllowed(asset, context)) {\n console.log('Stopped showing asset in response-check', {\n lastValidPosition: asset.lastValidPosition\n }, {\n isContactAllowed: isContactAllowed(asset, context)\n })\n continue;\n }\n\n if ($scope.asset && asset.id != $scope.asset.id) {\n\n asset.phone = $scope.getPropertyValue(asset, syntax.phone);\n asset.phoneFormatted = $scope.trimPhoneNumber($scope.getPropertyValue(asset, syntax.phone));\n asset.sms = $scope.getPropertyValue(asset, syntax.sms);\n asset.email = $scope.getPropertyValue(asset, syntax.email);\n asset.distance = calculateDistance(asset.lastValidPosition, $scope.asset.lastValidPosition);\n asset.distanceText = getDistanceText(asset.distance);\n //asset.allowConact = $scope.getPropertyValue(asset, syntax.allowConact);\n\n\n list.push(asset);\n\n }else{\n\n console.log('Stopped showing asset in response-check', 'missing data');\n\n }\n }\n list.sort(function (a, b) {\n return a.distance - b.distance;\n });\n\n repl(list);\n });\n }\n\n var downloadZones = function (zones) {\n if (!zones || zones.length < 1) {\n $scope.downloadStatus['RA'] = false;\n return;\n }\n var zoneIDS = \"\" + zones[0].id;\n for (var i = 1; i < zones.length; i++) {\n zoneIDS += \"%2B\" + zones[i].id;\n }\n\n console.log(\"IS GOING TO DOWNLOAD ZONES: \" + zones);\n // remove zones that the asset is no longer inside\n\n\n smarttrackerService.authGet(smarttrackerService.getCustomerId() + '/zone/?id:equals=' + zoneIDS + \"&select=type+labels+points&crossAccount=true\", {\n onErrorDoNotRedirect: true\n }).then(function (response) {\n var zs = response.data.result;\n // clear old zone contacts\n for (var i in $scope.responseAreas) {\n var ra = $scope.responseAreas[i];\n if (ra.code == codes.pd || ra.code == codes.bz || ra.code == codes.ra) {\n ra.contacts = [];\n }\n }\n\n for (var i in zs) {\n var z = zs[i];\n if (z.labels) {\n for (var l in z.labels) {\n var label = z.labels[l];\n switch (label.code) {\n case syntax.RATag:\n addResponseArea(z);\n break;\n case syntax.PDTag:\n if ($scope.isAlarmCenter)\n addContactsForCode(parseDataForZone(z).contacts, codes.pd);\n break;\n case syntax.BZTag:\n addContactsForCode(parseDataForZone(z).contacts, codes.bz);\n break;\n }\n }\n }\n }\n updateBZVisibility();\n $scope.downloadStatus['RA'] = false;\n });\n }\n\n var addResponseArea = function (z) {\n var data = parseDataForZone(z);\n var priority = data.priority ? data.priority : 20000;\n var contacts = data.contacts.sort(comparePriority);;\n getResponseAreaTextForZone(z).then(function (text) {\n var ra = {\n \"name\": text,\n \"color\": \"ra\",\n \"code\": codes.ra,\n \"priority\": priority,\n \"contacts\": contacts,\n \"expanded\": false,\n \"visible\": contacts.length > 0\n };\n if (data.messageData) ra.messageData = data.messageData;\n $scope.responseAreas.push(ra);\n $scope.setOrder($scope.order);\n var hp = ra.priority;\n var fp = false;\n for (var i in $scope.responseAreas) {\n var area = $scope.responseAreas[i];\n if (area.code == codes.ra && area.priority && area.priority < hp) {\n fp = true;\n break;\n }\n }\n if (!fp) {\n renderResponseArea(z);\n\n }\n });\n }\n\n var renderResponseArea = function (a) {\n var latlngs = [];\n for (var i in a.points) {\n var point = a.points[i];\n latlngs.push({\n 'lat': point['latitude'],\n 'lng': point['longitude']\n });\n }\n\n addPath(\"ResponseArea\", {\n type: \"polygon\",\n fillColor: 'darkgreen',\n color: 'darkgreen',\n latlngs: latlngs,\n clickable: false,\n weight: 2\n });\n }\n\n var getResponseAreaForCode = function (code, priority) {\n for (var i in $scope.responseAreas) {\n if ($scope.responseAreas[i].code == code) {\n var ra = $scope.responseAreas[i];\n if (priority && ra.priority != priority) {\n continue;\n }\n return ra;\n }\n }\n return false;\n }\n\n var updateRAPropertyForCode = function (code, property, value) {\n for (var i in $scope.responseAreas) {\n if ($scope.responseAreas[i].code == code) {\n $scope.responseAreas[i][property] = value;\n break;\n }\n }\n }\n\n var addContactsForCode = function (contacts, code, refresh) {\n var index = false;\n for (var i in $scope.responseAreas) {\n if ($scope.responseAreas[i].code == code) {\n index = i;\n break;\n }\n }\n if (index && index > -1) {\n if (refresh) {\n $scope.responseAreas[index].contacts = [];\n }\n for (var j in contacts) {\n $scope.responseAreas[i].contacts.push(contacts[j]);\n }\n\n }\n if (code == codes.nqr || code == codes.qr)\n $scope.responseAreas[i].contacts = $scope.responseAreas[i].contacts;\n else\n $scope.responseAreas[i].contacts = $scope.responseAreas[i].contacts.sort(comparePriority);\n }\n\n var days = [\"SUN\", \"MON\", \"TUE\", \"WED\", \"THU\", \"FRI\", \"SAT\"];\n\n var parseDataForZone = function (zone) {\n zone.contacts = [];\n var now = new Date();\n\n\n for (var i in zone.labels) {\n var label = zone.labels[i];\n if (label.code == \"ACR_CONTACT\") {\n try {\n var properties = JSON.parse(label.value);\n properties[\"name\"] = i;\n\n console.log('CONTACT NAME', properties[\"name\"])\n\n // Check if the contact is available \n if (properties.workhours.length > 0) {\n properties.working = false;\n whcheck:\n for (var y in properties.workhours) {\n var wh = properties.workhours[y];\n for (var z in wh.weekday) {\n if (days.indexOf(wh.weekday[z]) == now.getDay()) {\n\n var startBound = new Date();\n startBound.setHours(wh.hours.substring(0, 2));\n startBound.setMinutes(wh.hours.substring(2, 4));\n var endBound = new Date();\n endBound.setHours(wh.hours.substring(5, 7));\n endBound.setMinutes(wh.hours.substring(7, 9));\n\n if (now.getTime() > startBound.getTime() && now.getTime() < endBound.getTime()) {\n properties.working = true;\n zone.contacts.push(properties);\n break whcheck;\n }\n }\n }\n }\n\n } else {\n properties.working = true;\n zone.contacts.push(properties);\n }\n } catch (e) {\n console.log('error parsing workhours', e);\n }\n } else if (label.code == \"ACR_RA\") {\n\n try {\n var properties = JSON.parse(label.value);\n var kv = {\n showQR: \"qr\",\n showNQR: \"nqr\",\n showPD: \"pd\"\n };\n for (var k in kv) {\n if (properties.hasOwnProperty(k) && !properties[k]) {\n updateRAPropertyForCode(codes[kv[k]], \"visible\", false);\n }\n }\n zone.priority = properties.priority ? properties.priority : 20000;\n if (properties.messageData) {\n zone.messageData = properties.messageData;\n }\n } catch (e) {\n console.log(e);\n }\n }\n }\n\n\n return zone;\n }\n\n\n $translate([\"XGUARD_RESPONSE_AREAS_CUSTOMER\", \"XGUARD_RESPONSE_AREAS_QUICK_RESPONSE\",\n \"XGUARD_RESPONSE_AREAS_NATIONAL_QUICK_RESPONSE\", \"XGUARD_RESPONSE_AREAS_POLICE_REGION\", \"XGUARD_RESPONSE_AREAS_PRIVATE_CONTACTS\",\n \"XGUARD_RESPONSE_AREAS_BACKUP\"\n ]).then(function (data) {\n translations = data;\n\n $scope.responseAreas = [{\n \"name\": translations[\"XGUARD_RESPONSE_AREAS_CUSTOMER\"],\n \"color\": \"cu\",\n \"code\": codes.customer,\n \"contacts\": [],\n \"expanded\": false,\n \"visible\": true\n }, {\n \"name\": translations[\"XGUARD_RESPONSE_AREAS_QUICK_RESPONSE\"],\n \"color\": \"qr\",\n \"code\": codes.qr,\n \"contacts\": [],\n \"expanded\": false,\n \"visible\": true\n },\n //{\"name\":\"Response Area\", \"color\":\"ra\", \"code\":codes.ra, \"contacts\":[], \"expanded\":false, \"visible\":true},\n {\n \"name\": translations[\"XGUARD_RESPONSE_AREAS_NATIONAL_QUICK_RESPONSE\"],\n \"color\": \"nqr\",\n \"code\": codes.nqr,\n \"contacts\": [],\n \"expanded\": false,\n \"visible\": true\n }, {\n \"name\": translations[\"XGUARD_RESPONSE_AREAS_POLICE_REGION\"],\n \"color\": \"pd\",\n \"code\": codes.pd,\n \"contacts\": [],\n \"expanded\": false,\n \"visible\": true\n }, {\n \"name\": translations[\"XGUARD_RESPONSE_AREAS_BACKUP\"],\n \"color\": \"pd\",\n \"code\": codes.bz,\n \"contacts\": [],\n \"expanded\": false,\n \"visible\": false\n }\n ];\n\n });\n\n\n\n var isContactAllowed = function (asset, context) {\n var contactAllowed = true;\n var testValue = context == syntax.NQRTag ? syntax.allowContactNQR : syntax.allowContact;\n\n console.log('Testvalue', asset, testValue)\n\n for (var i in asset.properties) {\n var prop = asset.properties[i];\n if (prop.code == testValue) {\n contactAllowed = prop.value != \"false\";\n break;\n }\n }\n return contactAllowed;\n }\n\n $scope.getPropertyValue = function (asset, code) {\n var value = false;\n if (asset && code) {\n for (var i in asset.properties) {\n var property = asset.properties[i];\n if (property.code == code) {\n value = property.value;\n break;\n }\n }\n }\n return value;\n }\n\n\n\n var makeNamedIcon = function (name, icon, color) {\n if (!color) {\n color = \"#31708f\";\n }\n if (!icon) {\n icon = \"glyphicon glyphicon-map-marker\";\n }\n var div_icon = {\n type: 'div',\n iconAnchor: [18, 36 - 8], //these numbers come from the fact that we use an icon 36x36 and the leaflet positions this with its top-felt corner. Thus I shift so the the nidle of the icon shows right point in map\n iconSize: [2000, 0],\n className: 'myleaflet-div-icon',\n //html: '' + name + '',\n html: '' + name + '',\n popupAnchor: [0, 0]\n };\n\n\n return div_icon;\n }\n\n /* Map Commands*/\n var coreMarkers = [];\n $scope.securityGuardsVisible = false;\n\n var deselectSelectedMarker = function () {\n if (selectedMarker) {\n selectedMarker._icon.className = selectedMarker._icon.className.replace(\"selected\", \"\");\n }\n selectedMarker = false;\n }\n var selectedMarker = false;\n var addSelectedMarker = function (marker) {\n /*$scope.markers[marker.id] = {\n id: marker.id,\n lat: marker.lat,\n lng: marker.lng,\n icon: makeNamedIcon(marker.item.name, \"glyphicon glyphicon-map-marker\", \"DodgerBlue\"),//(item.logLevelFormatted === 'notification' ? 'success' : (item.logLevelFormatted === 'warning' ? 'warning' : 'danger' ) )),\n //message : \"message\",\n focus: false, //just add them on the map. not in focus\n draggable: false,\n 'item': marker.item,\n 'code': marker.code\n };*/\n if (selectedMarker) {\n deselectSelectedMarker();\n }\n selectedMarker = marker;\n selectedMarker._icon.className += \" selected\";\n }\n var addAlarmMarker = function (alarm) {\n addMarker(alarm, \"mdi mdi-bullseye\", \"#FF0000\", \"#e00000\", \"Alarm Position\", true, null, 18, 18);\n }\n var addQRMarker = function (asset) {\n addMarker(asset, \"mdi mdi-map-marker\", \"#22b573\", \"#1c925d\", asset.name, true, codes.qr);\n }\n var addCustomerMarker = function (asset) {\n addMarker(asset, \"mdi mdi-map-marker\", \"#FF0000\", \"#e00000\", \"Current Position\", true, codes.customer);\n //renderLineBetween();\n }\n var addNQRMarker = function (asset) {\n addMarker(asset, \"mdi mdi-marker-check\", \"#0b788a\", \"#095e6d\", asset.name, false, codes.nqr, 15, 29);\n }\n\n var oms = false;\n var addMarker = function (item, icon, color, colorDark, text, core, code, iconAnchorX, iconAnchorY) {\n leafletData.getMap(\"rcmap\").then(function (map) {\n\n if (!$scope.slInit) {\n oms = new OverlappingMarkerSpiderfier(map);\n oms.addListener(\"click\", function (marker) {\n if (marker.code == codes.nqr || marker.code == codes.qr || marker.code == codes.customer) {\n\n var ra = getResponseAreaForCode(marker.code);\n if (ra.contacts.indexOf(marker.item) >= 2)\n ra.expanded = true;\n\n deselectSelectedMarker();\n addSelectedMarker(marker);\n\n $scope.selectedMarker = marker.item.id;\n $scope.selectedMarkerName = marker.id;\n }\n });\n $scope.slInit = true;\n }\n\n if (item && item.id && (item.lastValidPosition || item.position)) {\n var positionKey = item.position ? 'position' : 'lastValidPosition';\n\n if (oms) {\n L.Icon.Default.imagePath = 'css/images';\n\n if (!iconAnchorX || !iconAnchorY) {\n iconAnchorX = 18;\n iconAnchorY = 32;\n }\n\n var micon = L.divIcon({\n type: 'div',\n iconAnchor: [iconAnchorX, iconAnchorY],\n className: 'myleaflet-div-icon',\n html: '
    ' + text + '
    ',\n popupAnchor: [0, 0]\n });\n var markerId = \"marker\" + item.id;\n\n var marker = $scope.markers[markerId];\n var loc = new L.LatLng(item[positionKey].latitude, item[positionKey].longitude);\n if (marker)  {\n oms.unspiderfy();\n try {\n marker.setLatLng(loc);\n } catch (err) {\n console.log(err);\n }\n } else {\n marker = new L.Marker(loc, {\n icon: micon,\n riseOnHover: true\n });\n map.addLayer(marker);\n oms.addMarker(marker);\n marker.item = item;\n marker.code = code;\n marker.id = markerId;\n marker.iconCode = micon;\n // marker.on('mouseover', function (e){\n // console.log(this);\n // });\n $scope.markers[markerId] = marker;\n }\n }\n\n if (core && coreMarkers.indexOf(\"marker\" + item.id) < 0) {\n coreMarkers.push(\"marker\" + item.id);\n }\n }\n });\n\n }\n\n var clearMarkersForCode = function (code) {\n var markers = {};\n for (var i in $scope.markers) {\n if (i.indexOf(code) != 0) {\n markers[i] = $scope.markers[i];\n }\n }\n $scope.markers = markers;\n }\n\n var addPath = function (name, path) {\n var p = $scope.paths;\n $scope.paths = {};\n for (var i in p) {\n $scope.paths[i] = p[i];\n }\n $scope.paths[name] = path;\n }\n\n\n $scope.initialCenterSet = false;\n\n $scope.setCenter = function (newCenter) {\n console.log(\"SetCenter\", newCenter);\n leafletData.getMap(\"rcmap\").then(function (map) {\n map.setView($scope.mapData.center = new L.LatLng(newCenter.lat, newCenter.lng), newCenter.zoom);\n });\n $scope.mapData.center.lat = newCenter.lat;\n $scope.mapData.center.lng = newCenter.lng;\n\n if (newCenter.zoom) {\n $scope.mapData.center.zoom = newCenter.zoom;\n }\n };\n\n $scope.centerOnItem = function (item) {\n console.log(\"center on item\", item);\n if (item && item.position && item.position.location && item.position.location.locationId) {\n $scope.mapMode.indoor = true;\n $scope.indoorViewer.location = item.position.location.locationId;\n } else if (item && item.position && item.position.valid) {\n $scope.mapMode.indoor = false;\n var newcenter = {\n lat: item.position.latitude,\n lng: item.position.longitude\n };\n\n $scope.setCenter(newcenter);\n }\n };\n\n $scope.toggleMap = function () {\n $scope.mapVisible = !$scope.mapVisible;\n if ($scope.mapVisible) {\n if (!mapInitiated) {\n mapInitiated = true;\n $scope.autoCenter();\n $scope.mapViewAltered = false;\n }\n $timeout(function () {\n leafletData.getMap(\"rcmap\").then(function (map) {\n map.invalidateSize();\n });\n }, 1050);\n }\n }\n\n $scope.zoomNQR = function () {\n $scope.securityGuardsVisible = true;\n $scope.autoCenter();\n }\n\n $scope.zoomCore = function () {\n\n $scope.securityGuardsVisible = false;\n $scope.autoCenter();\n $scope.mapViewAltered = false;\n }\n\n $scope.autoCenter = function () {\n var activeMarkersPoints = [];\n\n if ($scope.securityGuardsVisible) {\n for (var m in $scope.markers) {\n var item = $scope.markers[m];\n if (item && item.getLatLng()) {\n activeMarkersPoints.push(item.getLatLng());\n }\n }\n } else {\n for (var i in coreMarkers) {\n var item = $scope.markers[coreMarkers[i]];\n if (item && item.getLatLng()) {\n activeMarkersPoints.push(item.getLatLng());\n }\n }\n }\n\n var bounds = new L.latLngBounds(activeMarkersPoints);\n\n if (activeMarkersPoints.length > 0 && bounds.isValid()) {\n $timeout(function () {\n leafletData.getMap(\"rcmap\").then(function (map) {\n var f = bounds.isValid();\n map.fitBounds(bounds, {\n padding: [50, 50]\n });\n // map.zoomOut(1);\n });\n }, 310);\n }\n };\n\n /*Map Commands*/\n\n var calculateDistance = function (pos1, pos2) {\n var lat1 = pos1.latitude;\n var lat2 = pos2.latitude;\n var lon1 = pos1.longitude;\n var lon2 = pos2.longitude;\n\n var R = 6371e3; // metres\n var φ1 = toRadians(lat1);\n var φ2 = toRadians(lat2);\n var Δφ = toRadians(lat2 - lat1);\n var Δλ = toRadians(lon2 - lon1);\n\n var a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +\n Math.cos(φ1) * Math.cos(φ2) *\n Math.sin(Δλ / 2) * Math.sin(Δλ / 2);\n var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\n var d = R * c;\n return d;\n }\n\n var toRadians = function (deg) {\n return deg * Math.PI / 180.0;\n }\n\n var getDistanceText = function (distance) {\n if (distance > 100) {\n return (Math.round(distance / 100) / 10) + \" km\";\n } else return (Math.round(distance * 10) / 10) + \" m\";\n }\n\n function comparePriority(a, b) {\n return a.priority == b.priority ? 0 : a.priority < b.priority ? -1 : 1;\n }\n\n\n /** Helper functions*/\n $scope.isIndoor = function (item) {\n if (item.position) { // alarma\n return item.position.source && item.position.source.type == \"beacon\";\n } else {\n return item.lastValidPosition && item.lastValidPosition.source && item.lastValidPosition.source.type == \"beacon\";\n }\n }\n\n $scope.isInZone = function (item, zone) {\n\n if (zone && zone.id && (item.insideZones || (item.position && item.position.insideZones))) {\n var zones = item.insideZones ? item.insideZones : item.position.insideZones;\n for (var i in zones) {\n if (zones[i].id == zone.id)\n return true;\n }\n }\n return false;\n }\n\n $scope.isGuardsVisible = function () {\n var nqr = getResponseAreaForCode(codes.nqr);\n return $scope.asset && nqr.visible && nqr.contacts.length > 0;\n }\n\n $scope.timeString = \"\";\n var getTimeString = function () {\n\n if ($scope.asset && $scope.asset.lastValidPosition && $scope.translations) {\n var time = moment.tz($scope.asset.lastValidPosition.timestamp, \"YYYY-MM-DDTHH:mm:ss.SSS\", \"UTC\").toDate();\n var diff = Math.floor((new Date() - time) / 1000);\n if (diff < 86400) {\n var hours = Math.floor(diff / 3600);\n diff = diff = Math.floor(diff % 3600);\n var minutes = Math.floor(diff / 60);\n\n $scope.timeString = $scope.translations.timeTemplate.toString().replace(\"\", hours > 0 ? hours + (hours > 1 ? \" \" + $scope.translations.hours + \" \" : \" \" + $scope.translations.hour + \" \") : \"\")\n .replace(\"\", minutes >= 0 ? (minutes + (minutes == 1 ? \" \" + $scope.translations.minute + \" \" : \" \" + $scope.translations.minutes + \" \")) : \"\");\n } else {\n $scope.timeString = $scope.asset.lastValidPosition.timestampFormatted;\n }\n }\n };\n\n var getResponseAreaTextForZone = function (zone) {\n return $translate(\"XGUARD_RESPONSE_AREAS_RESPONSE_AREA\", {\n zoneName: zone.name\n });\n };\n\n /**End Helper functions*/\n\n /*$scope.googleMapsBackup = function (item) {\n $window.open('http://maps.google.com/maps?q=' + item.lastValidPosition.latitude + ',' + item.lastValidPosition.longitude);\n }*/\n\n $scope.googleMaps = function (item) {\n\n var lat = item.position.latitude;\n var lng = item.position.longitude;\n\n if ((navigator.platform.indexOf(\"iPhone\") !== -1) || (navigator.platform.indexOf(\"iPod\") !== -1)) {\n function iOSversion() {\n if (/iP(hone|od|ad)/.test(navigator.platform)) {\n // supports iOS 2.0 and later: \n var v = (navigator.appVersion).match(/OS (\\d+)_(\\d+)_?(\\d+)?/);\n return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)];\n }\n }\n\n var ver = iOSversion() || [0];\n\n if (ver[0] >= 6) {\n protocol = 'maps://';\n } else {\n protocol = 'http://';\n\n }\n window.location = protocol + 'maps.apple.com/maps?daddr=' + lat + ',' + lng + '&ll=';\n } else {\n window.open('http://maps.google.com?daddr=' + lat + ',' + lng + '&ll=');\n }\n };\n\n var getTableRow = function (col1, col2) {\n return \"\" + col1 + \"\" + col2 + \"\";\n }\n\n $scope.getGoogleMapsLink = function (lat, lon) {\n return \"http://maps.google.com/maps?q=\" + lat + \"%2C\" + lon;\n }\n\n var sendMailsSynchronized = function (list, index, endFN) {\n if (index < list.length) {\n smarttrackerService.authPost(smarttrackerService.getCustomerId() + \"/mail/\", list[index++]).then(function (response) {\n sendMailsSynchronized(list, index, endFN);\n }, function (response) {\n sendMailsSynchronized(list, index, endFN);\n });\n } else {\n endFN();\n }\n }\n\n var getActionStatusKey = function (contact) {\n return contact.name + \"\" + contact.phone + contact.email;\n }\n\n $scope.getActionStatus = function (contact) {\n var name = getActionStatusKey(contact);\n return $scope.actionStatus[name];\n }\n\n $scope.updateActionStatus = function (contact, status) {\n var name = getActionStatusKey(contact);\n if ($scope.actionStatus.hasOwnProperty(name) && $scope.actionStatus[name] == status) {\n delete $scope.actionStatus[name];\n } else {\n $scope.actionStatus[name] = status;\n }\n\n var meta = $scope.alarm.meta;\n meta[\"actionStatus\"] = $scope.actionStatus;\n\n //var labels = $scope.alarm.labels;\n //labels[\"ALARM_CENTER_ACTIONS\"] = {\"value\":JSON.stringify($scope.actionStatus)};\n smarttrackerService.authPut(smarttrackerService.getCustomerId() + \"/alarm/\" + $scope.alarm.id, {\n \"meta\": meta\n });\n updateBZVisibility();\n // put update\n }\n\n $scope.trimPhoneNumber = function (nbr) {\n return nbr ? nbr.replace(/\\+/, \"00\").replace(/\\s/g, \"\") : nbr;\n }\n\n $scope.sendEmail = function (name, mail) {\n\n var md_content = \"\";\n var va = $translate([\"ASSET_SITUATION_SEND_MAIL_DIALOG_CONTENT\", \"ASSET_SITUATION_SEND_MAIL_FAILED_TEXT\", \"ASSET_SITUATION_SEND_MAIL_DIALOG_TITLE\", \"ASSET_SITUATION_SEND_MAIL_DIALOG_BUTTONS_OK\",\n \"ASSET_SITUATION_SEND_MAIL_DIALOG_PLACEHOLDER\", \"ASSET_SITUATION_SEND_MAIL_SPLASH_TITLE\", \"ASSET_SITUATION_SEND_MAIL_SPLASH_CONTENT\"\n ], {\n assetName: $scope.asset.name,\n \"contactMail\": mail\n }).then(function (lan) {\n\n\n\n md_content = lan['ASSET_SITUATION_SEND_MAIL_DIALOG_CONTENT'];\n\n\n\n dialogService.prompt(\"ASSET_SITUATION_SEND_MAIL_DIALOG_TITLE\",\n md_content, {\n okButtonText: \"ASSET_SITUATION_SEND_MAIL_DIALOG_BUTTONS_OK\",\n multiline: true,\n placeHolder: \"ASSET_SITUATION_SEND_MAIL_DIALOG_PLACEHOLDER\"\n }).then(function (data) {\n\n var dialog = dialogService.wait(\"ASSET_SITUATION_SEND_MAIL_SPLASH_TITLE\",\n \"ASSET_SITUATION_SEND_MAIL_SPLASH_CONTENT\", {});\n\n messageService.sendAssetByMail(data.promptText, $scope.asset, mail, getResponseAreaForCode(codes.ra).messageData).then(function (response) {\n //$scope.registerEvent(lan['XGUARD_SEND_MAIL_EVENT_TEXT'], data.promptText);\n dialog.close();\n }, function (response) {\n //$scope.registerEvent(lan['XGUARD_SEND_MAIL_FAILED_TEXT'], data.promptText);\n dialog.close();\n });\n }, function () { /* Cancelled */ });\n\n\n });\n }\n\n $scope.contactCalled = function (name) {\n // $translate.use(\"nl\");\n $translate(\"XGUARD_CONTACT_CALLED_EVENT_TEXT\", {\n contact: name\n }).then(function (data) {\n $scope.registerEvent(data);\n // $translate.use(\"en\");\n })\n }\n\n $scope.linkClicked = function (link) {\n $location.path(link);\n };\n\n $scope.sendSMS = function (contact) {\n var formatNumber = false;\n var number = contact.sms;\n try {\n formatNumber = $scope.trimPhoneNumber(number);\n } catch (e) {}\n if (!formatNumber) {\n alert(\"The number: \" + number + \" is not a valid phone number \" + formatNumber);\n return;\n }\n var name = contact.name;\n var va = $translate(\"ASSET_SITUATION_SMS_DIALOG_CONTENT\", {\n assetName: $scope.asset.name,\n contact: name,\n number: number\n }).then(function (data) {\n\n\n dialogService.prompt(\"ASSET_SITUATION_SEND_SMS_DIALOG_TITLE\",\n data, {\n okButtonText: \"ASSET_SITUATION_SEND_SMS_DIALOG_BUTTONS_OK\",\n multiline: true,\n placeHolder: \"ASSET_SITUATION_SEND_SMS_DIALOG_PLACEHOLDER\"\n }).then(function (data) {\n\n\n var dialog = dialogService.wait(\"ASSET_SITUATION_SMS_SPLASH_TITLE\",\n \"ASSET_SITUATION_SMS_SPLASH_CONTENT\", {});\n\n messageService.sendAssetBySMS(data.promptText, $scope.asset, contact.sms).then(function () {\n dialog.close();\n }, function (response) {\n dialog.close();\n });\n }, function (data) { /** Cancelled*/ });\n\n });\n\n }\n\n\n\n\n //ALL THE CODE BELOW CUSTOM MADE BY X-GUARD\n\n\n\n\n $scope.mapData = {\n center: {\n lat: 52.386617,\n lng: 5.799990,\n zoom: 8\n },\n defaults: {\n 'dragging': true\n },\n events: {\n map: {\n enable: ['dragstart', 'zoomstart', 'click'],\n logic: 'emit'\n }\n }\n };\n\n var smallScreen = function () {\n if ($(this).width() > 1199) {\n $scope.screenSmallitems = false\n } else {\n $scope.screenSmallitems = true\n }\n };\n\n $scope.getIconColor = function (item) {\n var clazz = 'text-danger';\n var accuracy = item.position ? item.position.accuracy : item.lastValidPosition.accuracy;\n if ($scope.isIndoor(item) || (accuracy > 0 && accuracy <= 15))\n clazz = 'text-success';\n else if (accuracy > 15 && accuracy <= 40)\n clazz = 'text-warning';\n return clazz;\n }\n\n $scope.getTimeColor = function () {\n var clazz = 'text-danger';\n if ($scope.asset && $scope.asset.lastValidPosition) {\n var assetPositionDate = moment.tz($scope.asset.lastValidPosition.timestamp, \"YYYY-MM-DDTHH:mm:ss.SSS\", \"UTC\").toDate();\n var now = new Date();\n var diff = now - assetPositionDate;\n if (diff < 901 * 1000) {\n clazz = 'text-success';\n } else if (diff < 3900 * 1000) {\n clazz = 'text-warning';\n }\n }\n return clazz;\n }\n\n var setMobileView = function () {\n if ($(this).width() < 992) {\n $scope.appFormat = true\n } else {\n $scope.appFormat = false\n }\n };\n\n $(window).width(function () {\n smallScreen();\n setMobileView();\n leafletData.getMap(\"rcmap\").then(function (map) {\n map.invalidateSize();\n });\n $scope.autoCenter();\n });\n\n $(window).resize(function () {\n smallScreen();\n setMobileView();\n leafletData.getMap(\"rcmap\").then(function (map) {\n map.invalidateSize();\n });\n $scope.autoCenter();\n });\n\n $scope.centerOnAddress = function (data) {\n leafletData.getMap(\"rcmap\").then(function (map) {\n map.setView({\n 'lat': data.point.lat,\n 'lng': data.point.lng\n }, 16);\n });\n }\n\n\n // MOBILE FORMAT\n\n $scope.currentTab = 1;\n\n $scope.switchTabs = function (number) {\n $scope.currentTab = number;\n };\n\n $scope.localAlarmScreenMap = false;\n $scope.toggleAlarmScreenMap = function () {\n $scope.localAlarmScreenMap = !$scope.localAlarmScreenMap;\n localStorage[\"AlarmScreenMapSmall\"] = $scope.localAlarmScreenMap;\n setTimeout(function () {\n $scope.initMap();\n }, 310);\n };\n\n $scope.initMap = function () {\n leafletData.getMap(\"rcmap\").then(function (map) {\n map.invalidateSize();\n });\n $scope.autoCenter();\n };\n\n $scope.initMapDelayed = function () {\n setTimeout(function () {\n $scope.initMap();\n }, 50);\n };\n\n // Bind a color to the alarm\n $scope.getAlarmColor = function (item) {\n var color = 'text-danger';\n\n if (item.logLevelFormatted == null) {\n color = 'text-danger'\n } else {\n if (item.logLevelFormatted == 'notification') {\n color = 'text-success'\n } else if (item.logLevelFormatted == 'red_alert') {\n color = 'text-danger'\n } else if (item.logLevelFormatted == 'warning') {\n color = 'text-warning'\n }\n }\n return color\n };\n\n $scope.ZoomIn = function () {\n leafletData.getMap(\"rcmap\").then(function (map) {\n map.zoomIn();\n });\n };\n\n $scope.ZoomOut = function () {\n leafletData.getMap(\"rcmap\").then(function (map) {\n map.zoomOut();\n });\n };\n\n $scope.Screensize = function () {\n if ($(window).width() > 1400) {\n $scope.Sidebar = true;\n }\n };\n\n $(window).width(function () {\n $scope.Screensize()\n });\n $(window).resize(function () {\n $scope.Screensize()\n });\n\n $scope.Sidebar = true;\n $scope.toggleSidebar = function () {\n $scope.Sidebar = !$scope.Sidebar;\n $scope.popupExpand = false;\n setTimeout(function () {\n $scope.initMap();\n }, 350);\n };\n\n $scope.localCollapseResponse = (localStorage[\"CollapseResponse\"] === \"true\");\n $scope.toggleCollapseResponse = function () {\n $scope.localCollapseResponse = !$scope.localCollapseResponse;\n localStorage[\"CollapseResponse\"] = $scope.localCollapseResponse;\n };\n\n $scope.toggleFavorites = function (value) {\n if (value) {\n $scope.clearFilter();\n $scope.localFavorites = false;\n localStorage[\"Favorites\"] = $scope.localFavorites;\n } else if ($scope.localFavorites) {\n $scope.clearFilter();\n $scope.localFavorites = false;\n localStorage[\"Favorites\"] = $scope.localFavorites;\n } else {\n $scope.showFavorites();\n $scope.localFavorites = true;\n localStorage[\"Favorites\"] = $scope.localFavorites;\n }\n };\n\n}); // End Module alarm-screen-xguard-detail\nangular.module('stwo.changelog', [\"stwo.core\"]).config(function ($stateProvider, moduleStoreProvider) {\n\n moduleStoreProvider.registerModule({\n name: \"changelog\",\n links: [{\n name: \"XGUARD_APP_CHANGELOG\",\n category: \"\",\n sref: \"secure.content.changelog\",\n sort: 10,\n icon: \"playlist-check\",\n color: \"info\",\n controllers: ['ChangelogController']\n }]\n });\n\n $stateProvider.state(\"secure.content.changelog\", {\n url: \"/changelog/\",\n templateUrl: \"modules/changelog/changelog.html\",\n controller: \"ChangelogController\",\n titleName: 'XGUARD_APP_CHANGELOG',\n titleIcon: \"playlist-check\"\n });\n\n});\n\nangular.module('stwo.changelog').controller('ChangelogController', function ($scope, smarttrackerService) {\n\n $scope.showMore = 2;\n $scope.increaseBy = function (num) {\n $scope.showMore += num;\n };\n\n $scope.language = smarttrackerService.language();\n $scope.language = $scope.language ? $scope.language : 'en';\n\n $scope.items = {};\n\n $scope.items['1.6.3'] = {\n beta: false,\n update: false,\n date: '18 februari 2021',\n module: [\n {\n name: {\n 'nl': 'Alarmweergave',\n 'en': 'Alarm details',\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Dubbel geplaatste comments',\n 'en': 'Comments appearing twice'\n },\n subtext: {\n 'nl': 'Er is een probleem opgelost waarbij mogelijk het geplaatste commentaar twee keer (of vaker) werd geplaatst.',\n 'en': 'A problem was resolved where it was possible that a placed comment appeared more than once.'\n }\n }\n ]\n },\n ]\n };\n\n $scope.items['1.6.2'] = {\n beta: false,\n update: false,\n date: '27 augustus 2020',\n module: [\n {\n name: {\n 'nl': 'Telefoongesprekken (groene box)',\n 'en': 'Calls (green box)',\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Automatisch gedempte lijn bij paniekalarmen',\n 'en': 'Automatically muted phone calls for panic alarms'\n },\n subtext: {\n 'nl': 'Bij een paniekalarm is de lijn nu automatisch gedempt. Via de gemakkelijke interface kunt u uzelf dempen of ontdempen.',\n 'en': 'The phone calls are now automatically muted for pany alarms. You can easily mute or unmute yourself through the user interface.'\n }\n }\n ]\n },\n ]\n };\n\n $scope.items['1.6.1'] = {\n beta: false,\n update: false,\n date: '17 maart 2020',\n module: [\n {\n name: {\n 'nl': 'Alarmen',\n 'en': 'Alarms',\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'SMS- en e-mailberichten',\n 'en': 'Texts and e-mails'\n },\n subtext: {\n 'nl': 'Het versturen van een sms- of e-mailbericht is nu overzichtelijker. Daarnaast is de e-mail, die binnenkomt bij de ontvangende partij nu opgemaakt en overzichtlijk.',\n 'en': 'Sending an text or e-mail has been improved. The e-mail containing information about an alarm is now well-designed.'\n }\n }\n ]\n },\n ]\n };\n\n $scope.items['1.6.0'] = {\n beta: false,\n update: false,\n date: '6 februari 2020',\n module: [\n {\n name: {\n 'nl': 'Alarmen',\n 'en': 'Alarms',\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Volgorde opvolging',\n 'en': 'Response order'\n },\n subtext: {\n 'nl': 'De volgorde van de opvolging is aangepast. Een surveillant die de X-Guard Alarm-app gebruikt krijgt een hogere prioriteit dan beveiligingsbedrijven zonder X-Guard Alarm.',\n 'en': 'The response order has been changed to give more priority to professional X-Guard Alarm responders.'\n }\n },\n {\n icon: 'star',\n title: {\n 'nl': 'Inkomende gesprekken',\n 'en': 'Incoming calls'\n },\n subtext: {\n 'nl': 'Voor alarmen waarbij een aanbelcode beschikbaar is hebben we kleine visuele veranderingen doorgevoerd.',\n 'en': 'We made smal visual changes for alarms where an incoming call is available to pick up.'\n }\n },,\n {\n icon: 'star',\n title: {\n 'nl': 'Adressen',\n 'en': 'Addresses'\n },\n subtext: {\n 'nl': 'Klik op een adres om deze op te zoeken in Google Maps',\n 'en': 'You can now click an address to open it on Google Maps'\n }\n },\n ]\n },\n ]\n };\n\n $scope.items['1.5.7, 1.5.8'] = {\n beta: false,\n update: false,\n date: '6 december 2019',\n module: [\n {\n name: {\n 'nl': 'Alarmen',\n 'en': 'Alarms',\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Het nieuwe bellen is nu mogelijk via de Alarm Manager',\n 'en': 'The new calling method is now available in the alarm manager.'\n },\n subtext: {\n 'nl': 'U kunt vanaf nu telefoongesprekken oppakken via de Alarm Manager. Dit is alleen actief voor klanten en meldkamers waarbij dit met de meldkamer is besproken.',\n 'en': 'You are now able to get the phone call dynamically. This only has been activated for Alarm Centers who have been trained to use this feature.'\n }\n },\n ]\n },\n ]\n };\n\n $scope.items['1.5.6'] = {\n beta: false,\n update: false,\n date: '26 juli 2019',\n module: [\n {\n name: {\n 'nl': 'Alarmen',\n 'en': 'Alarms',\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Afmelden van alarmen zonder geldige positie',\n 'en': 'Acknowledging alarms without a valid position'\n },\n subtext: {\n 'nl': 'Er is een probleem opgelost waarbij het niet mogelijk was om een alarm af te melden wanneer er geen positie werd meegestuurd met het alarm.',\n 'en': 'A problem with acknowledging alarms which do not have a valid position has been resolved.'\n }\n },\n ]\n },\n ]\n };\n\n $scope.items['1.5.5'] = {\n beta: false,\n update: false,\n date: '7 juni 2019',\n module: [\n {\n name: {\n 'nl': 'SMS-berichten verzenden',\n 'en': 'Sending SMS messages'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Toevoeging van sjablonen aan SMS-berichten',\n 'en': 'Added templates to SMS messages'\n },\n subtext: {\n 'nl': 'Je kan bij het verzenden van een SMS nu een door ons vooraf geselecteerd bericht versturen.',\n 'en': 'It is now possible to select predefined messages for SMS messages'\n }\n },\n ]\n },\n ]\n };\n\n $scope.items['1.5.4'] = {\n beta: false,\n update: false,\n date: '24 mei 2019',\n module: [\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Logteksten op alfabetische volgorde',\n 'en': 'Log templates are now sorted'\n },\n subtext: {\n 'nl': 'Op verzoek staan nu alle logteksten op alfabetische volgorde.',\n 'en': 'All log templates are now sorted alphabetically.'\n }\n },\n {\n icon: 'star',\n title: {\n 'nl': 'Verbeterde ingangen voor meldkamers',\n 'en': 'Improved Alarm Center setup'\n },\n subtext: {\n 'nl': 'Technische verbetering voor specifieke alarmcentrale setup waarbij een alarm geopend wordt vanuit externe software.',\n 'en': 'Technical improvement in how alarms are opened from external software.'\n }\n },\n ]\n },\n ]\n };\n\n $scope.items['1.5.3'] = {\n beta: false,\n update: false,\n date: '18 februari 2019',\n module: [\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Alarmweergave',\n 'en': 'Alarm overview'\n },\n subtext: {\n 'nl': 'De tijd van een alarm wordt nu altijd weergegeven met tijdsaanduiding naast de standaard \"x minuten geleden\" weergave.',\n 'en': 'The alarm time is now always displayed with the actual date and time, on top of the already shown \"x minutes ago\" message.'\n }\n },\n {\n icon: 'star',\n title: {\n 'nl': 'Afmelden alarmen',\n 'en': 'Acknowledging alarms'\n },\n subtext: {\n 'nl': 'Het is nu mogeljik aan te geven dat de vraag of een klant tevreden is \"n.v.t\" is. In dit geval worden de afmeldingsvragen overgslagen.',\n 'en': 'It is now possible to answer \"n/a\" to the question if the customer is satisfied. In that case, the acknowledgement survey will be skipped.'\n }\n },\n {\n icon: 'bug',\n title: {\n 'nl': 'Vaste posities',\n 'en': 'Fixed positions'\n },\n subtext: {\n 'nl': 'Er is een probleem opgelost met het tonen van vaste posities.',\n 'en': 'We solved a problem with showing fixed positions.'\n }\n },\n ]\n },\n ]\n };\n\n $scope.items['1.5.2'] = {\n beta: false,\n update: false,\n date: '23 januari 2019',\n module: [\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Afmelden alarmen',\n 'en': 'Acknowledging alarms'\n },\n subtext: {\n 'nl': 'Er is een probleem opgelost met het invoeren van commentaar door de centralist.',\n 'en': 'We solved a problem with adding alarm acknowledgement comments by alarm center personnel.'\n }\n },\n ]\n },\n ]\n };\n\n $scope.items['1.5.1'] = {\n beta: false,\n update: false,\n date: '16 januari 2019',\n module: [\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Afmelden alarmen',\n 'en': 'Acknowledging alarms'\n },\n subtext: {\n 'nl': 'In aanvulling op de vragen die gesteld worden aan een centralist bij het afmelden van een alarm, wordt nu ook een significant verbeterde e-mail verstuurd naar de eindgebruiker.',\n 'en': 'In additition to the questions asked to the alarm center personnel, we also made an effort to hugely improve the emails which are sent when an alarm is acknowledged.'\n }\n },\n ]\n },\n ]\n };\n\n $scope.items['1.5.0'] = {\n beta: false,\n update: false,\n date: '15 januari 2019',\n module: [\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Afmelden alarmen',\n 'en': 'Acknowledging alarms'\n },\n subtext: {\n 'nl': 'Wanneer je een alarm wil afmelden vraagt het systeem nu naar de kwaliteit van het alarm. Deze informatie wordt gebruikt om onze dienstverlening te verbeteren en het gemakkelijker te maken voor centralisten om een alarm met zo veel mogelijk informatie af te melden.',\n 'en': 'When acknowledging alarms the system will now guide you through a short quality control survey.'\n }\n },\n {\n icon: 'star',\n title: {\n 'nl': 'Commentaarsjablonen',\n 'en': 'Comment templates'\n },\n subtext: {\n 'nl': 'Veelvoorkomend commentaar kan nu worden geselecteerd uit een handige sjabloonbox.',\n 'en': 'Frequently used comments for alarms are now selectable as comment templates.'\n }\n },\n ]\n },\n ]\n };\n\n $scope.items['1.4.3'] = {\n beta: false,\n update: false,\n date: '10 december 2018',\n module: [\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Objecten',\n 'en': 'Objects'\n },\n subtext: {\n 'nl': 'Vaste objecten kunnen nu videobeelden tonen.',\n 'en': 'Objects are now able to refer to video cameras.'\n }\n },\n ]\n },\n ]\n };\n\n $scope.items['1.4.2'] = {\n beta: false,\n update: false,\n date: '12 november 2018',\n module: [\n {\n name: {\n 'nl': 'Personen',\n 'en': 'Assets'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Alarmen maken',\n 'en': 'Raising alarms'\n },\n subtext: {\n 'nl': 'De functie om een alarm te maken via de X-Guard Alarm Manager is bijgewerkt om de meldkamerprocedure mee te sturen.',\n 'en': 'The raise alarm functionality is updated to also send the alarm centre procedure with an alarm.'\n }\n },\n ]\n },\n ]\n };\n\n $scope.items['1.4.1'] = {\n beta: false,\n update: false,\n date: '5 november 2018',\n module: [\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Objecten',\n 'en': 'Objects'\n },\n subtext: {\n 'nl': 'Er is een probleem opgelost waarbij Objecten niet verschenen in de alarmweergave voor meldkamers.',\n 'en': 'We solved a problem where Objects in some cases were not shown to alarm centres.'\n }\n },\n ]\n },\n ]\n };\n\n $scope.items['1.4.0'] = {\n beta: false,\n update: false,\n date: '1 november 2018',\n module: [\n {\n name: {\n 'nl': 'Menu',\n 'en': 'Menu'\n },\n fixes: [\n {\n icon: 'check',\n title: {\n 'nl': 'Alarmmeldingen',\n 'en': 'Alarm notifications'\n },\n subtext: {\n 'nl': 'De schakelaar voor het ontvangen van alarmmeldingen staat nu ook in het menu.',\n 'en': 'The toggle to enable alarm notifications is now also available in the menu.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Quick Response',\n 'en': 'Quick Response'\n },\n subtext: {\n 'nl': 'Bij \"Quick Response\" staat nu aangegeven hoe oud de positie van een Quick Responder is.',\n 'en': 'The location age is now displayed in the \"Quick Response\" information for a Quick Responder.'\n }\n },\n {\n icon: 'star',\n title: {\n 'nl': 'Objecten',\n 'en': 'Objects'\n },\n subtext: {\n 'nl': 'Het is nu mogelijk om vaste objecten op te nemen in het \"Quick Response\"-protocol.',\n 'en': 'It is now possible to show fixed objects in the \"Quick Response\" follow up protocol.'\n }\n },\n {\n icon: 'check',\n title: {\n 'nl': 'Alarmen zonder afmelding',\n 'en': 'Alarms without acknowledgements'\n },\n subtext: {\n 'nl': 'Voor klanten die gebruik maken van alarmen die niet afgemeld hoeven te worden zijn een aantal verbeteringen doorgevoerd. Het is nu duidelijk zichtbaar dat een alarm automatisch is afgemeld door het systeem.',\n 'en': 'Alarms which do not need acknowledgements do now have an improved alarm overview. It is now clearly visible the alarm has been acknowledged automatically.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Beveiligde Navigatie',\n 'en': 'Secure Navigation'\n },\n fixes: [\n {\n icon: 'check',\n title: {\n 'nl': 'iOS-probleem opgelost',\n 'en': 'iOS specific problem solved'\n },\n subtext: {\n 'nl': 'Een probleem waarbij Maps niet wou starten bij het gebruik van Beveiligde Navigatie op iOS is verholpen.',\n 'en': 'We solved a problem where Maps was not opening after using Secure Navigation on iOS devices.'\n }\n }\n ]\n },\n ]\n };\n\n $scope.items['1.3.1'] = {\n beta: false,\n update: false,\n date: '17 september 2018',\n module: [\n {\n name: {\n 'nl': 'Stabiliteitsupdates',\n 'en': 'Stability improvements'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Snelheid systeem',\n 'en': 'Speed of system'\n },\n subtext: {\n 'nl': 'Verschillende functies hebben verbeterde snelheden.',\n 'en': 'Various functions now have improved speeds.'\n }\n },\n {\n icon: 'star',\n title: {\n 'nl': 'Klantnaam zichtbaar voor alarmcentrales',\n 'en': 'Customer name now visible for alarm centers.'\n },\n subtext: {\n 'nl': 'Alarmcentrales zien nu vanuit welke klant een melding komt, naast de standaardinformatie over een persoon.',\n 'en': 'Alarm Centers now see information about the customer on top of the asset information already available.'\n }\n }\n ]\n }\n ]\n };\n\n $scope.items['1.3.0'] = {\n beta: false,\n update: false,\n date: '21 juni 2018',\n module: [\n {\n name: {\n 'nl': 'Nieuwe cloudomgeving aangesloten',\n 'en': 'Connected new Cloud environment'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Onderhoudsupdate',\n 'en': 'Maintenance update'\n },\n subtext: {\n 'nl': 'In deze versie is de Alarm Manager opnieuw geconfigureerd om te werken met de nieuwe cloudomgeving.',\n 'en': 'In this update the Alarm Manager has been updated to work with the new Cloud environment'\n }\n }\n ]\n }\n ]\n };\n\n $scope.items['1.2.0'] = {\n beta: false,\n update: false,\n date: '12 juni 2018',\n module: [\n {\n name: {\n 'nl': 'SMS- en email-voorbeelden',\n 'en': 'SMS and e-mail previews'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Nieuwe functionaliteit',\n 'en': 'New functionality'\n },\n subtext: {\n 'nl': 'Het is vanaf vandaag mogelijk om bij het verzenden van een SMS of e-mail naar een persoon in de opvolginslijst deze e-mail eerst te zien en/of aan te passen.',\n 'en': 'It is now possible to preview and/or edit any text messages or e-mails to people in the response follow up list.'\n }\n }\n ]\n }\n ]\n };\n\n $scope.items['1.1.8'] = {\n beta: false,\n update: false,\n date: '1 mei 2018',\n module: [\n {\n name: {\n 'nl': 'Beveiligde Navigatie',\n 'en': 'Secure Navigation'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Probleem opgelost',\n 'en': 'Resolved minor problem'\n },\n subtext: {\n 'nl': 'Probleem opgelost waarbij op iPhones de kaart niet juist opende',\n 'en': 'Resolved problem where the map sometimes did not open'\n }\n }\n ]\n }\n ]\n };\n\n $scope.items['1.1.6, 1.1.7'] = {\n beta: false,\n update: false,\n date: '10 april 2018',\n module: [\n {\n name: {\n 'nl': 'Wachtwoord Vergeten',\n 'en': 'Password Reset'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Heractivatie functionaliteit',\n 'en': 'Reactivation of functionality'\n },\n subtext: {\n 'nl': 'We zijn verheugd te melden dat vanaf heden de Wachtwoord Vergeten-functionaliteit weer naar behoren werkt. ',\n 'en': 'We are happy to announce the Password Reset functionality is now fully workign again.'\n }\n }\n ]\n }\n ]\n };\n\n $scope.items['1.1.4, 1.1.5'] = {\n beta: false,\n update: false,\n date: '29 maart 2018',\n module: [\n {\n name: {\n 'nl': 'Kaart',\n 'en': 'Maps'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Inactieve locaties',\n 'en': 'Inactive locations'\n },\n subtext: {\n 'nl': 'Locaties die ouder zijn dan 3 uur worden nu grijs weergegeven op de kaart.',\n 'en': 'Locations older than 3 minutes are now shown grey on the map.'\n }\n }\n ] \n },\n {\n name: {\n 'nl': 'Beveiligde Navigatie',\n 'en': 'Secure Navigation'\n },\n fixes: [\n {\n icon: 'check',\n title: {\n 'nl': 'Huisnummercheck',\n 'en': 'House number check'\n },\n subtext: {\n 'nl': 'Beveiligde Navigatie controleerd nu of u navigeert naar een adres met huisnummer.',\n 'en': 'Secure Navigation now checks if you are navigating to an address with a house number.'\n }\n },\n {\n icon: 'check',\n title: {\n 'nl': 'Bekende X-Guard locatie',\n 'en': 'Known X-Guard location'\n },\n subtext: {\n 'nl': 'Adressen die eerder gebruikt zijn tijdens het gebruik van Beveiligde Navigatie worden nu groen gemarkeerd.',\n 'en': 'Addresses which have been entered before in Secure Navigation are now marked green.'\n }\n },\n {\n icon: 'star',\n title: {\n 'nl': 'Betere adresweergave',\n 'en': 'Improved display of addresses'\n },\n subtext: {\n 'nl': 'Adressen worden nu inclusief de naam van een gebouw of bedrijf weergegeven, indien deze is ingevoerd.',\n 'en': 'Adresses are now shown including the name of a building or business, when entered.'\n }\n },\n {\n icon: 'bug',\n title: {\n 'nl': 'Verschillende kleine stabiliteitsupdates',\n 'en': 'Various small stability improvements'\n },\n subtext: {\n 'nl': 'Er zijn verschillende kleine aanpassingen gedaan om de stabiliteit van Beveiligde Navigatie te verbeteren.',\n 'en': 'We have done various small updates to improve the stability of Secure Navigation.'\n }\n }\n ] \n }\n ]\n };\n\n $scope.items['1.1.3'] = {\n beta: false,\n update: false,\n date: '1 maart 2018',\n module: [\n {\n name: {\n 'nl': 'Beveiligde Navigatie',\n 'en': 'Secure Navigation'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Stabiliteit Beveiligde Navigatie',\n 'en': 'Stability of Secure Navigation'\n },\n subtext: {\n 'nl': 'Voor de werking van Beveiligde Navigatie maken we gebruik van een API van Google. Helaas is deze vandaag gestopt met werken. Deze update wijzigt de werking van Beveiligde Navigatie zodanig dat we geen gebruik meer maken van deze API.',\n 'en': 'The Secure Navigation functionality uses a Google API to enable searching for addresses. Unfortunately this API stopped working this morning. This updates changes the Secure Navigation functionality so we do not rely on this API.'\n }\n }\n ]\n }\n ]\n };\n\n $scope.items['1.1.1, 1.1.2'] = {\n beta: false,\n update: false,\n date: '22 februari 2018',\n module: [\n {\n name: {\n 'nl': 'Nieuwe stijl',\n 'en': 'New styling'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Uitrol van het nieuwe X-Guard',\n 'en': 'Deployment of the new X-Guard'\n },\n subtext: {\n 'nl': 'X-Guard is continu bezig met vernieuwen. Bij een nieuwe website hoort een nieuw logo. Met trots presenteren wij u de nieuwe website.',\n 'en': 'X-Guard focuses on continous improvement. With a new website comes a new logo. We proudly present you the new X-Guard website'\n }\n }\n ]\n }\n ]\n };\n\n $scope.items['1.1.0'] = {\n beta: false,\n update: false,\n date: '19 februari 2018',\n module: [\n {\n name: {\n 'nl': 'Beveiligde Navigatie',\n 'en': 'Secure Navigation'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Beveiligd Navigeren',\n 'en': 'Secure Navigation'\n },\n subtext: {\n 'nl': 'Vanaf heden kunt u via de knop Beveiligde Navigatie uw route naar thuisadressen plannen. Uw eindbestemming wordt opgeslagen als binnenlocatie voor het nauwkeurig vaststellen van uw locatie.',\n 'en': 'You can now start Secure Navigation to navigate to home addresses securely. Your destination will be saved as an indoor position to make sure your location is correct on arrival.'\n }\n }\n ]\n }\n ]\n };\n\n $scope.items['1.0.0'] = {\n beta: false,\n update: false,\n date: '23 januari 2018',\n module: [\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Notificaties sturen naar Quick Response',\n 'en': 'Send notifications to Quick Response'\n },\n subtext: {\n 'nl': 'Tijdens een alarm kan er een notificatie gestuurd worden naar de dichtsbijzijnde Quick Responders.',\n 'en': 'During an alarm, a notification can be sent to the nearest Quick Responders.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Notificatiecentrum',\n 'en': 'Notification center'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Notificaties in de statusbalk',\n 'en': 'Notifications in the status bar'\n },\n subtext: {\n 'nl': 'Nieuwe notificatie worden getoond in de statusbalk. Vanaf hier kunnen notificaties bekeken en gewist worden.',\n 'en': 'New notifications will be shown in the status bar. From here notifications can be viewed and deleted.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Zones',\n 'en': 'Zones'\n },\n fixes: [\n {\n icon: 'check',\n title: {\n 'nl': 'Verdieping toevoegen',\n 'en': 'Add floorlevel'\n },\n subtext: {\n 'nl': 'Het is nu mogelijk om de verdieping van een zone aan te geven.',\n 'en': 'It is now possible to add the floorlevel of the zone.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Modules die een kaart tonen',\n 'en': 'Modules that show a map'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Zoek een adres op de kaart',\n 'en': 'Search address on the map'\n },\n subtext: {\n 'nl': 'Alle modules waar een kaart wordt getoond, bevat nu een zoekknop om snel naar een adres naar keuze te navigeren. De meest recente zoekopdrachten worden opgeslagen zodat deze snel getoond kunnen worden.',\n 'en': 'All modules where a map is shown, now contain a search button to quickly navigate to an address of your choice. The most recent searches are saved so that they can be displayed quickly.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Nieuwe Response check module',\n 'en': 'New Response check module'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Bekijk de huidige situatie voor uw response',\n 'en': 'View the current situation for your response'\n },\n subtext: {\n 'nl': 'Deze module toont u een situatie overzicht van de huidige response om u heen.',\n 'en': 'This module shows you a situation overview of the current response around you.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Nieuwe tekeningen module',\n 'en': 'New Drawings module'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Toevoegen van tekeningen aan de kaart',\n 'en': 'Adding drawings to the map'\n },\n subtext: {\n 'nl': 'Met deze module is het mogelijk om afbeeldingen aan het Alarm Manager kaartsysteem toe te voegen per verdieping. Deze kaarten zijn zichtbaar voor u en de alarmcentrale.',\n 'en': 'With this module you can add image overlays to the Alarm Manager map for multiple levels. These drawings are visibile for u and the monitoring center'\n }\n }\n ]\n }\n ]\n };\n\n $scope.items['2017.11'] = {\n beta: false,\n update: false,\n date: '28 november 2017',\n module: [\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Problemen na laatste update',\n 'en': 'Problems after last update'\n },\n subtext: {\n 'nl': 'De afgelopen update bracht voor specifieke gebruikers enkele problemen met zich mee. Deze zijn verholpen. Dit is onder andere het tonen van de ingelogde gebruiker in de bovenbalk en het niet kunnen aanpassen van de taal en geluidsnotificatie instellingen.',\n 'en': 'The last update caused some problems for specific users. These have been solved. This includes displaying the logged-in user in the notification bar and not being able to change the language and sound notification settings.'\n }\n },\n {\n icon: 'check',\n title: {\n 'nl': 'Alarm filters',\n 'en': 'Alarm filters'\n },\n subtext: {\n 'nl': 'Filters worden nu correct toegepast als de pagina vernieuwd wordt of wanneer je terugkeert naar de overzichtspagina van de alarmen.',\n 'en': 'Filters are now correctly applied when the page is refreshed or when you return to the overview page of the alarms.'\n }\n },\n {\n icon: 'check',\n title: {\n 'nl': 'Crash naar inlogscherm',\n 'en': 'Crash to login screen'\n },\n subtext: {\n 'nl': 'In uitzonderlijke gevallen kon het voorkomen dat de alarm pagina werd afgesloten en je terug werd gebracht naar de inlogpagina. Dit is verholpen.',\n 'en': 'In exceptional cases it could happen that the alarm page was closed and you were taken back to the login page. This has been solved.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': \"Zoeken op pagina's\",\n 'en': 'Searching on pages'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Fout in zoekbanner',\n 'en': 'Error in search banner'\n },\n subtext: {\n 'nl': 'De gele zoekbanner wordt nu correct bijgewerkt als er vaker achter elkaar gezocht wordt.',\n 'en': 'The yellow search banner is now correctly updated if you do multiple searches.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Personen bewerken',\n 'en': 'Edit persons'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Niet kunnen openen van persoonlijke contacten',\n 'en': 'Unable to open the personal contacts'\n },\n subtext: {\n 'nl': 'Het kwam voor dat een persoonlijk contact soms niet geopend kon worden. Dit is opgelost.',\n 'en': 'It sometimes happened that a personal contact could not be opened. This has been resolved.'\n }\n },\n {\n icon: 'check',\n title: {\n 'nl': 'Nieuwe personen aanmaken',\n 'en': 'Creating new person'\n },\n subtext: {\n 'nl': 'Alle velden zijn nu direct actief als er een nieuw persoon aangemaakt wordt. Voorheen moest dan vaak de persoon eerst opnieuw geladen worden.',\n 'en': 'All fields are now immediately active when a new person is created. Previously, the person often had to be reloaded first.'\n }\n }\n ]\n }\n ]\n };\n\n\n $scope.items['2017.10'] = {\n beta: false,\n update: false,\n date: '16 november 2017',\n module: [\n {\n name: {\n 'nl': 'Alarm Manager Android',\n 'en': 'Alarm Manager Android'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Alarm notificaties',\n 'en': 'Alarm notifications'\n },\n subtext: {\n 'nl': 'Indien u push notificaties heeft geactiveerd zal tijdens een alarm een popup verschijnen met daarin meer informatie omtrent het alarm.',\n 'en': 'If you have activated push notifications, a pop-up will appear during an alarm with more information about the alarm.'\n }\n }\n ]\n }\n ]\n };\n\n\n $scope.items['2017.9'] = {\n beta: false,\n update: false,\n date: '25 september 2017',\n module: [\n {\n name: {\n 'nl': 'Verbeterde layout',\n 'en': 'Improved layout'\n },\n fixes: [\n {\n icon: 'check',\n title: {\n 'nl': 'Verbeterde layout safari',\n 'en': 'Improved safari layout'\n },\n subtext: {\n 'nl': 'De layout voor de safari browser (Apple) is verbeterd en geoptimaliseerd. Met name de mobiele versie voor iPhones gebruikers.',\n 'en': 'The layout for the safari browser (Apple) has been improved and optimized. Especially the mobile version for iPhone users.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Zone beheer',\n 'en': 'Zone management'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Kaart centreren op locatie',\n 'en': 'Center map on location'\n },\n subtext: {\n 'nl': 'De zone bewerk tools geven nu de mogelijkheid om de kaart automatisch op een adres te centreren.',\n 'en': 'The zone editing tools now allow you to automatically center the map on an address.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Filteren op tijdsduur',\n 'en': 'Filter on timespan'\n },\n subtext: {\n 'nl': 'In enkele gevallen was het niet mogelijk om op tijdsduur te filteren. Dit is opgelost.',\n 'en': 'In some cases, it was not possible to filter for a certain timespan. This is solved.'\n }\n },\n {\n icon: 'bug',\n title: {\n 'nl': 'Dubbele alarmen',\n 'en': 'Doule alarms'\n },\n subtext: {\n 'nl': \"Actieve alarmen werden tevens weergegeven onder het kopje 'afgemelde alarmen'. Dit is verholpen.\",\n 'en': \"Active alarms were also displayed under the heading 'Acknowledged alarms'. This has been fixed.\"\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Bewerkt personen',\n 'en': 'Edit persons'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Persoon kopieëren',\n 'en': 'Duplicate person'\n },\n subtext: {\n 'nl': 'Het is nu mogelijk om een persoon te kopieëren. Zo kan er eenvoudig een persoon ingericht worden met bijvoorbeeld contacturen en groep instellingen die vervolgens gekopieërd kan worden voor de verder in te richten personen.',\n 'en': 'It is now possible to duplicate a person. For example, a person can easily be configured with, for example, contact hours and group settings that can then be copied for the other persons that need to be added.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Inloggen',\n 'en': 'Logging in'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Inlog token verlopen',\n 'en': 'Login token expired'\n },\n subtext: {\n 'nl': 'De functie dat een inlog token kan verlopen is voorlopig uitgeschakeld. Deze toevoeging geeft nog te veel problemen.',\n 'en': 'The function that a login token can expire has been temporarily disabled. This addition still gives too many problems.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Instellingen pagina',\n 'en': 'Settings page'\n },\n fixes: [\n {\n icon: 'check',\n title: {\n 'nl': 'Verbeterde layout',\n 'en': 'Improved layout'\n },\n subtext: {\n 'nl': 'De instellingen pagina is nu duidelijker en beter geoptimaliseerd voor mobiele apparaten.',\n 'en': 'The settings page is now more clear and better optimized for mobile devices.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Wat is er nieuw?',\n 'en': \"What's new?\"\n },\n fixes: [\n {\n icon: 'check',\n title: {\n 'nl': 'Nu ook Engels',\n 'en': 'Now including English'\n },\n subtext: {\n 'nl': 'Deze lijst met wijzigingen en verbeteringen is nu ook in het Engels beschikbaar',\n 'en': 'This list with additions and improvement is now also available in English.'\n }\n }\n ]\n }\n ]\n };\n\n $scope.items['2017.8'] = {\n beta: false,\n update: false,\n date: '20 juli 2017',\n module: [{\n name: {\n 'en': 'Settings',\n 'nl': 'Instellingen'\n },\n fixes: [\n {\n title: {\n 'en': 'Notification Sounds',\n 'nl': 'Notificatie geluiden'\n },\n subtext: {\n 'en': 'The 4 type notification sounds can now be set to the desired settings on the settings page. Note: These sounds only work in the web application and are not yet available for the Android and iOS apps. ',\n 'nl': 'De 4 type notificatie geluiden kunnen nu naar eigen wens ingesteld worden op de instellingen pagina. Let op: Deze geluiden werken nu alleen nog in de web applicatie en zijn nog niet beschikbaar voor de Android en iOS apps.'\n },\n icon: \"star\"\n },\n {\n icon: 'check',\n title: {\n 'nl': 'Snooze is verwijderd',\n 'en': 'Snooze is removed'\n },\n subtext: {\n 'nl': 'Vanwege onduidelijkheid is de snooze optie weggehaald. In plaats daarvan is het beheren van de afzonderlijke geluiden verbeterd.',\n 'en': 'Due to ambiguity, the snooze option has been removed. Instead, the management of the individual sounds has been improved.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Bewerk personen',\n 'en': 'Edit persons'\n },\n fixes: [\n {\n icon: 'check',\n title: {\n 'nl': 'Beschrijving annuleren',\n 'en': 'Cancel the description edit'\n },\n subtext: {\n 'nl': 'Indien u een beschrijving hebt bewerkt maar deze toch niet op wilt slaan, bestaat er nu de mogelijkheid de wijzigingen te annuleren.',\n 'en': 'If you have edited a description but do not want to save it, there is now the possibility to cancel the changes.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Kaart',\n 'en': 'Map'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'ln': 'Apparaat status en geschiedenis',\n 'en': 'Device status and history'\n },\n subtext: {\n 'nl': 'De laatste status en recente geschiedenis van het apparaat kan worden getoond op de kaart onder de persoon. Het hangt af van uw rechten of deze functie zichtbaar is.',\n 'en': 'The latest status and recent history of the device can be displayed on the map below the person. It depends on your rights or this feature is visible.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Favorieten',\n 'en': 'Favorites'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Favorieten onverwachts geactiveerd',\n 'en': 'Favorites unexpectedly activated'\n },\n subtext: {\n 'nl': 'Het kon voorkomen dat de favorieten onverwachts werden geactiveerd. Dit is verholpen.',\n 'en': 'The favorites may be activated unexpectedly. This has been fixed.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Fout in layout',\n 'en': 'Error in layout'\n },\n subtext: {\n 'nl': 'Een fout in de layout van het gebeurtenissenlogboek is opgelost.',\n 'en': 'An error in the event log layout has been resolved.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Wereldkaart',\n 'en': 'World map'\n },\n fixes: [\n {\n icon: 'check',\n title: {\n 'nl': 'Verder inzoomen mogelijk',\n 'en': 'Further zooming possible'\n },\n subtext: {\n 'nl': 'Het is nu mogelijk om tot 2x verder in te zoomen op de kaart. Het kan voorkomen dat de kaart onscherper oogt op het diepste zoomniveau. Dit is beschikbaar gemaakt voor alle modules waar een kaart getoond wordt.',\n 'en': 'It is now possible to zoom in to 2x further on the map. The map may appear unsharp at the deepest zoom level. This is made available to all modules where a map is displayed.'\n }\n }\n ]\n }\n ]\n };\n\n $scope.items['2017.7'] = {\n date: '27 juni 2017',\n module: [\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Alarmen filteren en zoeken',\n 'en': 'Filtering and searching alarms'\n },\n subtext: {\n 'nl': 'Het is nu mogelijk om alarmen te filteren en zoeken op bijvoorbeeld naam en binnen een bepaalde periode.',\n 'en': 'It is now possible to filter alarms and search alarms depending on for example the name or within a specified period.'\n }\n },\n {\n icon: 'check',\n title: {\n 'nl': 'Tijd van afmelden',\n 'en': 'Time of acknowledgement'\n },\n subtext: {\n 'nl': 'De tijd en datum waarop het alarm is afgemeld wordt nu getoond op de alarm pagina.',\n 'en': 'The time and date of the alarm acknowledgement is now displayed on the alarm page.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Kaart',\n 'en': 'Map'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Zoeken op de kaart',\n 'en': 'Searching on the map'\n },\n subtext: {\n 'nl': 'Als er gezocht wordt naar bepaalde personen op de kaart, dan zullen nu ook alleen deze personen zichtbaar zijn op de kaart. Voorheen bleven alle personen zichtbaar.',\n 'en': 'When looking for certain people on the map, now only those people will be visible on the map. Previously all persons remained visible.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Kaart en bewerk personen',\n 'en': 'Map and edit persons'\n },\n fixes: [\n {\n icon: 'star',\n title: {\n 'nl': 'Zoeken op ID',\n 'en': 'Search on ID'\n },\n subtext: {\n 'nl': 'Er kan nu ook gezocht worden op het ID en het externe ID van de personen. Dit kan door op het kleine pijltje naast de zoekbalk te klikken.',\n 'en': 'You can now also search for the ID and external ID of the people. This can be done by clicking the small arrow next to the search bar.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Nieuwe binnenposities',\n 'en': 'New indoor positions'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Kaart symbolen',\n 'en': 'Map symbols'\n },\n subtext: {\n 'nl': 'De symbolen op de kaart zijn weer hersteld. Door een bug waren deze niet zichtbaar.',\n 'en': 'The symbols on the map are restored. Due to a bug these were not visible.'\n }\n }\n ]\n },\n {\n name: {\n 'nl': 'Algemeen',\n 'en': 'Global'\n },\n fixes: [\n {\n icon: 'check',\n title: {\n 'nl': 'Gesplitste notificaties',\n 'en': 'Splitted notifications'\n },\n subtext: {\n 'nl': 'De verschillende alarmen worden nu gescheiden in de notificatiebalk getoond (Rood, oranje en groen). Tevens opent de knop direct het alarm als er maar één alarm open staat. Nieuwe binnenposities worden nu blauw weergegeven.',\n 'en': 'The different alarms are now separated in the notification bar (Red, Orange, and Green). The button also opens the alarm immediately when there is only one alarm open. New indoor positions will now appear blue.'\n }\n },\n {\n icon: 'bug',\n title: {\n 'nl': 'Favorieten',\n 'en': 'Favorites'\n },\n subtext: {\n 'nl': 'In bepaalde situaties kon het voorkomen dat de favorieten knop niet naar behoren werkte, dit is opgelost.',\n 'en': 'In certain situations, the favorites button did not work properly, this is resolved.'\n }\n }\n ]\n }\n ]\n };\n\n $scope.items['2017.6'] = {\n date: '23 mei 2017',\n module: [\n {\n name: {\n 'nl': 'Alarm Manager',\n 'en': 'Alarm Manager'\n },\n fixes: [\n {\n icon: 'bug',\n title: {\n 'nl': 'Alarm kan niet geopend worden',\n 'en': 'Alarm cannot be opened'\n },\n subtext: {\n 'nl': 'In bepaalde situaties ontstond de fout dat het alarm niet geopend kon worden. Er werd alleen een grijs scherm getoond. Dit is nu verholpen.',\n 'en': 'In some situations, the error occurred that the alarm could not be opened. Only a gray screen was shown. This is now fixed.'\n }\n }\n ]\n }\n ]\n };\n\n // $scope.items = [\n //\n // {\n // date: '23 mei 2017',\n // version: '2017.6',\n // module: [\n // {\n // name: 'Alarm Manager',\n // fixes: [\n // {\n // icon: 'bug',\n // title: 'Alarm kan niet geopend worden',\n // subtext: 'In bepaalde situaties ontstond de fout dat het alarm niet geopend kon worden. Er werd alleen een grijs scherm getoond. Dit is nu verholpen.'\n // }\n // ]\n // }\n // ]\n // },\n // {\n // date: '10 mei 2017',\n // version: '2017.5',\n // module: [\n // {\n // name: 'Bewerk personen',\n // fixes: [\n // {\n // icon: 'star',\n // title: 'Contacten toevoegen',\n // subtext: 'Persoonlijke contacten kunnen nu toegevoegd en bewerkt worden. Ook kan de prioriteit aangepast worden.'\n // },\n // {\n // icon: 'star',\n // title: 'Groep(en) koppelen',\n // subtext: 'Vanuit de Alarm Manager kan er nu een groep of meerdere groepen aan een persoon gekoppeld worden.'\n // }\n // ]\n // },\n // {\n // name: 'Alarm Manager en Kaart',\n // fixes: [\n // {\n // icon: 'check',\n // title: 'Overlappende personen',\n // subtext: 'Als er op de overlappende personen op de kaart geklikt wordt, zullen deze uitwaaien in een spiraal.'\n // }\n // ]\n // },\n // {\n // name: 'Nieuwe module: Contactenlijsten beheren',\n // fixes: [\n // {\n // icon: 'star',\n // title: 'Contactenlijst aanmaken en beheren',\n // subtext: 'In deze nieuwe module kunnen contactenlijsten gemaakt en beheerd worden. Deze kunnen vervolgens gekoppeld worden aan een groep in de nieuwe groepen module.'\n // }\n // ]\n // },\n // {\n // name: 'Nieuwe module: Groepen beheren',\n // fixes: [\n // {\n // icon: 'star',\n // title: 'Groepen aanmaken en beheren',\n // subtext: 'In deze nieuwe module kunnen groepen gemaakt en beheerd worden. Personen kunnen snel toegevoegd of verwijderd worden en een contactenlijst kan gekoppeld worden.'\n // }\n // ]\n // }\n // ]\n // },\n // {\n // date: '6 april 2017',\n // version: '2017.4',\n // module: [\n // {\n // name: 'Kaart',\n // fixes: [\n // {\n // icon: 'check',\n // title: 'Een persoon zichtbaar',\n // subtext: 'Als er maar één persoon zichtbaar is, zullen enkele overbodige knoppen verdwijnen.'\n // },\n // {\n // icon: 'bug',\n // title: 'Automatische update',\n // subtext: 'Als een persoon op de kaart geupdate wordt zal alle nodige informatie bijgewerkt worden. Voorheen was dit alleen de positie van de persoon.'\n // }\n // ]\n // },\n // {\n // name: 'Bewerk personen',\n // fixes: [\n // {\n // icon: 'star',\n // title: 'Personen toevoegen',\n // subtext: 'Er kunnen nu, indien u deze rechten heeft, nieuwe personen toegevoegd worden vanuit de app.'\n // },\n // {\n // icon: 'check',\n // title: 'Telefoonnummers bewerken',\n // subtext: 'Bij het bewerken van telefoonnummers moet nu een landcode geselecteerd worden om fouten te voorkomen.'\n // },\n // {\n // icon: 'check',\n // title: 'Kiezen van type en toestel',\n // subtext: 'Indien u hier toegang tot hebt, is het kiezen van een type en een toestel nu duidelijker.'\n // }\n // ]\n // }\n // ]\n // },\n // {\n // date: '15 maart 2017',\n // version: '2017.3',\n // module: [\n // {\n // name: 'Bewerk personen',\n // fixes: [\n // {\n // icon: 'star',\n // title: 'Beschrijving',\n // subtext: 'Het is nu mogelijk een beschrijving aan een persoon toe te voegen. Deze beschrijving zal zichtbaar zijn tijdens een alarm.'\n // },\n // {\n // icon: '',\n // title: 'Extern ID',\n // subtext: 'Het externe ID van een persoon wordt nu, indien beschikbaar, onder de naam getoond.'\n // }\n // ]\n // },\n // {\n // name: 'Alarm Manager',\n // fixes: [\n // {\n // icon: 'check',\n // title: 'Snellere laadtijden',\n // subtext: 'Het openen van een alarm zal nu aanzienlijk sneller gaan.'\n // }\n // ]\n // },\n // {\n // name: 'Wat is er nieuw?',\n // fixes: [\n // {\n // icon: 'star',\n // title: \"'Wat is er nieuw?' pagina\",\n // subtext: \"De 'Wat is er nieuw?' pagina is toegevoegd aan de X-Guard Alarm Manager. Deze pagina laat alle recente wijzigingen zien omtrent de verschillende pagina's.\"\n // }\n // ]\n // }\n // ]\n // },\n // {\n // date: '17 februari 2017',\n // version: '2017.2',\n // module: [\n // {\n // name: 'Kaart',\n // fixes: [\n // {\n // icon: 'bug',\n // title: 'Juiste kleurcodering',\n // subtext: 'De positietijden geven nu de juiste kleurcodering weer.'\n // }\n // ]\n // }\n // ]\n // },\n // {\n // date: '31 januari 2017',\n // version: '2017.1',\n // module: [\n // {\n // name: 'Kaart',\n // fixes: [\n // {\n // icon: 'star',\n // title: 'Download alles',\n // subtext: \"Een 'download alles' knop is toegoevoegd om alle resterende items in één keer te downloaden.\"\n // }\n // ]\n // },\n // {\n // name: 'Bewerk personen',\n // fixes: [\n // {\n // icon: 'star',\n // title: 'Download alles',\n // subtext: \"Een 'download alles' knop is toegoevoegd om alle resterende items in één keer te downloaden.\"\n // }\n // ]\n // }\n // ]\n // }\n // ]\n\n});\n\n\n//# sourceMappingURL=stwo_alarmmanager-modules.js.map"]}