aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--web/app/Application.js3
-rw-r--r--web/app/controller/Root.js1
-rw-r--r--web/app/model/Attribute.js6
-rw-r--r--web/app/model/AttributeAlias.js36
-rw-r--r--web/app/store/AllAttributesAliases.js30
-rw-r--r--web/app/store/AttributesAliases.js30
-rw-r--r--web/app/view/AttributeAliasDialog.js51
-rw-r--r--web/app/view/AttributesAliases.js62
-rw-r--r--web/app/view/AttributesAliasesController.js100
-rw-r--r--web/app/view/BaseMap.js6
-rw-r--r--web/app/view/SettingsMenu.js7
-rw-r--r--web/app/view/SettingsMenuController.js14
-rw-r--r--web/app/view/State.js26
-rw-r--r--web/app/view/StateController.js71
-rw-r--r--web/l10n/en.json3
15 files changed, 428 insertions, 18 deletions
diff --git a/web/app/Application.js b/web/app/Application.js
index 62db7bc..73b9e83 100644
--- a/web/app/Application.js
+++ b/web/app/Application.js
@@ -35,6 +35,7 @@ Ext.define('Traccar.Application', {
'Event',
'Geofence',
'Notification',
+ 'AttributeAlias',
'ReportSummary',
'ReportTrip'
],
@@ -60,6 +61,8 @@ Ext.define('Traccar.Application', {
'Notifications',
'AllNotifications',
'GeofenceTypes',
+ 'AttributesAliases',
+ 'AllAttributesAliases',
'ReportRoute',
'ReportEvents',
'ReportTrips',
diff --git a/web/app/controller/Root.js b/web/app/controller/Root.js
index 9cd6fd6..5e3c39d 100644
--- a/web/app/controller/Root.js
+++ b/web/app/controller/Root.js
@@ -84,6 +84,7 @@ Ext.define('Traccar.controller.Root', {
this.asyncUpdate(true);
}
});
+ Ext.getStore('AllAttributesAliases').load();
attribution = Ext.get('attribution');
if (attribution) {
attribution.remove();
diff --git a/web/app/model/Attribute.js b/web/app/model/Attribute.js
index d30ddf8..7bf5beb 100644
--- a/web/app/model/Attribute.js
+++ b/web/app/model/Attribute.js
@@ -27,5 +27,11 @@ Ext.define('Traccar.model.Attribute', {
}, {
name: 'value',
type: 'string'
+ }, {
+ name: 'attribute',
+ type: 'string'
+ }, {
+ name: 'alias',
+ type: 'string'
}]
});
diff --git a/web/app/model/AttributeAlias.js b/web/app/model/AttributeAlias.js
new file mode 100644
index 0000000..5c7ad68
--- /dev/null
+++ b/web/app/model/AttributeAlias.js
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2016 Andrey Kunitsyn (abyss@fox5.ru)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.model.AttributeAlias', {
+ extend: 'Ext.data.Model',
+ identifier: 'negative',
+
+ fields: [{
+ name: 'id',
+ type: 'int'
+ }, {
+ name: 'deviceId',
+ type: 'int'
+ }, {
+ name: 'attribute',
+ type: 'string'
+ }, {
+ name: 'alias',
+ type: 'string'
+ }]
+});
diff --git a/web/app/store/AllAttributesAliases.js b/web/app/store/AllAttributesAliases.js
new file mode 100644
index 0000000..7eb6c0c
--- /dev/null
+++ b/web/app/store/AllAttributesAliases.js
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2016 Andrey Kunitsyn (abyss@fox5.ru)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.store.AllAttributesAliases', {
+ extend: 'Ext.data.Store',
+ model: 'Traccar.model.AttributeAlias',
+
+ proxy: {
+ type: 'rest',
+ url: 'api/devices/aliases',
+ writer: {
+ writeAllFields: true
+ }
+ }
+});
diff --git a/web/app/store/AttributesAliases.js b/web/app/store/AttributesAliases.js
new file mode 100644
index 0000000..1f8d11d
--- /dev/null
+++ b/web/app/store/AttributesAliases.js
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2016 Andrey Kunitsyn (abyss@fox5.ru)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.store.AttributesAliases', {
+ extend: 'Ext.data.Store',
+ model: 'Traccar.model.AttributeAlias',
+
+ proxy: {
+ type: 'rest',
+ url: 'api/devices/aliases',
+ writer: {
+ writeAllFields: true
+ }
+ }
+});
diff --git a/web/app/view/AttributeAliasDialog.js b/web/app/view/AttributeAliasDialog.js
new file mode 100644
index 0000000..d86e92d
--- /dev/null
+++ b/web/app/view/AttributeAliasDialog.js
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2016 Andrey Kunitsyn (abyss@fox5.ru)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.view.AttributeAliasDialog', {
+ extend: 'Traccar.view.BaseDialog',
+
+ requires: [
+ 'Traccar.view.AttributeController'
+ ],
+
+ controller: 'attributeDialog',
+ title: Strings.sharedAttributeAlias,
+
+ items: {
+ xtype: 'form',
+ items: [{
+ xtype: 'textfield',
+ name: 'attribute',
+ fieldLabel: Strings.sharedAttribute,
+ allowBlank: false
+ }, {
+ xtype: 'textfield',
+ name: 'alias',
+ fieldLabel: Strings.sharedAlias,
+ allowBlank: false
+ }]
+ },
+
+ buttons: [{
+ text: Strings.sharedSave,
+ handler: 'onSaveClick'
+ }, {
+ text: Strings.sharedCancel,
+ handler: 'closeView'
+ }]
+});
diff --git a/web/app/view/AttributesAliases.js b/web/app/view/AttributesAliases.js
new file mode 100644
index 0000000..b1390e4
--- /dev/null
+++ b/web/app/view/AttributesAliases.js
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2016 Andrey Kunitsyn (abyss@fox5.ru)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.view.AttributesAliases', {
+ extend: 'Ext.grid.Panel',
+ xtype: 'attributesAliasesView',
+
+ requires: [
+ 'Traccar.view.AttributesAliasesController',
+ 'Traccar.view.EditToolbar'
+ ],
+
+ controller: 'attributesAliases',
+ store: 'AttributesAliases',
+
+ selType: 'rowmodel',
+
+ tbar: {
+ xtype: 'editToolbar',
+ items: ['-', {
+ xtype: 'combobox',
+ reference: 'deviceField',
+ store: 'Devices',
+ displayField: 'name',
+ valueField: 'id',
+ typeAhead: true,
+ listeners: {
+ change: 'onDeviceChange'
+ }
+ }]
+ },
+
+ listeners: {
+ selectionchange: 'onSelectionChange',
+ destroy: 'onClose'
+ },
+
+ columns: [{
+ text: Strings.sharedAttribute,
+ dataIndex: 'attribute',
+ flex: 1
+ }, {
+ text: Strings.sharedAlias,
+ dataIndex: 'alias',
+ flex: 1
+ }]
+});
diff --git a/web/app/view/AttributesAliasesController.js b/web/app/view/AttributesAliasesController.js
new file mode 100644
index 0000000..e848c48
--- /dev/null
+++ b/web/app/view/AttributesAliasesController.js
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2016 Andrey Kunitsyn (abyss@fox5.ru)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.view.AttributesAliasesController', {
+ extend: 'Ext.app.ViewController',
+ alias: 'controller.attributesAliases',
+
+ requires: [
+ 'Traccar.view.AttributeAliasDialog',
+ 'Traccar.model.AttributeAlias'
+ ],
+
+ init: function () {
+ var admin = Traccar.app.getUser().get('admin');
+ this.lookupReference('deviceField').setStore(admin ? 'AllDevices' : 'Devices');
+ this.lookupReference('toolbarAddButton').setDisabled(true);
+ this.lookupReference('toolbarEditButton').setDisabled(true);
+ this.lookupReference('toolbarRemoveButton').setDisabled(true);
+ this.getView().getStore().loadData([], false);
+ },
+
+ onAddClick: function () {
+ var attributeAlias, dialog, deviceId;
+ attributeAlias = Ext.create('Traccar.model.AttributeAlias');
+ attributeAlias.store = this.getView().getStore();
+ deviceId = this.lookupReference('deviceField').getValue();
+ attributeAlias.set('deviceId', deviceId);
+ dialog = Ext.create('Traccar.view.AttributeAliasDialog');
+ dialog.down('form').loadRecord(attributeAlias);
+ dialog.show();
+ },
+
+ onEditClick: function () {
+ var attributeAlias, dialog;
+ attributeAlias = this.getView().getSelectionModel().getSelection()[0];
+ dialog = Ext.create('Traccar.view.AttributeAliasDialog');
+ dialog.down('form').loadRecord(attributeAlias);
+ dialog.show();
+ },
+
+ onRemoveClick: function () {
+ var attributeAlias = this.getView().getSelectionModel().getSelection()[0];
+ Ext.Msg.show({
+ title: Strings.sharedAttributeAlias,
+ message: Strings.sharedRemoveConfirm,
+ buttons: Ext.Msg.YESNO,
+ buttonText: {
+ yes: Strings.sharedRemove,
+ no: Strings.sharedCancel
+ },
+ scope: this,
+ fn: function (btn) {
+ var store = this.getView().getStore();
+ if (btn === 'yes') {
+ store.remove(attributeAlias);
+ store.sync();
+ }
+ }
+ });
+ },
+
+ onSelectionChange: function (selected) {
+ var disabled = !this.lookupReference('deviceField').getValue();
+ this.lookupReference('toolbarAddButton').setDisabled(disabled);
+ disabled = selected.length === 0 || !this.lookupReference('deviceField').getValue();
+ this.lookupReference('toolbarEditButton').setDisabled(disabled);
+ this.lookupReference('toolbarRemoveButton').setDisabled(disabled);
+ },
+
+ onDeviceChange: function (combobox, newValue, oldValue) {
+ this.onSelectionChange('');
+ if (newValue !== null) {
+ this.getView().getStore().getProxy().setExtraParam('deviceId', newValue);
+ this.getView().getStore().load();
+ } else {
+ this.getView().getStore().loadData([], false);
+ }
+ },
+
+ onClose: function () {
+ Ext.getStore('AllAttributesAliases').load();
+ this.fireEvent('updatealiases');
+ }
+
+});
diff --git a/web/app/view/BaseMap.js b/web/app/view/BaseMap.js
index a352420..3a0f442 100644
--- a/web/app/view/BaseMap.js
+++ b/web/app/view/BaseMap.js
@@ -63,7 +63,7 @@ Ext.define('Traccar.view.BaseMap', {
imagerySet: 'Aerial'
})
});
- } else if (type === 'osm'){
+ } else if (type === 'osm') {
layer = new ol.layer.Tile({
source: new ol.source.OSM({})
});
@@ -79,8 +79,8 @@ Ext.define('Traccar.view.BaseMap', {
attributions: [
new ol.Attribution({
html: [
- '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> '
- + 'contributors, &copy; <a href="https://carto.com/attributions">CARTO</a>'
+ '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> ' +
+ 'contributors, &copy; <a href="https://carto.com/attributions">CARTO</a>'
]
})
]
diff --git a/web/app/view/SettingsMenu.js b/web/app/view/SettingsMenu.js
index 03b2f92..691bf65 100644
--- a/web/app/view/SettingsMenu.js
+++ b/web/app/view/SettingsMenu.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2015 - 2016 Anton Tananaev (anton.tananaev@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -58,6 +58,11 @@ Ext.define('Traccar.view.SettingsMenu', {
handler: 'onNotificationsClick',
reference: 'settingsNotificationsButton'
}, {
+ hidden: true,
+ text: Strings.sharedAttributesAliases,
+ handler: 'onAttributesAliasesClick',
+ reference: 'settingsAttributesAliasesButton'
+ }, {
text: Strings.loginLogout,
handler: 'onLogoutClick'
}]
diff --git a/web/app/view/SettingsMenuController.js b/web/app/view/SettingsMenuController.js
index 5c5a451..b01e4f8 100644
--- a/web/app/view/SettingsMenuController.js
+++ b/web/app/view/SettingsMenuController.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2015 - 2016 Anton Tananaev (anton.tananaev@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@ Ext.define('Traccar.view.SettingsMenuController', {
'Traccar.view.Groups',
'Traccar.view.Geofences',
'Traccar.view.Notifications',
+ 'Traccar.view.AttributesAliases',
'Traccar.view.BaseWindow'
],
@@ -42,6 +43,7 @@ Ext.define('Traccar.view.SettingsMenuController', {
this.lookupReference('settingsGroupsButton').setHidden(false);
this.lookupReference('settingsGeofencesButton').setHidden(false);
this.lookupReference('settingsNotificationsButton').setHidden(false);
+ this.lookupReference('settingsAttributesAliasesButton').setHidden(false);
}
},
@@ -99,6 +101,16 @@ Ext.define('Traccar.view.SettingsMenuController', {
}).show();
},
+ onAttributesAliasesClick: function () {
+ Ext.create('Traccar.view.BaseWindow', {
+ title: Strings.sharedAttributesAliases,
+ modal: false,
+ items: {
+ xtype: 'attributesAliasesView'
+ }
+ }).show();
+ },
+
onLogoutClick: function () {
Ext.create('Traccar.view.LoginController').logout();
}
diff --git a/web/app/view/State.js b/web/app/view/State.js
index 2974367..ddb9c0e 100644
--- a/web/app/view/State.js
+++ b/web/app/view/State.js
@@ -26,12 +26,34 @@ Ext.define('Traccar.view.State', {
controller: 'state',
store: 'Attributes',
- title: Strings.stateTitle,
+ header: {
+ xtype: 'header',
+ title: Strings.stateTitle,
+ items: [{
+ xtype: 'tbfill'
+ }, {
+ xtype: 'button',
+ disabled: true,
+ handler: 'onAliasEditClick',
+ reference: 'aliasEditButton',
+ glyph: 'xf040@FontAwesome',
+ tooltip: Strings.sharedEdit,
+ tooltipType: 'title'
+ }]
+ },
+
+ listeners: {
+ selectionchange: 'onSelectionChange'
+ },
columns: [{
text: Strings.stateName,
dataIndex: 'name',
- flex: 1
+ flex: 1,
+ renderer: function (value, metaData, record) {
+ var alias = record.get('alias');
+ return alias !== '' ? alias : value;
+ }
}, {
text: Strings.stateValue,
dataIndex: 'value',
diff --git a/web/app/view/StateController.js b/web/app/view/StateController.js
index d92201b..4bd43de 100644
--- a/web/app/view/StateController.js
+++ b/web/app/view/StateController.js
@@ -28,8 +28,9 @@ Ext.define('Traccar.view.StateController', {
listen: {
controller: {
'*': {
- selectDevice: 'selectDevice',
- selectReport: 'selectReport'
+ selectdevice: 'selectDevice',
+ selectreport: 'selectReport',
+ updatealiases: 'updateAliases'
}
},
store: {
@@ -39,6 +40,10 @@ Ext.define('Traccar.view.StateController', {
},
'#Positions': {
clear: 'clearReport'
+ },
+ '#AllAttributesAliases': {
+ add: 'updateAliases',
+ update: 'updateAliases'
}
}
}
@@ -66,7 +71,8 @@ Ext.define('Traccar.view.StateController', {
}
for (i = 0; i < data.length; i++) {
if (this.deviceId === data[i].get('deviceId')) {
- this.updatePosition(data[i]);
+ this.position = data[i];
+ this.updatePosition();
}
}
},
@@ -79,30 +85,41 @@ Ext.define('Traccar.view.StateController', {
}
},
- updatePosition: function (position) {
- var attributes, store, key;
+ updatePosition: function () {
+ var attributes, store, key, aliasesStore, attributeAlias, alias;
store = Ext.getStore('Attributes');
store.removeAll();
- for (key in position.data) {
- if (position.data.hasOwnProperty(key) && this.keys[key] !== undefined) {
+ for (key in this.position.data) {
+ if (this.position.data.hasOwnProperty(key) && this.keys[key] !== undefined) {
store.add(Ext.create('Traccar.model.Attribute', {
priority: this.keys[key].priority,
name: this.keys[key].name,
- value: Traccar.AttributeFormatter.getFormatter(key)(position.get(key))
+ value: Traccar.AttributeFormatter.getFormatter(key)(this.position.get(key))
}));
}
}
- attributes = position.get('attributes');
+ aliasesStore = Ext.getStore('AllAttributesAliases');
+ aliasesStore.filter('deviceId', this.position.get('deviceId'));
+
+ attributes = this.position.get('attributes');
if (attributes instanceof Object) {
for (key in attributes) {
if (attributes.hasOwnProperty(key)) {
+ attributeAlias = aliasesStore.findRecord('attribute', key, 0, false, true, true);
+ if (attributeAlias !== null) {
+ alias = attributeAlias.get('alias');
+ } else {
+ alias = '';
+ }
store.add(Ext.create('Traccar.model.Attribute', {
priority: 1024,
name: key.replace(/^./, function (match) {
return match.toUpperCase();
}),
+ attribute: key,
+ alias: alias,
value: Traccar.AttributeFormatter.getFormatter(key)(attributes[key])
}));
}
@@ -115,18 +132,50 @@ Ext.define('Traccar.view.StateController', {
this.deviceId = device.get('id');
position = Ext.getStore('LatestPositions').findRecord('deviceId', this.deviceId, 0, false, false, true);
if (position) {
- this.updatePosition(position);
+ this.position = position;
+ this.updatePosition();
} else {
+ this.position = null;
Ext.getStore('Attributes').removeAll();
}
},
selectReport: function (position) {
this.deviceId = null;
- this.updatePosition(position);
+ this.position = position;
+ this.updatePosition();
},
clearReport: function (store) {
+ this.position = null;
Ext.getStore('Attributes').removeAll();
+ },
+
+ onSelectionChange: function (selected, records) {
+ var enabled = selected.getCount() > 0 && records[0].get('attribute') !== '';
+ this.lookupReference('aliasEditButton').setDisabled(!enabled);
+ },
+
+ onAliasEditClick: function () {
+ var attribute, aliasesStore, attributeAlias, dialog;
+ attribute = this.getView().getSelectionModel().getSelection()[0];
+ aliasesStore = Ext.getStore('AllAttributesAliases');
+ attributeAlias = aliasesStore.findRecord('attribute', attribute.get('attribute'), 0, false, true, true);
+ if (attributeAlias === null) {
+ attributeAlias = Ext.create('Traccar.model.AttributeAlias', {
+ deviceId: this.position.get('deviceId'),
+ attribute: attribute.get('attribute')
+ });
+ attributeAlias.store = aliasesStore;
+ }
+ dialog = Ext.create('Traccar.view.AttributeAliasDialog');
+ dialog.down('form').loadRecord(attributeAlias);
+ dialog.show();
+ },
+
+ updateAliases: function () {
+ if (this.position !== null) {
+ this.updatePosition();
+ }
}
});
diff --git a/web/l10n/en.json b/web/l10n/en.json
index e34c8d1..1bf53b3 100644
--- a/web/l10n/en.json
+++ b/web/l10n/en.json
@@ -29,6 +29,9 @@
"sharedHourAbbreviation": "h",
"sharedMinuteAbbreviation": "m",
"sharedGetMapState": "Get Map State",
+ "sharedAttributeAlias": "Attribute Alias",
+ "sharedAttributesAliases": "Attributes Aliases",
+ "sharedAlias": "Alias",
"errorTitle": "Error",
"errorUnknown": "Unknown error",
"errorConnection": "Connection error",