aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2017-04-18 16:11:39 +1200
committerGitHub <noreply@github.com>2017-04-18 16:11:39 +1200
commit648d5fe1e4a0d92b79410572d386dac45b4e8d36 (patch)
treeb5d7911e71da3ec95f32a2f2161f248266363cbe
parent13b12ad936020476f8911fde498a820f94115a79 (diff)
parent6c8e4716489bc5d05a0c7794ee1cee342de417e3 (diff)
downloadtrackermap-web-648d5fe1e4a0d92b79410572d386dac45b4e8d36.tar.gz
trackermap-web-648d5fe1e4a0d92b79410572d386dac45b4e8d36.tar.bz2
trackermap-web-648d5fe1e4a0d92b79410572d386dac45b4e8d36.zip
Merge pull request #467 from Abyss777/known_attributes
Known attributes
-rw-r--r--web/app/Application.js10
-rw-r--r--web/app/model/KnownAttribute.js32
-rw-r--r--web/app/store/DeviceAttributes.js52
-rw-r--r--web/app/store/GeofenceAttributes.js28
-rw-r--r--web/app/store/GroupAttributes.js44
-rw-r--r--web/app/store/ServerAttributes.js41
-rw-r--r--web/app/store/UserAttributes.js76
-rw-r--r--web/app/view/ColorPicker.js43
-rw-r--r--web/app/view/dialog/Attribute.js11
-rw-r--r--web/app/view/dialog/AttributeController.js44
-rw-r--r--web/app/view/edit/Attributes.js9
-rw-r--r--web/app/view/edit/AttributesController.js56
-rw-r--r--web/l10n/en.json20
13 files changed, 456 insertions, 10 deletions
diff --git a/web/app/Application.js b/web/app/Application.js
index 9b450466..1658e7dc 100644
--- a/web/app/Application.js
+++ b/web/app/Application.js
@@ -38,7 +38,8 @@ Ext.define('Traccar.Application', {
'AttributeAlias',
'ReportSummary',
'ReportTrip',
- 'Calendar'
+ 'Calendar',
+ 'KnownAttribute'
],
stores: [
@@ -77,7 +78,12 @@ Ext.define('Traccar.Application', {
'AllCalendars',
'AllTimezones',
'VisibleDevices',
- 'DeviceStatuses'
+ 'DeviceStatuses',
+ 'DeviceAttributes',
+ 'GeofenceAttributes',
+ 'GroupAttributes',
+ 'ServerAttributes',
+ 'UserAttributes'
],
controllers: [
diff --git a/web/app/model/KnownAttribute.js b/web/app/model/KnownAttribute.js
new file mode 100644
index 00000000..9bb14dba
--- /dev/null
+++ b/web/app/model/KnownAttribute.js
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * 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.KnownAttribute', {
+ extend: 'Ext.data.Model',
+ idProperty: 'key',
+
+ fields: [{
+ name: 'key',
+ type: 'string'
+ }, {
+ name: 'name',
+ type: 'string'
+ }, {
+ name: 'type',
+ type: 'string'
+ }]
+});
diff --git a/web/app/store/DeviceAttributes.js b/web/app/store/DeviceAttributes.js
new file mode 100644
index 00000000..a4303546
--- /dev/null
+++ b/web/app/store/DeviceAttributes.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * 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.DeviceAttributes', {
+ extend: 'Ext.data.Store',
+ model: 'Traccar.model.KnownAttribute',
+ proxy: 'memory',
+
+ data: [{
+ key: 'speedLimit',
+ name: Strings.attributeSpeedLimit,
+ type: 'number'
+ }, {
+ key: 'report.ignoreOdometer',
+ name: Strings.attributeReportIgnoreOdometer,
+ type: 'boolean'
+ }, {
+ key: 'maintenance.start',
+ name: Strings.attributeMaintenanceStart,
+ type: 'number'
+ }, {
+ key: 'maintenance.interval',
+ name: Strings.attributeMaintenanceInterval,
+ type: 'number'
+ }, {
+ key: 'web.reportColor',
+ name: Strings.attributeWebReportColor,
+ type: 'color'
+ }, {
+ key: 'devicePassword',
+ name: Strings.attributeDevicePassword,
+ type: 'string'
+ }, {
+ key: 'processing.copyAttributes',
+ name: Strings.attributeProcessingCopyAttributes,
+ type: 'string'
+ }]
+});
diff --git a/web/app/store/GeofenceAttributes.js b/web/app/store/GeofenceAttributes.js
new file mode 100644
index 00000000..9034b3f3
--- /dev/null
+++ b/web/app/store/GeofenceAttributes.js
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * 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.GeofenceAttributes', {
+ extend: 'Ext.data.Store',
+ model: 'Traccar.model.KnownAttribute',
+ proxy: 'memory',
+
+ data: [{
+ key: 'color',
+ name: Strings.attributeColor,
+ type: 'color'
+ }]
+});
diff --git a/web/app/store/GroupAttributes.js b/web/app/store/GroupAttributes.js
new file mode 100644
index 00000000..35caa8c7
--- /dev/null
+++ b/web/app/store/GroupAttributes.js
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * 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.GroupAttributes', {
+ extend: 'Ext.data.Store',
+ model: 'Traccar.model.KnownAttribute',
+ proxy: 'memory',
+
+ data: [{
+ key: 'speedLimit',
+ name: Strings.attributeSpeedLimit,
+ type: 'number'
+ }, {
+ key: 'report.ignoreOdometer',
+ name: Strings.attributeReportIgnoreOdometer,
+ type: 'boolean'
+ }, {
+ key: 'maintenance.start',
+ name: Strings.attributeMaintenanceStart,
+ type: 'number'
+ }, {
+ key: 'maintenance.interval',
+ name: Strings.attributeMaintenanceInterval,
+ type: 'number'
+ }, {
+ key: 'processing.copyAttributes',
+ name: Strings.attributeProcessingCopyAttributes,
+ type: 'string'
+ }]
+});
diff --git a/web/app/store/ServerAttributes.js b/web/app/store/ServerAttributes.js
new file mode 100644
index 00000000..71705e04
--- /dev/null
+++ b/web/app/store/ServerAttributes.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * 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.ServerAttributes', {
+ extend: 'Ext.data.Store',
+ model: 'Traccar.model.KnownAttribute',
+ proxy: 'memory',
+
+ data: [{
+ key: 'speedLimit',
+ name: Strings.attributeSpeedLimit,
+ type: 'number'
+ }, {
+ key: 'maintenance.start',
+ name: Strings.attributeMaintenanceStart,
+ type: 'number'
+ }, {
+ key: 'maintenance.interval',
+ name: Strings.attributeMaintenanceInterval,
+ type: 'number'
+ }, {
+ key: 'web.liveRouteLength',
+ name: Strings.attributeWebLiveRouteLength,
+ type: 'number',
+ allowDecimals: false
+ }]
+});
diff --git a/web/app/store/UserAttributes.js b/web/app/store/UserAttributes.js
new file mode 100644
index 00000000..8649eb8b
--- /dev/null
+++ b/web/app/store/UserAttributes.js
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * 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.UserAttributes', {
+ extend: 'Ext.data.Store',
+ model: 'Traccar.model.KnownAttribute',
+ proxy: 'memory',
+
+ data: [{
+ key: 'mail.smtp.host',
+ name: Strings.attributeMailSmtpHost,
+ type: 'string'
+ }, {
+ key: 'mail.smtp.port',
+ name: Strings.attributeMailSmtpPort,
+ type: 'number',
+ allowDecimals: false,
+ minValue: 1,
+ maxValue: 65535
+ }, {
+ key: 'mail.smtp.starttls.enable',
+ name: Strings.attributeMailSmtpStarttlsEnable,
+ type: 'boolean'
+ }, {
+ key: 'mail.smtp.starttls.required',
+ name: Strings.attributeMailSmtpStarttlsRequired,
+ type: 'boolean'
+ }, {
+ key: 'mail.smtp.ssl.enable',
+ name: Strings.attributeMailSmtpSslEnable,
+ type: 'boolean'
+ }, {
+ key: 'mail.smtp.ssl.trust',
+ name: Strings.attributeMailSmtpSslTrust,
+ type: 'string'
+ }, {
+ key: 'mail.smtp.ssl.protocols',
+ name: Strings.attributeMailSmtpSslProtocols,
+ type: 'string'
+ }, {
+ key: 'mail.smtp.from',
+ name: Strings.attributeMailSmtpFrom,
+ type: 'string'
+ }, {
+ key: 'mail.smtp.auth',
+ name: Strings.attributeMailSmtpAuth,
+ type: 'boolean'
+ }, {
+ key: 'mail.smtp.username',
+ name: Strings.attributeMailSmtpUsername,
+ type: 'string'
+ }, {
+ key: 'mail.smtp.password',
+ name: Strings.attributeMailSmtpPassword,
+ type: 'string'
+ }, {
+ key: 'web.liveRouteLength',
+ name: Strings.attributeWebLiveRouteLength,
+ type: 'number',
+ allowDecimals: false
+ }]
+});
diff --git a/web/app/view/ColorPicker.js b/web/app/view/ColorPicker.js
new file mode 100644
index 00000000..5de03aa3
--- /dev/null
+++ b/web/app/view/ColorPicker.js
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * 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.ColorPicker', {
+ extend: 'Ext.form.field.Picker',
+ xtype: 'customcolorpicker',
+
+ config: {
+ value: '#008000'
+ },
+
+ editable: false,
+
+ createPicker: function () {
+ return Ext.create('Ext.picker.Color', {
+ floating: true,
+ picker: this,
+ select: function (selColor) {
+ this.picker.setValue('#' + selColor);
+ this.picker.collapse();
+ }
+ });
+ },
+
+ setValue: function (color) {
+ this.callParent([color]);
+ this.setFieldStyle('background-color:' + color);
+ }
+});
diff --git a/web/app/view/dialog/Attribute.js b/web/app/view/dialog/Attribute.js
index 993c2b12..6614c87f 100644
--- a/web/app/view/dialog/Attribute.js
+++ b/web/app/view/dialog/Attribute.js
@@ -19,7 +19,8 @@ Ext.define('Traccar.view.dialog.Attribute', {
extend: 'Traccar.view.dialog.Base',
requires: [
- 'Traccar.view.dialog.AttributeController'
+ 'Traccar.view.dialog.AttributeController',
+ 'Traccar.view.ColorPicker'
],
controller: 'attribute',
@@ -27,19 +28,27 @@ Ext.define('Traccar.view.dialog.Attribute', {
items: {
xtype: 'form',
+ listeners: {
+ validitychange: 'onValidityChange'
+ },
items: [{
xtype: 'textfield',
+ reference: 'nameTextField',
name: 'name',
+ allowBlank: false,
fieldLabel: Strings.sharedName
}, {
xtype: 'textfield',
name: 'value',
+ reference: 'valueField',
+ allowBlank: false,
fieldLabel: Strings.stateValue
}]
},
buttons: [{
glyph: 'xf00c@FontAwesome',
+ reference: 'saveButton',
tooltip: Strings.sharedSave,
tooltipType: 'title',
minWidth: 0,
diff --git a/web/app/view/dialog/AttributeController.js b/web/app/view/dialog/AttributeController.js
index 365a0df5..da5205b4 100644
--- a/web/app/view/dialog/AttributeController.js
+++ b/web/app/view/dialog/AttributeController.js
@@ -39,5 +39,49 @@ Ext.define('Traccar.view.dialog.AttributeController', {
record.save();
}
button.up('window').close();
+ },
+
+ onValidityChange: function (form, valid) {
+ this.lookupReference('saveButton').setDisabled(!valid);
+ },
+
+ defaultFieldConfig: {
+ name: 'value',
+ reference: 'valueField',
+ allowBlank: false,
+ fieldLabel: Strings.stateValue
+ },
+
+ onNameChange: function (combobox, newValue) {
+ var type, config, attribute, valueField = this.lookupReference('valueField');
+ attribute = combobox.getStore().getById(newValue);
+ if (attribute) {
+ type = attribute.get('type');
+ config = Ext.clone(this.defaultFieldConfig);
+ if (type === 'number') {
+ config.xtype = 'numberfield';
+ if (attribute.get('allowDecimals') !== undefined) {
+ config.allowDecimals = attribute.get('allowDecimals');
+ } else {
+ config.allowDecimals = true;
+ }
+ config.maxValue = attribute.get('maxValue');
+ config.minValue = attribute.get('minValue');
+ } else if (type === 'boolean') {
+ config.xtype = 'checkboxfield';
+ config.inputValue = true;
+ config.uncheckedValue = false;
+ } else if (type === 'color') {
+ config.xtype = 'customcolorpicker';
+ } else {
+ config.xtype = 'textfield';
+ }
+ if (valueField.getXType() !== config.xtype) {
+ this.getView().down('form').insert(this.getView().down('form').items.indexOf(valueField), config);
+ this.getView().down('form').remove(valueField);
+ } else if (config.xtype === 'numberfield') {
+ valueField.setConfig(config);
+ }
+ }
}
});
diff --git a/web/app/view/edit/Attributes.js b/web/app/view/edit/Attributes.js
index 93e5a3a7..80083193 100644
--- a/web/app/view/edit/Attributes.js
+++ b/web/app/view/edit/Attributes.js
@@ -41,7 +41,14 @@ Ext.define('Traccar.view.edit.Attributes', {
},
items: [{
text: Strings.sharedName,
- dataIndex: 'name'
+ dataIndex: 'name',
+ renderer: function (value, metaData) {
+ var result;
+ if (this.attributesStore) {
+ result = Ext.getStore(this.attributesStore).getById(value);
+ }
+ return result && result.get('name') ? result.get('name') : value;
+ }
}, {
text: Strings.stateValue,
dataIndex: 'value'
diff --git a/web/app/view/edit/AttributesController.js b/web/app/view/edit/AttributesController.js
index 1ae32c78..235f2c5b 100644
--- a/web/app/view/edit/AttributesController.js
+++ b/web/app/view/edit/AttributesController.js
@@ -25,8 +25,6 @@ Ext.define('Traccar.view.edit.AttributesController', {
'Traccar.model.Attribute'
],
- objectModel: 'Traccar.model.Attribute',
- objectDialog: 'Traccar.view.dialog.Attribute',
removeTitle: Strings.stateName,
init: function () {
@@ -42,18 +40,18 @@ Ext.define('Traccar.view.edit.AttributesController', {
store.add(Ext.create('Traccar.model.Attribute', {
priority: i++,
name: propertyName,
- value: this.getView().record.get('attributes')[propertyName]
+ value: attributes[propertyName]
}));
}
}
- store.addListener('add', function (store, records, index, eOpts) {
+ store.addListener('add', function (store, records) {
var i;
for (i = 0; i < records.length; i++) {
this.getView().record.get('attributes')[records[i].get('name')] = records[i].get('value');
}
this.getView().record.dirty = true;
}, this);
- store.addListener('update', function (store, record, operation, modifiedFieldNames, details, eOpts) {
+ store.addListener('update', function (store, record, operation) {
if (operation === Ext.data.Model.EDIT) {
if (record.modified.name !== record.get('name')) {
delete this.getView().record.get('attributes')[record.modified.name];
@@ -62,7 +60,7 @@ Ext.define('Traccar.view.edit.AttributesController', {
this.getView().record.dirty = true;
}
}, this);
- store.addListener('remove', function (store, records, index, isMove, eOpts) {
+ store.addListener('remove', function (store, records) {
var i;
for (i = 0; i < records.length; i++) {
delete this.getView().record.get('attributes')[records[i].get('name')];
@@ -71,5 +69,51 @@ Ext.define('Traccar.view.edit.AttributesController', {
}, this);
this.getView().setStore(store);
+ if (this.getView().record instanceof Traccar.model.Device) {
+ this.getView().attributesStore = 'DeviceAttributes';
+ } else if (this.getView().record instanceof Traccar.model.Geofence) {
+ this.getView().attributesStore = 'GeofenceAttributes';
+ } else if (this.getView().record instanceof Traccar.model.Group) {
+ this.getView().attributesStore = 'GroupAttributes';
+ } else if (this.getView().record instanceof Traccar.model.Server) {
+ this.getView().attributesStore = 'ServerAttributes';
+ } else if (this.getView().record instanceof Traccar.model.User) {
+ this.getView().attributesStore = 'UserAttributes';
+ }
+ },
+
+ comboConfig: {
+ xtype: 'combobox',
+ reference: 'nameComboField',
+ name: 'name',
+ fieldLabel: Strings.sharedName,
+ displayField: 'name',
+ valueField: 'key',
+ allowBlank: false,
+ listeners: {
+ change: 'onNameChange'
+ }
+ },
+
+ initDialog: function (record) {
+ var nameTextField, dialog = Ext.create('Traccar.view.dialog.Attribute');
+ if (this.getView().attributesStore) {
+ this.comboConfig.store = this.getView().attributesStore;
+ nameTextField = dialog.lookupReference('nameTextField');
+ dialog.down('form').insert(0, this.comboConfig);
+ dialog.down('form').remove(nameTextField);
+ }
+ dialog.down('form').loadRecord(record);
+ dialog.show();
+ },
+
+ onAddClick: function () {
+ var objectInstance = Ext.create('Traccar.model.Attribute');
+ objectInstance.store = this.getView().getStore();
+ this.initDialog(objectInstance);
+ },
+
+ onEditClick: function () {
+ this.initDialog(this.getView().getSelectionModel().getSelection()[0]);
}
});
diff --git a/web/l10n/en.json b/web/l10n/en.json
index 54a772af..075d2309 100644
--- a/web/l10n/en.json
+++ b/web/l10n/en.json
@@ -54,6 +54,26 @@
"sharedPermissions": "Permissions",
"sharedExtra": "Extra",
"sharedTimezone": "Timezone",
+ "attributeSpeedLimit": "Speed Limit",
+ "attributeReportIgnoreOdometer": "Report: Ignore Odometer",
+ "attributeMaintenanceStart": "Maintenance: Start",
+ "attributeMaintenanceInterval": "Maintenance: Interval",
+ "attributeWebReportColor": "Web: Report Color",
+ "attributeDevicePassword": "Device Password",
+ "attributeProcessingCopyAttributes": "Processing: Copy Attributes",
+ "attributeColor": "Color",
+ "attributeWebLiveRouteLength": "Web: Live Route Length",
+ "attributeMailSmtpHost": "Mail: SMTP Host",
+ "attributeMailSmtpPort": "Mail: SMTP Port",
+ "attributeMailSmtpStarttlsEnable": "Mail: SMTP STARTTLS Enable",
+ "attributeMailSmtpStarttlsRequired": "Mail: SMTP STARTTLS Required",
+ "attributeMailSmtpSslEnable": "Mail: SMTP SSL Enable",
+ "attributeMailSmtpSslTrust": "Mail: SMTP SSL Trust",
+ "attributeMailSmtpSslProtocols": "Mail: SMTP SSL Protocols",
+ "attributeMailSmtpFrom": "Mail: SMTP From",
+ "attributeMailSmtpAuth": "Mail: SMTP Auth Enable",
+ "attributeMailSmtpUsername": "Mail: SMTP Username",
+ "attributeMailSmtpPassword": "Mail: SMTP Password",
"errorTitle": "Error",
"errorUnknown": "Unknown error",
"errorConnection": "Connection error",