aboutsummaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/app.min.js150
-rw-r--r--web/app/view/LoginController.js9
-rw-r--r--web/l10n/bn.json136
-rw-r--r--web/l10n/hi.json136
-rw-r--r--web/l10n/hr.json136
-rw-r--r--web/l10n/hy.json136
-rw-r--r--web/l10n/ja.json136
-rw-r--r--web/l10n/ku.json136
8 files changed, 967 insertions, 8 deletions
diff --git a/web/app.min.js b/web/app.min.js
new file mode 100644
index 000000000..a9e78cbcd
--- /dev/null
+++ b/web/app.min.js
@@ -0,0 +1,150 @@
+Ext.define("Traccar.Style",{singleton:!0,panelPadding:10,windowWidth:640,windowHeight:480,dateTimeFormat24:"Y-m-d H:i:s",dateTimeFormat12:"Y-m-d g:i:s a",timeFormat24:"H:i",timeFormat12:"g:i a",dateFormat:"Y-m-d",weekStartDay:1,deviceWidth:350,reportHeight:250,reportTime:100,mapDefaultLat:51.507222,mapDefaultLon:-0.1275,mapDefaultZoom:6,mapRouteColor:"rgba(21, 127, 204, 1.0)",mapRouteWidth:5,mapArrowStrokeColor:"rgba(50, 50, 50, 1.0)",mapArrowStrokeWidth:2,mapTextColor:"rgba(50, 50, 50, 1.0)",mapTextStrokeColor:"rgba(255, 255, 255, 1.0)",
+mapTextStrokeWidth:2,mapTextOffset:10,mapTextFont:"bold 12px sans-serif",mapColorOnline:"rgba(77, 250, 144, 1.0)",mapColorUnknown:"rgba(250, 190, 77, 1.0)",mapColorOffline:"rgba(255, 84, 104, 1.0)",mapColorReport:"rgba(21, 127, 204, 1.0)",mapColorOverlay:"rgba(21, 127, 204, 0.2)",mapRadiusNormal:9,mapRadiusSelected:14,mapMaxZoom:19,mapDelay:500,coordinatePrecision:6,numberPrecision:2});
+Ext.define("Traccar.AttributeFormatter",{singleton:!0,coordinateFormatter:function(a){return a.toFixed(Traccar.Style.coordinatePrecision)},speedFormatter:function(a){return Ext.getStore("SpeedUnits").formatValue(a,Traccar.app.getPreference("speedUnit"))},courseFormatter:function(a){return"N NE E SE S SW W NW".split(" ")[Math.floor(a/45)]},distanceFormatter:function(a){return Ext.getStore("DistanceUnits").formatValue(a,Traccar.app.getPreference("distanceUnit"))},defaultFormatter:function(a){return"number"===
+typeof a?Number(a.toFixed(Traccar.Style.numberPrecision)):"boolean"===typeof a?a?Ext.Msg.buttonText.yes:Ext.Msg.buttonText.no:a instanceof Date?Traccar.app.getPreference("twelveHourFormat",!1)?Ext.Date.format(a,Traccar.Style.dateTimeFormat12):Ext.Date.format(a,Traccar.Style.dateTimeFormat24):a},getFormatter:function(a){return"latitude"===a||"longitude"===a?this.coordinateFormatter:"speed"===a?this.speedFormatter:"course"===a?this.courseFormatter:"distance"===a||"odometer"===a?this.distanceFormatter:
+this.defaultFormatter}});
+Ext.define("Traccar.model.Server",{extend:Ext.data.Model,identifier:"negative",fields:[{name:"id",type:"int"},{name:"registration",type:"boolean"},{name:"readonly",type:"boolean"},{name:"map",type:"string"},{name:"bingKey",type:"string"},{name:"mapUrl",type:"string"},{name:"distanceUnit",type:"string"},{name:"speedUnit",type:"string"},{name:"latitude",type:"float"},{name:"longitude",type:"float"},{name:"zoom",type:"int"},{name:"twelveHourFormat",type:"boolean"},{name:"attributes"}],proxy:{type:"ajax",
+url:"/api/server",actionMethods:{update:"PUT"},writer:{type:"json",writeAllFields:!0}}});
+Ext.define("Traccar.model.User",{extend:Ext.data.Model,identifier:"negative",fields:[{name:"id",type:"int"},{name:"name",type:"string"},{name:"email",type:"string"},{name:"password",type:"string"},{name:"admin",type:"boolean"},{name:"map",type:"string"},{name:"distanceUnit",type:"string"},{name:"speedUnit",type:"string"},{name:"latitude",type:"float"},{name:"longitude",type:"float"},{name:"zoom",type:"int"},{name:"twelveHourFormat",type:"boolean"},{name:"attributes"}],proxy:{type:"rest",url:"/api/users",
+writer:{type:"json",writeAllFields:!0}}});Ext.define("Traccar.model.Group",{extend:Ext.data.Model,identifier:"negative",fields:[{name:"id",type:"int"},{name:"name",type:"string"},{name:"groupId",type:"int"},{name:"attributes"}]});
+Ext.define("Traccar.model.Device",{extend:Ext.data.Model,identifier:"negative",fields:[{name:"id",type:"int"},{name:"name",type:"string"},{name:"uniqueId",type:"string"},{name:"status",type:"string"},{name:"lastUpdate",type:"date",dateFormat:"c"},{name:"groupId",type:"int"},{name:"geofenceIds"},{name:"attributes"}]});
+Ext.define("Traccar.model.Position",{extend:Ext.data.Model,identifier:"negative",fields:[{name:"id",type:"int"},{name:"protocol",type:"string"},{name:"deviceId",type:"int"},{name:"serverTime",type:"date",dateFormat:"c"},{name:"deviceTime",type:"date",dateFormat:"c"},{name:"fixTime",type:"date",dateFormat:"c"},{name:"valid",type:"boolean"},{name:"latitude",type:"float"},{name:"longitude",type:"float"},{name:"altitude",type:"float"},{name:"speed",type:"float"},{name:"course",type:"float"},{name:"address",
+type:"string"},{name:"attributes"}]});Ext.define("Traccar.model.Attribute",{extend:Ext.data.Model,fields:[{name:"priority",type:"int"},{name:"name",type:"string"},{name:"value",type:"string"}]});Ext.define("Traccar.model.Command",{extend:Ext.data.Model,identifier:"negative",fields:[{name:"deviceId",type:"int"},{name:"type",type:"string"},{name:"attributes"}]});
+Ext.define("Traccar.model.Event",{extend:Ext.data.Model,identifier:"negative",fields:[{name:"id",type:"int"},{name:"type",type:"string"},{name:"serverTime",type:"date",dateFormat:"c"},{name:"deviceId",type:"int"},{name:"positionId",type:"int"},{name:"geofenceId",type:"int"},{name:"attributes"}]});
+Ext.define("Traccar.model.Geofence",{extend:Ext.data.Model,identifier:"negative",fields:[{name:"id",type:"int"},{name:"name",type:"string"},{name:"description",type:"string"},{name:"area",type:"string"},{name:"attributes"}]});Ext.define("Traccar.model.Notification",{extend:Ext.data.Model,identifier:"negative",fields:[{name:"id",type:"int"},{name:"type",type:"string"},{name:"userId",type:"int"},{name:"attributes"}]});
+Ext.define("Traccar.store.Groups",{extend:Ext.data.Store,model:"Traccar.model.Group",proxy:{type:"rest",url:"/api/groups",writer:{writeAllFields:!0}}});Ext.define("Traccar.store.Devices",{extend:Ext.data.Store,model:"Traccar.model.Device",proxy:{type:"rest",url:"/api/devices",writer:{writeAllFields:!0}}});Ext.define("Traccar.store.AllGroups",{extend:Ext.data.Store,model:"Traccar.model.Group",proxy:{type:"rest",url:"/api/groups",extraParams:{all:!0}}});
+Ext.define("Traccar.store.AllDevices",{extend:Ext.data.Store,model:"Traccar.model.Device",proxy:{type:"rest",url:"/api/devices",extraParams:{all:!0}}});Ext.define("Traccar.store.Positions",{extend:Ext.data.Store,model:"Traccar.model.Position",proxy:{type:"rest",url:"/api/positions"}});Ext.define("Traccar.store.LatestPositions",{extend:Ext.data.Store,model:"Traccar.model.Position"});
+Ext.define("Traccar.store.Users",{extend:Ext.data.Store,model:"Traccar.model.User",proxy:{type:"rest",url:"/api/users",writer:{writeAllFields:!0}}});Ext.define("Traccar.store.Attributes",{extend:Ext.data.Store,model:"Traccar.model.Attribute",sorters:[{property:"priority"}]});Ext.define("Traccar.store.MapTypes",{extend:Ext.data.Store,fields:["key","name"],data:[{key:"osm",name:Strings.mapOsm},{key:"bingRoad",name:Strings.mapBingRoad},{key:"bingAerial",name:Strings.mapBingAerial},{key:"custom",name:Strings.mapCustom}]});
+Ext.define("Traccar.store.DistanceUnits",{extend:Ext.data.Store,fields:["key","name","factor"],data:[{key:"km",name:Strings.sharedKm,factor:0.001},{key:"mi",name:Strings.sharedMi,factor:6.21371E-4}],formatValue:function(a,b){var c;b||(b="km");c=this.findRecord("key",b);return(a*c.get("factor")).toFixed(2)+" "+c.get("name")}});
+Ext.define("Traccar.store.SpeedUnits",{extend:Ext.data.Store,fields:["key","name","factor"],data:[{key:"kn",name:Strings.sharedKn,factor:1},{key:"kmh",name:Strings.sharedKmh,factor:1.852},{key:"mph",name:Strings.sharedMph,factor:1.15078}],formatValue:function(a,b){var c;b||(b="kn");c=this.findRecord("key",b);return(a*c.get("factor")).toFixed(1)+" "+c.get("name")}});
+Ext.define("Traccar.store.CommandTypes",{extend:Ext.data.Store,fields:["type","name"],listeners:{beforeload:function(a){a=a.getProxy();a.setUrl("/api/commandtypes?deviceId"+a.extraParams.deviceId)}},proxy:{type:"rest",url:"",reader:{type:"json",getData:function(a){Ext.each(a,function(a){var c;a.name=a.type;"undefined"!==typeof a.type&&(c="command"+a.type.charAt(0).toUpperCase()+a.type.slice(1),c=Strings[c],"undefined"!==typeof c&&(a.name=c))});return a}}}});
+Ext.define("Traccar.store.TimeUnits",{extend:Ext.data.Store,fields:["name","factor"],data:[{name:Strings.sharedSecond,factor:1},{name:Strings.sharedMinute,factor:60},{name:Strings.sharedHour,factor:3600}]});Ext.define("Traccar.store.Languages",{extend:Ext.data.Store,fields:["code","name"],data:function(){var a,b=[];for(a in Locale.languages)Locale.languages.hasOwnProperty(a)&&b.push({code:a,name:Locale.languages[a].name});return b}()});
+Ext.define("Traccar.store.Events",{extend:Ext.data.Store,model:"Traccar.model.Event",proxy:{type:"rest",url:"/api/events"}});Ext.define("Traccar.store.Geofences",{extend:Ext.data.Store,model:"Traccar.model.Geofence",proxy:{type:"rest",url:"/api/geofences",writer:{writeAllFields:!0}}});Ext.define("Traccar.store.AllGeofences",{extend:Ext.data.Store,model:"Traccar.model.Geofence",proxy:{type:"rest",url:"/api/geofences",extraParams:{all:!0}}});
+Ext.define("Traccar.store.Notifications",{extend:Ext.data.Store,model:"Traccar.model.Notification",proxy:{type:"rest",url:"/api/users/notifications"}});Ext.define("Traccar.store.AllNotifications",{extend:Ext.data.Store,model:"Traccar.model.Notification",proxy:{type:"rest",url:"/api/users/notifications",extraParams:{all:!0}},sortOnLoad:!0,sorters:{property:"type",direction:"ASC"}});
+Ext.define("Traccar.store.GeofenceTypes",{extend:Ext.data.Store,fields:["key","name"],data:[{key:"Polygon",name:Strings.mapShapePolygon},{key:"Circle",name:Strings.mapShapeCircle}]});Ext.define("Traccar.view.BaseDialog",{extend:Ext.window.Window,bodyPadding:Traccar.Style.panelPadding,resizable:!1,modal:!0});
+Ext.define("Traccar.view.RegisterController",{extend:Ext.app.ViewController,alias:"controller.register",onCreateClick:function(){var a=this.lookupReference("form");a.isValid()&&Ext.Ajax.request({scope:this,method:"POST",url:"/api/users",jsonData:a.getValues(),callback:this.onCreateReturn})},onCreateReturn:function(a,b,c){b?(this.closeView(),Ext.toast(Strings.loginCreated)):Traccar.app.showError(c)}});
+Ext.define("Traccar.view.Register",{extend:Traccar.view.BaseDialog,controller:"register",title:Strings.loginRegister,items:{xtype:"form",reference:"form",jsonSubmit:!0,items:[{xtype:"textfield",name:"name",fieldLabel:Strings.sharedName,allowBlank:!1},{xtype:"textfield",name:"email",fieldLabel:Strings.userEmail,vtype:"email",allowBlank:!1},{xtype:"textfield",name:"password",fieldLabel:Strings.userPassword,inputType:"password",allowBlank:!1}]},buttons:[{text:Strings.sharedSave,handler:"onCreateClick"},
+{text:Strings.sharedCancel,handler:"closeView"}]});
+Ext.define("Traccar.view.LoginController",{extend:Ext.app.ViewController,alias:"controller.login",init:function(){this.lookupReference("registerButton").setDisabled(!Traccar.app.getServer().get("registration"));this.lookupReference("languageField").setValue(Locale.language);var a=Ext.util.Cookies.get("user"),b=Ext.util.Cookies.get("pass");a&&b&&(this.lookupReference("txtUser").setValue(a),this.lookupReference("txtPassword").setValue(b),this.login())},login:function(){var a=this.lookupReference("form");
+a.isValid()&&(Ext.getBody().mask(Strings.sharedLoading),Ext.Ajax.request({scope:this,method:"POST",url:"/api/session",params:a.getValues(),callback:function(a,c,d){Ext.getBody().unmask();c?(this.lookupReference("chkRememberMe").getValue()&&(Ext.util.Cookies.set("user",this.lookupReference("txtUser").getValue(),Ext.Date.add(new Date,Ext.Date.YEAR,1)),Ext.util.Cookies.set("pass",this.lookupReference("txtPassword").getValue(),Ext.Date.add(new Date,Ext.Date.YEAR,1))),Traccar.app.setUser(Ext.decode(d.responseText)),
+this.fireViewEvent("login")):Traccar.app.showError(Strings.loginFailed)}}))},logout:function(){Ext.util.Cookies.clear("user");Ext.util.Cookies.clear("pass");Ext.Ajax.request({scope:this,method:"DELETE",url:"/api/session",callback:function(){window.location.reload()}})},onSelectLanguage:function(a){var b,c;a=a.getValue();b=window.location.href;0<=b.indexOf("locale\x3d")?(c=b.substring(0,b.indexOf("locale")),b=b.substring(b.indexOf("locale")),b=b.substring(b.indexOf("\x3d")+1),b=0<=b.indexOf("\x26")?
+b.substring(b.indexOf("\x26")):"",b=c+"locale\x3d"+a+b):b=0>b.indexOf("?")?b+("?locale\x3d"+a):b+("\x26locale\x3d"+a);window.location.href=b},onAfterRender:function(a){a.focus()},onSpecialKey:function(a,b){b.getKey()===b.ENTER&&this.login()},onLoginClick:function(){Ext.getElementById("submitButton").click();this.login()},onRegisterClick:function(){Ext.create("Traccar.view.Register").show()}});
+Ext.define("Traccar.view.Login",{extend:Traccar.view.BaseDialog,alias:"widget.login",controller:"login",title:Strings.loginTitle,closable:!1,modal:!1,items:{xtype:"form",reference:"form",autoEl:{tag:"form",method:"POST",action:"fake-login.html",target:"submitTarget"},items:[{xtype:"combobox",name:"language",fieldLabel:Strings.loginLanguage,store:"Languages",displayField:"name",valueField:"code",submitValue:!1,listeners:{select:"onSelectLanguage"},reference:"languageField"},{xtype:"textfield",name:"email",
+reference:"txtUser",fieldLabel:Strings.userEmail,allowBlank:!1,enableKeyEvents:!0,listeners:{specialKey:"onSpecialKey",afterrender:"onAfterRender"},inputAttrTpl:['autocomplete\x3d"on"']},{xtype:"textfield",name:"password",reference:"txtPassword",fieldLabel:Strings.userPassword,inputType:"password",allowBlank:!1,enableKeyEvents:!0,listeners:{specialKey:"onSpecialKey"},inputAttrTpl:['autocomplete\x3d"on"']},{xtype:"checkboxfield",reference:"chkRememberMe",fieldLabel:Strings.rememberMe},{xtype:"component",
+html:'\x3ciframe id\x3d"submitTarget" name\x3d"submitTarget" style\x3d"display:none"\x3e\x3c/iframe\x3e'},{xtype:"component",html:'\x3cinput type\x3d"submit" id\x3d"submitButton" style\x3d"display:none"\x3e'}]},buttons:[{text:Strings.loginRegister,handler:"onRegisterClick",reference:"registerButton"},{text:Strings.loginLogin,handler:"onLoginClick"}]});
+Ext.define("Traccar.view.CommandDialogController",{extend:Ext.app.ViewController,alias:"controller.commandDialog",onSelect:function(a){this.lookupReference("paramPositionPeriodic").setHidden("positionPeriodic"!==a.getValue());this.lookupReference("paramCustom").setHidden("custom"!==a.getValue())},onSendClick:function(a){var b,c;a=a.up("window").down("form");a.updateRecord();c=a.getRecord();"positionPeriodic"===c.get("type")&&(a=this.lookupReference("paramPositionPeriodic"),b=a.down('numberfield[name\x3d"frequency"]').getValue(),
+b*=a.down('combobox[name\x3d"unit"]').getValue(),c.set("attributes",{frequency:b}));"custom"===c.get("type")&&(b=this.lookupReference("paramCustom").getValue(),c.set("attributes",{data:b}));Ext.Ajax.request({scope:this,url:"/api/commands",jsonData:c.getData(),callback:this.onSendResult})},onSendResult:function(a,b,c){b?(Ext.toast(Strings.commandSent),this.closeView()):Traccar.app.showError(c)}});
+Ext.define("Traccar.view.CommandDialog",{extend:Traccar.view.BaseDialog,controller:"commandDialog",title:Strings.commandTitle,items:{xtype:"form",items:[{xtype:"combobox",name:"type",fieldLabel:Strings.commandType,store:"CommandTypes",displayField:"name",valueField:"type",listeners:{select:"onSelect"}},{xtype:"fieldcontainer",reference:"paramPositionPeriodic",name:"attributes",hidden:!0,items:[{xtype:"numberfield",fieldLabel:Strings.commandFrequency,name:"frequency"},{xtype:"combobox",fieldLabel:Strings.commandUnit,
+name:"unit",store:"TimeUnits",displayField:"name",valueField:"factor"}]},{xtype:"textfield",reference:"paramCustom",fieldLabel:Strings.commandCustom,name:"customCommand",hidden:!0,allowBlank:!1}]},buttons:[{text:Strings.commandSend,handler:"onSendClick"},{text:Strings.sharedCancel,handler:"closeView"}]});
+Ext.define("Traccar.view.BaseEditDialog",{extend:Traccar.view.BaseDialog,buttons:[{text:Strings.sharedAttributes,handler:"showAttributesView"},{xtype:"tbfill"},{text:Strings.sharedSave,handler:"onSaveClick"},{text:Strings.sharedCancel,handler:"closeView"}]});
+Ext.define("Traccar.view.DeviceDialog",{extend:Traccar.view.BaseEditDialog,controller:"baseEditDialog",title:Strings.deviceDialog,items:{xtype:"form",items:[{xtype:"textfield",name:"name",fieldLabel:Strings.sharedName,allowBlank:!1},{xtype:"textfield",name:"uniqueId",fieldLabel:Strings.deviceIdentifier,allowBlank:!1},{xtype:"combobox",name:"groupId",fieldLabel:Strings.groupParent,store:"Groups",queryMode:"local",displayField:"name",valueField:"id"}]}});
+Ext.define("Traccar.view.BasePermissionsController",{extend:Ext.app.ViewController,alias:"controller.basePermissionsController",init:function(){var a={},b,c;a[this.getView().baseObjectName]=this.getView().baseObject;b=this.getView().linkStoreName;c=this.getView().storeName;b="undefined"===typeof b?c:b;this.getView().setStore(Ext.getStore(c));this.getView().getStore().load({scope:this,callback:function(){Ext.create("Traccar.store."+b).load({params:a,scope:this,callback:function(a,b,c){if(c)for(b=0;b<
+a.length;b++)c=this.getView().getStore().find("id",a[b].getData().id),this.getView().getSelectionModel().select(c,!0,!0)}})}})},onBeforeSelect:function(a,b){var c={};c[this.getView().baseObjectName]=this.getView().baseObject;c[this.getView().linkObjectName]=b.getData().id;Ext.Ajax.request({scope:this,url:this.getView().urlApi,jsonData:Ext.util.JSON.encode(c),callback:function(a,b,c){b||Traccar.app.showError(c)}})},onBeforeDeselect:function(a,b){var c={};c[this.getView().baseObjectName]=this.getView().baseObject;
+c[this.getView().linkObjectName]=b.getData().id;Ext.Ajax.request({scope:this,method:"DELETE",url:this.getView().urlApi,jsonData:Ext.util.JSON.encode(c),callback:function(a,b,c){b||Traccar.app.showError(c)}})}});
+Ext.define("Traccar.view.DeviceGeofences",{extend:Ext.grid.Panel,xtype:"deviceGeofencesView",controller:"basePermissionsController",selModel:{selType:"checkboxmodel",checkOnly:!0,showHeaderCheckbox:!1},listeners:{beforedeselect:"onBeforeDeselect",beforeselect:"onBeforeSelect"},columns:[{text:Strings.sharedName,dataIndex:"name",flex:1}]});
+Ext.define("Traccar.view.DevicesController",{extend:Ext.app.ViewController,alias:"controller.devices",config:{listen:{controller:{"*":{selectDevice:"selectDevice",selectReport:"selectReport"}},store:{"#Devices":{update:"onUpdateDevice"}}}},init:function(){var a=Traccar.app.getServer().get("readonly")&&!Traccar.app.getUser().get("admin");this.lookupReference("toolbarAddButton").setVisible(!a);this.lookupReference("toolbarEditButton").setVisible(!a);this.lookupReference("toolbarRemoveButton").setVisible(!a)},
+onAddClick:function(){var a,b;a=Ext.create("Traccar.model.Device");a.store=Ext.getStore("Devices");b=Ext.create("Traccar.view.DeviceDialog");b.down("form").loadRecord(a);b.show()},onEditClick:function(){var a,b;a=this.getView().getSelectionModel().getSelection()[0];b=Ext.create("Traccar.view.DeviceDialog");b.down("form").loadRecord(a);b.show()},onRemoveClick:function(){var a=this.getView().getSelectionModel().getSelection()[0];Ext.Msg.show({title:Strings.deviceDialog,message:Strings.sharedRemoveConfirm,
+buttons:Ext.Msg.YESNO,buttonText:{yes:Strings.sharedRemove,no:Strings.sharedCancel},fn:function(b){"yes"===b&&(b=Ext.getStore("Devices"),b.remove(a),b.sync())}})},onGeofencesClick:function(){var a;Traccar.app.getUser().get("admin");a=this.getView().getSelectionModel().getSelection()[0];Ext.create("Traccar.view.BaseWindow",{title:Strings.sharedGeofences,items:{xtype:"deviceGeofencesView",baseObjectName:"deviceId",linkObjectName:"geofenceId",storeName:"Geofences",urlApi:"/api/devices/geofences",baseObject:a.getData().id}}).show()},
+onCommandClick:function(){var a,b,c;a=this.getView().getSelectionModel().getSelection()[0].get("id");b=Ext.create("Traccar.model.Command");b.set("deviceId",a);c=Ext.create("Traccar.view.CommandDialog");c.down("form").down("combobox").getStore().getProxy().setExtraParam("deviceId",a);c.down("form").loadRecord(b);c.show()},onFollowClick:function(a,b){var c;b&&(c=this.getView().getSelectionModel().getSelection()[0],this.fireEvent("selectDevice",c,!0))},updateButtons:function(a){var b=0===a.getCount();
+this.lookupReference("toolbarEditButton").setDisabled(b);this.lookupReference("toolbarRemoveButton").setDisabled(b);this.lookupReference("toolbarGeofencesButton").setDisabled(b);this.lookupReference("deviceCommandButton").setDisabled(b||"online"!==a.getLastSelected().get("status"))},onSelectionChange:function(a){this.updateButtons(a);0<a.getCount()&&this.fireEvent("selectDevice",a.getLastSelected(),!0)},selectDevice:function(a){this.getView().getSelectionModel().select([a],!1,!0)},selectReport:function(a){void 0!==
+a&&this.getView().getSelectionModel().deselectAll()},onUpdateDevice:function(){this.updateButtons(this.getView().getSelectionModel())}});
+Ext.define("Traccar.view.EditToolbar",{extend:Ext.toolbar.Toolbar,xtype:"editToolbar",initComponent:function(){this.callParent(arguments);this.add(0,[{xtype:"button",handler:"onAddClick",reference:"toolbarAddButton",glyph:"xf067@FontAwesome",tooltip:Strings.sharedAdd,tooltipType:"title"},{xtype:"button",disabled:!0,handler:"onEditClick",reference:"toolbarEditButton",glyph:"xf040@FontAwesome",tooltip:Strings.sharedEdit,tooltipType:"title"},{xtype:"button",disabled:!0,handler:"onRemoveClick",reference:"toolbarRemoveButton",
+glyph:"xf00d@FontAwesome",tooltip:Strings.sharedRemove,tooltipType:"title"}])}});Ext.define("Traccar.view.AttributeController",{extend:Ext.app.ViewController,alias:"controller.attributeDialog",onSaveClick:function(a){var b,c;b=a.up("window").down("form");b.updateRecord();b=b.getRecord();(c=b.store)?(b.phantom&&c.add(b),c.sync({failure:function(a){c.rejectChanges();Traccar.app.showError(a.exceptions[0].getError().response)}})):b.save();a.up("window").close()}});
+Ext.define("Traccar.view.AttributeDialog",{extend:Traccar.view.BaseDialog,controller:"attributeDialog",title:Strings.sharedAttribute,items:{xtype:"form",items:[{xtype:"textfield",name:"name",fieldLabel:Strings.sharedName},{xtype:"textfield",name:"value",fieldLabel:Strings.stateValue}]},buttons:[{text:Strings.sharedSave,handler:"onSaveClick"},{text:Strings.sharedCancel,handler:"closeView"}]});
+Ext.define("Traccar.view.AttributesController",{extend:Ext.app.ViewController,alias:"controller.attributes",init:function(){var a,b,c=0,d;a=Ext.create("Traccar.store.Attributes");a.setProxy(Ext.create("Ext.data.proxy.Memory"));"undefined"===typeof this.getView().record.get("attributes")&&this.getView().record.set("attributes",{});d=this.getView().record.get("attributes");for(b in d)d.hasOwnProperty(b)&&a.add(Ext.create("Traccar.model.Attribute",{priority:c++,name:b,value:this.getView().record.get("attributes")[b]}));
+a.addListener("add",function(a,b){var c;for(c=0;c<b.length;c++)this.getView().record.get("attributes")[b[c].get("name")]=b[c].get("value");this.getView().record.dirty=!0},this);a.addListener("update",function(a,b,c){c===Ext.data.Model.EDIT&&(b.modified.name!==b.get("name")&&delete this.getView().record.get("attributes")[b.modified.name],this.getView().record.get("attributes")[b.get("name")]=b.get("value"),this.getView().record.dirty=!0)},this);a.addListener("remove",function(a,b){var c;for(c=0;c<
+b.length;c++)delete this.getView().record.get("attributes")[b[c].get("name")];this.getView().record.dirty=!0},this);this.getView().setStore(a)},onAddClick:function(){var a,b;a=Ext.create("Traccar.model.Attribute");a.store=this.getView().getStore();b=Ext.create("Traccar.view.AttributeDialog");b.down("form").loadRecord(a);b.show()},onEditClick:function(){var a,b;a=this.getView().getSelectionModel().getSelection()[0];b=Ext.create("Traccar.view.AttributeDialog");b.down("form").loadRecord(a);b.show()},
+onRemoveClick:function(){var a=this.getView().getSelectionModel().getSelection()[0];Ext.Msg.show({title:Strings.stateName,message:Strings.sharedRemoveConfirm,buttons:Ext.Msg.YESNO,buttonText:{yes:Strings.sharedRemove,no:Strings.sharedCancel},scope:this,fn:function(b){var c=this.getView().getStore();"yes"===b&&(c.remove(a),c.sync())}})},onSelectionChange:function(a){a=0<a.length;this.lookupReference("toolbarEditButton").setDisabled(a);this.lookupReference("toolbarRemoveButton").setDisabled(a)}});
+Ext.define("Traccar.view.Attributes",{extend:Ext.grid.Panel,xtype:"attributesView",controller:"attributes",selType:"rowmodel",tbar:{xtype:"editToolbar"},listeners:{selectionchange:"onSelectionChange"},columns:[{text:Strings.sharedName,dataIndex:"name",flex:1},{text:Strings.stateValue,dataIndex:"value",flex:1}]});
+Ext.define("Traccar.view.BaseEditDialogController",{extend:Ext.app.ViewController,alias:"controller.baseEditDialog",onSaveClick:function(a){var b,c;b=a.up("window").down("form");b.updateRecord();b=b.getRecord();(c=b.store)?(b.phantom&&c.add(b),c.sync({failure:function(a){c.rejectChanges();Traccar.app.showError(a.exceptions[0].getError().response)}})):b.save();a.up("window").close()},showAttributesView:function(a){a=a.up("window").down("form").getRecord();Ext.create("Traccar.view.BaseWindow",{title:Strings.sharedAttributes,
+modal:!1,items:{xtype:"attributesView",record:a}}).show()}});
+Ext.define("Traccar.view.UserDialogController",{extend:Traccar.view.BaseEditDialogController,alias:"controller.userDialog",init:function(){Traccar.app.getUser().get("admin")&&this.lookupReference("adminField").setDisabled(!1)},onSaveClick:function(a){var b,c;b=a.up("window").down("form");b.updateRecord();b=b.getRecord();b===Traccar.app.getUser()?b.save():(c=Ext.getStore("Users"),b.phantom&&c.add(b),c.sync({failure:function(a){c.rejectChanges();Traccar.app.showError(a.exceptions[0].getError().response)}}));
+a.up("window").close()}});
+Ext.define("Traccar.view.UserDialog",{extend:Traccar.view.BaseEditDialog,controller:"userDialog",title:Strings.settingsUser,items:[{xtype:"form",items:[{xtype:"textfield",name:"name",fieldLabel:Strings.sharedName},{xtype:"textfield",name:"email",fieldLabel:Strings.userEmail,allowBlank:!1},{xtype:"textfield",name:"password",fieldLabel:Strings.userPassword,inputType:"password",allowBlank:!1},{xtype:"checkboxfield",name:"admin",fieldLabel:Strings.userAdmin,allowBlank:!1,disabled:!0,reference:"adminField"},
+{xtype:"combobox",name:"map",fieldLabel:Strings.mapLayer,store:"MapTypes",displayField:"name",valueField:"key"},{xtype:"combobox",name:"distanceUnit",fieldLabel:Strings.settingsDistanceUnit,store:"DistanceUnits",displayField:"name",valueField:"key"},{xtype:"combobox",name:"speedUnit",fieldLabel:Strings.settingsSpeedUnit,store:"SpeedUnits",displayField:"name",valueField:"key"},{xtype:"numberfield",name:"latitude",fieldLabel:Strings.positionLatitude,decimalPrecision:Traccar.Style.coordinatePrecision},
+{xtype:"numberfield",name:"longitude",fieldLabel:Strings.positionLongitude,decimalPrecision:Traccar.Style.coordinatePrecision},{xtype:"numberfield",name:"zoom",fieldLabel:Strings.serverZoom},{xtype:"checkboxfield",name:"twelveHourFormat",fieldLabel:Strings.settingsTwelveHourFormat,allowBlank:!1}]}]});
+Ext.define("Traccar.view.ServerDialog",{extend:Traccar.view.BaseEditDialog,controller:"baseEditDialog",title:Strings.serverTitle,items:{xtype:"form",items:[{xtype:"checkboxfield",name:"registration",fieldLabel:Strings.serverRegistration,allowBlank:!1},{xtype:"checkboxfield",name:"readonly",fieldLabel:Strings.serverReadonly,allowBlank:!1},{xtype:"combobox",name:"map",fieldLabel:Strings.mapLayer,store:"MapTypes",displayField:"name",valueField:"key"},{xtype:"textfield",name:"bingKey",fieldLabel:Strings.mapBingKey},
+{xtype:"textfield",name:"mapUrl",fieldLabel:Strings.mapCustom},{xtype:"combobox",name:"distanceUnit",fieldLabel:Strings.settingsDistanceUnit,store:"DistanceUnits",displayField:"name",valueField:"key"},{xtype:"combobox",name:"speedUnit",fieldLabel:Strings.settingsSpeedUnit,store:"SpeedUnits",displayField:"name",valueField:"key"},{xtype:"numberfield",name:"latitude",fieldLabel:Strings.positionLatitude,decimalPrecision:Traccar.Style.coordinatePrecision},{xtype:"numberfield",name:"longitude",fieldLabel:Strings.positionLongitude,
+decimalPrecision:Traccar.Style.coordinatePrecision},{xtype:"numberfield",name:"zoom",fieldLabel:Strings.serverZoom},{xtype:"checkboxfield",name:"twelveHourFormat",fieldLabel:Strings.settingsTwelveHourFormat,allowBlank:!1}]}});
+Ext.define("Traccar.view.UserDevices",{extend:Ext.grid.Panel,xtype:"userDevicesView",controller:"basePermissionsController",selModel:{selType:"checkboxmodel",checkOnly:!0,showHeaderCheckbox:!1},listeners:{beforedeselect:"onBeforeDeselect",beforeselect:"onBeforeSelect"},columns:[{text:Strings.sharedName,dataIndex:"name",flex:1},{text:Strings.deviceIdentifier,dataIndex:"uniqueId",flex:1}]});
+Ext.define("Traccar.view.UserGroups",{extend:Ext.grid.Panel,xtype:"userGroupsView",controller:"basePermissionsController",selModel:{selType:"checkboxmodel",checkOnly:!0,showHeaderCheckbox:!1},listeners:{beforedeselect:"onBeforeDeselect",beforeselect:"onBeforeSelect"},columns:[{text:Strings.sharedName,dataIndex:"name",flex:1}]});
+Ext.define("Traccar.view.UserGeofences",{extend:Ext.grid.Panel,xtype:"userGeofencesView",controller:"basePermissionsController",selModel:{selType:"checkboxmodel",checkOnly:!0,showHeaderCheckbox:!1},listeners:{beforedeselect:"onBeforeDeselect",beforeselect:"onBeforeSelect"},columns:[{text:Strings.sharedName,dataIndex:"name",flex:1}]});
+Ext.define("Traccar.view.NotificationsController",{extend:Ext.app.ViewController,alias:"controller.notificationsController",init:function(){this.userId=this.getView().user.getData().id;this.getView().getStore().load({scope:this,callback:function(){Ext.create("Traccar.store.Notifications").load({params:{userId:this.userId},scope:this,callback:function(a,b,c){var d;if(c)for(b=0;b<a.length;b++)d=this.getView().getStore().find("type",a[b].getData().type),c=a[b].getData().attributes,d=this.getView().getStore().getAt(d),
+d.set("attributes",c),d.commit()}})}})},onBeforeCheckChange:function(a,b){var c,d,f;c=a.dataIndex.split(".",2);d=this.getView().getStore().getAt(b);f=d.get(c[0]);f[c[1]]?delete f[c[1]]:f[c[1]]="true";d.set(c[0],f);d.commit()},onCheckChange:function(a,b){var c=this.getView().getStore().getAt(b);Ext.Ajax.request({scope:this,url:"/api/users/notifications",jsonData:{userId:this.userId,type:c.getData().type,attributes:c.getData().attributes},callback:function(a,b,c){b||Traccar.app.showError(c)}})}});
+Ext.define("Traccar.view.Notifications",{extend:Ext.grid.Panel,xtype:"notificationsView",controller:"notificationsController",store:"AllNotifications",selModel:{selType:"cellmodel"},viewConfig:{markDirty:!1},columns:[{text:Strings.notificationType,dataIndex:"type",flex:1,renderer:function(a){a="event"+a.charAt(0).toUpperCase()+a.slice(1);return Strings[a]}},{text:Strings.notificationWeb,dataIndex:"attributes.web",xtype:"checkcolumn",flex:1,listeners:{beforeCheckChange:"onBeforeCheckChange",checkChange:"onCheckChange"},
+renderer:function(a,b,c){a=this.dataIndex.split(".",2);return(new Ext.ux.CheckColumn).renderer(c.get(a[0])[a[1]],b)}},{text:Strings.notificationMail,dataIndex:"attributes.mail",xtype:"checkcolumn",flex:1,listeners:{beforeCheckChange:"onBeforeCheckChange",checkChange:"onCheckChange"},renderer:function(a,b,c){a=this.dataIndex.split(".",2);return(new Ext.ux.CheckColumn).renderer(c.get(a[0])[a[1]],b)}}]});
+Ext.define("Traccar.view.BaseWindow",{extend:Ext.window.Window,width:Traccar.Style.windowWidth,height:Traccar.Style.windowHeight,layout:"fit",modal:!0});
+Ext.define("Traccar.view.UsersController",{extend:Ext.app.ViewController,alias:"controller.users",init:function(){Ext.getStore("Users").load()},onAddClick:function(){var a,b;a=Ext.create("Traccar.model.User");b=Ext.create("Traccar.view.UserDialog");b.down("form").loadRecord(a);b.show()},onEditClick:function(){var a,b;a=this.getView().getSelectionModel().getSelection()[0];b=Ext.create("Traccar.view.UserDialog");b.down("form").loadRecord(a);b.show()},onRemoveClick:function(){var a=this.getView().getSelectionModel().getSelection()[0];
+Ext.Msg.show({title:Strings.settingsUser,message:Strings.sharedRemoveConfirm,buttons:Ext.Msg.YESNO,buttonText:{yes:Strings.sharedRemove,no:Strings.sharedCancel},fn:function(b){var c=Ext.getStore("Users");"yes"===b&&(c.remove(a),c.sync())}})},onDevicesClick:function(){var a=this.getView().getSelectionModel().getSelection()[0];Ext.create("Traccar.view.BaseWindow",{title:Strings.deviceTitle,items:{xtype:"userDevicesView",baseObjectName:"userId",linkObjectName:"deviceId",storeName:"AllDevices",linkStoreName:"Devices",
+urlApi:"/api/permissions/devices",baseObject:a.getData().id}}).show()},onGroupsClick:function(){var a=this.getView().getSelectionModel().getSelection()[0];Ext.create("Traccar.view.BaseWindow",{title:Strings.settingsGroups,items:{xtype:"userGroupsView",baseObjectName:"userId",linkObjectName:"groupId",storeName:"AllGroups",linkStoreName:"Groups",urlApi:"/api/permissions/groups",baseObject:a.getData().id}}).show()},onGeofencesClick:function(){var a=this.getView().getSelectionModel().getSelection()[0];
+Ext.create("Traccar.view.BaseWindow",{title:Strings.sharedGeofences,items:{xtype:"userGeofencesView",baseObjectName:"userId",linkObjectName:"geofenceId",storeName:"AllGeofences",linkStoreName:"Geofences",urlApi:"/api/permissions/geofences",baseObject:a.getData().id}}).show()},onNotificationsClick:function(){var a=this.getView().getSelectionModel().getSelection()[0];Ext.create("Traccar.view.BaseWindow",{title:Strings.sharedNotifications,modal:!1,items:{xtype:"notificationsView",user:a}}).show()},onSelectionChange:function(a){a=
+0<a.length;this.lookupReference("toolbarEditButton").setDisabled(a);this.lookupReference("toolbarRemoveButton").setDisabled(a);this.lookupReference("userDevicesButton").setDisabled(a);this.lookupReference("userGroupsButton").setDisabled(a);this.lookupReference("userGeofencesButton").setDisabled(a);this.lookupReference("userNotificationsButton").setDisabled(a)}});
+Ext.define("Traccar.view.Users",{extend:Ext.grid.Panel,xtype:"usersView",controller:"users",store:"Users",selType:"rowmodel",tbar:{xtype:"editToolbar",items:[{text:Strings.deviceTitle,disabled:!0,handler:"onDevicesClick",reference:"userDevicesButton"},{text:Strings.settingsGroups,disabled:!0,handler:"onGroupsClick",reference:"userGroupsButton"},{text:Strings.sharedGeofences,disabled:!0,handler:"onGeofencesClick",reference:"userGeofencesButton"},{text:Strings.sharedNotifications,disabled:!0,handler:"onNotificationsClick",
+reference:"userNotificationsButton"}]},listeners:{selectionchange:"onSelectionChange"},columns:[{text:Strings.sharedName,dataIndex:"name",flex:1},{text:Strings.userEmail,dataIndex:"email",flex:1},{text:Strings.userAdmin,dataIndex:"admin",flex:1}]});
+Ext.define("Traccar.view.GroupDialog",{extend:Traccar.view.BaseEditDialog,controller:"baseEditDialog",title:Strings.groupDialog,items:{xtype:"form",items:[{xtype:"textfield",name:"name",fieldLabel:Strings.sharedName,allowBlank:!1},{xtype:"combobox",name:"groupId",fieldLabel:Strings.groupParent,store:"Groups",queryMode:"local",displayField:"name",valueField:"id"}]}});
+Ext.define("Traccar.view.GroupGeofences",{extend:Ext.grid.Panel,xtype:"groupGeofencesView",controller:"basePermissionsController",selModel:{selType:"checkboxmodel",checkOnly:!0,showHeaderCheckbox:!1},listeners:{beforedeselect:"onBeforeDeselect",beforeselect:"onBeforeSelect"},columns:[{text:Strings.sharedName,dataIndex:"name",flex:1}]});
+Ext.define("Traccar.view.GroupsController",{extend:Ext.app.ViewController,alias:"controller.groups",onAddClick:function(){var a,b;a=Ext.create("Traccar.model.Group");a.store=this.getView().getStore();b=Ext.create("Traccar.view.GroupDialog");b.down("form").loadRecord(a);b.show()},onEditClick:function(){var a,b;a=this.getView().getSelectionModel().getSelection()[0];b=Ext.create("Traccar.view.GroupDialog");b.down("form").loadRecord(a);b.show()},onRemoveClick:function(){var a=this.getView().getSelectionModel().getSelection()[0];
+Ext.Msg.show({title:Strings.groupDialog,message:Strings.sharedRemoveConfirm,buttons:Ext.Msg.YESNO,buttonText:{yes:Strings.sharedRemove,no:Strings.sharedCancel},fn:function(b){var c=Ext.getStore("Groups");"yes"===b&&(c.remove(a),c.sync())}})},onGeofencesClick:function(){var a,b;a=Traccar.app.getUser().get("admin");b=this.getView().getSelectionModel().getSelection()[0];Ext.create("Traccar.view.BaseWindow",{title:Strings.sharedGeofences,items:{xtype:"groupGeofencesView",baseObjectName:"groupId",linkObjectName:"geofenceId",
+storeName:a?"AllGeofences":"Geofences",urlApi:"/api/groups/geofences",baseObject:b.getData().id}}).show()},onSelectionChange:function(a){a=0<a.length;this.lookupReference("toolbarEditButton").setDisabled(a);this.lookupReference("toolbarRemoveButton").setDisabled(a);this.lookupReference("toolbarGeofencesButton").setDisabled(a)}});
+Ext.define("Traccar.view.Groups",{extend:Ext.grid.Panel,xtype:"groupsView",controller:"groups",store:"Groups",selType:"rowmodel",tbar:{xtype:"editToolbar",items:[{xtype:"button",disabled:!0,handler:"onGeofencesClick",reference:"toolbarGeofencesButton",glyph:"xf21d@FontAwesome",tooltip:Strings.sharedGeofences,tooltipType:"title"}]},listeners:{selectionchange:"onSelectionChange"},columns:[{text:Strings.sharedName,dataIndex:"name",flex:1}]});
+Ext.define("Traccar.view.BaseMap",{extend:Ext.form.Panel,xtype:"baseMapView",layout:"fit",getMap:function(){return this.map},getMapView:function(){return this.mapView},initMap:function(){var a,b,c,d,f,e;a=Traccar.app.getUser();b=Traccar.app.getServer();c=a.get("map")||b.get("map");d=b.get("bingKey");c="custom"===c?new ol.layer.Tile({source:new ol.source.XYZ({url:b.get("mapUrl"),attributions:[new ol.Attribution({html:""})]})}):"bingRoad"===c?new ol.layer.Tile({source:new ol.source.BingMaps({key:d,
+imagerySet:"Road"})}):"bingAerial"===c?new ol.layer.Tile({source:new ol.source.BingMaps({key:d,imagerySet:"Aerial"})}):new ol.layer.Tile({source:new ol.source.OSM({})});d=a.get("latitude")||b.get("latitude")||Traccar.Style.mapDefaultLat;f=a.get("longitude")||b.get("longitude")||Traccar.Style.mapDefaultLon;a=a.get("zoom")||b.get("zoom")||Traccar.Style.mapDefaultZoom;this.mapView=new ol.View({center:ol.proj.fromLonLat([f,d]),zoom:a,maxZoom:Traccar.Style.mapMaxZoom});this.map=new ol.Map({target:this.body.dom.id,
+layers:[c],view:this.mapView});e=this.map.getTarget();"string"===typeof e&&(e=Ext.get(e).dom);this.map.on("pointermove",function(a){e.style.cursor=this.forEachFeatureAtPixel(a.pixel,function(){return!0})?"pointer":""});this.map.on("click",function(a){this.map.forEachFeatureAtPixel(a.pixel,function(a){this.fireEvent("selectFeature",a)},this)},this)},listeners:{afterrender:function(){this.initMap()},resize:function(){this.map.updateSize()}}});
+Ext.define("Traccar.GeofenceConverter",{singleton:!0,wktToGeometry:function(a,b){var c,d,f=[],e,g,h;if(0===b.lastIndexOf("POLYGON",0)){if(e=b.match(/\([^\(\)]+\)/),null!==e&&(e=e[0].match(/-?\d+\.?\d*/g),null!==e)){c=a.getProjection();for(d=0;d<e.length;d+=2)g=Number(e[d]),h=Number(e[d+1]),f.push(ol.proj.transform([h,g],"EPSG:4326",c));c=new ol.geom.Polygon([f])}}else 0===b.lastIndexOf("CIRCLE",0)&&(e=b.match(/\([^\(\)]+\)/),null!==e&&(e=e[0].match(/-?\d+\.?\d*/g),null!==e&&(c=a.getProjection(),f=
+ol.proj.transform([Number(e[1]),Number(e[0])],"EPSG:4326",c),d=a.getResolution(),c=c.getPointResolution(d,f),e=Number(e[2])/ol.proj.METERS_PER_UNIT.m*(d/c),c=new ol.geom.Circle(f,e))));return c},geometryToWkt:function(a,b){var c,d,f;if(b instanceof ol.geom.Circle)c=b.getCenter(),d=b.getRadius(),d=[c[0]+d,c[1]],c=ol.proj.transform(c,a,"EPSG:4326"),f=new ol.Sphere(6378137),d=f.haversineDistance(c,ol.proj.transform(d,a,"EPSG:4326")),c="CIRCLE ("+(c[1]+" "+c[0]+", "),c+=Number(d.toFixed(1))+")";else if(b instanceof
+ol.geom.Polygon){b.transform(a,"EPSG:4326");f=b.getCoordinates();c="POLYGON((";for(d=0;d<f[0].length;d+=1)c+=f[0][d][1]+" "+f[0][d][0]+", ";c=c.substring(0,c.length-2)+"))"}return c}});
+Ext.define("Traccar.view.GeofenceMapController",{extend:Ext.app.ViewController,alias:"controller.geofenceMap",onSaveClick:function(a){var b,c;0<this.getView().getFeatures().getLength()&&(b=this.getView().getFeatures().pop().getGeometry(),c=this.getView().getMapView().getProjection(),this.fireEvent("saveArea",Traccar.GeofenceConverter.geometryToWkt(c,b)),a.up("window").close())},onCancelClick:function(a){a.up("window").close()},onTypeSelect:function(a){this.getView().removeInteraction();this.getView().addInteraction(a.getValue())}});
+Ext.define("Traccar.view.GeofenceMap",{extend:Traccar.view.BaseMap,xtype:"geofenceMapView",controller:"geofenceMap",bodyBorder:!0,tbar:{items:[{xtype:"combobox",store:"GeofenceTypes",valueField:"key",displayField:"name",listeners:{select:"onTypeSelect"}},{xtype:"tbfill"},{text:Strings.sharedSave,handler:"onSaveClick"},{text:Strings.sharedCancel,handler:"onCancelClick"}]},getFeatures:function(){return this.features},initMap:function(){var a,b;this.callParent();a=this.map;this.features=new ol.Collection;
+""!==this.area&&(b=Traccar.GeofenceConverter.wktToGeometry(this.mapView,this.area),this.features.push(new ol.Feature(b)),b instanceof ol.geom.Circle?this.mapView.setCenter(b.getCenter()):b instanceof ol.geom.Polygon&&this.mapView.setCenter(b.getCoordinates()[0][0]));(new ol.layer.Vector({source:new ol.source.Vector({features:this.features}),style:new ol.style.Style({fill:new ol.style.Fill({color:Traccar.Style.mapColorOverlay}),stroke:new ol.style.Stroke({color:Traccar.Style.mapColorReport,width:Traccar.Style.mapRouteWidth}),
+image:new ol.style.Circle({radius:Traccar.Style.mapRadiusNormal,fill:new ol.style.Fill({color:Traccar.Style.mapColorReport})})})})).setMap(a);a.addInteraction(new ol.interaction.Modify({features:this.features,deleteCondition:function(a){return ol.events.condition.shiftKeyOnly(a)&&ol.events.condition.singleClick(a)}}))},addInteraction:function(a){this.draw=new ol.interaction.Draw({features:this.features,type:a});this.draw.on("drawstart",function(){this.features.clear()},this);this.map.addInteraction(this.draw)},
+removeInteraction:function(){this.draw&&(this.map.removeInteraction(this.draw),this.draw=null)}});
+Ext.define("Traccar.view.GeofenceDialogController",{extend:Traccar.view.BaseEditDialogController,alias:"controller.geofenceDialog",config:{listen:{controller:{"*":{saveArea:"saveArea"}}}},saveArea:function(a){this.lookupReference("areaField").setValue(a)},onAreaClick:function(a){a=a.up("window").down("form").getRecord();Ext.create("Traccar.view.BaseWindow",{title:Strings.sharedArea,items:{xtype:"geofenceMapView",area:a.get("area")}}).show()}});
+Ext.define("Traccar.view.GeofenceDialog",{extend:Traccar.view.BaseDialog,controller:"geofenceDialog",title:Strings.sharedGeofence,items:{xtype:"form",items:[{xtype:"textfield",name:"name",fieldLabel:Strings.sharedName},{xtype:"textfield",name:"description",fieldLabel:Strings.sharedDescription},{xtype:"hiddenfield",name:"area",allowBlank:!1,reference:"areaField"}]},buttons:[{text:Strings.sharedArea,glyph:"xf21d@FontAwesome",handler:"onAreaClick"},{xtype:"tbfill"},{text:Strings.sharedSave,handler:"onSaveClick"},
+{text:Strings.sharedCancel,handler:"closeView"}]});
+Ext.define("Traccar.view.GeofencesController",{extend:Ext.app.ViewController,alias:"controller.geofences",init:function(){Ext.getStore("Geofences").load()},onAddClick:function(){var a,b;a=Ext.create("Traccar.model.Geofence");a.store=this.getView().getStore();b=Ext.create("Traccar.view.GeofenceDialog");b.down("form").loadRecord(a);b.show()},onEditClick:function(){var a,b;a=this.getView().getSelectionModel().getSelection()[0];b=Ext.create("Traccar.view.GeofenceDialog");b.down("form").loadRecord(a);
+b.show()},onRemoveClick:function(){var a=this.getView().getSelectionModel().getSelection()[0];Ext.Msg.show({title:Strings.sharedGeofence,message:Strings.sharedRemoveConfirm,buttons:Ext.Msg.YESNO,buttonText:{yes:Strings.sharedRemove,no:Strings.sharedCancel},fn:function(b){var c=Ext.getStore("Geofences");"yes"===b&&(c.remove(a),c.sync())}})},onSelectionChange:function(a){a=0<a.length;this.lookupReference("toolbarEditButton").setDisabled(a);this.lookupReference("toolbarRemoveButton").setDisabled(a)}});
+Ext.define("Traccar.view.Geofences",{extend:Ext.grid.Panel,xtype:"geofencesView",controller:"geofences",store:"Geofences",selType:"rowmodel",tbar:{xtype:"editToolbar"},listeners:{selectionchange:"onSelectionChange"},columns:[{text:Strings.sharedName,dataIndex:"name",flex:1},{text:Strings.sharedDescription,dataIndex:"description",flex:1}]});
+Ext.define("Traccar.view.SettingsMenuController",{extend:Ext.app.ViewController,alias:"controller.settings",init:function(){Traccar.app.getUser().get("admin")&&(this.lookupReference("settingsServerButton").setHidden(!1),this.lookupReference("settingsUsersButton").setHidden(!1))},onUserClick:function(){var a=Ext.create("Traccar.view.UserDialog");a.down("form").loadRecord(Traccar.app.getUser());a.show()},onGroupsClick:function(){Ext.create("Traccar.view.BaseWindow",{title:Strings.settingsGroups,modal:!1,
+items:{xtype:"groupsView"}}).show()},onGeofencesClick:function(){Ext.create("Traccar.view.BaseWindow",{title:Strings.sharedGeofences,modal:!1,items:{xtype:"geofencesView"}}).show()},onServerClick:function(){var a=Ext.create("Traccar.view.ServerDialog");a.down("form").loadRecord(Traccar.app.getServer());a.show()},onUsersClick:function(){Ext.create("Traccar.view.BaseWindow",{title:Strings.settingsUsers,modal:!1,items:{xtype:"usersView"}}).show()},onNotificationsClick:function(){var a=Traccar.app.getUser();
+Ext.create("Traccar.view.BaseWindow",{title:Strings.sharedNotifications,modal:!1,items:{xtype:"notificationsView",user:a}}).show()},onLogoutClick:function(){Ext.create("Traccar.view.LoginController").logout()}});
+Ext.define("Traccar.view.SettingsMenu",{extend:Ext.button.Button,xtype:"settingsMenu",glyph:"xf013@FontAwesome",text:Strings.settingsTitle,menu:{controller:"settings",items:[{text:Strings.settingsUser,handler:"onUserClick"},{text:Strings.settingsGroups,handler:"onGroupsClick"},{text:Strings.sharedGeofences,handler:"onGeofencesClick"},{text:Strings.settingsServer,hidden:!0,handler:"onServerClick",reference:"settingsServerButton"},{text:Strings.settingsUsers,hidden:!0,handler:"onUsersClick",reference:"settingsUsersButton"},
+{text:Strings.sharedNotifications,handler:"onNotificationsClick"},{text:Strings.loginLogout,handler:"onLogoutClick"}]}});
+Ext.define("Traccar.view.Devices",{extend:Ext.grid.Panel,xtype:"devicesView",controller:"devices",rootVisible:!1,initComponent:function(){this.store=Ext.create("Ext.data.ChainedStore",{source:"Devices",groupField:"groupId"});this.callParent()},title:Strings.deviceTitle,selType:"rowmodel",tbar:{xtype:"editToolbar",items:[{xtype:"button",disabled:!0,handler:"onGeofencesClick",reference:"toolbarGeofencesButton",glyph:"xf21d@FontAwesome",tooltip:Strings.sharedGeofences,tooltipType:"title"},{disabled:!0,
+handler:"onCommandClick",reference:"deviceCommandButton",glyph:"xf093@FontAwesome",tooltip:Strings.deviceCommand,tooltipType:"title"},{xtype:"tbfill"},{id:"muteButton",glyph:"xf1f7@FontAwesome",tooltip:Strings.sharedMute,tooltipType:"title",pressed:!0,enableToggle:!0,listeners:{toggle:function(a,b){b?a.setGlyph("xf1f7@FontAwesome"):a.setGlyph("xf0a2@FontAwesome")},scope:this}},{id:"deviceFollowButton",glyph:"xf05b@FontAwesome",tooltip:Strings.deviceFollow,tooltipType:"title",enableToggle:!0,toggleHandler:"onFollowClick"},
+{xtype:"settingsMenu"}]},bbar:[{xtype:"tbtext",html:Strings.groupParent},{xtype:"combobox",store:"Groups",queryMode:"local",displayField:"name",valueField:"id",flex:1,listeners:{change:function(){Ext.isNumber(this.getValue())?this.up("grid").store.filter({id:"groupFilter",filterFn:function(a){var b,c=!0;b=a.get("groupId");for(a=Ext.getStore("Groups");b;)if(b=a.getById(b)){if(b.get("id")===this.getValue()){c=!1;break}b=b.get("groupId")}else b=0;return!c},scope:this}):this.up("grid").store.removeFilter("groupFilter")}}},
+{xtype:"tbtext",html:Strings.sharedSearch},{xtype:"textfield",flex:1,listeners:{change:function(){this.up("grid").store.filter("name",this.getValue())}}}],listeners:{selectionchange:"onSelectionChange"},columns:[{text:Strings.sharedName,dataIndex:"name",flex:1},{text:Strings.deviceLastUpdate,dataIndex:"lastUpdate",flex:1,renderer:function(a,b,c){switch(c.get("status")){case "online":b.tdCls="view-color-green";break;case "offline":b.tdCls="view-color-red";break;default:b.tdCls="view-color-yellow"}return Traccar.app.getPreference("twelveHourFormat",
+!1)?Ext.Date.format(a,Traccar.Style.dateTimeFormat12):Ext.Date.format(a,Traccar.Style.dateTimeFormat24)}}]});
+Ext.define("Traccar.view.StateController",{extend:Ext.app.ViewController,alias:"controller.state",config:{listen:{controller:{"*":{selectDevice:"selectDevice",selectReport:"selectReport"}},store:{"#LatestPositions":{add:"updateLatest",update:"updateLatest"},"#Positions":{clear:"clearReport"}}}},keys:function(){var a,b,c;c={};b="fixTime latitude longitude valid altitude speed course address protocol".split(" ");for(a=0;a<b.length;a++)c[b[a]]={priority:a,name:Strings["position"+b[a].replace(/^\w/g,
+function(a){return a.toUpperCase()})]};return c}(),updateLatest:function(a,b){var c;Ext.isArray(b)||(b=[b]);for(c=0;c<b.length;c++)this.deviceId===b[c].get("deviceId")&&this.updatePosition(b[c])},formatValue:function(a){return"number"===typeof id?Number(a.toFixed(2)):a},updatePosition:function(a){var b,c;b=Ext.getStore("Attributes");b.removeAll();for(c in a.data)a.data.hasOwnProperty(c)&&void 0!==this.keys[c]&&b.add(Ext.create("Traccar.model.Attribute",{priority:this.keys[c].priority,name:this.keys[c].name,
+value:Traccar.AttributeFormatter.getFormatter(c)(a.get(c))}));a=a.get("attributes");if(a instanceof Object)for(c in a)a.hasOwnProperty(c)&&b.add(Ext.create("Traccar.model.Attribute",{priority:1024,name:c.replace(/^./,function(a){return a.toUpperCase()}),value:Traccar.AttributeFormatter.getFormatter(c)(a[c])}))},selectDevice:function(a){this.deviceId=a.get("id");(a=Ext.getStore("LatestPositions").findRecord("deviceId",this.deviceId,0,!1,!1,!0))?this.updatePosition(a):Ext.getStore("Attributes").removeAll()},
+selectReport:function(a){this.deviceId=null;this.updatePosition(a)},clearReport:function(){Ext.getStore("Attributes").removeAll()}});Ext.define("Traccar.view.State",{extend:Ext.grid.Panel,xtype:"stateView",controller:"state",store:"Attributes",title:Strings.stateTitle,columns:[{text:Strings.stateName,dataIndex:"name",flex:1},{text:Strings.stateValue,dataIndex:"value",flex:1,renderer:function(a,b,c){"Alarm"===c.get("name")&&(b.tdCls="view-color-red");return a}}]});
+Ext.define("Traccar.view.ReportController",{extend:Ext.app.ViewController,alias:"controller.report",config:{listen:{controller:{"*":{selectDevice:"selectDevice",selectReport:"selectReport"}}}},onShowClick:function(){var a,b,c,d;a=this.lookupReference("deviceField").getValue();b=this.lookupReference("fromDateField").getValue();c=this.lookupReference("fromTimeField").getValue();a&&(b=new Date(b.getFullYear(),b.getMonth(),b.getDate(),c.getHours(),c.getMinutes(),c.getSeconds(),c.getMilliseconds()),c=
+this.lookupReference("toDateField").getValue(),d=this.lookupReference("toTimeField").getValue(),c=new Date(c.getFullYear(),c.getMonth(),c.getDate(),d.getHours(),d.getMinutes(),d.getSeconds(),d.getMilliseconds()),d=Ext.getStore("Positions"),d.load({params:{deviceId:a,from:b.toISOString(),to:c.toISOString()}}))},onClearClick:function(){Ext.getStore("Positions").removeAll()},onSelectionChange:function(a){0<a.getCount()&&this.fireEvent("selectReport",a.getLastSelected(),!0)},selectDevice:function(a){a&&
+this.getView().getSelectionModel().deselectAll()},selectReport:function(a){this.getView().getSelectionModel().select([a],!1,!0)}});Ext.define("Traccar.view.CustomTimeField",{extend:Ext.form.field.Time,xtype:"customTimeField",constructor:function(a){a.format=Traccar.app.getPreference("twelveHourFormat",!1)?Traccar.Style.timeFormat12:Traccar.Style.timeFormat24;this.callParent(arguments)}});
+Ext.define("Traccar.view.Report",{extend:Ext.grid.Panel,xtype:"reportView",controller:"report",store:"Positions",title:Strings.reportTitle,tbar:[{xtype:"tbtext",html:Strings.reportDevice},{xtype:"combobox",reference:"deviceField",store:"Devices",valueField:"id",displayField:"name",typeAhead:!0,queryMode:"local"},"-",{xtype:"tbtext",html:Strings.reportFrom},{xtype:"datefield",reference:"fromDateField",startDay:Traccar.Style.weekStartDay,format:Traccar.Style.dateFormat,value:new Date((new Date).getTime()-
+18E5)},{xtype:"customTimeField",reference:"fromTimeField",maxWidth:Traccar.Style.reportTime,value:new Date((new Date).getTime()-18E5)},"-",{xtype:"tbtext",html:Strings.reportTo},{xtype:"datefield",reference:"toDateField",startDay:Traccar.Style.weekStartDay,format:Traccar.Style.dateFormat,value:new Date},{xtype:"customTimeField",reference:"toTimeField",maxWidth:Traccar.Style.reportTime,value:new Date},"-",{text:Strings.reportShow,handler:"onShowClick"},{text:Strings.reportClear,handler:"onClearClick"}],
+listeners:{selectionchange:"onSelectionChange"},columns:[{text:Strings.positionValid,dataIndex:"valid",flex:1,renderer:Traccar.AttributeFormatter.getFormatter("valid")},{text:Strings.positionFixTime,dataIndex:"fixTime",flex:1,xtype:"datecolumn",renderer:Traccar.AttributeFormatter.getFormatter("fixTime")},{text:Strings.positionLatitude,dataIndex:"latitude",flex:1,renderer:Traccar.AttributeFormatter.getFormatter("latitude")},{text:Strings.positionLongitude,dataIndex:"longitude",flex:1,renderer:Traccar.AttributeFormatter.getFormatter("latitude")},
+{text:Strings.positionAltitude,dataIndex:"altitude",flex:1,renderer:Traccar.AttributeFormatter.getFormatter("altitude")},{text:Strings.positionSpeed,dataIndex:"speed",flex:1,renderer:Traccar.AttributeFormatter.getFormatter("speed")},{text:Strings.positionAddress,dataIndex:"address",flex:1,renderer:Traccar.AttributeFormatter.getFormatter("address")}]});
+Ext.define("Traccar.view.MapController",{extend:Ext.app.ViewController,alias:"controller.map",config:{listen:{controller:{"*":{selectDevice:"selectDevice",selectReport:"selectReport"}},store:{"#Devices":{add:"updateDevice",update:"updateDevice"},"#LatestPositions":{add:"updateLatest",update:"updateLatest"},"#Positions":{load:"loadReport",clear:"clearReport"}},component:{"#":{selectFeature:"selectFeature"}}}},init:function(){this.latestMarkers={};this.reportMarkers={}},getDeviceColor:function(a){switch(a.get("status")){case "online":return Traccar.Style.mapColorOnline;
+case "offline":return Traccar.Style.mapColorOffline;default:return Traccar.Style.mapColorUnknown}},changeMarkerColor:function(a,b){return new ol.style.Style({image:new ol.style.Arrow({radius:a.getImage().getRadius(),fill:new ol.style.Fill({color:b}),stroke:a.getImage().getStroke(),rotation:a.getImage().getRotation()}),text:a.getText()})},updateDevice:function(a,b){var c,d,f;Ext.isArray(b)||(b=[b]);for(c=0;c<b.length;c++)d=b[c],f=d.get("id"),f in this.latestMarkers&&(f=this.latestMarkers[f],f.setStyle(this.changeMarkerColor(f.getStyle(),
+this.getDeviceColor(d))))},followSelected:function(){return Ext.getCmp("deviceFollowButton")&&Ext.getCmp("deviceFollowButton").pressed},updateLatest:function(a,b){var c,d,f,e,g,h;Ext.isArray(b)||(b=[b]);for(c=0;c<b.length;c++)if(d=b[c],g=d.get("deviceId"),e=Ext.getStore("Devices").findRecord("id",g,0,!1,!1,!0))f=new ol.geom.Point(ol.proj.fromLonLat([d.get("longitude"),d.get("latitude")])),g in this.latestMarkers?(h=this.latestMarkers[g],h.setGeometry(f)):(h=new ol.Feature(f),h.set("record",e),this.latestMarkers[g]=
+h,this.getView().getLatestSource().addFeature(h),f=this.getLatestMarker(this.getDeviceColor(e)),f.getText().setText(e.get("name")),h.setStyle(f)),h.getStyle().getImage().setRotation(d.get("course")*Math.PI/180),h===this.selectedMarker&&this.followSelected()&&this.getView().getMapView().setCenter(h.getGeometry().getCoordinates())},loadReport:function(a,b){var c,d,f,e,g;this.clearReport(a);if(0<b.length){this.reportRoute=new ol.Feature({geometry:new ol.geom.LineString([])});this.reportRoute.setStyle(this.getRouteStyle());
+this.getView().getRouteSource().addFeature(this.reportRoute);for(c=0;c<b.length;c++)d=b[c],f=ol.proj.fromLonLat([d.get("longitude"),d.get("latitude")]),e=new ol.geom.Point(f),e=new ol.Feature(e),e.set("record",d),this.reportMarkers[d.get("id")]=e,this.getView().getReportSource().addFeature(e),g=this.getReportMarker(),g.getImage().setRotation(d.get("course")*Math.PI/180),e.setStyle(g),this.reportRoute.getGeometry().appendCoordinate(f);this.getView().getMapView().fit(this.reportRoute.getGeometry(),
+this.getView().getMap().getSize())}},clearReport:function(){var a;this.reportRoute&&(this.getView().getRouteSource().removeFeature(this.reportRoute),this.reportRoute=null);if(this.reportMarkers){for(a in this.reportMarkers)this.reportMarkers.hasOwnProperty(a)&&this.getView().getReportSource().removeFeature(this.reportMarkers[a]);this.reportMarkers={}}},getRouteStyle:function(){return new ol.style.Style({stroke:new ol.style.Stroke({color:Traccar.Style.mapRouteColor,width:Traccar.Style.mapRouteWidth})})},
+getMarkerStyle:function(a,b){return new ol.style.Style({image:new ol.style.Arrow({radius:a,fill:new ol.style.Fill({color:b}),stroke:new ol.style.Stroke({color:Traccar.Style.mapArrowStrokeColor,width:Traccar.Style.mapArrowStrokeWidth})}),text:new ol.style.Text({textBaseline:"bottom",fill:new ol.style.Fill({color:Traccar.Style.mapTextColor}),stroke:new ol.style.Stroke({color:Traccar.Style.mapTextStrokeColor,width:Traccar.Style.mapTextStrokeWidth}),offsetY:-a/2-Traccar.Style.mapTextOffset,font:Traccar.Style.mapTextFont})})},
+getLatestMarker:function(a){return this.getMarkerStyle(Traccar.Style.mapRadiusNormal,a)},getReportMarker:function(){return this.getMarkerStyle(Traccar.Style.mapRadiusNormal,Traccar.Style.mapColorReport)},resizeMarker:function(a,b){return new ol.style.Style({image:new ol.style.Arrow({radius:b,fill:a.getImage().getFill(),stroke:a.getImage().getStroke(),rotation:a.getImage().getRotation()}),text:a.getText()})},selectMarker:function(a,b){this.selectedMarker&&this.selectedMarker.setStyle(this.resizeMarker(this.selectedMarker.getStyle(),
+Traccar.Style.mapRadiusNormal));a&&(a.setStyle(this.resizeMarker(a.getStyle(),Traccar.Style.mapRadiusSelected)),b&&this.getView().getMapView().setCenter(a.getGeometry().getCoordinates()));this.selectedMarker=a},selectDevice:function(a,b){this.selectMarker(this.latestMarkers[a.get("id")],b)},selectReport:function(a,b){this.selectMarker(this.reportMarkers[a.get("id")],b)},selectFeature:function(a){(a=a.get("record"))&&(a instanceof Traccar.model.Device?this.fireEvent("selectDevice",a,!1):this.fireEvent("selectReport",
+a,!1))}});
+Ext.define("Traccar.view.Map",{extend:Traccar.view.BaseMap,xtype:"mapView",controller:"map",title:Strings.mapTitle,getLatestSource:function(){return this.latestSource},getRouteSource:function(){return this.routeSource},getReportSource:function(){return this.reportSource},initMap:function(){this.callParent();this.latestSource=new ol.source.Vector({});this.map.addLayer(new ol.layer.Vector({source:this.latestSource}));this.routeSource=new ol.source.Vector({});this.map.addLayer(new ol.layer.Vector({source:this.routeSource}));this.reportSource=
+new ol.source.Vector({});this.map.addLayer(new ol.layer.Vector({source:this.reportSource}))}});
+Ext.define("Traccar.view.Main",{extend:Ext.container.Viewport,alias:"widget.main",layout:"border",defaults:{header:!1,collapsible:!0,split:!0},items:[{region:"west",layout:"border",width:Traccar.Style.deviceWidth,title:Strings.devicesAndState,defaults:{split:!0,flex:1},items:[{region:"center",xtype:"devicesView"},{region:"south",xtype:"stateView"}]},{region:"south",xtype:"reportView",height:Traccar.Style.reportHeight,collapsed:!0,titleCollapse:!0,floatable:!1},{region:"center",xtype:"mapView",header:!0,
+collapsible:!1}]});Ext.define("Traccar.view.MainMobile",{extend:Ext.container.Viewport,alias:"widget.mainMobile",layout:"border",defaults:{header:!1,collapsible:!0,split:!0},items:[{region:"east",xtype:"stateView",flex:4,collapsed:!0,titleCollapse:!0,floatable:!1},{region:"center",xtype:"mapView",collapsible:!1,flex:2},{region:"south",xtype:"devicesView",flex:1}]});
+Ext.define("Traccar.controller.Root",{extend:Ext.app.Controller,init:function(){var a=document.createElement("div");a.className="state-indicator";document.body.appendChild(a);this.isPhone=0!==parseInt(window.getComputedStyle(a).getPropertyValue("z-index"),10)},onLaunch:function(){Ext.Ajax.request({scope:this,url:"/api/server",callback:this.onServerReturn})},onServerReturn:function(a,b,c){Ext.get("spinner").remove();b?(Traccar.app.setServer(Ext.decode(c.responseText)),Ext.Ajax.request({scope:this,
+url:"/api/session",callback:this.onSessionReturn})):Traccar.app.showError(c)},onSessionReturn:function(a,b,c){b?(Traccar.app.setUser(Ext.decode(c.responseText)),this.loadApp()):(this.login=Ext.create("widget.login",{listeners:{scope:this,login:this.onLogin}}),this.login.show())},onLogin:function(){this.login.close();this.loadApp()},loadApp:function(){Ext.getStore("Groups").load();Ext.getStore("Geofences").load();Ext.getStore("Devices").load({scope:this,callback:function(){this.asyncUpdate(!0)}});
+var a=Ext.get("attribution");a&&a.remove();this.isPhone?Ext.create("widget.mainMobile"):Ext.create("widget.main")},beep:function(){this.beepSound||(this.beepSound=new Audio("beep.wav"));this.beepSound.play()},mutePressed:function(){var a=Ext.getCmp("muteButton");return a&&!a.pressed},asyncUpdate:function(){var a,b=this;a=new WebSocket(("https:"===location.protocol?"wss:":"ws:")+"//"+window.location.host+"/api/socket");a.onclose=function(){b.asyncUpdate(!1)};a.onmessage=function(a){var d,f,e,g,h;e=
+Ext.decode(a.data);if(e.devices){g=e.devices;f=Ext.getStore("Devices");for(a=0;a<g.length;a++)(d=f.getById(g[a].id))&&d.set({status:g[a].status,lastUpdate:g[a].lastUpdate},{dirty:!1})}if(e.positions&&!e.events){g=e.positions;f=Ext.getStore("LatestPositions");for(a=0;a<g.length;a++)(d=f.findRecord("deviceId",g[a].deviceId,0,!1,!1,!0))?d.set(g[a]):f.add(Ext.create("Traccar.model.Position",g[a]))}if(e.events){g=e.events;f=Ext.getStore("Events");for(a=0;a<g.length;a++){f.add(g[a]);if("commandResult"===
+g[a].type&&e.positions){for(d=0;d<e.positions.length;d++)if(e.positions[d].id===g[a].positionId){h=e.positions[d].attributes.result;break}h=Strings.eventCommandResult+": "+h}else if("alarm"===g[a].type&&e.positions){d="alarm";(h=Strings[d])||(h=d);for(d=0;d<e.positions.length;d++)if(e.positions[d].id===g[a].positionId&&null!==e.positions[d].attributes.alarm){"string"===typeof e.positions[d].attributes.alarm&&2<=e.positions[d].attributes.alarm.length&&(d="alarm"+e.positions[d].attributes.alarm.charAt(0).toUpperCase()+
+e.positions[d].attributes.alarm.slice(1),(h=Strings[d])||(h=d));break}}else d="event"+g[a].type.charAt(0).toUpperCase()+g[a].type.slice(1),(h=Strings[d])||(h=d);0!==g[a].geofenceId&&(d=Ext.getStore("Geofences").getById(g[a].geofenceId),"undefined"!==typeof d&&(h+=' "'+d.getData().name+'"'));d=Ext.getStore("Devices").getById(g[a].deviceId);"undefined"!==typeof d&&(b.mutePressed()&&b.beep(),Ext.toast(h,d.get("name")))}}}}});
+Ext.define("Traccar.Application",{extend:Ext.app.Application,name:"Traccar",models:"Server User Group Device Position Attribute Command Event Geofence Notification".split(" "),stores:"Groups Devices AllGroups AllDevices Positions LatestPositions Users Attributes MapTypes DistanceUnits SpeedUnits CommandTypes TimeUnits Languages Events Geofences AllGeofences Notifications AllNotifications GeofenceTypes".split(" "),controllers:["Root"],setUser:function(a){this.user=Ext.create("Ext.data.reader.Json",
+{model:"Traccar.model.User"}).readRecords(a).getRecords()[0]},getUser:function(){return this.user},setServer:function(a){this.server=Ext.create("Ext.data.reader.Json",{model:"Traccar.model.Server"}).readRecords(a).getRecords()[0]},getServer:function(){return this.server},getPreference:function(a,b){return this.getUser().get(a)||this.getServer().get(a)||b},showError:function(a){Ext.isString(a)?Ext.Msg.alert(Strings.errorTitle,a):a.responseText?(a=Ext.decode(a.responseText),a.details?Ext.Msg.alert(Strings.errorTitle,
+a.details):Ext.Msg.alert(Strings.errorTitle,a.message)):a.statusText?Ext.Msg.alert(Strings.errorTitle,a.statusText):Ext.Msg.alert(Strings.errorTitle,Strings.errorConnection)}});Ext.application({name:"Traccar",extend:Traccar.Application}); \ No newline at end of file
diff --git a/web/app/view/LoginController.js b/web/app/view/LoginController.js
index 7a78a6fb1..8beef1e04 100644
--- a/web/app/view/LoginController.js
+++ b/web/app/view/LoginController.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 - 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,13 +26,6 @@ Ext.define('Traccar.view.LoginController', {
this.lookupReference('registerButton').setDisabled(
!Traccar.app.getServer().get('registration'));
this.lookupReference('languageField').setValue(Locale.language);
- var user = Ext.util.Cookies.get('user');
- var password = Ext.util.Cookies.get('password');
- if (user && password) {
- this.lookupReference('userField').setValue(user);
- this.lookupReference('passwordField').setValue(password);
- this.login();
- }
},
login: function () {
diff --git a/web/l10n/bn.json b/web/l10n/bn.json
new file mode 100644
index 000000000..16cdc050a
--- /dev/null
+++ b/web/l10n/bn.json
@@ -0,0 +1,136 @@
+{
+ "sharedLoading": "লোড হচ্ছে ...",
+ "sharedSave": "সংরক্ষণ",
+ "sharedCancel": "বাতিল",
+ "sharedAdd": "যোগ",
+ "sharedEdit": "সম্পাদন",
+ "sharedRemove": "অপসারণ",
+ "sharedRemoveConfirm": "Remove item?",
+ "sharedKm": "km",
+ "sharedMi": "mi",
+ "sharedKn": "kn",
+ "sharedKmh": "km/h",
+ "sharedMph": "mph",
+ "sharedHour": "Hour",
+ "sharedMinute": "Minute",
+ "sharedSecond": "Second",
+ "sharedName": "Name",
+ "sharedDescription": "Description",
+ "sharedSearch": "Search",
+ "sharedGeofence": "Geofence",
+ "sharedGeofences": "Geofences",
+ "sharedNotifications": "Notifications",
+ "sharedAttributes": "Attributes",
+ "sharedAttribute": "Attribute",
+ "sharedArea": "Area",
+ "sharedMute": "Mute",
+ "errorTitle": "Error",
+ "errorUnknown": "Unknown error",
+ "errorConnection": "Connection error",
+ "userEmail": "Email",
+ "userPassword": "Password",
+ "userAdmin": "Admin",
+ "userRemember": "Remember",
+ "loginTitle": "Login",
+ "loginLanguage": "Language",
+ "loginRegister": "Register",
+ "loginLogin": "Login",
+ "loginFailed": "Incorrect email address or password",
+ "loginCreated": "New user has been registered",
+ "loginLogout": "Logout",
+ "devicesAndState": "Devices and State",
+ "deviceDialog": "Device",
+ "deviceTitle": "Devices",
+ "deviceIdentifier": "Identifier",
+ "deviceLastUpdate": "Last Update",
+ "deviceCommand": "Command",
+ "deviceFollow": "Follow",
+ "groupDialog": "Group",
+ "groupParent": "Group",
+ "groupNoGroup": "No Group",
+ "settingsTitle": "Settings",
+ "settingsUser": "Account",
+ "settingsGroups": "Groups",
+ "settingsServer": "Server",
+ "settingsUsers": "Users",
+ "settingsDistanceUnit": "Distance",
+ "settingsSpeedUnit": "Speed",
+ "settingsTwelveHourFormat": "12-hour Format",
+ "reportTitle": "Reports",
+ "reportDevice": "Device",
+ "reportFrom": "From",
+ "reportTo": "To",
+ "reportShow": "Show",
+ "reportClear": "Clear",
+ "positionFixTime": "Time",
+ "positionValid": "Valid",
+ "positionLatitude": "Latitude",
+ "positionLongitude": "Longitude",
+ "positionAltitude": "Altitude",
+ "positionSpeed": "Speed",
+ "positionCourse": "Course",
+ "positionAddress": "Address",
+ "positionProtocol": "Protocol",
+ "serverTitle": "Server Settings",
+ "serverZoom": "Zoom",
+ "serverRegistration": "Registration",
+ "serverReadonly": "Readonly",
+ "mapTitle": "Map",
+ "mapLayer": "Map Layer",
+ "mapCustom": "Custom Map",
+ "mapOsm": "Open Street Map",
+ "mapBingKey": "Bing Maps Key",
+ "mapBingRoad": "Bing Maps Road",
+ "mapBingAerial": "Bing Maps Aerial",
+ "mapShapePolygon": "Polygon",
+ "mapShapeCircle": "Circle",
+ "stateTitle": "State",
+ "stateName": "Attribute",
+ "stateValue": "Value",
+ "commandTitle": "Command",
+ "commandSend": "Send",
+ "commandType": "Type",
+ "commandSent": "Command has been sent",
+ "commandPositionPeriodic": "Periodic Reporting",
+ "commandPositionStop": "Stop Reporting",
+ "commandEngineStop": "Engine Stop",
+ "commandEngineResume": "Engine Resume",
+ "commandFrequency": "Frequency",
+ "commandUnit": "Unit",
+ "commandCustom": "Custom command",
+ "commandPositionSingle": "Single Reporting",
+ "commandAlarmArm": "Arm Alarm",
+ "commandAlarmDisarm": "Disarm Alarm",
+ "commandSetTimezone": "Set Timezone",
+ "commandRequestPhoto": "Request Photo",
+ "commandRebootDevice": "Reboot Device",
+ "commandSendSms": "Send SMS",
+ "commandSosNumber": "Set SOS Number",
+ "commandSilenceTime": "Set Silence Time",
+ "commandSetPhonebook": "Set Phonebook",
+ "commandVoiceMessage": "Voice Message",
+ "commandOutputControl": "Output Control",
+ "commandAlarmSpeed": "Overspeed Alarm",
+ "commandDeviceIdentification": "Device Identification",
+ "eventDeviceOnline": "Device is online",
+ "eventDeviceOffline": "Device is offline",
+ "eventDeviceMoving": "Device is moving",
+ "eventDeviceStopped": "Device is stopped",
+ "eventDeviceOverspeed": "Device exceeds the speed",
+ "eventCommandResult": "Command result",
+ "eventGeofenceEnter": "Device has entered geofence",
+ "eventGeofenceExit": "Device has exited geofence",
+ "eventAlarm": "Alarms",
+ "alarm": "Alarm",
+ "alarmSos": "SOS Alarm",
+ "alarmVibration": "Vibration Alarm",
+ "alarmMovement": "Movement Alarm",
+ "alarmOverspeed": "Overspeed Alarm",
+ "alarmFallDown": "FallDown Alarm",
+ "alarmLowBattery": "LowBattery Alarm",
+ "alarmMotion": "Motion Alarm",
+ "alarmFault": "Fault Alarm",
+ "notificationType": "Type of Notification",
+ "notificationWeb": "Send via Web",
+ "notificationMail": "Send via Mail"
+} \ No newline at end of file
diff --git a/web/l10n/hi.json b/web/l10n/hi.json
new file mode 100644
index 000000000..1fff378cb
--- /dev/null
+++ b/web/l10n/hi.json
@@ -0,0 +1,136 @@
+{
+ "sharedLoading": "लोड हो रहा है...",
+ "sharedSave": "सुरक्षित करें",
+ "sharedCancel": "रद्द करें ",
+ "sharedAdd": "जोड़ें ",
+ "sharedEdit": "संपादित करें",
+ "sharedRemove": "हटाएं ",
+ "sharedRemoveConfirm": "आइटम हटाएं ?",
+ "sharedKm": "किमी ( किलोमीटर )",
+ "sharedMi": "एम आई ",
+ "sharedKn": "के.एन.",
+ "sharedKmh": "किमी / घंटा",
+ "sharedMph": "मील प्रति घंटा",
+ "sharedHour": "घंटा",
+ "sharedMinute": "मिनट",
+ "sharedSecond": "सैकंड ",
+ "sharedName": "नाम",
+ "sharedDescription": "विवरण",
+ "sharedSearch": "खोजें",
+ "sharedGeofence": "जिओफेंस / भूगौलिक परिधि",
+ "sharedGeofences": "जिओफेंसस / भूगौलिक परिधियां",
+ "sharedNotifications": "सूचनाएं",
+ "sharedAttributes": "गुण",
+ "sharedAttribute": "गुण",
+ "sharedArea": "क्षेत्र",
+ "sharedMute": "Mute",
+ "errorTitle": "त्रुटि",
+ "errorUnknown": "अज्ञात त्रुटि",
+ "errorConnection": "कनेक्शन त्रुटि",
+ "userEmail": "ईमेल",
+ "userPassword": "पासवर्ड / गोपनीय शब्द ",
+ "userAdmin": "एडमिन / व्यवस्थापक",
+ "userRemember": "Remember",
+ "loginTitle": "लॉगिन / प्रवेश करें ",
+ "loginLanguage": "भाषा",
+ "loginRegister": "रजिस्टर / पंजीकृत करें",
+ "loginLogin": "लॉगिन / प्रवेश करें ",
+ "loginFailed": "ई-मेल पता या पासवर्ड गलत है",
+ "loginCreated": "New user has been registered",
+ "loginLogout": "लॉगआउट / निष्कासन करें",
+ "devicesAndState": "Devices and State",
+ "deviceDialog": "उपकरण",
+ "deviceTitle": "उपकरण",
+ "deviceIdentifier": "पहचानकर्ता",
+ "deviceLastUpdate": "Last Update",
+ "deviceCommand": "आदेश",
+ "deviceFollow": "Follow",
+ "groupDialog": "Group",
+ "groupParent": "Group",
+ "groupNoGroup": "No Group",
+ "settingsTitle": "सेटिंग्स",
+ "settingsUser": "Account",
+ "settingsGroups": "Groups",
+ "settingsServer": "सर्वर",
+ "settingsUsers": "Users",
+ "settingsDistanceUnit": "Distance",
+ "settingsSpeedUnit": "गति",
+ "settingsTwelveHourFormat": "12-hour Format",
+ "reportTitle": "Reports",
+ "reportDevice": "उपकरण",
+ "reportFrom": "From",
+ "reportTo": "To",
+ "reportShow": "Show",
+ "reportClear": "Clear",
+ "positionFixTime": "समय",
+ "positionValid": "Valid",
+ "positionLatitude": "अक्षांश / अक्षरेखा",
+ "positionLongitude": "देशान्तर",
+ "positionAltitude": "ऊंचाई",
+ "positionSpeed": "गति",
+ "positionCourse": "मार्ग",
+ "positionAddress": "Address",
+ "positionProtocol": "Protocol",
+ "serverTitle": "Server Settings",
+ "serverZoom": "Zoom",
+ "serverRegistration": "Registration",
+ "serverReadonly": "Readonly",
+ "mapTitle": "Map",
+ "mapLayer": "Map Layer",
+ "mapCustom": "Custom Map",
+ "mapOsm": "Open Street Map",
+ "mapBingKey": "Bing Maps Key",
+ "mapBingRoad": "Bing Maps Road",
+ "mapBingAerial": "Bing Maps Aerial",
+ "mapShapePolygon": "Polygon",
+ "mapShapeCircle": "Circle",
+ "stateTitle": "State",
+ "stateName": "Attribute",
+ "stateValue": "Value",
+ "commandTitle": "आदेश",
+ "commandSend": "भेजें / प्रेषित करें",
+ "commandType": "Type",
+ "commandSent": "कमांड / आदेश भेज दी गयी है ",
+ "commandPositionPeriodic": "Periodic Reporting",
+ "commandPositionStop": "Stop Reporting",
+ "commandEngineStop": "Engine Stop",
+ "commandEngineResume": "Engine Resume",
+ "commandFrequency": "फ्रीक्वेंसी / आवृत्ति",
+ "commandUnit": "इकाई",
+ "commandCustom": "Custom command",
+ "commandPositionSingle": "Single Reporting",
+ "commandAlarmArm": "Arm Alarm",
+ "commandAlarmDisarm": "Disarm Alarm",
+ "commandSetTimezone": "Set Timezone",
+ "commandRequestPhoto": "Request Photo",
+ "commandRebootDevice": "Reboot Device",
+ "commandSendSms": "Send SMS",
+ "commandSosNumber": "Set SOS Number",
+ "commandSilenceTime": "Set Silence Time",
+ "commandSetPhonebook": "Set Phonebook",
+ "commandVoiceMessage": "Voice Message",
+ "commandOutputControl": "Output Control",
+ "commandAlarmSpeed": "Overspeed Alarm",
+ "commandDeviceIdentification": "Device Identification",
+ "eventDeviceOnline": "Device is online",
+ "eventDeviceOffline": "Device is offline",
+ "eventDeviceMoving": "Device is moving",
+ "eventDeviceStopped": "Device is stopped",
+ "eventDeviceOverspeed": "Device exceeds the speed",
+ "eventCommandResult": "Command result",
+ "eventGeofenceEnter": "Device has entered geofence",
+ "eventGeofenceExit": "Device has exited geofence",
+ "eventAlarm": "Alarms",
+ "alarm": "Alarm",
+ "alarmSos": "SOS Alarm",
+ "alarmVibration": "Vibration Alarm",
+ "alarmMovement": "Movement Alarm",
+ "alarmOverspeed": "Overspeed Alarm",
+ "alarmFallDown": "FallDown Alarm",
+ "alarmLowBattery": "LowBattery Alarm",
+ "alarmMotion": "Motion Alarm",
+ "alarmFault": "Fault Alarm",
+ "notificationType": "Type of Notification",
+ "notificationWeb": "Send via Web",
+ "notificationMail": "Send via Mail"
+} \ No newline at end of file
diff --git a/web/l10n/hr.json b/web/l10n/hr.json
new file mode 100644
index 000000000..37e4537f2
--- /dev/null
+++ b/web/l10n/hr.json
@@ -0,0 +1,136 @@
+{
+ "sharedLoading": "Loading...",
+ "sharedSave": "Save",
+ "sharedCancel": "Cancel",
+ "sharedAdd": "Add",
+ "sharedEdit": "Edit",
+ "sharedRemove": "Remove",
+ "sharedRemoveConfirm": "Remove item?",
+ "sharedKm": "km",
+ "sharedMi": "mi",
+ "sharedKn": "kn",
+ "sharedKmh": "km/h",
+ "sharedMph": "mph",
+ "sharedHour": "Hour",
+ "sharedMinute": "Minute",
+ "sharedSecond": "Second",
+ "sharedName": "Name",
+ "sharedDescription": "Description",
+ "sharedSearch": "Search",
+ "sharedGeofence": "Geofence",
+ "sharedGeofences": "Geofences",
+ "sharedNotifications": "Notifications",
+ "sharedAttributes": "Attributes",
+ "sharedAttribute": "Attribute",
+ "sharedArea": "Area",
+ "sharedMute": "Mute",
+ "errorTitle": "Error",
+ "errorUnknown": "Unknown error",
+ "errorConnection": "Connection error",
+ "userEmail": "Email",
+ "userPassword": "Password",
+ "userAdmin": "Admin",
+ "userRemember": "Remember",
+ "loginTitle": "Login",
+ "loginLanguage": "Language",
+ "loginRegister": "Register",
+ "loginLogin": "Login",
+ "loginFailed": "Incorrect email address or password",
+ "loginCreated": "New user has been registered",
+ "loginLogout": "Logout",
+ "devicesAndState": "Devices and State",
+ "deviceDialog": "Device",
+ "deviceTitle": "Devices",
+ "deviceIdentifier": "Identifier",
+ "deviceLastUpdate": "Last Update",
+ "deviceCommand": "Command",
+ "deviceFollow": "Follow",
+ "groupDialog": "Group",
+ "groupParent": "Group",
+ "groupNoGroup": "No Group",
+ "settingsTitle": "Settings",
+ "settingsUser": "Account",
+ "settingsGroups": "Groups",
+ "settingsServer": "Server",
+ "settingsUsers": "Users",
+ "settingsDistanceUnit": "Distance",
+ "settingsSpeedUnit": "Speed",
+ "settingsTwelveHourFormat": "12-hour Format",
+ "reportTitle": "Reports",
+ "reportDevice": "Device",
+ "reportFrom": "From",
+ "reportTo": "To",
+ "reportShow": "Show",
+ "reportClear": "Clear",
+ "positionFixTime": "Time",
+ "positionValid": "Valid",
+ "positionLatitude": "Latitude",
+ "positionLongitude": "Longitude",
+ "positionAltitude": "Altitude",
+ "positionSpeed": "Speed",
+ "positionCourse": "Course",
+ "positionAddress": "Address",
+ "positionProtocol": "Protocol",
+ "serverTitle": "Server Settings",
+ "serverZoom": "Zoom",
+ "serverRegistration": "Registration",
+ "serverReadonly": "Readonly",
+ "mapTitle": "Map",
+ "mapLayer": "Map Layer",
+ "mapCustom": "Custom Map",
+ "mapOsm": "Open Street Map",
+ "mapBingKey": "Bing Maps Key",
+ "mapBingRoad": "Bing Maps Road",
+ "mapBingAerial": "Bing Maps Aerial",
+ "mapShapePolygon": "Polygon",
+ "mapShapeCircle": "Circle",
+ "stateTitle": "State",
+ "stateName": "Attribute",
+ "stateValue": "Value",
+ "commandTitle": "Command",
+ "commandSend": "Send",
+ "commandType": "Type",
+ "commandSent": "Command has been sent",
+ "commandPositionPeriodic": "Periodic Reporting",
+ "commandPositionStop": "Stop Reporting",
+ "commandEngineStop": "Engine Stop",
+ "commandEngineResume": "Engine Resume",
+ "commandFrequency": "Frequency",
+ "commandUnit": "Unit",
+ "commandCustom": "Custom command",
+ "commandPositionSingle": "Single Reporting",
+ "commandAlarmArm": "Arm Alarm",
+ "commandAlarmDisarm": "Disarm Alarm",
+ "commandSetTimezone": "Set Timezone",
+ "commandRequestPhoto": "Request Photo",
+ "commandRebootDevice": "Reboot Device",
+ "commandSendSms": "Send SMS",
+ "commandSosNumber": "Set SOS Number",
+ "commandSilenceTime": "Set Silence Time",
+ "commandSetPhonebook": "Set Phonebook",
+ "commandVoiceMessage": "Voice Message",
+ "commandOutputControl": "Output Control",
+ "commandAlarmSpeed": "Overspeed Alarm",
+ "commandDeviceIdentification": "Device Identification",
+ "eventDeviceOnline": "Device is online",
+ "eventDeviceOffline": "Device is offline",
+ "eventDeviceMoving": "Device is moving",
+ "eventDeviceStopped": "Device is stopped",
+ "eventDeviceOverspeed": "Device exceeds the speed",
+ "eventCommandResult": "Command result",
+ "eventGeofenceEnter": "Device has entered geofence",
+ "eventGeofenceExit": "Device has exited geofence",
+ "eventAlarm": "Alarms",
+ "alarm": "Alarm",
+ "alarmSos": "SOS Alarm",
+ "alarmVibration": "Vibration Alarm",
+ "alarmMovement": "Movement Alarm",
+ "alarmOverspeed": "Overspeed Alarm",
+ "alarmFallDown": "FallDown Alarm",
+ "alarmLowBattery": "LowBattery Alarm",
+ "alarmMotion": "Motion Alarm",
+ "alarmFault": "Fault Alarm",
+ "notificationType": "Type of Notification",
+ "notificationWeb": "Send via Web",
+ "notificationMail": "Send via Mail"
+} \ No newline at end of file
diff --git a/web/l10n/hy.json b/web/l10n/hy.json
new file mode 100644
index 000000000..37e4537f2
--- /dev/null
+++ b/web/l10n/hy.json
@@ -0,0 +1,136 @@
+{
+ "sharedLoading": "Loading...",
+ "sharedSave": "Save",
+ "sharedCancel": "Cancel",
+ "sharedAdd": "Add",
+ "sharedEdit": "Edit",
+ "sharedRemove": "Remove",
+ "sharedRemoveConfirm": "Remove item?",
+ "sharedKm": "km",
+ "sharedMi": "mi",
+ "sharedKn": "kn",
+ "sharedKmh": "km/h",
+ "sharedMph": "mph",
+ "sharedHour": "Hour",
+ "sharedMinute": "Minute",
+ "sharedSecond": "Second",
+ "sharedName": "Name",
+ "sharedDescription": "Description",
+ "sharedSearch": "Search",
+ "sharedGeofence": "Geofence",
+ "sharedGeofences": "Geofences",
+ "sharedNotifications": "Notifications",
+ "sharedAttributes": "Attributes",
+ "sharedAttribute": "Attribute",
+ "sharedArea": "Area",
+ "sharedMute": "Mute",
+ "errorTitle": "Error",
+ "errorUnknown": "Unknown error",
+ "errorConnection": "Connection error",
+ "userEmail": "Email",
+ "userPassword": "Password",
+ "userAdmin": "Admin",
+ "userRemember": "Remember",
+ "loginTitle": "Login",
+ "loginLanguage": "Language",
+ "loginRegister": "Register",
+ "loginLogin": "Login",
+ "loginFailed": "Incorrect email address or password",
+ "loginCreated": "New user has been registered",
+ "loginLogout": "Logout",
+ "devicesAndState": "Devices and State",
+ "deviceDialog": "Device",
+ "deviceTitle": "Devices",
+ "deviceIdentifier": "Identifier",
+ "deviceLastUpdate": "Last Update",
+ "deviceCommand": "Command",
+ "deviceFollow": "Follow",
+ "groupDialog": "Group",
+ "groupParent": "Group",
+ "groupNoGroup": "No Group",
+ "settingsTitle": "Settings",
+ "settingsUser": "Account",
+ "settingsGroups": "Groups",
+ "settingsServer": "Server",
+ "settingsUsers": "Users",
+ "settingsDistanceUnit": "Distance",
+ "settingsSpeedUnit": "Speed",
+ "settingsTwelveHourFormat": "12-hour Format",
+ "reportTitle": "Reports",
+ "reportDevice": "Device",
+ "reportFrom": "From",
+ "reportTo": "To",
+ "reportShow": "Show",
+ "reportClear": "Clear",
+ "positionFixTime": "Time",
+ "positionValid": "Valid",
+ "positionLatitude": "Latitude",
+ "positionLongitude": "Longitude",
+ "positionAltitude": "Altitude",
+ "positionSpeed": "Speed",
+ "positionCourse": "Course",
+ "positionAddress": "Address",
+ "positionProtocol": "Protocol",
+ "serverTitle": "Server Settings",
+ "serverZoom": "Zoom",
+ "serverRegistration": "Registration",
+ "serverReadonly": "Readonly",
+ "mapTitle": "Map",
+ "mapLayer": "Map Layer",
+ "mapCustom": "Custom Map",
+ "mapOsm": "Open Street Map",
+ "mapBingKey": "Bing Maps Key",
+ "mapBingRoad": "Bing Maps Road",
+ "mapBingAerial": "Bing Maps Aerial",
+ "mapShapePolygon": "Polygon",
+ "mapShapeCircle": "Circle",
+ "stateTitle": "State",
+ "stateName": "Attribute",
+ "stateValue": "Value",
+ "commandTitle": "Command",
+ "commandSend": "Send",
+ "commandType": "Type",
+ "commandSent": "Command has been sent",
+ "commandPositionPeriodic": "Periodic Reporting",
+ "commandPositionStop": "Stop Reporting",
+ "commandEngineStop": "Engine Stop",
+ "commandEngineResume": "Engine Resume",
+ "commandFrequency": "Frequency",
+ "commandUnit": "Unit",
+ "commandCustom": "Custom command",
+ "commandPositionSingle": "Single Reporting",
+ "commandAlarmArm": "Arm Alarm",
+ "commandAlarmDisarm": "Disarm Alarm",
+ "commandSetTimezone": "Set Timezone",
+ "commandRequestPhoto": "Request Photo",
+ "commandRebootDevice": "Reboot Device",
+ "commandSendSms": "Send SMS",
+ "commandSosNumber": "Set SOS Number",
+ "commandSilenceTime": "Set Silence Time",
+ "commandSetPhonebook": "Set Phonebook",
+ "commandVoiceMessage": "Voice Message",
+ "commandOutputControl": "Output Control",
+ "commandAlarmSpeed": "Overspeed Alarm",
+ "commandDeviceIdentification": "Device Identification",
+ "eventDeviceOnline": "Device is online",
+ "eventDeviceOffline": "Device is offline",
+ "eventDeviceMoving": "Device is moving",
+ "eventDeviceStopped": "Device is stopped",
+ "eventDeviceOverspeed": "Device exceeds the speed",
+ "eventCommandResult": "Command result",
+ "eventGeofenceEnter": "Device has entered geofence",
+ "eventGeofenceExit": "Device has exited geofence",
+ "eventAlarm": "Alarms",
+ "alarm": "Alarm",
+ "alarmSos": "SOS Alarm",
+ "alarmVibration": "Vibration Alarm",
+ "alarmMovement": "Movement Alarm",
+ "alarmOverspeed": "Overspeed Alarm",
+ "alarmFallDown": "FallDown Alarm",
+ "alarmLowBattery": "LowBattery Alarm",
+ "alarmMotion": "Motion Alarm",
+ "alarmFault": "Fault Alarm",
+ "notificationType": "Type of Notification",
+ "notificationWeb": "Send via Web",
+ "notificationMail": "Send via Mail"
+} \ No newline at end of file
diff --git a/web/l10n/ja.json b/web/l10n/ja.json
new file mode 100644
index 000000000..37e4537f2
--- /dev/null
+++ b/web/l10n/ja.json
@@ -0,0 +1,136 @@
+{
+ "sharedLoading": "Loading...",
+ "sharedSave": "Save",
+ "sharedCancel": "Cancel",
+ "sharedAdd": "Add",
+ "sharedEdit": "Edit",
+ "sharedRemove": "Remove",
+ "sharedRemoveConfirm": "Remove item?",
+ "sharedKm": "km",
+ "sharedMi": "mi",
+ "sharedKn": "kn",
+ "sharedKmh": "km/h",
+ "sharedMph": "mph",
+ "sharedHour": "Hour",
+ "sharedMinute": "Minute",
+ "sharedSecond": "Second",
+ "sharedName": "Name",
+ "sharedDescription": "Description",
+ "sharedSearch": "Search",
+ "sharedGeofence": "Geofence",
+ "sharedGeofences": "Geofences",
+ "sharedNotifications": "Notifications",
+ "sharedAttributes": "Attributes",
+ "sharedAttribute": "Attribute",
+ "sharedArea": "Area",
+ "sharedMute": "Mute",
+ "errorTitle": "Error",
+ "errorUnknown": "Unknown error",
+ "errorConnection": "Connection error",
+ "userEmail": "Email",
+ "userPassword": "Password",
+ "userAdmin": "Admin",
+ "userRemember": "Remember",
+ "loginTitle": "Login",
+ "loginLanguage": "Language",
+ "loginRegister": "Register",
+ "loginLogin": "Login",
+ "loginFailed": "Incorrect email address or password",
+ "loginCreated": "New user has been registered",
+ "loginLogout": "Logout",
+ "devicesAndState": "Devices and State",
+ "deviceDialog": "Device",
+ "deviceTitle": "Devices",
+ "deviceIdentifier": "Identifier",
+ "deviceLastUpdate": "Last Update",
+ "deviceCommand": "Command",
+ "deviceFollow": "Follow",
+ "groupDialog": "Group",
+ "groupParent": "Group",
+ "groupNoGroup": "No Group",
+ "settingsTitle": "Settings",
+ "settingsUser": "Account",
+ "settingsGroups": "Groups",
+ "settingsServer": "Server",
+ "settingsUsers": "Users",
+ "settingsDistanceUnit": "Distance",
+ "settingsSpeedUnit": "Speed",
+ "settingsTwelveHourFormat": "12-hour Format",
+ "reportTitle": "Reports",
+ "reportDevice": "Device",
+ "reportFrom": "From",
+ "reportTo": "To",
+ "reportShow": "Show",
+ "reportClear": "Clear",
+ "positionFixTime": "Time",
+ "positionValid": "Valid",
+ "positionLatitude": "Latitude",
+ "positionLongitude": "Longitude",
+ "positionAltitude": "Altitude",
+ "positionSpeed": "Speed",
+ "positionCourse": "Course",
+ "positionAddress": "Address",
+ "positionProtocol": "Protocol",
+ "serverTitle": "Server Settings",
+ "serverZoom": "Zoom",
+ "serverRegistration": "Registration",
+ "serverReadonly": "Readonly",
+ "mapTitle": "Map",
+ "mapLayer": "Map Layer",
+ "mapCustom": "Custom Map",
+ "mapOsm": "Open Street Map",
+ "mapBingKey": "Bing Maps Key",
+ "mapBingRoad": "Bing Maps Road",
+ "mapBingAerial": "Bing Maps Aerial",
+ "mapShapePolygon": "Polygon",
+ "mapShapeCircle": "Circle",
+ "stateTitle": "State",
+ "stateName": "Attribute",
+ "stateValue": "Value",
+ "commandTitle": "Command",
+ "commandSend": "Send",
+ "commandType": "Type",
+ "commandSent": "Command has been sent",
+ "commandPositionPeriodic": "Periodic Reporting",
+ "commandPositionStop": "Stop Reporting",
+ "commandEngineStop": "Engine Stop",
+ "commandEngineResume": "Engine Resume",
+ "commandFrequency": "Frequency",
+ "commandUnit": "Unit",
+ "commandCustom": "Custom command",
+ "commandPositionSingle": "Single Reporting",
+ "commandAlarmArm": "Arm Alarm",
+ "commandAlarmDisarm": "Disarm Alarm",
+ "commandSetTimezone": "Set Timezone",
+ "commandRequestPhoto": "Request Photo",
+ "commandRebootDevice": "Reboot Device",
+ "commandSendSms": "Send SMS",
+ "commandSosNumber": "Set SOS Number",
+ "commandSilenceTime": "Set Silence Time",
+ "commandSetPhonebook": "Set Phonebook",
+ "commandVoiceMessage": "Voice Message",
+ "commandOutputControl": "Output Control",
+ "commandAlarmSpeed": "Overspeed Alarm",
+ "commandDeviceIdentification": "Device Identification",
+ "eventDeviceOnline": "Device is online",
+ "eventDeviceOffline": "Device is offline",
+ "eventDeviceMoving": "Device is moving",
+ "eventDeviceStopped": "Device is stopped",
+ "eventDeviceOverspeed": "Device exceeds the speed",
+ "eventCommandResult": "Command result",
+ "eventGeofenceEnter": "Device has entered geofence",
+ "eventGeofenceExit": "Device has exited geofence",
+ "eventAlarm": "Alarms",
+ "alarm": "Alarm",
+ "alarmSos": "SOS Alarm",
+ "alarmVibration": "Vibration Alarm",
+ "alarmMovement": "Movement Alarm",
+ "alarmOverspeed": "Overspeed Alarm",
+ "alarmFallDown": "FallDown Alarm",
+ "alarmLowBattery": "LowBattery Alarm",
+ "alarmMotion": "Motion Alarm",
+ "alarmFault": "Fault Alarm",
+ "notificationType": "Type of Notification",
+ "notificationWeb": "Send via Web",
+ "notificationMail": "Send via Mail"
+} \ No newline at end of file
diff --git a/web/l10n/ku.json b/web/l10n/ku.json
new file mode 100644
index 000000000..37e4537f2
--- /dev/null
+++ b/web/l10n/ku.json
@@ -0,0 +1,136 @@
+{
+ "sharedLoading": "Loading...",
+ "sharedSave": "Save",
+ "sharedCancel": "Cancel",
+ "sharedAdd": "Add",
+ "sharedEdit": "Edit",
+ "sharedRemove": "Remove",
+ "sharedRemoveConfirm": "Remove item?",
+ "sharedKm": "km",
+ "sharedMi": "mi",
+ "sharedKn": "kn",
+ "sharedKmh": "km/h",
+ "sharedMph": "mph",
+ "sharedHour": "Hour",
+ "sharedMinute": "Minute",
+ "sharedSecond": "Second",
+ "sharedName": "Name",
+ "sharedDescription": "Description",
+ "sharedSearch": "Search",
+ "sharedGeofence": "Geofence",
+ "sharedGeofences": "Geofences",
+ "sharedNotifications": "Notifications",
+ "sharedAttributes": "Attributes",
+ "sharedAttribute": "Attribute",
+ "sharedArea": "Area",
+ "sharedMute": "Mute",
+ "errorTitle": "Error",
+ "errorUnknown": "Unknown error",
+ "errorConnection": "Connection error",
+ "userEmail": "Email",
+ "userPassword": "Password",
+ "userAdmin": "Admin",
+ "userRemember": "Remember",
+ "loginTitle": "Login",
+ "loginLanguage": "Language",
+ "loginRegister": "Register",
+ "loginLogin": "Login",
+ "loginFailed": "Incorrect email address or password",
+ "loginCreated": "New user has been registered",
+ "loginLogout": "Logout",
+ "devicesAndState": "Devices and State",
+ "deviceDialog": "Device",
+ "deviceTitle": "Devices",
+ "deviceIdentifier": "Identifier",
+ "deviceLastUpdate": "Last Update",
+ "deviceCommand": "Command",
+ "deviceFollow": "Follow",
+ "groupDialog": "Group",
+ "groupParent": "Group",
+ "groupNoGroup": "No Group",
+ "settingsTitle": "Settings",
+ "settingsUser": "Account",
+ "settingsGroups": "Groups",
+ "settingsServer": "Server",
+ "settingsUsers": "Users",
+ "settingsDistanceUnit": "Distance",
+ "settingsSpeedUnit": "Speed",
+ "settingsTwelveHourFormat": "12-hour Format",
+ "reportTitle": "Reports",
+ "reportDevice": "Device",
+ "reportFrom": "From",
+ "reportTo": "To",
+ "reportShow": "Show",
+ "reportClear": "Clear",
+ "positionFixTime": "Time",
+ "positionValid": "Valid",
+ "positionLatitude": "Latitude",
+ "positionLongitude": "Longitude",
+ "positionAltitude": "Altitude",
+ "positionSpeed": "Speed",
+ "positionCourse": "Course",
+ "positionAddress": "Address",
+ "positionProtocol": "Protocol",
+ "serverTitle": "Server Settings",
+ "serverZoom": "Zoom",
+ "serverRegistration": "Registration",
+ "serverReadonly": "Readonly",
+ "mapTitle": "Map",
+ "mapLayer": "Map Layer",
+ "mapCustom": "Custom Map",
+ "mapOsm": "Open Street Map",
+ "mapBingKey": "Bing Maps Key",
+ "mapBingRoad": "Bing Maps Road",
+ "mapBingAerial": "Bing Maps Aerial",
+ "mapShapePolygon": "Polygon",
+ "mapShapeCircle": "Circle",
+ "stateTitle": "State",
+ "stateName": "Attribute",
+ "stateValue": "Value",
+ "commandTitle": "Command",
+ "commandSend": "Send",
+ "commandType": "Type",
+ "commandSent": "Command has been sent",
+ "commandPositionPeriodic": "Periodic Reporting",
+ "commandPositionStop": "Stop Reporting",
+ "commandEngineStop": "Engine Stop",
+ "commandEngineResume": "Engine Resume",
+ "commandFrequency": "Frequency",
+ "commandUnit": "Unit",
+ "commandCustom": "Custom command",
+ "commandPositionSingle": "Single Reporting",
+ "commandAlarmArm": "Arm Alarm",
+ "commandAlarmDisarm": "Disarm Alarm",
+ "commandSetTimezone": "Set Timezone",
+ "commandRequestPhoto": "Request Photo",
+ "commandRebootDevice": "Reboot Device",
+ "commandSendSms": "Send SMS",
+ "commandSosNumber": "Set SOS Number",
+ "commandSilenceTime": "Set Silence Time",
+ "commandSetPhonebook": "Set Phonebook",
+ "commandVoiceMessage": "Voice Message",
+ "commandOutputControl": "Output Control",
+ "commandAlarmSpeed": "Overspeed Alarm",
+ "commandDeviceIdentification": "Device Identification",
+ "eventDeviceOnline": "Device is online",
+ "eventDeviceOffline": "Device is offline",
+ "eventDeviceMoving": "Device is moving",
+ "eventDeviceStopped": "Device is stopped",
+ "eventDeviceOverspeed": "Device exceeds the speed",
+ "eventCommandResult": "Command result",
+ "eventGeofenceEnter": "Device has entered geofence",
+ "eventGeofenceExit": "Device has exited geofence",
+ "eventAlarm": "Alarms",
+ "alarm": "Alarm",
+ "alarmSos": "SOS Alarm",
+ "alarmVibration": "Vibration Alarm",
+ "alarmMovement": "Movement Alarm",
+ "alarmOverspeed": "Overspeed Alarm",
+ "alarmFallDown": "FallDown Alarm",
+ "alarmLowBattery": "LowBattery Alarm",
+ "alarmMotion": "Motion Alarm",
+ "alarmFault": "Fault Alarm",
+ "notificationType": "Type of Notification",
+ "notificationWeb": "Send via Web",
+ "notificationMail": "Send via Mail"
+} \ No newline at end of file